Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/sqlite/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 1 MB image not shown  

Quellcode-Bibliothek shell.c   Sprache: C

 

/*
** This is the amalgamated source code to the "sqlite3" or "sqlite3.exe"
** command-line shell (CLI) for SQLite.  This file is automatically
** generated by the tool/mkshellc.tcl script from the following sources:
**
**   ext/expert/sqlite3expert.c
**   ext/expert/sqlite3expert.h
**   ext/intck/sqlite3intck.c
**   ext/intck/sqlite3intck.h
**   ext/misc/appendvfs.c
**   ext/misc/base64.c
**   ext/misc/base85.c
**   ext/misc/completion.c
**   ext/misc/decimal.c
**   ext/misc/fileio.c
**   ext/misc/ieee754.c
**   ext/misc/memtrace.c
**   ext/misc/pcachetrace.c
**   ext/misc/regexp.c
**   ext/misc/series.c
**   ext/misc/sha1.c
**   ext/misc/shathree.c
**   ext/misc/sqlar.c
**   ext/misc/sqlite3_stdio.c
**   ext/misc/sqlite3_stdio.h
**   ext/misc/stmtrand.c
**   ext/misc/uint.c
**   ext/misc/vfstrace.c
**   ext/misc/windirent.h
**   ext/misc/zipfile.c
**   ext/qrf/qrf.c
**   ext/qrf/qrf.h
**   ext/recover/dbdata.c
**   ext/recover/sqlite3recover.c
**   ext/recover/sqlite3recover.h
**   src/shell.c.in
**
** To modify this program, get a copy of the canonical SQLite source tree,
** edit the src/shell.c.in file and/or some of the other files that are
** listed above, then rerun the command "make shell.c".
*/

/************************* Begin src/shell.c.in ******************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite3" command line
** utility for accessing SQLite databases.
*/

#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
/* 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;

/*
** Limit input nesting via .read or any other input redirect.
** It's not too expensive, so a generous allowance can be made.
*/

#define MAX_INPUT_NESTING 25

/*
** Used to prevent warnings about unused parameters
*/

#define UNUSED_PARAMETER(x) (void)(x)

/*
** Number of elements in an array
*/

#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))

/*
** Optionally #include a user-defined header, whereby compilation options
** may be set prior to where they take effect, but after platform setup.
** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
** file. Note that this macro has a like effect on sqlite3.c compilation.
*/

# define SHELL_STRINGIFY_(f) #f
# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
#ifdef SQLITE_CUSTOM_INCLUDE
# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
#endif

/*
** 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.
*/

#if defined(SQLITE_SHELL_FIDDLE)
# undef SQLITE_OMIT_LOAD_EXTENSION
# define SQLITE_OMIT_LOAD_EXTENSION 1
#endif

/*
** Warning pragmas copied from msvc.h in the core.
*/

#if defined(_MSC_VER)
#pragma warning(disable : 4054)
#pragma warning(disable : 4055)
#pragma warning(disable : 4100)
#pragma warning(disable : 4127)
#pragma warning(disable : 4130)
#pragma warning(disable : 4152)
#pragma warning(disable : 4189)
#pragma warning(disable : 4206)
#pragma warning(disable : 4210)
#pragma warning(disable : 4232)
#pragma warning(disable : 4244)
#pragma warning(disable : 4305)
#pragma warning(disable : 4306)
#pragma warning(disable : 4702)
#pragma warning(disable : 4706)
#endif /* defined(_MSC_VER) */

/*
** No support for loadable extensions in VxWorks.
*/

#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
# define SQLITE_OMIT_LOAD_EXTENSION 1
#endif

/*
** Enable large-file support for fopen() and friends on unix.
*/

#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE       1
# ifndef _FILE_OFFSET_BITS
#   define _FILE_OFFSET_BITS 64
# endif
# 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>
#include <assert.h>
#include <math.h>
#include <stdint.h>
#include "sqlite3.h"
typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;
typedef unsigned char u8;
#include <ctype.h>
#include <stdarg.h>
#ifndef _WIN32
# include <sys/time.h>
# include <sys/ioctl.h>
#endif

#if !defined(_WIN32) && !defined(WIN32)
# include <signal.h>
# if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
#  include <pwd.h>
# endif
#endif
#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
# include <unistd.h>
# include <dirent.h>
# define GETPID getpid
# if defined(__MINGW32__)
#  define DIRENT dirent
#  ifndef S_ISLNK
#   define S_ISLNK(mode) (0)
#  endif
# endif
#else
# define GETPID (int)GetCurrentProcessId
#endif
#include <sys/types.h>
#include <sys/stat.h>

#if HAVE_READLINE
# include <readline/readline.h>
# include <readline/history.h>
#endif

#if HAVE_EDITLINE
# include <editline/readline.h>
#endif

#if HAVE_EDITLINE || HAVE_READLINE

# define shell_add_history(X) add_history(X)
# define shell_read_history(X) read_history(X)
# define shell_write_history(X) write_history(X)
# define shell_stifle_history(X) stifle_history(X)
# define shell_readline(X) readline(X)

#elif HAVE_LINENOISE

# include "linenoise.h"
# define shell_add_history(X) linenoiseHistoryAdd(X)
# define shell_read_history(X) linenoiseHistoryLoad(X)
# define shell_write_history(X) linenoiseHistorySave(X)
# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
# define shell_readline(X) linenoise(X)

#else

# define shell_read_history(X)
# define shell_write_history(X)
# define shell_stifle_history(X)

# define SHELL_USE_LOCAL_GETLINE 1
#endif

#ifndef deliberate_fall_through
/* Quiet some compilers about some of our intentional code. */
# if defined(GCC_VERSION) && GCC_VERSION>=7000000
#  define deliberate_fall_through __attribute__((fallthrough));
# else
#  define deliberate_fall_through
# endif
#endif

#if defined(_WIN32) || defined(WIN32)
#  include <io.h>
#  include <fcntl.h>
#  define isatty(h) _isatty(h)
#  ifndef access
#   define access(f,m) _access((f),(m))
#  endif
#  ifndef unlink
#   define unlink _unlink
#  endif
#  ifndef strdup
#   define strdup _strdup
#  endif
#  undef pclose
#  define pclose _pclose
#else
 /* Make sure isatty() has a prototype. */
 extern int isatty(int);

# if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
  /* popen and pclose are not C89 functions and so are
  ** sometimes omitted from the <stdio.h> header */

   extern FILE *popen(const char*,const char*);
   extern int pclose(FILE*);
# else
#  define SQLITE_OMIT_POPEN 1
# endif
#endif

#if defined(_WIN32_WCE)
/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
 * thus we always assume that we have a console. That can be
 * overridden with the -batch command line option.
 */

#define isatty(x) 1
#endif

/* ctype macros that work with signed characters */
#define IsSpace(X)  isspace((unsigned char)X)
#define IsDigit(X)  isdigit((unsigned char)X)
#define ToLower(X)  (char)tolower((unsigned char)X)
#define IsAlnum(X)  isalnum((unsigned char)X)
#define IsAlpha(X)  isalpha((unsigned char)X)

#if defined(_WIN32) || defined(WIN32)
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/* string conversion routines only needed on Win32 */
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
#endif

/************************* Begin ext/misc/sqlite3_stdio.h ******************/
/*
** 2024-09-24
**
** 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 contains definitions of interfaces that provide 
** cross-platform I/O for UTF-8 content.
**
** On most platforms, the interfaces definitions in this file are
** just #defines.  For example sqlite3_fopen() is a macro that resolves
** to the standard fopen() in the C-library.
**
** But Windows does not have a standard C-library, at least not one that
** can handle UTF-8.  So for windows build, the interfaces resolve to new
** C-language routines contained in the separate sqlite3_stdio.c source file.
**
** So on all non-Windows platforms, simply #include this header file and
** use the interfaces defined herein.  Then to run your application on Windows,
** also link in the accompanying sqlite3_stdio.c source file when compiling
** to get compatible interfaces.
*/

#ifndef _SQLITE3_STDIO_H_
#define _SQLITE3_STDIO_H_ 1
#ifdef _WIN32
/**** Definitions For Windows ****/
#include <stdio.h>
#include <stdarg.h>
#include <windows.h>

FILE *sqlite3_fopen(const char *zFilename, const char *zMode);
FILE *sqlite3_popen(const char *zCommand, const char *type);
char *sqlite3_fgets(char *s, int size, FILE *stream);
int sqlite3_fputs(const char *s, FILE *stream);
int sqlite3_fprintf(FILE *stream, const char *format, ...);
int sqlite3_vfprintf(FILE *stream, const char *format, va_list);
void sqlite3_fsetmode(FILE *stream, int mode);


#else
/**** Definitions For All Other Platforms ****/
#include <stdio.h>
#define sqlite3_fopen     fopen
#define sqlite3_popen     popen
#define sqlite3_fgets     fgets
#define sqlite3_fputs     fputs
#define sqlite3_fprintf   fprintf
#define sqlite3_vfprintf  vfprintf
#define sqlite3_fsetmode(F,X)   /*no-op*/

#endif
#endif /* _SQLITE3_STDIO_H_ */

/************************* End ext/misc/sqlite3_stdio.h ********************/
/************************* Begin ext/misc/sqlite3_stdio.c ******************/
/*
** 2024-09-24
**
** 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.
**
*************************************************************************
**
** Implementation of standard I/O interfaces for UTF-8 that are missing
** on Windows.
*/

#ifdef _WIN32  /* This file is a no-op on all platforms except Windows */
#ifndef _SQLITE3_STDIO_H_
/* #include "sqlite3_stdio.h" */
#endif
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
/* #include "sqlite3.h" */
#include <ctype.h>
#include <stdarg.h>
#include <io.h>
#include <fcntl.h>

/*
** If the SQLITE_U8TEXT_ONLY option is defined, then use O_U8TEXT
** when appropriate on all output.  (Sometimes use O_BINARY when
** rendering ASCII text in cases where NL-to-CRLF expansion would
** not be correct.)
**
** If the SQLITE_U8TEXT_STDIO option is defined, then use O_U8TEXT
** when appropriate when writing to stdout or stderr.  Use O_BINARY
** or O_TEXT (depending on things like the .mode and the .crlf setting
** in the CLI, or other context clues in other applications) for all
** other output channels.
**
** The default behavior, if neither of the above is defined is to
** use O_U8TEXT when writing to the Windows console (or anything
** else for which _isatty() returns true) and to use O_BINARY or O_TEXT
** for all other output channels.
**
** The SQLITE_USE_W32_FOR_CONSOLE_IO macro is also available.  If
** defined, it forces the use of Win32 APIs for all console I/O, both
** input and output.  This is necessary for some non-Microsoft run-times
** that implement stdio differently from Microsoft/Visual-Studio.
*/

#if defined(SQLITE_U8TEXT_ONLY)
# define UseWtextForOutput(fd) 1
# define UseWtextForInput(fd)  1
# define IsConsole(fd)         _isatty(_fileno(fd))
#elif defined(SQLITE_U8TEXT_STDIO)
# define UseWtextForOutput(fd) ((fd)==stdout || (fd)==stderr)
# define UseWtextForInput(fd)  ((fd)==stdin)
# define IsConsole(fd)         _isatty(_fileno(fd))
#else
# define UseWtextForOutput(fd) _isatty(_fileno(fd))
# define UseWtextForInput(fd)  _isatty(_fileno(fd))
# define IsConsole(fd)         1
#endif

/*
** Global variables determine if simulated O_BINARY mode is to be
** used for stdout or other, respectively.  Simulated O_BINARY mode
** means the mode is usually O_BINARY, but switches to O_U8TEXT for
** unicode characters U+0080 or greater (any character that has a
** multi-byte representation in UTF-8).  This is the only way we
** have found to render Unicode characters on a Windows console while
** at the same time avoiding undesirable \n to \r\n translation.
*/

static int simBinaryStdout = 0;
static int simBinaryOther = 0;


/*
** Determine if simulated binary mode should be used for output to fd
*/

static int UseBinaryWText(FILE *fd){
  if( fd==stdout || fd==stderr ){
    return simBinaryStdout;
  }else{
    return simBinaryOther;
  }
}


/*
** Work-alike for the fopen() routine from the standard C library.
*/

FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
  FILE *fp = 0;
  wchar_t *b1, *b2;
  int sz1, sz2;

  sz1 = (int)strlen(zFilename);
  sz2 = (int)strlen(zMode);
  b1 = sqlite3_malloc64( (sz1+1)*sizeof(b1[0]) );
  b2 = sqlite3_malloc64( (sz2+1)*sizeof(b1[0]) );
  if( b1 && b2 ){
    sz1 = MultiByteToWideChar(CP_UTF8, 0, zFilename, sz1, b1, sz1);
    b1[sz1] = 0;
    sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2);
    b2[sz2] = 0;
    fp = _wfopen(b1, b2);
  }
  sqlite3_free(b1);
  sqlite3_free(b2);
  simBinaryOther = 0;
  return fp;
}


/*
** Work-alike for the popen() routine from the standard C library.
*/

FILE *sqlite3_popen(const char *zCommand, const char *zMode){
  FILE *fp = 0;
  wchar_t *b1, *b2;
  int sz1, sz2;

  sz1 = (int)strlen(zCommand);
  sz2 = (int)strlen(zMode);
  b1 = sqlite3_malloc64( (sz1+1)*sizeof(b1[0]) );
  b2 = sqlite3_malloc64( (sz2+1)*sizeof(b1[0]) );
  if( b1 && b2 ){
    sz1 = MultiByteToWideChar(CP_UTF8, 0, zCommand, sz1, b1, sz1);
    b1[sz1] = 0;
    sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2);
    b2[sz2] = 0;
    fp = _wpopen(b1, b2);
  }
  sqlite3_free(b1);
  sqlite3_free(b2);
  return fp;
}

/*
** Work-alike for fgets() from the standard C library.
*/

char *sqlite3_fgets(char *buf, int sz, FILE *in){
  if( UseWtextForInput(in) ){
    /* When reading from the command-prompt in Windows, it is necessary
    ** to use _O_WTEXT input mode to read UTF-16 characters, then translate
    ** that into UTF-8.  Otherwise, non-ASCII characters all get translated
    ** into '?'.
    */

    wchar_t *b1 = sqlite3_malloc64( sz*sizeof(wchar_t) );
    if( b1==0 ) return 0;
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
    DWORD nRead = 0;
    if( IsConsole(in)
     && ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), b1, sz-1, &nRead, 0)
    ){
      b1[nRead] = 0;
    }else
#endif
    {
      _setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
      if( fgetws(b1, sz/4, in)==0 ){
        sqlite3_free(b1);
        return 0;
      }
    }
    WideCharToMultiByte(CP_UTF8, 0, b1, -1, buf, sz, 0, 0);
    sqlite3_free(b1);
    return buf;
  }else{
    /* Reading from a file or other input source, just read bytes without
    ** any translation. */

    return fgets(buf, sz, in);
  }
}

/*
** Send ASCII text as O_BINARY.  But for Unicode characters U+0080 and
** greater, switch to O_U8TEXT.
*/

static void piecemealOutput(wchar_t *b1, int sz, FILE *out){
  int i;
  wchar_t c;
  while( sz>0 ){
    for(i=0; i<sz && b1[i]>=0x80; i++){}
    if( i>0 ){
      c = b1[i];
      b1[i] = 0;
      fflush(out);
      _setmode(_fileno(out), _O_U8TEXT);
      fputws(b1, out);
      fflush(out);
      b1 += i;
      b1[0] = c;
      sz -= i;
    }else{
      fflush(out);
      _setmode(_fileno(out), _O_TEXT);
      _setmode(_fileno(out), _O_BINARY);
      fwrite(&b1[0], 1, 1, out);
      for(i=1; i<sz && b1[i]<0x80; i++){
        fwrite(&b1[i], 1, 1, out);
      }
      fflush(out);
      _setmode(_fileno(out), _O_U8TEXT);
      b1 += i;
      sz -= i;
    }
  }
}

/*
** Work-alike for fputs() from the standard C library.
*/

int sqlite3_fputs(const char *z, FILE *out){
  if( !UseWtextForOutput(out) ){
    /* Writing to a file or other destination, just write bytes without
    ** any translation. */

    return fputs(z, out);
  }else{
    /* One must use UTF16 in order to get unicode support when writing
    ** to the console on Windows. 
    */

    int sz = (int)strlen(z);
    wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(wchar_t) );
    if( b1==0 ) return 0;
    sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
    b1[sz] = 0;

#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
    DWORD nWr = 0;
    if( IsConsole(out)
      && WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),b1,sz,&nWr,0)
    ){
      /* If writing to the console, then the WriteConsoleW() is all we
      ** need to do. */

    }else
#endif
    {
      /* As long as SQLITE_USE_W32_FOR_CONSOLE_IO is not defined, or for
      ** non-console I/O even if that macro is defined, write using the
      ** standard library. */

      _setmode(_fileno(out), _O_U8TEXT);
      if( UseBinaryWText(out) ){
        piecemealOutput(b1, sz, out);
      }else{
        fputws(b1, out);
      }
    }
    sqlite3_free(b1);
    return 0;
  }
}


/*
** Work-alikes for fprintf() and vfprintf() from the standard C library.
*/

int sqlite3_fprintf(FILE *out, const char *zFormat, ...){
  int rc;
  if( UseWtextForOutput(out) ){
    /* When writing to the command-prompt in Windows, it is necessary
    ** to use _O_WTEXT input mode and write UTF-16 characters.
    */

    char *z;
    va_list ap;

    va_start(ap, zFormat);
    z = sqlite3_vmprintf(zFormat, ap);
    va_end(ap);
    sqlite3_fputs(z, out);
    rc = (int)strlen(z);
    sqlite3_free(z);
  }else{
    /* Writing to a file or other destination, just write bytes without
    ** any translation. */

    va_list ap;
    va_start(ap, zFormat);
    rc = vfprintf(out, zFormat, ap);
    va_end(ap);
  }
  return rc;
}
int sqlite3_vfprintf(FILE *out, const char *zFormat, va_list ap){
  int rc;
  if( UseWtextForOutput(out) ){
    /* When writing to the command-prompt in Windows, it is necessary
    ** to use _O_WTEXT input mode and write UTF-16 characters.
    */

    char *z;
    z = sqlite3_vmprintf(zFormat, ap);
    sqlite3_fputs(z, out);
    rc = (int)strlen(z);
    sqlite3_free(z);
  }else{
    /* Writing to a file or other destination, just write bytes without
    ** any translation. */

    rc = vfprintf(out, zFormat, ap);
  }
  return rc;
}

/*
** Set the mode for an output stream.  mode argument is typically _O_BINARY or
** _O_TEXT.
*/

void sqlite3_fsetmode(FILE *fp, int mode){
  if( !UseWtextForOutput(fp) ){
    fflush(fp);
    _setmode(_fileno(fp), mode);
  }else if( fp==stdout || fp==stderr ){
    simBinaryStdout = (mode==_O_BINARY);
  }else{
    simBinaryOther = (mode==_O_BINARY);
  }
}

#endif /* defined(_WIN32) */

/************************* End ext/misc/sqlite3_stdio.c ********************/
/************************* Begin ext/qrf/qrf.h ******************/
/*
** 2025-10-20
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Header file for the Query Result-Format or "qrf" utility library for
** SQLite.  See the README.md documentation for additional information.
*/

#ifndef SQLITE_QRF_H
#define SQLITE_QRF_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
/* #include "sqlite3.h" */

/*
** Specification used by clients to define the output format they want
*/

typedef struct sqlite3_qrf_spec sqlite3_qrf_spec;
struct sqlite3_qrf_spec {
  unsigned char iVersion;     /* Version number of this structure */
  unsigned char eStyle;       /* Formatting style.  "box", "csv", etc... */
  unsigned char eEsc;         /* How to escape control characters in text */
  unsigned char eText;        /* Quoting style for text */
  unsigned char eTitle;       /* Quating style for the text of column names */
  unsigned char eBlob;        /* Quoting style for BLOBs */
  unsigned char bTitles;      /* True to show column names */
  unsigned char bWordWrap;    /* Try to wrap on word boundaries */
  unsigned char bTextJsonb;   /* Render JSONB blobs as JSON text */
  unsigned char eDfltAlign;   /* Default alignment, no covered by aAlignment */
  unsigned char eTitleAlign;  /* Alignment for column headers */
  unsigned char bSplitColumn; /* Wrap single-column output into many columns */
  unsigned char bBorder;      /* Show outer border in Box and Table styles */
  short int nWrap;            /* Wrap columns wider than this */
  short int nScreenWidth;     /* Maximum overall table width */
  short int nLineLimit;       /* Maximum number of lines for any row */
  short int nTitleLimit;      /* Maximum number of characters in a title */
  unsigned int nMultiInsert;  /* Add rows to one INSERT until size exceeds */
  int nCharLimit;             /* Maximum number of characters in a cell */
  int nWidth;                 /* Number of entries in aWidth[] */
  int nAlign;                 /* Number of entries in aAlignment[] */
  short int *aWidth;          /* Column widths */
  unsigned char *aAlign;      /* Column alignments */
  char *zColumnSep;           /* Alternative column separator */
  char *zRowSep;              /* Alternative row separator */
  char *zTableName;           /* Output table name */
  char *zNull;                /* Rendering of NULL */
  char *(*xRender)(void*,sqlite3_value*);           /* Render a value */
  int (*xWrite)(void*,const char*,sqlite3_int64);   /* Write output */
  void *pRenderArg;           /* First argument to the xRender callback */
  void *pWriteArg;            /* First argument to the xWrite callback */
  char **pzOutput;            /* Storage location for output string */
  /* Additional fields may be added in the future */
};

/*
** Interfaces
*/

int sqlite3_format_query_result(
  sqlite3_stmt *pStmt,             /* SQL statement to run */
  const sqlite3_qrf_spec *pSpec,   /* Result format specification */
  char **pzErr                     /* OUT: Write error message here */
);

/*
** Range of values for sqlite3_qrf_spec.aWidth[] entries and for
** sqlite3_qrf_spec.mxColWidth and .nScreenWidth
*/

#define QRF_MAX_WIDTH    10000
#define QRF_MIN_WIDTH    0

/*
** Output styles:
*/

#define QRF_STYLE_Auto      0 /* Choose a style automatically */
#define QRF_STYLE_Box       1 /* Unicode box-drawing characters */
#define QRF_STYLE_Column    2 /* One record per line in neat columns */
#define QRF_STYLE_Count     3 /* Output only a count of the rows of output */
#define QRF_STYLE_Csv       4 /* Comma-separated-value */
#define QRF_STYLE_Eqp       5 /* Format EXPLAIN QUERY PLAN output */
#define QRF_STYLE_Explain   6 /* EXPLAIN output */
#define QRF_STYLE_Html      7 /* Generate an XHTML table */
#define QRF_STYLE_Insert    8 /* Generate SQL "insert" statements */
#define QRF_STYLE_Json      9 /* Output is a list of JSON objects */
#define QRF_STYLE_JObject  10 /* Independent JSON objects for each row */
#define QRF_STYLE_Line     11 /* One column per line. */
#define QRF_STYLE_List     12 /* One record per line with a separator */
#define QRF_STYLE_Markdown 13 /* Markdown formatting */
#define QRF_STYLE_Off      14 /* No query output shown */
#define QRF_STYLE_Quote    15 /* SQL-quoted, comma-separated */
#define QRF_STYLE_Stats    16 /* EQP-like output but with performance stats */
#define QRF_STYLE_StatsEst 17 /* EQP-like output with planner estimates */
#define QRF_STYLE_StatsVm  18 /* EXPLAIN-like output with performance stats */
#define QRF_STYLE_Table    19 /* MySQL-style table formatting */

/*
** Quoting styles for text.
** Allowed values for sqlite3_qrf_spec.eText
*/

#define QRF_TEXT_Auto    0 /* Choose text encoding automatically */
#define QRF_TEXT_Plain   1 /* Literal text */
#define QRF_TEXT_Sql     2 /* Quote as an SQL literal */
#define QRF_TEXT_Csv     3 /* CSV-style quoting */
#define QRF_TEXT_Html    4 /* HTML-style quoting */
#define QRF_TEXT_Tcl     5 /* C/Tcl quoting */
#define QRF_TEXT_Json    6 /* JSON quoting */
#define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */

/*
** Quoting styles for BLOBs
** Allowed values for sqlite3_qrf_spec.eBlob
*/

#define QRF_BLOB_Auto    0 /* Determine BLOB quoting using eText */
#define QRF_BLOB_Text    1 /* Display content exactly as it is */
#define QRF_BLOB_Sql     2 /* Quote as an SQL literal */
#define QRF_BLOB_Hex     3 /* Hexadecimal representation */
#define QRF_BLOB_Tcl     4 /* "\000" notation */
#define QRF_BLOB_Json    5 /* A JSON string */
#define QRF_BLOB_Size    6 /* Display the blob size only */

/*
** Control-character escape modes.
** Allowed values for sqlite3_qrf_spec.eEsc
*/

#define QRF_ESC_Auto    0 /* Choose the ctrl-char escape automatically */
#define QRF_ESC_Off     1 /* Do not escape control characters */
#define QRF_ESC_Ascii   2 /* Unix-style escapes.  Ex: U+0007 shows ^G */
#define QRF_ESC_Symbol  3 /* Unicode escapes. Ex: U+0007 shows U+2407 */

/*
** Allowed values for "boolean" fields, such as "bColumnNames", "bWordWrap",
** and "bTextJsonb".  There is an extra "auto" variants so these are actually
** tri-state settings, not booleans.
*/

#define QRF_SW_Auto     0 /* Let QRF choose the best value */
#define QRF_SW_Off      1 /* This setting is forced off */
#define QRF_SW_On       2 /* This setting is forced on */
#define QRF_Auto        0 /* Alternate spelling for QRF_*_Auto */
#define QRF_No          1 /* Alternate spelling for QRF_SW_Off */
#define QRF_Yes         2 /* Alternate spelling for QRF_SW_On */

/*
** Possible alignment values alignment settings
**
**                             Horizontal   Vertial
**                             ----------   --------  */

#define QRF_ALIGN_Auto    0 /*   auto        auto     */
#define QRF_ALIGN_Left    1 /*   left        auto     */
#define QRF_ALIGN_Center  2 /*   center      auto     */
#define QRF_ALIGN_Right   3 /*   right       auto     */
#define QRF_ALIGN_Top     4 /*   auto        top      */
#define QRF_ALIGN_NW      5 /*   left        top      */
#define QRF_ALIGN_N       6 /*   center      top      */
#define QRF_ALIGN_NE      7 /*   right       top      */
#define QRF_ALIGN_Middle  8 /*   auto        middle   */
#define QRF_ALIGN_W       9 /*   left        middle   */
#define QRF_ALIGN_C      10 /*   center      middle   */
#define QRF_ALIGN_E      11 /*   right       middle   */
#define QRF_ALIGN_Bottom 12 /*   auto        bottom   */
#define QRF_ALIGN_SW     13 /*   left        bottom   */
#define QRF_ALIGN_S      14 /*   center      bottom   */
#define QRF_ALIGN_SE     15 /*   right       bottom   */
#define QRF_ALIGN_HMASK   3 /* Horizontal alignment mask */
#define QRF_ALIGN_VMASK  12 /* Vertical alignment mask */

/*
** Auxiliary routines contined within this module that might be useful
** in other contexts, and which are therefore exported.
*/

/*
** Return an estimate of the width, in columns, for the single Unicode
** character c.  For normal characters, the answer is always 1.  But the
** estimate might be 0 or 2 for zero-width and double-width characters.
**
** Different devices display unicode using different widths.  So
** it is impossible to know that true display width with 100% accuracy.
** Inaccuracies in the width estimates might cause columns to be misaligned.
** Unfortunately, there is nothing we can do about that.
*/

int sqlite3_qrf_wcwidth(int c);

/*
** Return an estimate of the number of display columns used by the
** string in the argument.  The width of individual characters is
** determined as for sqlite3_qrf_wcwidth().  VT100 escape code sequences
** are assigned a width of zero.
*/

size_t sqlite3_qrf_wcswidth(const char*);


#ifdef __cplusplus
}
#endif
#endif /* !defined(SQLITE_QRF_H) */

/************************* End ext/qrf/qrf.h ********************/
/************************* Begin ext/qrf/qrf.c ******************/
/*
** 2025-10-20
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Implementation of the Query Result-Format or "qrf" utility library for
** SQLite.  See the README.md documentation for additional information.
*/

#ifndef SQLITE_QRF_H
#include "qrf.h"
#endif
#include <string.h>
#include <assert.h>
#include <stdint.h>

#ifndef SQLITE_AMALGAMATION
/* typedef sqlite3_int64 i64; */
#endif

/* A single line in the EQP output */
typedef struct qrfEQPGraphRow qrfEQPGraphRow;
struct qrfEQPGraphRow {
  int iEqpId;            /* ID for this row */
  int iParentId;         /* ID of the parent row */
  qrfEQPGraphRow *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 qrfEQPGraph qrfEQPGraph;
struct qrfEQPGraph {
  qrfEQPGraphRow *pRow;  /* Linked list of all rows of the EQP output */
  qrfEQPGraphRow *pLast; /* Last element of the pRow list */
  int nWidth;            /* Width of the graph */
  char zPrefix[400];     /* Graph prefix */
};

/*
** Private state information.  Subject to change from one release to the
** next.
*/

typedef struct Qrf Qrf;
struct Qrf {
  sqlite3_stmt *pStmt;        /* The statement whose output is to be rendered */
  sqlite3 *db;                /* The corresponding database connection */
  sqlite3_stmt *pJTrans;      /* JSONB to JSON translator statement */
  char **pzErr;               /* Write error message here, if not NULL */
  sqlite3_str *pOut;          /* Accumulated output */
  int iErr;                   /* Error code */
  int nCol;                   /* Number of output columns */
  int expMode;                /* Original sqlite3_stmt_isexplain() plus 1 */
  int mxWidth;                /* Screen width */
  int mxHeight;               /* nLineLimit */
  union {
    struct {                  /* Content for QRF_STYLE_Line */
      int mxColWth;             /* Maximum display width of any column */
      char **azCol;             /* Names of output columns (MODE_Line) */
    } sLine;
    qrfEQPGraph *pGraph;      /* EQP graph (Eqp, Stats, and StatsEst) */
    struct {                  /* Content for QRF_STYLE_Explain */
      int nIndent;              /* Slots allocated for aiIndent */
      int iIndent;              /* Current slot */
      int *aiIndent;            /* Indentation for each opcode */
    } sExpln;
    unsigned int nIns;        /* Bytes used for current INSERT stmt */
  } u;
  sqlite3_int64 nRow;         /* Number of rows handled so far */
  int *actualWidth;           /* Actual width of each column */
  sqlite3_qrf_spec spec;      /* Copy of the original spec */
};

/*
** Data for substitute ctype.h functions.  Used for x-platform
** consistency and so that '_' is counted as an alphabetic
** character.
**
**    0x01 -  space
**    0x02 -  digit
**    0x04 -  alphabetic, including '_'
*/

static const char qrfCType[] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
  0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4,
  0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#define qrfSpace(x) ((qrfCType[(unsigned char)x]&1)!=0)
#define qrfDigit(x) ((qrfCType[(unsigned char)x]&2)!=0)
#define qrfAlpha(x) ((qrfCType[(unsigned char)x]&4)!=0)
#define qrfAlnum(x) ((qrfCType[(unsigned char)x]&6)!=0)

#ifndef deliberate_fall_through
/* Quiet some compilers about some of our intentional code. */
# if defined(GCC_VERSION) && GCC_VERSION>=7000000
#  define deliberate_fall_through __attribute__((fallthrough));
# else
#  define deliberate_fall_through
# endif
#endif

/*
** Set an error code and error message.
*/

static void qrfError(
  Qrf *p,                /* Query result state */
  int iCode,             /* Error code */
  const char *zFormat,   /* Message format (or NULL) */
  ...
){
  p->iErr = iCode;
  if( p->pzErr!=0 ){
    sqlite3_free(*p->pzErr);
    *p->pzErr = 0;
    if( zFormat ){
      va_list ap;
      va_start(ap, zFormat);
      *p->pzErr = sqlite3_vmprintf(zFormat, ap);
      va_end(ap);
    }
  }
}

/*
** Out-of-memory error.
*/

static void qrfOom(Qrf *p){
  qrfError(p, SQLITE_NOMEM, "out of memory");
}

/*
** Transfer any error in pStr over into p.
*/

static void qrfStrErr(Qrf *p, sqlite3_str *pStr){
  int rc = pStr ? sqlite3_str_errcode(pStr) : 0;
  if( rc ){
    qrfError(p, rc, sqlite3_errstr(rc));
  }
}


/*
** Add a new entry to the EXPLAIN QUERY PLAN data
*/

static void qrfEqpAppend(Qrf *p, int iEqpId, int p2, const char *zText){
  qrfEQPGraphRow *pNew;
  sqlite3_int64 nText;
  if( zText==0 ) return;
  if( p->u.pGraph==0 ){
    p->u.pGraph = sqlite3_malloc64( sizeof(qrfEQPGraph) );
    if( p->u.pGraph==0 ){
      qrfOom(p);
      return;
    }
    memset(p->u.pGraph, 0, sizeof(qrfEQPGraph) );
  }
  nText = strlen(zText);
  pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
  if( pNew==0 ){
    qrfOom(p);
    return;
  }
  pNew->iEqpId = iEqpId;
  pNew->iParentId = p2;
  memcpy(pNew->zText, zText, nText+1);
  pNew->pNext = 0;
  if( p->u.pGraph->pLast ){
    p->u.pGraph->pLast->pNext = pNew;
  }else{
    p->u.pGraph->pRow = pNew;
  }
  p->u.pGraph->pLast = pNew;
}

/*
** Free and reset the EXPLAIN QUERY PLAN data that has been collected
** in p->u.pGraph.
*/

static void qrfEqpReset(Qrf *p){
  qrfEQPGraphRow *pRow, *pNext;
  if( p->u.pGraph ){
    for(pRow = p->u.pGraph->pRow; pRow; pRow = pNext){
      pNext = pRow->pNext;
      sqlite3_free(pRow);
    }
    sqlite3_free(p->u.pGraph);
    p->u.pGraph = 0;
  }
}

/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
** pOld, or return the first such line if pOld is NULL
*/

static qrfEQPGraphRow *qrfEqpNextRow(Qrf *p, int iEqpId, qrfEQPGraphRow *pOld){
  qrfEQPGraphRow *pRow = pOld ? pOld->pNext : p->u.pGraph->pRow;
  while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
  return pRow;
}

/* Render a single level of the graph that has iEqpId as its parent.  Called
** recursively to render sublevels.
*/

static void qrfEqpRenderLevel(Qrf *p, int iEqpId){
  qrfEQPGraphRow *pRow, *pNext;
  i64 n = strlen(p->u.pGraph->zPrefix);
  char *z;
  for(pRow = qrfEqpNextRow(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = qrfEqpNextRow(p, iEqpId, pRow);
    z = pRow->zText;
    sqlite3_str_appendf(p->pOut, "%s%s%s\n", p->u.pGraph->zPrefix,
                            pNext ? "|--" : "`--", z);
    if( n<(i64)sizeof(p->u.pGraph->zPrefix)-7 ){
      memcpy(&p->u.pGraph->zPrefix[n], pNext ? "|  " : "   ", 4);
      qrfEqpRenderLevel(p, pRow->iEqpId);
      p->u.pGraph->zPrefix[n] = 0;
    }
  }
}

/*
** Render the 64-bit value N in a more human-readable format into
** pOut.
**
**   +  Only show the first three significant digits.
**   +  Append suffixes K, M, G, T, P, and E for 1e3, 1e6, ... 1e18
*/

static void qrfApproxInt64(sqlite3_str *pOut, i64 N){
  static const char aSuffix[] = { 'K', 'M', 'G', 'T', 'P', 'E' };
  int i;
  if( N<0 ){
    N = N==INT64_MIN ? INT64_MAX : -N;
    sqlite3_str_append(pOut, "-", 1);
  }
  if( N<10000 ){
    sqlite3_str_appendf(pOut, "%4lld ", N);
    return;
  }
  for(i=1; i<=18; i++){
    N = (N+5)/10;
    if( N<10000 ){
      int n = (int)N;
      switch( i%3 ){
        case 0:
          sqlite3_str_appendf(pOut, "%d.%02d", n/1000, (n%1000)/10);
          break;
        case 1:
          sqlite3_str_appendf(pOut, "%2d.%d", n/100, (n%100)/10);
          break;
        case 2:
          sqlite3_str_appendf(pOut, "%4d", n/10);
          break;
      }
      sqlite3_str_append(pOut, &aSuffix[i/3], 1);
      break;
    }
  }
}

/*
** Display and reset the EXPLAIN QUERY PLAN data
*/

static void qrfEqpRender(Qrf *p, i64 nCycle){
  qrfEQPGraphRow *pRow;
  if( p->u.pGraph!=0 && (pRow = p->u.pGraph->pRow)!=0 ){
    if( pRow->zText[0]=='-' ){
      if( pRow->pNext==0 ){
        qrfEqpReset(p);
        return;
      }
      sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3);
      p->u.pGraph->pRow = pRow->pNext;
      sqlite3_free(pRow);
    }else if( nCycle>0 ){
      int nSp = p->u.pGraph->nWidth - 2;
      if( p->spec.eStyle==QRF_STYLE_StatsEst ){
        sqlite3_str_appendchar(p->pOut, nSp, ' ');
        sqlite3_str_appendall(p->pOut,
                                "Cycles      Loops  (est)  Rows   (est)\n");
        sqlite3_str_appendchar(p->pOut, nSp, ' ');
        sqlite3_str_appendall(p->pOut,
                                "----------  ------------  ------------\n");
      }else{
        sqlite3_str_appendchar(p->pOut, nSp, ' ');
        sqlite3_str_appendall(p->pOut,
                                "Cycles      Loops  Rows \n");
        sqlite3_str_appendchar(p->pOut, nSp, ' ');
        sqlite3_str_appendall(p->pOut,
                                "----------  -----  -----\n");
      }
      sqlite3_str_appendall(p->pOut, "QUERY PLAN");
      sqlite3_str_appendchar(p->pOut, nSp - 10, ' ');
      qrfApproxInt64(p->pOut, nCycle);
      sqlite3_str_appendall(p->pOut, " 100%\n");
    }else{
      sqlite3_str_appendall(p->pOut, "QUERY PLAN\n");
    }
    p->u.pGraph->zPrefix[0] = 0;
    qrfEqpRenderLevel(p, 0);
    qrfEqpReset(p);
  }
}

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Helper function for qrfExpStats().
**
*/

static int qrfStatsHeight(sqlite3_stmt *p, int iEntry){
  int iPid = 0;
  int ret = 1;
  sqlite3_stmt_scanstatus_v2(p, iEntry,
      SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid
  );
  while( iPid!=0 ){
    int ii;
    for(ii=0; 1; ii++){
      int iId;
      int res;
      res = sqlite3_stmt_scanstatus_v2(p, ii,
          SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iId
      );
      if( res ) break;
      if( iId==iPid ){
        sqlite3_stmt_scanstatus_v2(p, ii,
            SQLITE_SCANSTAT_PARENTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid
        );
      }
    }
    ret++;
  }
  return ret;
}
#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */


/*
** Generate ".scanstatus est" style of EQP output.
*/

static void qrfEqpStats(Qrf *p){
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
  qrfError(p, SQLITE_ERROR, "not available in this build");
#else
  static const int f = SQLITE_SCANSTAT_COMPLEX;
  sqlite3_stmt *pS = p->pStmt;
  int i = 0;
  i64 nTotal = 0;
  int nWidth = 0;
  int prevPid = -1;             /* Previous iPid */
  double rEstCum = 1.0;         /* Cumulative row estimate */
  sqlite3_str *pLine = sqlite3_str_new(p->db);
  sqlite3_str *pStats = sqlite3_str_new(p->db);
  qrfEqpReset(p);

  for(i=0; 1; i++){
    const char *z = 0;
    int n = 0;
    if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){
      break;
    }
    n = (int)strlen(z) + qrfStatsHeight(pS,i)*3;
    if( n>nWidth ) nWidth = n;
  }
  nWidth += 2;

  sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal);
  for(i=0; 1; i++){
    i64 nLoop = 0;
    i64 nRow = 0;
    i64 nCycle = 0;
    int iId = 0;
    int iPid = 0;
    const char *zo = 0;
    const char *zName = 0;
    double rEst = 0.0;

    if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){
      break;
    }
    sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid);
    if( iPid!=prevPid ){
      prevPid = iPid;
      rEstCum = 1.0;
    }
    sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst);
    rEstCum *= rEst;
    sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop);
    sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow);
    sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle);
    sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId);
    sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName);

    if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
      int nSp = 0;
      sqlite3_str_reset(pStats);
      if( nCycle>=0 && nTotal>0 ){
        qrfApproxInt64(pStats, nCycle);
        sqlite3_str_appendf(pStats, " %3d%%",
            ((nCycle*100)+nTotal/2) / nTotal
        );
        nSp = 2;
      }
      if( nLoop>=0 ){
        if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
        qrfApproxInt64(pStats, nLoop);
        nSp = 2;
        if( p->spec.eStyle==QRF_STYLE_StatsEst ){
          sqlite3_str_appendf(pStats, "  ");
          qrfApproxInt64(pStats, (i64)(rEstCum/rEst));
        }
      }
      if( nRow>=0 ){
        if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
        qrfApproxInt64(pStats, nRow);
        nSp = 2;
        if( p->spec.eStyle==QRF_STYLE_StatsEst ){
          sqlite3_str_appendf(pStats, "  ");
          qrfApproxInt64(pStats, (i64)rEstCum);
        }
      }
      sqlite3_str_appendf(pLine,
          "% *s %s", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo,
          sqlite3_str_value(pStats)
      );
      sqlite3_str_reset(pStats);
      qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine));
      sqlite3_str_reset(pLine);
    }else{
      qrfEqpAppend(p, iId, iPid, zo);
    }
  }
  if( p->u.pGraph ) p->u.pGraph->nWidth = nWidth;
  qrfStrErr(p, pLine);
  sqlite3_free(sqlite3_str_finish(pLine));
  qrfStrErr(p, pStats);
  sqlite3_free(sqlite3_str_finish(pStats));
#endif
}


/*
** Reset the prepared statement.
*/

static void qrfResetStmt(Qrf *p){
  int rc = sqlite3_reset(p->pStmt);
  if( rc!=SQLITE_OK && p->iErr==SQLITE_OK ){
    qrfError(p, rc, "%s", sqlite3_errmsg(p->db));
  }
}

/*
** If xWrite is defined, send all content of pOut to xWrite and
** reset pOut.
*/

static void qrfWrite(Qrf *p){
  int n;
  if( p->spec.xWrite && (n = sqlite3_str_length(p->pOut))>0 ){
    int rc = p->spec.xWrite(p->spec.pWriteArg,
                 sqlite3_str_value(p->pOut),
                 (sqlite3_int64)n);
    sqlite3_str_reset(p->pOut);
    if( rc ){
      qrfError(p, rc, "Failed to write %d bytes of output", n);
    }
  }
}

/* Lookup table to estimate the number of columns consumed by a Unicode
** character.
*/

static const struct {
  unsigned char w;    /* Width of the character in columns */
  int iFirst;         /* First character in a span having this width */
} aQrfUWidth[] = {
   /* {1, 0x00000}, */
  {0, 0x00300},  {1, 0x00370},  {0, 0x00483},  {1, 0x00487},  {0, 0x00488},
  {1, 0x0048a},  {0, 0x00591},  {1, 0x005be},  {0, 0x005bf},  {1, 0x005c0},
  {0, 0x005c1},  {1, 0x005c3},  {0, 0x005c4},  {1, 0x005c6},  {0, 0x005c7},
  {1, 0x005c8},  {0, 0x00600},  {1, 0x00604},  {0, 0x00610},  {1, 0x00616},
  {0, 0x0064b},  {1, 0x0065f},  {0, 0x00670},  {1, 0x00671},  {0, 0x006d6},
  {1, 0x006e5},  {0, 0x006e7},  {1, 0x006e9},  {0, 0x006ea},  {1, 0x006ee},
  {0, 0x0070f},  {1, 0x00710},  {0, 0x00711},  {1, 0x00712},  {0, 0x00730},
  {1, 0x0074b},  {0, 0x007a6},  {1, 0x007b1},  {0, 0x007eb},  {1, 0x007f4},
  {0, 0x00901},  {1, 0x00903},  {0, 0x0093c},  {1, 0x0093d},  {0, 0x00941},
  {1, 0x00949},  {0, 0x0094d},  {1, 0x0094e},  {0, 0x00951},  {1, 0x00955},
  {0, 0x00962},  {1, 0x00964},  {0, 0x00981},  {1, 0x00982},  {0, 0x009bc},
  {1, 0x009bd},  {0, 0x009c1},  {1, 0x009c5},  {0, 0x009cd},  {1, 0x009ce},
  {0, 0x009e2},  {1, 0x009e4},  {0, 0x00a01},  {1, 0x00a03},  {0, 0x00a3c},
  {1, 0x00a3d},  {0, 0x00a41},  {1, 0x00a43},  {0, 0x00a47},  {1, 0x00a49},
  {0, 0x00a4b},  {1, 0x00a4e},  {0, 0x00a70},  {1, 0x00a72},  {0, 0x00a81},
  {1, 0x00a83},  {0, 0x00abc},  {1, 0x00abd},  {0, 0x00ac1},  {1, 0x00ac6},
  {0, 0x00ac7},  {1, 0x00ac9},  {0, 0x00acd},  {1, 0x00ace},  {0, 0x00ae2},
  {1, 0x00ae4},  {0, 0x00b01},  {1, 0x00b02},  {0, 0x00b3c},  {1, 0x00b3d},
  {0, 0x00b3f},  {1, 0x00b40},  {0, 0x00b41},  {1, 0x00b44},  {0, 0x00b4d},
  {1, 0x00b4e},  {0, 0x00b56},  {1, 0x00b57},  {0, 0x00b82},  {1, 0x00b83},
  {0, 0x00bc0},  {1, 0x00bc1},  {0, 0x00bcd},  {1, 0x00bce},  {0, 0x00c3e},
  {1, 0x00c41},  {0, 0x00c46},  {1, 0x00c49},  {0, 0x00c4a},  {1, 0x00c4e},
  {0, 0x00c55},  {1, 0x00c57},  {0, 0x00cbc},  {1, 0x00cbd},  {0, 0x00cbf},
  {1, 0x00cc0},  {0, 0x00cc6},  {1, 0x00cc7},  {0, 0x00ccc},  {1, 0x00cce},
  {0, 0x00ce2},  {1, 0x00ce4},  {0, 0x00d41},  {1, 0x00d44},  {0, 0x00d4d},
  {1, 0x00d4e},  {0, 0x00dca},  {1, 0x00dcb},  {0, 0x00dd2},  {1, 0x00dd5},
  {0, 0x00dd6},  {1, 0x00dd7},  {0, 0x00e31},  {1, 0x00e32},  {0, 0x00e34},
  {1, 0x00e3b},  {0, 0x00e47},  {1, 0x00e4f},  {0, 0x00eb1},  {1, 0x00eb2},
  {0, 0x00eb4},  {1, 0x00eba},  {0, 0x00ebb},  {1, 0x00ebd},  {0, 0x00ec8},
  {1, 0x00ece},  {0, 0x00f18},  {1, 0x00f1a},  {0, 0x00f35},  {1, 0x00f36},
  {0, 0x00f37},  {1, 0x00f38},  {0, 0x00f39},  {1, 0x00f3a},  {0, 0x00f71},
  {1, 0x00f7f},  {0, 0x00f80},  {1, 0x00f85},  {0, 0x00f86},  {1, 0x00f88},
  {0, 0x00f90},  {1, 0x00f98},  {0, 0x00f99},  {1, 0x00fbd},  {0, 0x00fc6},
  {1, 0x00fc7},  {0, 0x0102d},  {1, 0x01031},  {0, 0x01032},  {1, 0x01033},
  {0, 0x01036},  {1, 0x0103b},  {0, 0x01058},
  {1, 0x0105a},  {2, 0x01100},  {0, 0x01160},  {1, 0x01200},  {0, 0x0135f},
  {1, 0x01360},  {0, 0x01712},  {1, 0x01715},  {0, 0x01732},  {1, 0x01735},
  {0, 0x01752},  {1, 0x01754},  {0, 0x01772},  {1, 0x01774},  {0, 0x017b4},
  {1, 0x017b6},  {0, 0x017b7},  {1, 0x017be},  {0, 0x017c6},  {1, 0x017c7},
  {0, 0x017c9},  {1, 0x017d4},  {0, 0x017dd},  {1, 0x017de},  {0, 0x0180b},
  {1, 0x0180e},  {0, 0x018a9},  {1, 0x018aa},  {0, 0x01920},  {1, 0x01923},
  {0, 0x01927},  {1, 0x01929},  {0, 0x01932},  {1, 0x01933},  {0, 0x01939},
  {1, 0x0193c},  {0, 0x01a17},  {1, 0x01a19},  {0, 0x01b00},  {1, 0x01b04},
  {0, 0x01b34},  {1, 0x01b35},  {0, 0x01b36},  {1, 0x01b3b},  {0, 0x01b3c},
  {1, 0x01b3d},  {0, 0x01b42},  {1, 0x01b43},  {0, 0x01b6b},  {1, 0x01b74},
  {0, 0x01dc0},  {1, 0x01dcb},  {0, 0x01dfe},  {1, 0x01e00},  {0, 0x0200b},
  {1, 0x02010},  {0, 0x0202a},  {1, 0x0202f},  {0, 0x02060},  {1, 0x02064},
  {0, 0x0206a},  {1, 0x02070},  {0, 0x020d0},  {1, 0x020f0},  {2, 0x02329},
  {1, 0x0232b},  {2, 0x02e80},  {0, 0x0302a},  {2, 0x03030},  {1, 0x0303f},
  {2, 0x03040},  {0, 0x03099},  {2, 0x0309b},  {1, 0x0a4d0},  {0, 0x0a806},
  {1, 0x0a807},  {0, 0x0a80b},  {1, 0x0a80c},  {0, 0x0a825},  {1, 0x0a827},
  {2, 0x0ac00},  {1, 0x0d7a4},  {2, 0x0f900},  {1, 0x0fb00},  {0, 0x0fb1e},
  {1, 0x0fb1f},  {0, 0x0fe00},  {2, 0x0fe10},  {1, 0x0fe1a},  {0, 0x0fe20},
  {1, 0x0fe24},  {2, 0x0fe30},  {1, 0x0fe70},  {0, 0x0feff},  {2, 0x0ff00},
  {1, 0x0ff61},  {2, 0x0ffe0},  {1, 0x0ffe7},  {0, 0x0fff9},  {1, 0x0fffc},
  {0, 0x10a01},  {1, 0x10a04},  {0, 0x10a05},  {1, 0x10a07},  {0, 0x10a0c},
  {1, 0x10a10},  {0, 0x10a38},  {1, 0x10a3b},  {0, 0x10a3f},  {1, 0x10a40},
  {0, 0x1d167},  {1, 0x1d16a},  {0, 0x1d173},  {1, 0x1d183},  {0, 0x1d185},
  {1, 0x1d18c},  {0, 0x1d1aa},  {1, 0x1d1ae},  {0, 0x1d242},  {1, 0x1d245},
  {2, 0x20000},  {1, 0x2fffe},  {2, 0x30000},  {1, 0x3fffe},  {0, 0xe0001},
  {1, 0xe0002},  {0, 0xe0020},  {1, 0xe0080},  {0, 0xe0100},  {1, 0xe01f0}
};

/*
** Return an estimate of the width, in columns, for the single Unicode
** character c.  For normal characters, the answer is always 1.  But the
** estimate might be 0 or 2 for zero-width and double-width characters.
**
** Different display devices display unicode using different widths.  So
** it is impossible to know that true display width with 100% accuracy.
** Inaccuracies in the width estimates might cause columns to be misaligned.
** Unfortunately, there is nothing we can do about that.
*/

int sqlite3_qrf_wcwidth(int c){
  int iFirst, iLast;

  /* Fast path for common characters */
  if( c<0x300 ) return 1;

  /* The general case */
  iFirst = 0;
  iLast = sizeof(aQrfUWidth)/sizeof(aQrfUWidth[0]) - 1;
  while( iFirst<iLast-1 ){
    int iMid = (iFirst+iLast)/2;
    int cMid = aQrfUWidth[iMid].iFirst;
    if( cMid < c ){
      iFirst = iMid;
    }else if( cMid > c ){
      iLast = iMid - 1;
    }else{
      return aQrfUWidth[iMid].w;
    }
  }
  if( aQrfUWidth[iLast].iFirst > c ) return aQrfUWidth[iFirst].w;
  return aQrfUWidth[iLast].w;
}

/*
** Compute the value and length of a multi-byte UTF-8 character that
** begins at z[0]. Return the length.  Write the Unicode value into *pU.
**
** This routine only works for *multi-byte* UTF-8 characters.  It does
** not attempt to detect illegal characters.
*/

int sqlite3_qrf_decode_utf8(const unsigned char *z, int *pU){
  if( (z[0] & 0xe0)==0xc0 && (z[1] & 0xc0)==0x80 ){
    *pU = ((z[0] & 0x1f)<<6) | (z[1] & 0x3f);
    return 2;
  }
  if( (z[0] & 0xf0)==0xe0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80 ){
    *pU = ((z[0] & 0x0f)<<12) | ((z[1] & 0x3f)<<6) | (z[2] & 0x3f);
    return 3;
  }
  if( (z[0] & 0xf8)==0xf0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80
   && (z[3] & 0xc0)==0x80
  ){
    *pU = ((z[0] & 0x0f)<<18) | ((z[1] & 0x3f)<<12) | ((z[2] & 0x3f))<<6
                              | (z[3] & 0x3f);
    return 4;
  }
  *pU = 0;
  return 1;
}

/*
** Check to see if z[] is a valid VT100 escape.  If it is, then
** return the number of bytes in the escape sequence.  Return 0 if
** z[] is not a VT100 escape.
**
** This routine assumes that z[0] is \033 (ESC).
*/

static int qrfIsVt100(const unsigned char *z){
  int i;
  if( z[1]!='[' ) return 0;
  i = 2;
  while( z[i]>=0x30 && z[i]<=0x3f ){ i++; }
  while( z[i]>=0x20 && z[i]<=0x2f ){ i++; }
  if( z[i]<0x40 || z[i]>0x7e ) return 0;
  return i+1;
}

/*
** Return the length of a string in display characters.
**
** Most characters of the input string count as 1, including
** multi-byte UTF8 characters.  However, zero-width unicode
** characters and VT100 escape sequences count as zero, and
** double-width characters count as two.
**
** The definition of "zero-width" and "double-width" characters
** is not precise.  It depends on the output device, to some extent,
** and it varies according to the Unicode version.  This routine
** makes the best guess that it can.
*/

size_t sqlite3_qrf_wcswidth(const char *zIn){
  const unsigned char *z = (const unsigned char*)zIn;
  size_t n = 0;
  while( *z ){
    if( z[0]<' ' ){
      int k;
      if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
        z += k;
      }else{
        z++;
      }
    }else if( (0x80&z[0])==0 ){
      n++;
      z++;
    }else{
      int u = 0;
      int len = sqlite3_qrf_decode_utf8(z, &u);
      z += len;
      n += sqlite3_qrf_wcwidth(u);
    }
  }
  return n;
}

/*
** Return the display width of the longest line of text
** in the (possibly) multi-line input string zIn[0..nByte].
** zIn[] is not necessarily zero-terminated.  Take
** into account tab characters, zero- and double-width
** characters, CR and NL, and VT100 escape codes.
**
** Write the number of newlines into *pnNL.  So, *pnNL will
** return 0 if everything fits on one line, or positive it
** it will need to be split.
*/

static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){
  const unsigned char *z;
  const unsigned char *zEnd;
  int mx = 0;
  int n = 0;
  int nNL = 0;
  if( zIn==0 ) zIn = "";
  z = (const unsigned char*)zIn;
  zEnd = &z[nByte];
  while( z<zEnd ){
    if( z[0]<' ' ){
      int k;
      if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
        z += k;
      }else{
        if( z[0]=='\t' ){
          n = (n+8)&~7;
        }else if( z[0]=='\n' || z[0]=='\r' ){
          nNL++;
          if( n>mx ) mx = n;
          n = 0;
        }
        z++;
      }
    }else if( (0x80&z[0])==0 ){
      n++;
      z++;
    }else{
      int u = 0;
      int len = sqlite3_qrf_decode_utf8(z, &u);
      z += len;
      n += sqlite3_qrf_wcwidth(u);
    }
  }
  if( mx>n ) n = mx;
  if( pnNL ) *pnNL = nNL;
  return n;
}

/*
** Escape the input string if it is needed and in accordance with
** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
**
** Escaping is needed if the string contains any control characters
** other than \t, \n, and \r\n
**
** If no escaping is needed (the common case) then set *ppOut to NULL
** and return 0.  If escaping is needed, write the escaped string into
** memory obtained from sqlite3_malloc64() and make *ppOut point to that
** memory and return 0.  If an error occurs, return non-zero.
**
** The caller is responsible for freeing *ppFree if it is non-NULL in order
** to reclaim memory.
*/

static void qrfEscape(
  int eEsc,            /* QRF_ESC_Ascii or QRF_ESC_Symbol */
  sqlite3_str *pStr,      /* String to be escaped */
  int iStart              /* Begin escapding on this byte of pStr */
){
  sqlite3_int64 i, j;     /* Loop counters */
  sqlite3_int64 sz;       /* Size of the string prior to escaping */
  sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
  unsigned char *zIn;     /* Text to be escaped */
  unsigned char c;        /* A single character of the text */
  unsigned char *zOut;    /* Where to write the results */

  /* Find the text to be escaped */
  zIn = (unsigned char*)sqlite3_str_value(pStr);
  if( zIn==0 ) return;
  zIn += iStart;

  /* Count the control characters */
  for(i=0; (c = zIn[i])!=0; i++){
    if( c<=0x1f
     && c!='\t'
     && c!='\n'
     && (c!='\r' || zIn[i+1]!='\n')
    ){
      nCtrl++;
    }
  }
  if( nCtrl==0 ) return;  /* Early out if no control characters */

  /* Make space to hold the escapes.  Copy the original text to the end
  ** of the available space. */

  sz = sqlite3_str_length(pStr) - iStart;
  if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
  sqlite3_str_appendchar(pStr, nCtrl, ' ');
  zOut = (unsigned char*)sqlite3_str_value(pStr);
  if( zOut==0 ) return;
  zOut += iStart;
  zIn = zOut + nCtrl;
  memmove(zIn,zOut,sz);

  /* Convert the control characters */
  for(i=j=0; (c = zIn[i])!=0; i++){
    if( c>0x1f
     || c=='\t'
     || c=='\n'
     || (c=='\r' && zIn[i+1]=='\n')
    ){
      continue;
    }
    if( i>0 ){
      memmove(&zOut[j], zIn, i);
      j += i;
    }
    zIn += i+1;
    i = -1;
    if( eEsc==QRF_ESC_Symbol ){
      zOut[j++] = 0xe2;
      zOut[j++] = 0x90;
      zOut[j++] = 0x80+c;
    }else{
      zOut[j++] = '^';
      zOut[j++] = 0x40+c;
    }
  }
}

/*
** Determine if the string z[] can be shown as plain text.  Return true
** if z[] is unambiguously text.  Return false if z[] needs to be
** quoted.
**
** All of the following must be true in order for z[] to be relaxable:
**
**    (1) z[] does not begin or end with ' or whitespace
**    (2) z[] is not the same as the NULL rendering
**    (3) z[] does not looks like a numeric literal
*/

static int qrfRelaxable(Qrf *p, const char *z){
  size_t i, n;
  if( z[0]=='\'' || qrfSpace(z[0]) ) return 0;
  if( z[0]==0 ){
    return (p->spec.zNull!=0 && p->spec.zNull[0]!=0);
  }
  n = strlen(z);
  if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0;
  if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0;
  i = (z[0]=='-' || z[0]=='+');
  if( strcmp(z+i,"Inf")==0 ) return 0;
  if( !qrfDigit(z[i]) ) return 1;
  i++;
  while( qrfDigit(z[i]) ){ i++; }
  if( z[i]==0 ) return 0;
  if( z[i]=='.' ){
    i++;
    while( qrfDigit(z[i]) ){ i++; }
    if( z[i]==0 ) return 0;
  }
  if( z[i]=='e' || z[i]=='E' ){
    i++;
    if( z[i]=='+' || z[i]=='-' ){ i++; }
    if( !qrfDigit(z[i]) ) return 1;
    i++;
    while( qrfDigit(z[i]) ){ i++; }
  }
  return z[i]!=0;
}

/*
** If a field contains any character identified by a 1 in the following
** array, then the string must be quoted for CSV.
*/

static const char qrfCsvQuote[] = {
  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, 0, 0, 0, 0, 1,   0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 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,
};

/*
** Encode text appropriately and append it to pOut.
*/

static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){
  int iStart = sqlite3_str_length(pOut);
  switch( p->spec.eText ){
    case QRF_TEXT_Relaxed:
      if( qrfRelaxable(p, zTxt) ){
        sqlite3_str_appendall(pOut, zTxt);
        break;
      }
      deliberate_fall_through; /* FALLTHRU */
    case QRF_TEXT_Sql: {
      if( p->spec.eEsc==QRF_ESC_Off ){
        sqlite3_str_appendf(pOut, "%Q", zTxt);
      }else{
        sqlite3_str_appendf(pOut, "%#Q", zTxt);
      }
      break;
    }
    case QRF_TEXT_Csv: {
      unsigned int i;
      for(i=0; zTxt[i]; i++){
        if( qrfCsvQuote[((const unsigned char*)zTxt)[i]] ){
          i = 0;
          break;
        }
      }
      if( i==0 || strstr(zTxt, p->spec.zColumnSep)!=0 ){
        sqlite3_str_appendf(pOut, "\"%w\"", zTxt);
      }else{
        sqlite3_str_appendall(pOut, zTxt);
      }
      break;
    }
    case QRF_TEXT_Html: {
      const unsigned char *z = (const unsigned char*)zTxt;
      while( *z ){
        unsigned int i = 0;
        unsigned char c;
        while( (c=z[i])>'>'
            || (c && c!='<' && c!='>' && c!='&' && c!='\"' && c!='\'')
        ){
          i++;
        }
        if( i>0 ){
          sqlite3_str_append(pOut, (const char*)z, i);
        }
        switch( z[i] ){
          case '>':   sqlite3_str_append(pOut, "<", 4);   break;
          case '&':   sqlite3_str_append(pOut, "&", 5);  break;
          case '<':   sqlite3_str_append(pOut, "<", 4);   break;
          case '"':   sqlite3_str_append(pOut, """, 6); break;
          case '\'':  sqlite3_str_append(pOut, "'", 5);  break;
          default:    i--;
        }
        z += i + 1;
      }
      break;
    }
    case QRF_TEXT_Tcl:
    case QRF_TEXT_Json: {
      const unsigned char *z = (const unsigned char*)zTxt;
      sqlite3_str_append(pOut, "\"", 1);
      while( *z ){
        unsigned int i;
        for(i=0; z[i]>=0x20 && z[i]!='\\' && z[i]!='"'; i++){}
        if( i>0 ){
          sqlite3_str_append(pOut, (const char*)z, i);
        }
        if( z[i]==0 ) break;
        switch( z[i] ){
          case '"':   sqlite3_str_append(pOut, "\\\"", 2);  break;
          case '\\':  sqlite3_str_append(pOut, "\\\\", 2);  break;
          case '\b':  sqlite3_str_append(pOut, "\\b", 2);   break;
          case '\f':  sqlite3_str_append(pOut, "\\f", 2);   break;
          case '\n':  sqlite3_str_append(pOut, "\\n", 2);   break;
          case '\r':  sqlite3_str_append(pOut, "\\r", 2);   break;
          case '\t':  sqlite3_str_append(pOut, "\\t", 2);   break;
          default: {
            if( p->spec.eText==QRF_TEXT_Json ){
              sqlite3_str_appendf(pOut, "\\u%04x", z[i]);
            }else{
              sqlite3_str_appendf(pOut, "\\%03o", z[i]);
            }
            break;
          }
        }
        z += i + 1;
      }
      sqlite3_str_append(pOut, "\"", 1);
      break;
    }
    default: {
      sqlite3_str_appendall(pOut, zTxt);
      break;
    }
  }
  if( p->spec.eEsc!=QRF_ESC_Off ){
    qrfEscape(p->spec.eEsc, pOut, iStart);
  }
}

/*
** Do a quick sanity check to see aBlob[0..nBlob-1] is valid JSONB
** return true if it is and false if it is not.
**
** False positives are possible, but not false negatives.
*/

static int qrfJsonbQuickCheck(unsigned char *aBlob, int nBlob){
  unsigned char x;   /* Payload size half-byte */
  int i;             /* Loop counter */   
  int n;             /* Bytes in the payload size integer */
  sqlite3_uint64 sz; /* value of the payload size integer */

  if( nBlob==0 ) return 0;
  x = aBlob[0]>>4;
  if( x<=11 ) return nBlob==(1+x);
  n = x<14 ? x-11 : 4*(x-13);
  if( nBlob<1+n ) return 0;
  sz = aBlob[1];
  for(i=1; i<n; i++) sz = (sz<<8) + aBlob[i+1];
  return sz+n+1==(sqlite3_uint64)nBlob;
}

/*
** The current iCol-th column of p->pStmt is known to be a BLOB.  Check
** to see if that BLOB is really a JSONB blob.  If it is, then translate
** it into a text JSON representation and return a pointer to that text JSON.
** If the BLOB is not JSONB, then return a NULL pointer.
**
** The memory used to hold the JSON text is managed internally by the
** "p" object and is overwritten and/or deallocated upon the next call
** to this routine (with the same p argument) or when the p object is
** finailized.
*/

static const char *qrfJsonbToJson(Qrf *p, int iCol){
  int nByte;
  const void *pBlob;
  int rc;
  nByte = sqlite3_column_bytes(p->pStmt, iCol);
  pBlob = sqlite3_column_blob(p->pStmt, iCol);
  if( qrfJsonbQuickCheck((unsigned char*)pBlob, nByte)==0 ){
    return 0;
  }
  if( p->pJTrans==0 ){
    sqlite3 *db;
    rc = sqlite3_open(":memory:",&db);
    if( rc ){
      sqlite3_close(db);
      return 0;
    }
    rc = sqlite3_prepare_v2(db, "SELECT json(?1)", -1, &p->pJTrans, 0);
    if( rc ){
      sqlite3_finalize(p->pJTrans);
      p->pJTrans = 0;
      sqlite3_close(db);
      return 0;
    }
  }else{
    sqlite3_reset(p->pJTrans);
  }
  sqlite3_bind_blob(p->pJTrans, 1, (void*)pBlob, nByte, SQLITE_STATIC);
  rc = sqlite3_step(p->pJTrans);
  if( rc==SQLITE_ROW ){
    return (const char*)sqlite3_column_text(p->pJTrans, 0);
  }else{
    return 0;
  }
}

/*
** Adjust the input string zIn[] such that it is no more than N display
** characters wide.  If it is wider than that, then truncate and add
** ellipsis.  Or if zIn[] contains a \r or \n, truncate at that point,
** adding ellipsis.  Embedded tabs in zIn[] are converted into ordinary
** spaces.
**
** Return this display width of the modified title string.
*/

static int qrfTitleLimit(char *zIn, int N){
  unsigned char *z = (unsigned char*)zIn;
  int n = 0;
  unsigned char *zEllipsis = 0;
  while( 1 /*exit-by-break*/ ){
    if( z[0]<' ' ){
      int k;
      if( z[0]==0 ){
        zEllipsis = 0;
        break;
      }else if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
        z += k;
      }else if( z[0]=='\t' ){
        z[0] = ' ';
      }else if( z[0]=='\n' || z[0]=='\r' ){
        z[0] = ' ';
      }else{
        z++;
      }
    }else if( (0x80&z[0])==0 ){
      if( n>=(N-3) && zEllipsis==0 ) zEllipsis = z;
      if( n==N ){ z[0] = 0; break; }
      n++;
      z++;
    }else{
      int u = 0;
      int len = sqlite3_qrf_decode_utf8(z, &u);
      if( n+len>(N-3) && zEllipsis==0 ) zEllipsis = z;
      if( n+len>N ){ z[0] = 0; break; }
      z += len;
      n += sqlite3_qrf_wcwidth(u);
    }
  }
  if( zEllipsis && N>=3 ) memcpy(zEllipsis,"...",4);
  return n;
}


/*
** Render value pVal into pOut
*/

static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){
#if SQLITE_VERSION_NUMBER>=3052000
  int iStartLen = sqlite3_str_length(pOut);
#endif
  if( p->spec.xRender ){
    sqlite3_value *pVal;
    char *z;
    pVal = sqlite3_value_dup(sqlite3_column_value(p->pStmt,iCol));
    z = p->spec.xRender(p->spec.pRenderArg, pVal);
    sqlite3_value_free(pVal);
    if( z ){
      sqlite3_str_appendall(pOut, z);
      sqlite3_free(z);
      return;
    }
  }
  switch( sqlite3_column_type(p->pStmt,iCol) ){
    case SQLITE_INTEGER: {
      sqlite3_str_appendf(pOut, "%lld", sqlite3_column_int64(p->pStmt,iCol));
      break;
    }
    case SQLITE_FLOAT: {
      const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
      sqlite3_str_appendall(pOut, zTxt);
      break;
    }
    case SQLITE_BLOB: {
      if( p->spec.bTextJsonb==QRF_Yes ){
        const char *zJson = qrfJsonbToJson(p, iCol);
        if( zJson ){
          if( p->spec.eText==QRF_TEXT_Sql ){
            sqlite3_str_append(pOut,"jsonb(",6);
            qrfEncodeText(p, pOut, zJson);
            sqlite3_str_append(pOut,")",1);
          }else{
            qrfEncodeText(p, pOut, zJson);
          }
          break;
        }
      }
      switch( p->spec.eBlob ){
        case QRF_BLOB_Hex:
        case QRF_BLOB_Sql: {
          int iStart;
          int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
          int i, j;
          char *zVal;
          const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol);
          if( p->spec.eBlob==QRF_BLOB_Sql ){
            sqlite3_str_append(pOut, "x'", 2);
          }
          iStart = sqlite3_str_length(pOut);
          sqlite3_str_appendchar(pOut, nBlob, ' ');
          sqlite3_str_appendchar(pOut, nBlob, ' ');
          if( p->spec.eBlob==QRF_BLOB_Sql ){
            sqlite3_str_appendchar(pOut, 1, '\'');
          }
          if( sqlite3_str_errcode(pOut) ) return;
          zVal = sqlite3_str_value(pOut);
          for(i=0, j=iStart; i<nBlob; i++, j+=2){
            unsigned char c = a[i];
            zVal[j] = "0123456789abcdef"[(c>>4)&0xf];
            zVal[j+1] = "0123456789abcdef"[(c)&0xf];
          }
          break;
        }
        case QRF_BLOB_Tcl:
        case QRF_BLOB_Json: {
          int iStart;
          int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
          int i, j;
          char *zVal;
          const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol);
          int szC = p->spec.eBlob==QRF_BLOB_Json ? 6 : 4;
          sqlite3_str_append(pOut, "\"", 1);
          iStart = sqlite3_str_length(pOut);
          for(i=szC; i>0; i--){
            sqlite3_str_appendchar(pOut, nBlob, ' ');
          }
          sqlite3_str_appendchar(pOut, 1, '"');
          if( sqlite3_str_errcode(pOut) ) return;
          zVal = sqlite3_str_value(pOut);
          for(i=0, j=iStart; i<nBlob; i++, j+=szC){
            unsigned char c = a[i];
            zVal[j] = '\\';
            if( szC==4 ){
              zVal[j+1] = '0' + ((c>>6)&3);
              zVal[j+2] = '0' + ((c>>3)&7);
              zVal[j+3] = '0' + (c&7);
            }else{
              zVal[j+1] = 'u';
              zVal[j+2] = '0';
              zVal[j+3] = '0';
              zVal[j+4] = "0123456789abcdef"[(c>>4)&0xf];
              zVal[j+5] = "0123456789abcdef"[(c)&0xf];
            }
          }
          break;
        }
        case QRF_BLOB_Size: {
          int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
          sqlite3_str_appendf(pOut, "(%d-byte blob)", nBlob);
          break;
        }
        default: {
          const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
          qrfEncodeText(p, pOut, zTxt);
        }
      }
      break;
    }
    case SQLITE_NULL: {
      sqlite3_str_appendall(pOut, p->spec.zNull);
      break;
    }
    case SQLITE_TEXT: {
      const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
      qrfEncodeText(p, pOut, zTxt);
      break;
    }
  }
#if SQLITE_VERSION_NUMBER>=3052000
  if( p->spec.nCharLimit>0
   && (sqlite3_str_length(pOut) - iStartLen) > p->spec.nCharLimit
  ){
    const unsigned char *z;
    int ii = 0, w = 0, limit = p->spec.nCharLimit;
    z = (const unsigned char*)sqlite3_str_value(pOut) + iStartLen;
    if( limit<4 ) limit = 4;
    while( 1 ){
      if( z[ii]<' ' ){
        int k;
        if( z[ii]=='\033' && (k = qrfIsVt100(z+ii))>0 ){
          ii += k;
        }else if( z[ii]==0 ){
          break;
        }else{
          ii++;
        }
      }else if( (0x80&z[ii])==0 ){
        w++;
        if( w>limit ) break;
        ii++;
      }else{
        int u = 0;
        int len = sqlite3_qrf_decode_utf8(&z[ii], &u);
        w += sqlite3_qrf_wcwidth(u);
        if( w>limit ) break;
        ii += len;
      }
    }
    if( w>limit ){
      sqlite3_str_truncate(pOut, iStartLen+ii);
      sqlite3_str_append(pOut, "...", 3);
    }
  }
#endif
}

/* Trim spaces of the end if pOut
*/

static void qrfRTrim(sqlite3_str *pOut){
#if SQLITE_VERSION_NUMBER>=3052000
  int nByte = sqlite3_str_length(pOut);
  const char *zOut = sqlite3_str_value(pOut);
  while( nByte>0 && zOut[nByte-1]==' ' ){ nByte--; }
  sqlite3_str_truncate(pOut, nByte);
#endif
}

/*
** Store string zUtf to pOut as w characters.  If w is negative,
** then right-justify the text.  W is the width in display characters, not
** in bytes.  Double-width unicode characters count as two characters.
** VT100 escape sequences count as zero.  And so forth.
*/

static void qrfWidthPrint(Qrf *p, sqlite3_str *pOut, int w, const char *zUtf){
  const unsigned char *a = (const unsigned char*)zUtf;
  static const int mxW = 10000000;
  unsigned char c;
  int i = 0;
  int n = 0;
  int k;
  int aw;
  (void)p;
  if( w<-mxW ){
    w = -mxW;
  }else if( w>mxW ){
    w= mxW;
  }
  aw = w<0 ? -w : w;
  if( a==0 ) a = (const unsigned char*)"";
  while( (c = a[i])!=0 ){
    if( (c&0xc0)==0xc0 ){
      int u;
      int len = sqlite3_qrf_decode_utf8(a+i, &u);
      int x = sqlite3_qrf_wcwidth(u);
      if( x+n>aw ){
        break;
      }
      i += len;
      n += x;
    }else if( c==0x1b && (k = qrfIsVt100(&a[i]))>0 ){
      i += k;       
    }else if( n>=aw ){
      break;
    }else{
      n++;
      i++;
    }
  }
  if( n>=aw ){
    sqlite3_str_append(pOut, zUtf, i);
  }else if( w<0 ){
    if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' ');
    sqlite3_str_append(pOut, zUtf, i);
  }else{
    sqlite3_str_append(pOut, zUtf, i);
    if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' ');
  }
}

/*
** (*pz)[] is a line of text that is to be displayed the box or table or
** similar tabular formats.  z[] contain newlines or might be too wide
** to fit in the columns so will need to be split into multiple line.
**
** This routine determines:
**
**    *  How many bytes of z[] should be shown on the current line.
**    *  How many character positions those bytes will cover.
**    *  The byte offset to the start of the next line.
*/

static void qrfWrapLine(
  const char *zIn,   /* Input text to be displayed */
  int w,             /* Column width in characters (not bytes) */
  int bWrap,         /* True if we should do word-wrapping */
  int *pnThis,       /* OUT: How many bytes of z[] for the current line */
  int *pnWide,       /* OUT: How wide is the text of this line */
  int *piNext        /* OUT: Offset into z[] to start of the next line */
){
  int i;                 /* Input bytes consumed */
  int k;                 /* Bytes in a VT100 code */
  int n;                 /* Output column number */
  const unsigned char *z = (const unsigned char*)zIn;
  unsigned char c = 0;

  if( z[0]==0 ){
    *pnThis = 0;
    *pnWide = 0;
    *piNext = 0;
    return;
  }
  n = 0;
  for(i=0; n<=w; i++){
    c = z[i];
    if( c>=0xc0 ){
      int u;
      int len = sqlite3_qrf_decode_utf8(&z[i], &u);
      int wcw = sqlite3_qrf_wcwidth(u);
      if( wcw+n>w ) break;
      i += len-1;
      n += wcw;
      continue;
    }
    if( c>=' ' ){
      if( n==w ) break;
      n++;
      continue;
    }
    if( c==0 || c=='\n' ) break;
    if( c=='\r' && z[i+1]=='\n' ){ c = z[++i]; break; }
    if( c=='\t' ){
      int wcw = 8 - (n&7);
      if( n+wcw>w ) break;
      n += wcw;
      continue;
    }
    if( c==0x1b && (k = qrfIsVt100(&z[i]))>0 ){
      i += k-1;
    }else if( n==w ){
      break;
    }else{
      n++;
    }
  }
  if( c==0 ){
    *pnThis = i;
    *pnWide = n;
    *piNext = i;
    return;
  }
  if( c=='\n' ){
    *pnThis = i;
    *pnWide = n;
    *piNext = i+1;
    return;
  }

  /* If we get this far, that means the current line will end at some
  ** point that is neither a "\n" or a 0x00.  Figure out where that
  ** split should occur
  */

  if( bWrap && z[i]!=0 && !qrfSpace(z[i]) && qrfAlnum(c)==qrfAlnum(z[i]) ){
    /* Perhaps try to back up to a better place to break the line */
    for(k=i-1; k>=i/2; k--){
      if( qrfSpace(z[k]) ) break;
    }
    if( k<i/2 ){
      for(k=i; k>=i/2; k--){
        if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
      }
    }
    if( k>=i/2 ){
      i = k;
      n = qrfDisplayWidth((const char*)z, k, 0);
    }
  }
  *pnThis = i;
  *pnWide = n;
  while( zIn[i]==' ' || zIn[i]=='\t' || zIn[i]=='\r' ){ i++; }
  *piNext = i;
}

/*
** Append nVal bytes of text from zVal onto the end of pOut.
** Convert tab characters in zVal to the appropriate number of
** spaces.
*/

static void qrfAppendWithTabs(
  sqlite3_str *pOut,       /* Append text here */
  const char *zVal,        /* Text to append */
  int nVal                 /* Use only the first nVal bytes of zVal[] */
){
  int i = 0;
  unsigned int col = 0;
  unsigned char *z = (unsigned char *)zVal;
  while( i<nVal ){
    unsigned char c = z[i];
    if( c<' ' ){
      int k;
      sqlite3_str_append(pOut, (const char*)z, i);
      nVal -= i;
      z += i;
      i = 0;
      if( c=='\033' && (k = qrfIsVt100(z))>0 ){
        sqlite3_str_append(pOut, (const char*)z, k);
        z += k;
        nVal -= k;
      }else if( c=='\t' ){
        k = 8 - (col&7);
        sqlite3_str_appendchar(pOut, k, ' ');
        col += k;
        z++;
        nVal--;
      }else if( c=='\r' && nVal==1 ){
        z++;
        nVal--;
      }else{
        char zCtrlPik[4];
        col++;
        zCtrlPik[0] = 0xe2;
        zCtrlPik[1] = 0x90;
        zCtrlPik[2] = 0x80+c;
        sqlite3_str_append(pOut, zCtrlPik, 3);
        z++;
        nVal--;
      }
    }else if( (0x80&c)==0 ){
      i++;
      col++;
    }else{
      int u = 0;
      int len = sqlite3_qrf_decode_utf8(&z[i], &u);
      i += len;
      col += sqlite3_qrf_wcwidth(u);
    }
  }
  sqlite3_str_append(pOut, (const char*)z, i);
}    

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/

#ifndef offsetof
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif

/*
** Data for columnar layout, collected into a single object so
** that it can be more easily passed into subroutines.
*/

typedef struct qrfColData qrfColData;
struct qrfColData {
  Qrf *p;                  /* The QRF instance */
  int nCol;                /* Number of columns in the table */
  unsigned char bMultiRow; /* One or more cells will span multiple lines */
  unsigned char nMargin;   /* Width of column margins */
  sqlite3_int64 nRow;      /* Number of rows */
  sqlite3_int64 nAlloc;    /* Number of cells allocated */
  sqlite3_int64 n;         /* Number of cells.  nCol*nRow */
  char **az;               /* Content of all cells */
  int *aiWth;              /* Width of each cell */
  unsigned char *abNum;    /* True for each numeric cell */
  struct qrfPerCol {       /* Per-column data */
    char *z;                 /* Cache of text for current row */
    int w;                   /* Computed width of this column */
    int mxW;                 /* Maximum natural (unwrapped) width */
    unsigned char e;         /* Alignment */
    unsigned char fx;        /* Width is fixed */
    unsigned char bNum;      /* True if is numeric */
  } *a;                    /* One per column */
};

/*
** Output horizontally justified text into pOut.  The text is the
** first nVal bytes of zVal.  Include nWS bytes of whitespace, either
** split between both sides, or on the left, or on the right, depending
** on eAlign.
*/

static void qrfPrintAligned(
  sqlite3_str *pOut,       /* Append text here */
  struct qrfPerCol *pCol,  /* Information about the text to print */
  int nVal,                /* Use only the first nVal bytes of zVal[] */
  int nWS                 /* Whitespace for horizonal alignment */
){
  unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK;
  if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right;
  if( eAlign==QRF_ALIGN_Center ){
    /* Center the text */
    sqlite3_str_appendchar(pOut, nWS/2, ' ');
    qrfAppendWithTabs(pOut, pCol->z, nVal);
    sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
  }else if( eAlign==QRF_ALIGN_Right ){
    /* Right justify the text */
    sqlite3_str_appendchar(pOut, nWS, ' ');
    qrfAppendWithTabs(pOut, pCol->z, nVal);
  }else{
    /* Left justify the text */
    qrfAppendWithTabs(pOut, pCol->z, nVal);
    sqlite3_str_appendchar(pOut, nWS, ' ');
  }
}

/*
** Free all the memory allocates in the qrfColData object
*/

static void qrfColDataFree(qrfColData *p){
  sqlite3_int64 i;
  for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
  sqlite3_free(p->az);
  sqlite3_free(p->aiWth);
  sqlite3_free(p->abNum);
  sqlite3_free(p->a);
  memset(p, 0, sizeof(*p));
}

/*
** Allocate space for more cells in the qrfColData object.
** Return non-zero if a memory allocation fails.
*/

static int qrfColDataEnlarge(qrfColData *p){
  char **azData;
  int *aiWth;
  unsigned char *abNum;
  p->nAlloc = 2*p->nAlloc + 10*p->nCol;
  azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
  if( azData==0 ){
    qrfOom(p->p);
    qrfColDataFree(p);
    return 1;
  }
  p->az = azData;
  aiWth = sqlite3_realloc64(p->aiWth, p->nAlloc*sizeof(int));
  if( aiWth==0 ){
    qrfOom(p->p);
    qrfColDataFree(p);
    return 1;
  }
  p->aiWth = aiWth;
  abNum = sqlite3_realloc64(p->abNum, p->nAlloc);
  if( abNum==0 ){
    qrfOom(p->p);
    qrfColDataFree(p);
    return 1;
  }
  p->abNum = abNum;
  return 0;
}

/*
** Print a markdown or table-style row separator using ascii-art
*/

static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){
  int i;
  if( p->nCol>0 ){
    int useBorder = p->p->spec.bBorder!=QRF_No;
    if( useBorder ){
      sqlite3_str_append(pOut, &cSep, 1);
    }
    sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-');
    for(i=1; i<p->nCol; i++){
      sqlite3_str_append(pOut, &cSep, 1);
      sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-');
    }
    if( useBorder ){
      sqlite3_str_append(pOut, &cSep, 1);
    }
  }
  sqlite3_str_append(pOut, "\n", 1);
}

/*
** UTF8 box-drawing characters.  Imagine box lines like this:
**
**           1
**           |
**       4 --+-- 2
**           |
**           3
**
** Each box characters has between 2 and 4 of the lines leading from
** the center.  The characters are here identified by the numbers of
** their corresponding lines.
*/

#define BOX_24   "\342\224\200"  /* U+2500 --- */
#define BOX_13   "\342\224\202"  /* U+2502  |  */
#define BOX_23   "\342\224\214"  /* U+250c  ,- */
#define BOX_34   "\342\224\220"  /* U+2510 -,  */
#define BOX_12   "\342\224\224"  /* U+2514  '- */
#define BOX_14   "\342\224\230"  /* U+2518 -'  */
#define BOX_123  "\342\224\234"  /* U+251c  |- */
#define BOX_134  "\342\224\244"  /* U+2524 -|  */
#define BOX_234  "\342\224\254"  /* U+252c -,- */
#define BOX_124  "\342\224\264"  /* U+2534 -'- */
#define BOX_1234 "\342\224\274"  /* U+253c -|- */

/* Rounded corners: */
#define BOX_R12  "\342\225\260"  /* U+2570  '- */
#define BOX_R23  "\342\225\255"  /* U+256d  ,- */
#define BOX_R34  "\342\225\256"  /* U+256e -,  */
#define BOX_R14  "\342\225\257"  /* U+256f -'  */

/* Doubled horizontal lines: */
#define DBL_24   "\342\225\220"  /* U+2550 === */
#define DBL_123  "\342\225\236"  /* U+255e  |= */
#define DBL_134  "\342\225\241"  /* U+2561 =|  */
#define DBL_1234 "\342\225\252"  /* U+256a =|= */

/* Draw horizontal line N characters long using unicode box
** characters
*/

static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){
  const char *azDash[2] = {
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24   BOX_24 BOX_24 BOX_24 BOX_24 BOX_24,
      DBL_24 DBL_24 DBL_24 DBL_24 DBL_24   DBL_24 DBL_24 DBL_24 DBL_24 DBL_24
  };/*  0       1      2     3      4        5      6      7      8      9   */
  const int nDash = 30;
  N *= 3;
  while( N>nDash ){
    sqlite3_str_append(pOut, azDash[bDbl], nDash);
    N -= nDash;
  }
  sqlite3_str_append(pOut, azDash[bDbl], N);
}

/*
** Draw a horizontal separator for a QRF_STYLE_Box table.
*/

static void qrfBoxSeparator(
  sqlite3_str *pOut,
  qrfColData *p,
  const char *zSep1,
  const char *zSep2,
  const char *zSep3,
  int bDbl
){
  int i;
  if( p->nCol>0 ){
    int useBorder = p->p->spec.bBorder!=QRF_No;
    if( useBorder ){
      sqlite3_str_appendall(pOut, zSep1);
    }
    qrfBoxLine(pOut, p->a[0].w+p->nMargin, bDbl);
    for(i=1; i<p->nCol; i++){
      sqlite3_str_appendall(pOut, zSep2);
      qrfBoxLine(pOut, p->a[i].w+p->nMargin, bDbl);
    }
    if( useBorder ){
      sqlite3_str_appendall(pOut, zSep3);
    }
  }
  sqlite3_str_append(pOut, "\n", 1);
}

/*
** Load into pData the default alignment for the body of a table.
*/

static void qrfLoadAlignment(qrfColData *pData, Qrf *p){
  sqlite3_int64 i;
  for(i=0; i<pData->nCol; i++){
    pData->a[i].e = p->spec.eDfltAlign;
    if( i<p->spec.nAlign ){
      unsigned char ax = p->spec.aAlign[i];
      if( (ax & QRF_ALIGN_HMASK)!=0 ){
        pData->a[i].e = (ax & QRF_ALIGN_HMASK) |
                            (pData->a[i].e & QRF_ALIGN_VMASK);
      }
    }else if( i<p->spec.nWidth ){
      if( p->spec.aWidth[i]<0 ){
         pData->a[i].e = QRF_ALIGN_Right |
                               (pData->a[i].e & QRF_ALIGN_VMASK);
      }
    }
  }
}

/*
** If the single column in pData->a[] with pData->n entries can be
** laid out as nCol columns with a 2-space gap between each such
** that all columns fit within nSW, then return a pointer to an array
** of integers which is the width of each column from left to right.
**
** If the layout is not possible, return a NULL pointer.
**
** Space to hold the returned array is from sqlite_malloc64().
*/

static int *qrfValidLayout(
  qrfColData *pData,   /* Collected query results */
  Qrf *p,              /* On which to report an OOM */
  int nCol,            /* Attempt this many columns */
  int nSW              /* Screen width */
){
  int i;        /* Loop counter */
  int nr;       /* Number of rows */
  int w = 0;    /* Width of the current column */
  int t;        /* Total width of all columns */
  int *aw;      /* Array of individual column widths */

  aw = sqlite3_malloc64( sizeof(int)*nCol );
  if( aw==0 ){
    qrfOom(p);
    return 0;
  }
  nr = (pData->n + nCol - 1)/nCol;
  for(i=0; i<pData->n; i++){
    if( (i%nr)==0 ){
      if( i>0 ) aw[i/nr-1] = w;
      w = pData->aiWth[i];
    }else if( pData->aiWth[i]>w ){
      w = pData->aiWth[i];
    }
  }
  aw[nCol-1] = w;
  for(t=i=0; i<nCol; i++) t += aw[i];
  t += 2*(nCol-1);
  if( t>nSW ){
    sqlite3_free(aw);
    return 0;
  }
  return aw;
}

/*
** The output is single-column and the bSplitColumn flag is set.
** Check to see if the single-column output can be split into multiple
** columns that appear side-by-side.  Adjust pData appropriately.
*/

static void qrfSplitColumn(qrfColData *pData, Qrf *p){
  int nCol = 1;
  int *aw = 0;
  char **az = 0;
  int *aiWth = 0;
  unsigned char *abNum = 0;
  int nColNext = 2;
  int w;
  struct qrfPerCol *a = 0;
  sqlite3_int64 nRow = 1;
  sqlite3_int64 i;
  while( 1/*exit-by-break*/ ){
    int *awNew = qrfValidLayout(pData, p, nColNext, p->spec.nScreenWidth);
    if( awNew==0 ) break;
    sqlite3_free(aw);
    aw = awNew;
    nCol = nColNext;
    nRow = (pData->n + nCol - 1)/nCol;
    if( nRow==1 ) break;
    nColNext++;
    while( (pData->n + nColNext - 1)/nColNext == nRow ) nColNext++;
  }
  if( nCol==1 ){
    sqlite3_free(aw);
    return;  /* Cannot do better than 1 column */
  }
  az = sqlite3_malloc64( nRow*nCol*sizeof(char*) );
  if( az==0 ){
    qrfOom(p);
    return;
  }
  aiWth = sqlite3_malloc64( nRow*nCol*sizeof(int) );
  if( aiWth==0 ){
    sqlite3_free(az);
    qrfOom(p);
    return;
  }
  a = sqlite3_malloc64( nCol*sizeof(struct qrfPerCol) );
  if( a==0 ){
    sqlite3_free(az);
    sqlite3_free(aiWth);
    qrfOom(p);
    return;
  }
  abNum = sqlite3_malloc64( nRow*nCol );
  if( abNum==0 ){
    sqlite3_free(az);
    sqlite3_free(aiWth);
    sqlite3_free(a);
    qrfOom(p);
    return;
  }
  for(i=0; i<pData->n; i++){
    sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
    az[j] = pData->az[i];
    abNum[j]= pData->abNum[i];
    pData->az[i] = 0;
    aiWth[j] = pData->aiWth[i];
  }
  while( i<nRow*nCol ){
    sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
    az[j] = sqlite3_mprintf("");
    if( az[j]==0 ) qrfOom(p);
    aiWth[j] = 0;
    abNum[j] = 0;
    i++;
  }
  for(i=0; i<nCol; i++){
    a[i].fx = a[i].mxW = a[i].w = aw[i];
    a[i].e = pData->a[0].e;
  }
  sqlite3_free(pData->az);
  sqlite3_free(pData->aiWth);
  sqlite3_free(pData->a);
  sqlite3_free(pData->abNum);
  sqlite3_free(aw);
  pData->az = az;
  pData->aiWth = aiWth;
  pData->a = a;
  pData->abNum = abNum;
  pData->nCol = nCol;
  pData->n = pData->nAlloc = nRow*nCol;
  for(i=w=0; i<nCol; i++) w += a[i].w;
  pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
  if( pData->nMargin>5 ) pData->nMargin = 5;
}

/*
** Adjust the layout for the screen width restriction
*/

static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){
  int sepW;             /* Width of all box separators and margins */
  int sumW;             /* Total width of data area over all columns */
  int targetW;          /* Desired total data area */
  int i;                /* Loop counters */
  int nCol;             /* Number of columns */

  pData->nMargin = 2;   /* Default to normal margins */
  if( p->spec.nScreenWidth==0 ) return;
  if( p->spec.eStyle==QRF_STYLE_Column ){
    sepW = pData->nCol*2 - 2;
  }else{
    sepW = pData->nCol*3 + 1;
    if( p->spec.bBorder==QRF_No ) sepW -= 2;
  }
  nCol = pData->nCol;
  for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
  if( p->spec.nScreenWidth >= sumW+sepW ) return;

  /* First thing to do is reduce the separation between columns */
  pData->nMargin = 0;
  if( p->spec.eStyle==QRF_STYLE_Column ){
    sepW = pData->nCol - 1;
  }else{
    sepW = pData->nCol + 1;
    if( p->spec.bBorder==QRF_No ) sepW -= 2;
  }
  targetW = p->spec.nScreenWidth - sepW;

#define MIN_SQUOZE    8
#define MIN_EX_SQUOZE 16
  /* Reduce the width of the widest eligible column.  A column is
  ** eligible for narrowing if:
  **
  **    *  It is not a fixed-width column  (a[0].fx is false)
  **    *  The current width is more than MIN_SQUOZE
  **    *  Either:
  **         +  The current width is more then MIN_EX_SQUOZE, or
  **         +  The current width is more than half the max width (a[].mxW)
  **
  ** Keep making reductions until either no more reductions are
  ** possible or until the size target is reached.
  */

  while( sumW > targetW ){
    int gain, w;
    int ix = -1;
    int mx = 0;
    for(i=0; i<nCol; i++){
      if( pData->a[i].fx==0
       && (w = pData->a[i].w)>mx
       && w>MIN_SQUOZE
       && (w>MIN_EX_SQUOZE || w*2>pData->a[i].mxW)
      ){
        ix = i;
        mx = w;
      }
    }
    if( ix<0 ) break;
    if( mx>=MIN_SQUOZE*2 ){
      gain = mx/2;
    }else{
      gain = mx - MIN_SQUOZE;
    }
    if( sumW - gain < targetW ){
      gain = sumW - targetW;
    }
    sumW -= gain;
    pData->a[ix].w -= gain;
    pData->bMultiRow = 1;
  }
}

/*
** Columnar modes require that the entire query be evaluated first, with
** results written into memory, so that we can compute appropriate column
** widths.
*/

static void qrfColumnar(Qrf *p){
  sqlite3_int64 i, j;                     /* Loop counters */
  const char *colSep = 0;                 /* Column separator text */
  const char *rowSep = 0;                 /* Row terminator text */
  const char *rowStart = 0;               /* Row start text */
  int szColSep, szRowSep, szRowStart;     /* Size in bytes of previous 3 */
  int rc;                                 /* Result code */
  int nColumn = p->nCol;                  /* Number of columns */
  int bWW;                                /* True to do word-wrap */
  sqlite3_str *pStr;                      /* Temporary rendering */
  qrfColData data;                        /* Columnar layout data */
  int bRTrim;                             /* Trim trailing space */

  rc = sqlite3_step(p->pStmt);
  if( rc!=SQLITE_ROW || nColumn==0 ){
    return;   /* No output */
  }

  /* Initialize the data container */
  memset(&data, 0, sizeof(data));
  data.nCol = p->nCol;
  data.p = p;
  data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) );
  if( data.a==0 ){
    qrfOom(p);
    return;
  }
  memset(data.a, 0, nColumn*sizeof(struct qrfPerCol) );
  if( qrfColDataEnlarge(&data) ) return;
  assert( data.az!=0 );

  /* Load the column header names and all cell content into data */
  if( p->spec.bTitles==QRF_Yes ){
    unsigned char saved_eText = p->spec.eText;
    p->spec.eText = p->spec.eTitle;
    memset(data.abNum, 0, nColumn);
    for(i=0; i<nColumn; i++){
      const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
      int nNL = 0;
      int n, w;
      pStr = sqlite3_str_new(p->db);
      qrfEncodeText(p, pStr, z ? z : "");
      n = sqlite3_str_length(pStr);
      qrfStrErr(p, pStr);
      z = data.az[data.n] = sqlite3_str_finish(pStr);
      if( p->spec.nTitleLimit ){
        nNL = 0;
        data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
                                               p->spec.nTitleLimit );
      }else{
        data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
      }
      data.n++;
      if( w>data.a[i].mxW ) data.a[i].mxW = w;
      if( nNL ) data.bMultiRow = 1;
    }
    p->spec.eText = saved_eText;
    p->nRow++;
  }
  do{
    if( data.n+nColumn > data.nAlloc ){
      if( qrfColDataEnlarge(&data) ) return;
    }
    for(i=0; i<nColumn; i++){
      char *z;
      int nNL = 0;
      int n, w;
      int eType = sqlite3_column_type(p->pStmt,i);
      pStr = sqlite3_str_new(p->db);
      qrfRenderValue(p, pStr, i);
      n = sqlite3_str_length(pStr);
      qrfStrErr(p, pStr);
      z = data.az[data.n] = sqlite3_str_finish(pStr);
      data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
      data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
      data.n++;
      if( w>data.a[i].mxW ) data.a[i].mxW = w;
      if( nNL ) data.bMultiRow = 1;
    }
    p->nRow++;
  }while( sqlite3_step(p->pStmt)==SQLITE_ROW && p->iErr==SQLITE_OK );
  if( p->iErr ){
    qrfColDataFree(&data);
    return;
  }

  /* Compute the width and alignment of every column */
  if( p->spec.bTitles==QRF_No ){
    qrfLoadAlignment(&data, p);
  }else{
    unsigned char e;
    if( p->spec.eTitleAlign==QRF_Auto ){
      e = QRF_ALIGN_Center;
    }else{
      e = p->spec.eTitleAlign;
    }
    for(i=0; i<nColumn; i++) data.a[i].e = e;
  }

  for(i=0; i<nColumn; i++){
    int w = 0;
    if( i<p->spec.nWidth ){
      w = p->spec.aWidth[i];
      if( w==(-32768) ){
        w = 0;
        if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){
          data.a[i].e |= QRF_ALIGN_Right;
        }
      }else if( w<0 ){
        w = -w;
        if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){
          data.a[i].e |= QRF_ALIGN_Right;
        }
      }
      if( w ) data.a[i].fx = 1;
    }
    if( w==0 ){
      w = data.a[i].mxW;
      if( p->spec.nWrap>0 && w>p->spec.nWrap ){
        w = p->spec.nWrap;
        data.bMultiRow = 1;
      }
    }else if( (data.bMultiRow==0 || w==1) && data.a[i].mxW>w ){
      data.bMultiRow = 1;
      if( w==1 ){
        /* If aiWth[j] is 2 or more, then there might be a double-wide
        ** character somewhere.  So make the column width at least 2. */

        w = 2;
      }
    }
    data.a[i].w = w;
  }

  if( nColumn==1
   && data.n>1
   && p->spec.bSplitColumn==QRF_Yes
   && p->spec.eStyle==QRF_STYLE_Column
   && p->spec.bTitles==QRF_No
   && p->spec.nScreenWidth>data.a[0].w+3
  ){
    /* Attempt to convert single-column tables into multi-column by
    ** verticle wrapping, if the screen is wide enough and if the
    ** bSplitColumn flag is set. */

    qrfSplitColumn(&data, p);
    nColumn = data.nCol;
  }else{
    /* Adjust the column widths due to screen width restrictions */
    qrfRestrictScreenWidth(&data, p);
  }

  /* Draw the line across the top of the table.  Also initialize
  ** the row boundary and column separator texts. */

  switch( p->spec.eStyle ){
    case QRF_STYLE_Box:
      if( data.nMargin ){
        rowStart = BOX_13 " ";
        colSep = " " BOX_13 " ";
        rowSep = " " BOX_13 "\n";
      }else{
        rowStart = BOX_13;
        colSep = BOX_13;
        rowSep = BOX_13 "\n";
      }
      if( p->spec.bBorder==QRF_No){
        rowStart += 3;
        rowSep = "\n";
      }else{
        qrfBoxSeparator(p->pOut, &data, BOX_R23, BOX_234, BOX_R34, 0);
      }
      break;
    case QRF_STYLE_Table:
      if( data.nMargin ){
        rowStart = "| ";
        colSep = " | ";
        rowSep = " |\n";
      }else{
        rowStart = "|";
        colSep = "|";
        rowSep = "|\n";
      }
      if( p->spec.bBorder==QRF_No ){
        rowStart += 1;
        rowSep = "\n";
      }else{
        qrfRowSeparator(p->pOut, &data, '+');
      }
      break;
    case QRF_STYLE_Column: {
      static const char zSpace[] = "     ";
      rowStart = "";
      if( data.nMargin<2 ){
        colSep = " ";
      }else if( data.nMargin<=5 ){
        colSep = &zSpace[5-data.nMargin];
      }else{
        colSep = zSpace;
      }
      rowSep = "\n";
      break;
    }
    default:  /*case QRF_STYLE_Markdown:*/
      if( data.nMargin ){
        rowStart = "| ";
        colSep = " | ";
        rowSep = " |\n";
      }else{
        rowStart = "|";
        colSep = "|";
        rowSep = "|\n";
      }
      break;
  }
  szRowStart = (int)strlen(rowStart);
  szRowSep = (int)strlen(rowSep);
  szColSep = (int)strlen(colSep);

  bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
  if( p->spec.eStyle==QRF_STYLE_Column
   || (p->spec.bBorder==QRF_No
       && (p->spec.eStyle==QRF_STYLE_Box || p->spec.eStyle==QRF_STYLE_Table)
      )
  ){
    bRTrim = 1;
  }else{
    bRTrim = 0;
  }
  for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){
    int bMore;
    int nRow = 0;

    /* Draw a single row of the table.  This might be the title line
    ** (if there is a title line) or a row in the body of the table.
    ** The column number will be j.  The row number is i/nColumn.
    */

    for(j=0; j<nColumn; j++){
      data.a[j].z = data.az[i+j];
      if( data.a[j].z==0 ) data.a[j].z = "";
      data.a[j].bNum = data.abNum[i+j];
    }
    do{
      sqlite3_str_append(p->pOut, rowStart, szRowStart);
      bMore = 0;
      for(j=0; j<nColumn; j++){
        int nThis = 0;
        int nWide = 0;
        int iNext = 0;
        int nWS;
        qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
        nWS = data.a[j].w - nWide;
        qrfPrintAligned(p->pOut, &data.a[j], nThis, nWS);
        data.a[j].z += iNext;
        if( data.a[j].z[0]!=0 ){
          bMore = 1;
        }
        if( j<nColumn-1 ){
          sqlite3_str_append(p->pOut, colSep, szColSep);
        }else{
          if( bRTrim ) qrfRTrim(p->pOut);
          sqlite3_str_append(p->pOut, rowSep, szRowSep);
        }
      }
    }while( bMore && ++nRow < p->mxHeight );
    if( bMore ){
      /* This row was terminated by nLineLimit.  Show ellipsis. */
      sqlite3_str_append(p->pOut, rowStart, szRowStart);
      for(j=0; j<nColumn; j++){
        if( data.a[j].z[0]==0 ){
          sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
        }else{
          int nE = 3;
          if( nE>data.a[j].w ) nE = data.a[j].w;
          data.a[j].z = "...";
          qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE);
        }
        if( j<nColumn-1 ){
          sqlite3_str_append(p->pOut, colSep, szColSep);
        }else{
          if( bRTrim ) qrfRTrim(p->pOut);
          sqlite3_str_append(p->pOut, rowSep, szRowSep);
        }
      }
    }

    /* Draw either (1) the separator between the title line and the body
    ** of the table, or (2) separators between individual rows of the table
    ** body.  isTitleDataSeparator will be true if we are doing (1).
    */

    if( (i==0 || data.bMultiRow) && i+nColumn<data.n ){
      int isTitleDataSeparator = (i==0 && p->spec.bTitles==QRF_Yes);
      if( isTitleDataSeparator ){
        qrfLoadAlignment(&data, p);
      }
      switch( p->spec.eStyle ){
        case QRF_STYLE_Table: {
          if( isTitleDataSeparator || data.bMultiRow ){
            qrfRowSeparator(p->pOut, &data, '+');
          }
          break;
        }
        case QRF_STYLE_Box: {
          if( isTitleDataSeparator ){
            qrfBoxSeparator(p->pOut, &data, DBL_123, DBL_1234, DBL_134, 1);
          }else if( data.bMultiRow ){
            qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134, 0);
          }
          break;
        }
        case QRF_STYLE_Markdown: {
          if( isTitleDataSeparator ){
            qrfRowSeparator(p->pOut, &data, '|');
          }
          break;
        }
        case QRF_STYLE_Column: {
          if( isTitleDataSeparator ){
            for(j=0; j<nColumn; j++){
              sqlite3_str_appendchar(p->pOut, data.a[j].w, '-');
              if( j<nColumn-1 ){
                sqlite3_str_append(p->pOut, colSep, szColSep);
              }else{
                qrfRTrim(p->pOut);
                sqlite3_str_append(p->pOut, rowSep, szRowSep);
              }
            }
          }else if( data.bMultiRow ){
            qrfRTrim(p->pOut);
            sqlite3_str_append(p->pOut, "\n", 1);
          }
          break;
        }
      }
    }
  }

  /* Draw the line across the bottom of the table */
  if( p->spec.bBorder!=QRF_No ){
    switch( p->spec.eStyle ){
      case QRF_STYLE_Box:
        qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0);
        break;
      case QRF_STYLE_Table:
        qrfRowSeparator(p->pOut, &data, '+');
        break;
    }
  }
  qrfWrite(p);

  qrfColDataFree(&data);
  return;
}

/*
** Parameter azArray points to a zero-terminated array of strings. zStr
** points to a single nul-terminated string. Return non-zero if zStr
** is equal, according to strcmp(), to any of the strings in the array.
** Otherwise, return zero.
*/

static int qrfStringInArray(const char *zStr, const char **azArray){
  int i;
  if( zStr==0 ) return 0;
  for(i=0; azArray[i]; i++){
    if( 0==strcmp(zStr, azArray[i]) ) return 1;
  }
  return 0;
}

/*
** Print out an EXPLAIN with indentation.  This is a two-pass algorithm.
**
** On the first pass, we compute aiIndent[iOp] which is the amount of
** indentation to apply to the iOp-th opcode.  The output actually occurs
** on the second pass.
**
** The indenting rules are:
**
**     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
**       all opcodes that occur between the p2 jump destination and the opcode
**       itself by 2 spaces.
**
**     * Do the previous for "Return" instructions for when P2 is positive.
**       See tag-20220407a in wherecode.c and vdbe.c.
**
**     * For each "Goto", if the jump destination is earlier in the program
**       and ends on one of:
**          Yield  SeekGt  SeekLt  RowSetRead  Rewind
**       or if the P1 parameter is one instead of zero,
**       then indent all opcodes between the earlier instruction
**       and "Goto" by 2 spaces.
*/

static void qrfExplain(Qrf *p){
  int *abYield = 0;     /* abYield[iOp] is rue if opcode iOp is an OP_Yield */
  int *aiIndent = 0;    /* Indent the iOp-th opcode by aiIndent[iOp] */
  i64 nAlloc = 0;       /* Allocated size of aiIndent[], abYield */
  int nIndent = 0;      /* Number of entries in aiIndent[] */
  int iOp;              /* Opcode number */
  int i;                /* Column loop counter */

  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
                           "Return", 0 };
  const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
                            "Rewind", 0 };
  const char *azGoto[] = { "Goto", 0 };

  /* The caller guarantees that the leftmost 4 columns of the statement
  ** passed to this function are equivalent to the leftmost 4 columns
  ** of EXPLAIN statement output. In practice the statement may be
  ** an EXPLAIN, or it may be a query on the bytecode() virtual table.  */

  assert( sqlite3_column_count(p->pStmt)>=4 );
  assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
  assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
  assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
  assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );

  for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){
    int iAddr = sqlite3_column_int(p->pStmt, 0);
    const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
    int p1 = sqlite3_column_int(p->pStmt, 2);
    int p2 = sqlite3_column_int(p->pStmt, 3);

    /* Assuming that p2 is an instruction address, set variable p2op to the
    ** index of that instruction in the aiIndent[] array. p2 and p2op may be
    ** different if the current instruction is part of a sub-program generated
    ** by an SQL trigger or foreign key.  */

    int p2op = (p2 + (iOp-iAddr));

    /* Grow the aiIndent array as required */
    if( iOp>=nAlloc ){
      nAlloc += 100;
      aiIndent = (int*)sqlite3_realloc64(aiIndent, nAlloc*sizeof(int));
      abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
      if( aiIndent==0 || abYield==0 ){
        qrfOom(p);
        sqlite3_free(aiIndent);
        sqlite3_free(abYield);
        return;
      }
    }

    abYield[iOp] = qrfStringInArray(zOp, azYield);
    aiIndent[iOp] = 0;
    nIndent = iOp+1;
    if( qrfStringInArray(zOp, azNext) && p2op>0 ){
      for(i=p2op; i<iOp; i++) aiIndent[i] += 2;
    }
    if( qrfStringInArray(zOp, azGoto) && p2op<iOp && (abYield[p2op] || p1) ){
      for(i=p2op; i<iOp; i++) aiIndent[i] += 2;
    }
  }
  sqlite3_free(abYield);

  /* Second pass.  Actually generate output */
  sqlite3_reset(p->pStmt);
  if( p->iErr==SQLITE_OK ){
    static const int aExplainWidth[] = {4,       13, 4, 4, 4, 13, 2, 13};
    static const int aExplainMap[] =   {0,       1,  2, 3, 4, 5,  6, 7 };
    static const int aScanExpWidth[] = {4,15, 6, 13, 4, 4, 4, 13, 2, 13};
    static const int aScanExpMap[] =   {0, 9, 8, 1,  2, 3, 4, 5,  6, 7 };
    const int *aWidth = aExplainWidth;
    const int *aMap = aExplainMap;
    int nWidth = sizeof(aExplainWidth)/sizeof(int);
    int iIndent = 1;
    int nArg = p->nCol;
    if( p->spec.eStyle==QRF_STYLE_StatsVm ){
      aWidth = aScanExpWidth;
      aMap = aScanExpMap;
      nWidth = sizeof(aScanExpWidth)/sizeof(int);
      iIndent = 3;
    }
    if( nArg>nWidth ) nArg = nWidth;

    for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){
      /* If this is the first row seen, print out the headers */
      if( iOp==0 ){
        for(i=0; i<nArg; i++){
          const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]);
          qrfWidthPrint(p,p->pOut, aWidth[i], zCol);
          if( i==nArg-1 ){
            sqlite3_str_append(p->pOut, "\n", 1);
          }else{
            sqlite3_str_append(p->pOut, "  ", 2);
          }
        }
        for(i=0; i<nArg; i++){
          sqlite3_str_appendf(p->pOut, "%.*c", aWidth[i], '-');
          if( i==nArg-1 ){
            sqlite3_str_append(p->pOut, "\n", 1);
          }else{
            sqlite3_str_append(p->pOut, "  ", 2);
          }
        }
      }
  
      for(i=0; i<nArg; i++){
        const char *zSep = "  ";
        int w = aWidth[i];
        const char *zVal = (const char*)sqlite3_column_text(p->pStmt, aMap[i]);
        int len;
        if( i==nArg-1 ) w = 0;
        if( zVal==0 ) zVal = "";
        len = (int)sqlite3_qrf_wcswidth(zVal);
        if( len>w ){
          w = len;
          zSep = " ";
        }
        if( i==iIndent && aiIndent && iOp<nIndent ){
          sqlite3_str_appendchar(p->pOut, aiIndent[iOp], ' ');
        }
        qrfWidthPrint(p, p->pOut, w, zVal);
        if( i==nArg-1 ){
          sqlite3_str_append(p->pOut, "\n", 1);
        }else{
          sqlite3_str_appendall(p->pOut, zSep);
        }
      }
      p->nRow++;
    }
    qrfWrite(p);
  }
  sqlite3_free(aiIndent);
}

/*
** Do a "scanstatus vm" style EXPLAIN listing on p->pStmt.
**
** p->pStmt is probably not an EXPLAIN query.  Instead, construct a
** new query that is a bytecode() rendering of p->pStmt with extra
** columns for the "scanstatus vm" outputs, and run the results of
** that new query through the normal EXPLAIN formatting.
*/

static void qrfScanStatusVm(Qrf *p){
  sqlite3_stmt *pOrigStmt = p->pStmt;
  sqlite3_stmt *pExplain;
  int rc;
  static const char *zSql =
      "  SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
      "   format('% 6s (%.2f%%)',"
      "      CASE WHEN ncycle<100_000 THEN ncycle || ' '"
      "         WHEN ncycle<100_000_000 THEN (ncycle/1_000) || 'K'"
      "         WHEN ncycle<100_000_000_000 THEN (ncycle/1_000_000) || 'M'"
      "         ELSE (ncycle/1000_000_000) || 'G' END,"
      "       ncycle*100.0/(sum(ncycle) OVER ())"
      "   )  AS cycles"
      "   FROM bytecode(?1)";
  rc = sqlite3_prepare_v2(p->db, zSql, -1, &pExplain, 0);
  if( rc ){
    qrfError(p, rc, "%s", sqlite3_errmsg(p->db));
    sqlite3_finalize(pExplain);
    return;
  }
  sqlite3_bind_pointer(pExplain, 1, pOrigStmt, "stmt-pointer", 0);
  p->pStmt = pExplain;
  p->nCol = 10;
  qrfExplain(p);
  sqlite3_finalize(pExplain);
  p->pStmt = pOrigStmt;
}

/*
** Attempt to determine if identifier zName needs to be quoted, either
** because it contains non-alphanumeric characters, or because it is an
** SQLite keyword.  Be conservative in this estimate:  When in doubt assume
** that quoting is required.
**
** Return 1 if quoting is required.  Return 0 if no quoting is required.
*/


static int qrf_need_quote(const char *zName){
  int i;
  const unsigned char *z = (const unsigned char*)zName;
  if( z==0 ) return 1;
  if( !qrfAlpha(z[0]) ) return 1;
  for(i=0; z[i]; i++){
    if( !qrfAlnum(z[i]) ) return 1;
  }
  return sqlite3_keyword_check(zName, i)!=0;
}

/*
** Helper function for QRF_STYLE_Json and QRF_STYLE_JObject.
** The initial "{" for a JSON object that will contain row content
** has been output.  Now output all the content.
*/

static void qrfOneJsonRow(Qrf *p){
  int i, nItem; 
  for(nItem=i=0; i<p->nCol; i++){
    const char *zCName;
    zCName = sqlite3_column_name(p->pStmt, i);
    if( nItem>0 ) sqlite3_str_append(p->pOut, ",", 1);
    nItem++;
    qrfEncodeText(p, p->pOut, zCName);
    sqlite3_str_append(p->pOut, ":", 1);
    qrfRenderValue(p, p->pOut, i);
  }
  qrfWrite(p);
}

/*
** Render a single row of output for non-columnar styles - any
** style that lets us render row by row as the content is received
** from the query.
*/

static void qrfOneSimpleRow(Qrf *p){
  int i;
  switch( p->spec.eStyle ){
    case QRF_STYLE_Off:
    case QRF_STYLE_Count: {
      /* No-op */
      break;
    }
    case QRF_STYLE_Json: {
      if( p->nRow==0 ){
        sqlite3_str_append(p->pOut, "[{", 2);
      }else{
        sqlite3_str_append(p->pOut, "},\n{", 4);
      }
      qrfOneJsonRow(p);
      break;
    }
    case QRF_STYLE_JObject: {
      if( p->nRow==0 ){
        sqlite3_str_append(p->pOut, "{", 1);
      }else{
        sqlite3_str_append(p->pOut, "}\n{", 3);
      }
      qrfOneJsonRow(p);
      break;
    }
    case QRF_STYLE_Html: {
      if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){
        sqlite3_str_append(p->pOut, "<TR>", 4);
        for(i=0; i<p->nCol; i++){
          const char *zCName = sqlite3_column_name(p->pStmt, i);
          sqlite3_str_append(p->pOut, "\n<TH>", 5);
          qrfEncodeText(p, p->pOut, zCName);
        }
        sqlite3_str_append(p->pOut, "\n</TR>\n", 7);
      }
      sqlite3_str_append(p->pOut, "<TR>", 4);
      for(i=0; i<p->nCol; i++){
        sqlite3_str_append(p->pOut, "\n<TD>", 5);
        qrfRenderValue(p, p->pOut, i);
      }
      sqlite3_str_append(p->pOut, "\n</TR>\n", 7);
      qrfWrite(p);
      break;
    }
    case QRF_STYLE_Insert: {
      unsigned int mxIns = p->spec.nMultiInsert;
      int szStart = sqlite3_str_length(p->pOut);
      if( p->u.nIns==0 || p->u.nIns>=mxIns ){
        if( p->u.nIns ){
          sqlite3_str_append(p->pOut, ";\n", 2);
          p->u.nIns = 0;
        }
        if( qrf_need_quote(p->spec.zTableName) ){
          sqlite3_str_appendf(p->pOut,"INSERT INTO \"%w\"",p->spec.zTableName);
        }else{
          sqlite3_str_appendf(p->pOut,"INSERT INTO %s",p->spec.zTableName);
        }
        if( p->spec.bTitles==QRF_Yes ){
          for(i=0; i<p->nCol; i++){
            const char *zCName = sqlite3_column_name(p->pStmt, i);
            if( qrf_need_quote(zCName) ){
              sqlite3_str_appendf(p->pOut, "%c\"%w\"",
                                  i==0 ? '(' : ',', zCName);
            }else{
              sqlite3_str_appendf(p->pOut, "%c%s",
                                  i==0 ? '(' : ',', zCName);
            }
          }
          sqlite3_str_append(p->pOut, ")", 1);
        }
        sqlite3_str_append(p->pOut," VALUES(", 8);
      }else{
        sqlite3_str_append(p->pOut,",\n  (", 5);
      }
      for(i=0; i<p->nCol; i++){
        if( i>0 ) sqlite3_str_append(p->pOut, ",", 1);
        qrfRenderValue(p, p->pOut, i);
      }
      p->u.nIns += sqlite3_str_length(p->pOut) + 2 - szStart;
      if( p->u.nIns>=mxIns ){
        sqlite3_str_append(p->pOut, ");\n", 3);
        p->u.nIns = 0;
      }else{
        sqlite3_str_append(p->pOut, ")", 1);
      }
      qrfWrite(p);
      break;
    }
    case QRF_STYLE_Line: {
      sqlite3_str *pVal;
      int mxW;
      int bWW;
      int nSep;
      if( p->u.sLine.azCol==0 ){
        p->u.sLine.azCol = sqlite3_malloc64( p->nCol*sizeof(char*) );
        if( p->u.sLine.azCol==0 ){
          qrfOom(p);
          break;
        }
        p->u.sLine.mxColWth = 0;
        for(i=0; i<p->nCol; i++){
          int sz;
          const char *zCName = sqlite3_column_name(p->pStmt, i);
          if( zCName==0 ) zCName = "unknown";
          p->u.sLine.azCol[i] = sqlite3_mprintf("%s", zCName);
          if( p->spec.nTitleLimit>0 ){
            (void)qrfTitleLimit(p->u.sLine.azCol[i], p->spec.nTitleLimit);
          }
          sz = (int)sqlite3_qrf_wcswidth(p->u.sLine.azCol[i]);
          if( sz > p->u.sLine.mxColWth ) p->u.sLine.mxColWth = sz;
        }
      }
      if( p->nRow ) sqlite3_str_append(p->pOut, "\n", 1);
      pVal = sqlite3_str_new(p->db);
      nSep = (int)strlen(p->spec.zColumnSep);
      mxW = p->mxWidth - (nSep + p->u.sLine.mxColWth);
      bWW = p->spec.bWordWrap==QRF_Yes;
      for(i=0; i<p->nCol; i++){
        const char *zVal;
        int cnt = 0;
        qrfWidthPrint(p, p->pOut, -p->u.sLine.mxColWth, p->u.sLine.azCol[i]);
        sqlite3_str_append(p->pOut, p->spec.zColumnSep, nSep);
        qrfRenderValue(p, pVal, i);
        zVal = sqlite3_str_value(pVal);
        if( zVal==0 ) zVal = "";
        do{
          int nThis, nWide, iNext;
          qrfWrapLine(zVal, mxW, bWW, &nThis, &nWide, &iNext);
          if( cnt ){
            sqlite3_str_appendchar(p->pOut,p->u.sLine.mxColWth+nSep,' ');
          }
          cnt++;
          if( cnt>p->mxHeight ){
            zVal = "...";
            nThis = iNext = 3;
          }
          sqlite3_str_append(p->pOut, zVal, nThis);
          sqlite3_str_append(p->pOut, "\n", 1);
          zVal += iNext;
        }while( zVal[0] );
        sqlite3_str_reset(pVal);
      }
      qrfStrErr(p, pVal);
      sqlite3_free(sqlite3_str_finish(pVal));
      qrfWrite(p);
      break;
    }
    case QRF_STYLE_Eqp: {
      const char *zEqpLine = (const char*)sqlite3_column_text(p->pStmt,3);
      int iEqpId = sqlite3_column_int(p->pStmt, 0);
      int iParentId = sqlite3_column_int(p->pStmt, 1);
      if( zEqpLine==0 ) zEqpLine = "";
      if( zEqpLine[0]=='-' ) qrfEqpRender(p, 0);
      qrfEqpAppend(p, iEqpId, iParentId, zEqpLine);
      break;
    }
    default: {  /* QRF_STYLE_List */
      if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){
        int saved_eText = p->spec.eText;
        p->spec.eText = p->spec.eTitle;
        for(i=0; i<p->nCol; i++){
          const char *zCName = sqlite3_column_name(p->pStmt, i);
          if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
          qrfEncodeText(p, p->pOut, zCName);
        }
        sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
        qrfWrite(p);
        p->spec.eText = saved_eText;
      }
      for(i=0; i<p->nCol; i++){
        if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
        qrfRenderValue(p, p->pOut, i);
      }
      sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
      qrfWrite(p);
      break;
    }
  }
  p->nRow++;
}

/*
** Initialize the internal Qrf object.
*/

static void qrfInitialize(
  Qrf *p,                        /* State object to be initialized */
  sqlite3_stmt *pStmt,           /* Query whose output to be formatted */
  const sqlite3_qrf_spec *pSpec, /* Format specification */
  char **pzErr                   /* Write errors here */
){
  size_t sz;                     /* Size of pSpec[], based on pSpec->iVersion */
  memset(p, 0, sizeof(*p));
  p->pzErr = pzErr;
  if( pSpec->iVersion>1 ){
    qrfError(p, SQLITE_ERROR,
       "unusable sqlite3_qrf_spec.iVersion (%d)",
       pSpec->iVersion);
    return;
  }
  p->pStmt = pStmt;
  p->db = sqlite3_db_handle(pStmt);
  p->pOut = sqlite3_str_new(p->db);
  if( p->pOut==0 ){
    qrfOom(p);
    return;
  }
  p->iErr = SQLITE_OK;
  p->nCol = sqlite3_column_count(p->pStmt);
  p->nRow = 0;
  sz = sizeof(sqlite3_qrf_spec);
  memcpy(&p->spec, pSpec, sz);
  if( p->spec.zNull==0 ) p->spec.zNull = "";
  p->mxWidth = p->spec.nScreenWidth;
  if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH;
  p->mxHeight = p->spec.nLineLimit;
  if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
  if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
  if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto;
  if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto;
  if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto;
  if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto;
qrf_reinit:
  switch( p->spec.eStyle ){
    case QRF_Auto: {
      switch( sqlite3_stmt_isexplain(pStmt) ){
        case 0:  p->spec.eStyle = QRF_STYLE_Box;      break;
        case 1:  p->spec.eStyle = QRF_STYLE_Explain;  break;
        default: p->spec.eStyle = QRF_STYLE_Eqp;      break;
      }
      goto qrf_reinit;
    }
    case QRF_STYLE_List: {
      if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = "|";
      if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n";
      break;
    }
    case QRF_STYLE_JObject:
    case QRF_STYLE_Json: {
      p->spec.eText = QRF_TEXT_Json;
      p->spec.zNull = "null";
      break;
    }
    case QRF_STYLE_Html: {
      p->spec.eText = QRF_TEXT_Html;
      p->spec.zNull = "null";
      break;
    }
    case QRF_STYLE_Insert: {
      p->spec.eText = QRF_TEXT_Sql;
      p->spec.zNull = "NULL";
      if( p->spec.zTableName==0 || p->spec.zTableName[0]==0 ){
        p->spec.zTableName = "tab";
      }
      p->u.nIns = 0;
      break;
    }
    case QRF_STYLE_Line: {
      if( p->spec.zColumnSep==0 ){
        p->spec.zColumnSep = ": ";
      }
      break;
    }
    case QRF_STYLE_Csv: {
      p->spec.eStyle = QRF_STYLE_List;
      p->spec.eText = QRF_TEXT_Csv;
      p->spec.zColumnSep = ",";
      p->spec.zRowSep = "\r\n";
      p->spec.zNull = "";
      break;
    }
    case QRF_STYLE_Quote: {
      p->spec.eText = QRF_TEXT_Sql;
      p->spec.zNull = "NULL";
      p->spec.zColumnSep = ",";
      p->spec.zRowSep = "\n";
      break;
    }
    case QRF_STYLE_Eqp: {
      int expMode = sqlite3_stmt_isexplain(p->pStmt);
      if( expMode!=2 ){
        sqlite3_stmt_explain(p->pStmt, 2);
        p->expMode = expMode+1;
      }
      break;
    }
    case QRF_STYLE_Explain: {
      int expMode = sqlite3_stmt_isexplain(p->pStmt);
      if( expMode!=1 ){
        sqlite3_stmt_explain(p->pStmt, 1);
        p->expMode = expMode+1;
      }
      break;
    }
  }
  if( p->spec.eEsc==QRF_Auto ){
    p->spec.eEsc = QRF_ESC_Ascii;
  }
  if( p->spec.eText==QRF_Auto ){
    p->spec.eText = QRF_TEXT_Plain;
  }
  if( p->spec.eTitle==QRF_Auto ){
    switch( p->spec.eStyle ){
      case QRF_STYLE_Box:
      case QRF_STYLE_Column:
      case QRF_STYLE_Table:
        p->spec.eTitle = QRF_TEXT_Plain;
        break;
      default:
        p->spec.eTitle = p->spec.eText;
        break;
    }
  }
  if( p->spec.eBlob==QRF_Auto ){
    switch( p->spec.eText ){
      case QRF_TEXT_Sql:  p->spec.eBlob = QRF_BLOB_Sql;  break;
      case QRF_TEXT_Csv:  p->spec.eBlob = QRF_BLOB_Tcl;  break;
      case QRF_TEXT_Tcl:  p->spec.eBlob = QRF_BLOB_Tcl;  break;
      case QRF_TEXT_Json: p->spec.eBlob = QRF_BLOB_Json; break;
      default:            p->spec.eBlob = QRF_BLOB_Text; break;
    }
  }
  if( p->spec.bTitles==QRF_Auto ){
    switch( p->spec.eStyle ){
      case QRF_STYLE_Box:
      case QRF_STYLE_Csv:
      case QRF_STYLE_Column:
      case QRF_STYLE_Table:
      case QRF_STYLE_Markdown:
        p->spec.bTitles = QRF_Yes;
        break;
      default:
        p->spec.bTitles = QRF_No;
        break;
    }
  }
  if( p->spec.bWordWrap==QRF_Auto ){
    p->spec.bWordWrap = QRF_Yes;
  }
  if( p->spec.bTextJsonb==QRF_Auto ){
    p->spec.bTextJsonb = QRF_No;
  }
  if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = ",";
  if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n";
}

/*
** Finish rendering the results
*/

static void qrfFinalize(Qrf *p){
  switch( p->spec.eStyle ){
    case QRF_STYLE_Count: {
      sqlite3_str_appendf(p->pOut, "%lld\n", p->nRow);
      break;
    }
    case QRF_STYLE_Json: {
      if( p->nRow>0 ){
        sqlite3_str_append(p->pOut, "}]\n", 3);
      }
      break;
    }
    case QRF_STYLE_JObject: {
      if( p->nRow>0 ){
        sqlite3_str_append(p->pOut, "}\n", 2);
      }
      break;
    }
    case QRF_STYLE_Insert: {
      if( p->u.nIns ){
        sqlite3_str_append(p->pOut, ";\n", 2);
      }
      break;
    }
    case QRF_STYLE_Line: {
      if( p->u.sLine.azCol ){
        int i;
        for(i=0; i<p->nCol; i++) sqlite3_free(p->u.sLine.azCol[i]);
        sqlite3_free(p->u.sLine.azCol);
      }
      break;
    }
    case QRF_STYLE_Stats:
    case QRF_STYLE_StatsEst: {
      i64 nCycle = 0;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
      sqlite3_stmt_scanstatus_v2(p->pStmt, -1, SQLITE_SCANSTAT_NCYCLE,
                                 SQLITE_SCANSTAT_COMPLEX, (void*)&nCycle);
#endif
      qrfEqpRender(p, nCycle);
      break;
    }
    case QRF_STYLE_Eqp: {
      qrfEqpRender(p, 0);
      break;
    }
  }
  qrfWrite(p);
  qrfStrErr(p, p->pOut);
  if( p->spec.pzOutput ){
    if( p->spec.pzOutput[0] ){
      sqlite3_int64 n, sz;
      char *zCombined;
      sz = strlen(p->spec.pzOutput[0]);
      n = sqlite3_str_length(p->pOut);
      zCombined = sqlite3_realloc64(p->spec.pzOutput[0], sz+n+1);
      if( zCombined==0 ){
        sqlite3_free(p->spec.pzOutput[0]);
        p->spec.pzOutput[0] = 0;
        qrfOom(p);
      }else{
        p->spec.pzOutput[0] = zCombined;
        memcpy(zCombined+sz, sqlite3_str_value(p->pOut), n+1);
      }
      sqlite3_free(sqlite3_str_finish(p->pOut));
    }else{
      p->spec.pzOutput[0] = sqlite3_str_finish(p->pOut);
    }
  }else if( p->pOut ){
    sqlite3_free(sqlite3_str_finish(p->pOut));
  }
  if( p->expMode>0 ){
    sqlite3_stmt_explain(p->pStmt, p->expMode-1);
  }
  if( p->actualWidth ){
    sqlite3_free(p->actualWidth);
  }
  if( p->pJTrans ){
    sqlite3 *db = sqlite3_db_handle(p->pJTrans);
    sqlite3_finalize(p->pJTrans);
    sqlite3_close(db);
  }
}

/*
** Run the prepared statement pStmt and format the results according
** to the specification provided in pSpec.  Return an error code.
** If pzErr is not NULL and if an error occurs, write an error message
** into *pzErr.
*/

int sqlite3_format_query_result(
  sqlite3_stmt *pStmt,                 /* Statement to evaluate */
  const sqlite3_qrf_spec *pSpec,       /* Format specification */
  char **pzErr                         /* Write error message here */
){
  Qrf qrf;         /* The new Qrf being created */

  if( pStmt==0 ) return SQLITE_OK;       /* No-op */
  if( pSpec==0 ) return SQLITE_MISUSE;
  qrfInitialize(&qrf, pStmt, pSpec, pzErr);
  switch( qrf.spec.eStyle ){
    case QRF_STYLE_Box:
    case QRF_STYLE_Column:
    case QRF_STYLE_Markdown: 
    case QRF_STYLE_Table: {
      /* Columnar modes require that the entire query be evaluated and the
      ** results stored in memory, so that we can compute column widths */

      qrfColumnar(&qrf);
      break;
    }
    case QRF_STYLE_Explain: {
      qrfExplain(&qrf);
      break;
    }
    case QRF_STYLE_StatsVm: {
      qrfScanStatusVm(&qrf);
      break;
    }
    case QRF_STYLE_Stats:
    case QRF_STYLE_StatsEst: {
      qrfEqpStats(&qrf);
      break;
    }
    default: {
      /* Non-columnar modes where the output can occur after each row
      ** of result is received */

      while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
        qrfOneSimpleRow(&qrf);
      }
      break;
    }
  }
  qrfResetStmt(&qrf);
  qrfFinalize(&qrf);
  return qrf.iErr;
}

/************************* End ext/qrf/qrf.c ********************/

/* Use console I/O package as a direct INCLUDE. */
#define SQLITE_INTERNAL_LINKAGE static

#ifdef SQLITE_SHELL_FIDDLE
/* Deselect most features from the console I/O package for Fiddle. */
# define SQLITE_CIO_NO_REDIRECT
# define SQLITE_CIO_NO_CLASSIFY
# define SQLITE_CIO_NO_TRANSLATE
# define SQLITE_CIO_NO_SETMODE
# define SQLITE_CIO_NO_FLUSH
#endif

/*
** The source code for several run-time loadable extensions is inserted
** below by the ../tool/mkshellc.tcl script.  Before processing that included
** code, we need to override some macros to make the included program code
** work here in the middle of this regular program.
*/

#define SQLITE_EXTENSION_INIT1
#define SQLITE_EXTENSION_INIT2(X) (void)(X)

/************************* Begin ext/misc/windirent.h ******************/
/*
** 2025-06-05
**
** 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.
**
*************************************************************************
**
** An implementation of opendir(), readdir(), and closedir() for Windows,
** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs
** of Win32.
**
** #include this file inside any C-code module that needs to use
** opendir()/readdir()/closedir().  This file is a no-op on non-Windows
** machines.  On Windows, static functions are defined that implement
** those standard interfaces.
*/

#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
#define SQLITE_WINDIRENT_H

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#ifndef FILENAME_MAX
# define FILENAME_MAX (260)
#endif
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISLNK
#define S_ISLNK(m) (0)
#endif
typedef unsigned short mode_t;

/* The dirent object for Windows is abbreviated.  The only field really
** usable by applications is d_name[].
*/

struct dirent {
 int d_ino;                  /* Inode number (synthesized) */
 unsigned d_attributes;      /* File attributes */
 char d_name[FILENAME_MAX];  /* Null-terminated filename */
};

/* The internals of DIR are opaque according to standards.  So it
** does not matter what we put here. */

typedef struct DIR DIR;
struct DIR {
  intptr_t d_handle;         /* Handle for findfirst()/findnext() */
  struct dirent cur;         /* Current entry */
};

/* Ignore hidden and system files */
#define WindowsFileToIgnore(a) \
    ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))

/*
** Close a previously opened directory
*/

static int closedir(DIR *pDir){
  int rc = 0;
  if( pDir==0 ){
    return EINVAL;
  }
  if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){
    rc = _findclose(pDir->d_handle);
  }
  sqlite3_free(pDir);
  return rc;
}

/*
** Open a new directory.  The directory name should be UTF-8 encoded.
** appropriate translations happen automatically.
*/

static DIR *opendir(const char *zDirName){
  DIR *pDir;
  wchar_t *b1;
  sqlite3_int64 sz;
  struct _wfinddata_t data;

  pDir = sqlite3_malloc64( sizeof(DIR) );
  if( pDir==0 ) return 0;
  memset(pDir, 0, sizeof(DIR));
  memset(&data, 0, sizeof(data));
  sz = strlen(zDirName);
  b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
  if( b1==0 ){
    closedir(pDir);
    return NULL;
  }
  sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz);
  b1[sz++] = '\\';
  b1[sz++] = '*';
  b1[sz] = 0;
  if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){
    closedir(pDir);
    sqlite3_free(b1);
    return NULL;
  }
  memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
  sqlite3_free(b1);
  pDir->d_handle = _wfindfirst(data.name, &data);
  if( pDir->d_handle<0 ){
    closedir(pDir);
    return NULL;
  }
  while( WindowsFileToIgnore(data) ){
    memset(&data, 0, sizeof(data));
    if( _wfindnext(pDir->d_handle, &data)==-1 ){
      closedir(pDir);
      return NULL;
    }
  }
  pDir->cur.d_ino = 0;
  pDir->cur.d_attributes = data.attrib;
  WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
                      pDir->cur.d_name, FILENAME_MAX, 0, 0);
  return pDir;
}

/*
** Read the next entry from a directory.
**
** The returned struct-dirent object is managed by DIR.  It is only
** valid until the next readdir() or closedir() call.  Only the
** d_name[] field is meaningful.  The d_name[] value has been
** translated into UTF8.
*/

static struct dirent *readdir(DIR *pDir){
  struct _wfinddata_t data;
  if( pDir==0 ) return 0;
  if( (pDir->cur.d_ino++)==0 ){
    return &pDir->cur;
  }
  do{
    memset(&data, 0, sizeof(data));
    if( _wfindnext(pDir->d_handle, &data)==-1 ){
      return NULL;
    }
  }while( WindowsFileToIgnore(data) );
  pDir->cur.d_attributes = data.attrib;
  WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
                      pDir->cur.d_name, FILENAME_MAX, 0, 0);
  return &pDir->cur;
}

#endif /* defined(_WIN32) && defined(_MSC_VER) */

/************************* End ext/misc/windirent.h ********************/
/************************* Begin ext/misc/memtrace.c ******************/
/*
** 2019-01-21
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
** mechanism to add a tracing layer on top of SQLite.  If this extension
** is registered prior to sqlite3_initialize(), it will cause all memory
** allocation activities to be logged on standard output, or to some other
** FILE specified by the initializer.
**
** This file needs to be compiled into the application that uses it.
**
** This extension is used to implement the --memtrace option of the
** command-line shell.
*/

#include <assert.h>
#include <string.h>
#include <stdio.h>

/* The original memory allocation routines */
static sqlite3_mem_methods memtraceBase;
static FILE *memtraceOut;

/* Methods that trace memory allocations */
static void *memtraceMalloc(int n){
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", 
            memtraceBase.xRoundup(n));
  }
  return memtraceBase.xMalloc(n);
}
static void memtraceFree(void *p){
  if( p==0 ) return;
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
  }
  memtraceBase.xFree(p);
}
static void *memtraceRealloc(void *p, int n){
  if( p==0 ) return memtraceMalloc(n);
  if( n==0 ){
    memtraceFree(p);
    return 0;
  }
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
            memtraceBase.xSize(p), memtraceBase.xRoundup(n));
  }
  return memtraceBase.xRealloc(p, n);
}
static int memtraceSize(void *p){
  return memtraceBase.xSize(p);
}
static int memtraceRoundup(int n){
  return memtraceBase.xRoundup(n);
}
static int memtraceInit(void *p){
  return memtraceBase.xInit(p);
}
static void memtraceShutdown(void *p){
  memtraceBase.xShutdown(p);
}

/* The substitute memory allocator */
static sqlite3_mem_methods ersaztMethods = {
  memtraceMalloc,
  memtraceFree,
  memtraceRealloc,
  memtraceSize,
  memtraceRoundup,
  memtraceInit,
  memtraceShutdown,
  0
};

/* Begin tracing memory allocations to out. */
int sqlite3MemTraceActivate(FILE *out){
  int rc = SQLITE_OK;
  if( memtraceBase.xMalloc==0 ){
    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
    if( rc==SQLITE_OK ){
      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
    }
  }
  memtraceOut = out;
  return rc;
}

/* Deactivate memory tracing */
int sqlite3MemTraceDeactivate(void){
  int rc = SQLITE_OK;
  if( memtraceBase.xMalloc!=0 ){
    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
    if( rc==SQLITE_OK ){
      memset(&memtraceBase, 0, sizeof(memtraceBase));
    }
  }
  memtraceOut = 0;
  return rc;
}

/************************* End ext/misc/memtrace.c ********************/
/************************* Begin ext/misc/pcachetrace.c ******************/
/*
** 2023-06-21
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements an extension that uses the SQLITE_CONFIG_PCACHE2
** mechanism to add a tracing layer on top of pluggable page cache of
** SQLite.  If this extension is registered prior to sqlite3_initialize(),
** it will cause all page cache activities to be logged on standard output,
** or to some other FILE specified by the initializer.
**
** This file needs to be compiled into the application that uses it.
**
** This extension is used to implement the --pcachetrace option of the
** command-line shell.
*/

#include <assert.h>
#include <string.h>
#include <stdio.h>

/* The original page cache routines */
static sqlite3_pcache_methods2 pcacheBase;
static FILE *pcachetraceOut;

/* Methods that trace pcache activity */
static int pcachetraceInit(void *pArg){
  int nRes;
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p)\n", pArg);
  }
  nRes = pcacheBase.xInit(pArg);
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p) -> %d\n", pArg, nRes);
  }
  return nRes;
}
static void pcachetraceShutdown(void *pArg){
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xShutdown(%p)\n", pArg);
  }
  pcacheBase.xShutdown(pArg);
}
static sqlite3_pcache *pcachetraceCreate(int szPage, int szExtra, int bPurge){
  sqlite3_pcache *pRes;
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d)\n",
            szPage, szExtra, bPurge);
  }
  pRes = pcacheBase.xCreate(szPage, szExtra, bPurge);
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d) -> %p\n",
            szPage, szExtra, bPurge, pRes);
  }
  return pRes;
}
static void pcachetraceCachesize(sqlite3_pcache *p, int nCachesize){
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xCachesize(%p, %d)\n", p, nCachesize);
  }
  pcacheBase.xCachesize(p, nCachesize);
}
static int pcachetracePagecount(sqlite3_pcache *p){
  int nRes;
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p)\n", p);
  }
  nRes = pcacheBase.xPagecount(p);
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p) -> %d\n", p, nRes);
  }
  return nRes;
}
static sqlite3_pcache_page *pcachetraceFetch(
  sqlite3_pcache *p,
  unsigned key,
  int crFg
){
  sqlite3_pcache_page *pRes;
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d)\n", p, key, crFg);
  }
  pRes = pcacheBase.xFetch(p, key, crFg);
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d) -> %p\n",
            p, key, crFg, pRes);
  }
  return pRes;
}
static void pcachetraceUnpin(
  sqlite3_pcache *p,
  sqlite3_pcache_page *pPg,
  int bDiscard
){
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xUnpin(%p, %p, %d)\n",
            p, pPg, bDiscard);
  }
  pcacheBase.xUnpin(p, pPg, bDiscard);
}
static void pcachetraceRekey(
  sqlite3_pcache *p,
  sqlite3_pcache_page *pPg,
  unsigned oldKey,
  unsigned newKey
){
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xRekey(%p, %p, %u, %u)\n",
        p, pPg, oldKey, newKey);
  }
  pcacheBase.xRekey(p, pPg, oldKey, newKey);
}
static void pcachetraceTruncate(sqlite3_pcache *p, unsigned n){
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xTruncate(%p, %u)\n", p, n);
  }
  pcacheBase.xTruncate(p, n);
}
static void pcachetraceDestroy(sqlite3_pcache *p){
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xDestroy(%p)\n", p);
  }
  pcacheBase.xDestroy(p);
}
static void pcachetraceShrink(sqlite3_pcache *p){
  if( pcachetraceOut ){
    fprintf(pcachetraceOut, "PCACHETRACE: xShrink(%p)\n", p);
  }
  pcacheBase.xShrink(p);
}

/* The substitute pcache methods */
static sqlite3_pcache_methods2 ersaztPcacheMethods = {
  0,
  0,
  pcachetraceInit,
  pcachetraceShutdown,
  pcachetraceCreate,
  pcachetraceCachesize,
  pcachetracePagecount,
  pcachetraceFetch,
  pcachetraceUnpin,
  pcachetraceRekey,
  pcachetraceTruncate,
  pcachetraceDestroy,
  pcachetraceShrink
};

/* Begin tracing memory allocations to out. */
int sqlite3PcacheTraceActivate(FILE *out){
  int rc = SQLITE_OK;
  if( pcacheBase.xFetch==0 ){
    rc = sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &pcacheBase);
    if( rc==SQLITE_OK ){
      rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &ersaztPcacheMethods);
    }
  }
  pcachetraceOut = out;
  return rc;
}

/* Deactivate memory tracing */
int sqlite3PcacheTraceDeactivate(void){
  int rc = SQLITE_OK;
  if( pcacheBase.xFetch!=0 ){
    rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcacheBase);
    if( rc==SQLITE_OK ){
      memset(&pcacheBase, 0, sizeof(pcacheBase));
    }
  }
  pcachetraceOut = 0;
  return rc;
}

/************************* End ext/misc/pcachetrace.c ********************/
/************************* Begin ext/misc/shathree.c ******************/
/*
** 2017-03-08
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This SQLite extension implements functions that compute SHA3 hashes
** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
** Three SQL functions are implemented:
**
**     sha3(X,SIZE)
**     sha3_agg(Y,SIZE)
**     sha3_query(Z,SIZE)
**
** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
** X is NULL.  If inputs X is text, the UTF-8 rendering of that text is
** used to compute the hash.  If X is a BLOB, then the binary data of the
** blob is used to compute the hash.  If X is an integer or real number,
** then that number if converted into UTF-8 text and the hash is computed
** over the text.
**
** The sha3_agg(Y) function computes the SHA3 hash of all Y inputs.  Since
** order is important for the hash, it is recommended that the Y expression
** by followed by an ORDER BY clause to guarantee that the inputs occur
** in the desired order.
**
** The sha3_query(Y) function evaluates all queries in the SQL statements of Y
** and returns a hash of their results.
**
** The SIZE argument is optional.  If omitted, the SHA3-256 hash algorithm
** is used.  If SIZE is included it must be one of the integers 224, 256,
** 384, or 512, to determine SHA3 hash variant that is computed.
**
** Because the sha3_agg() and sha3_query() functions compute a hash over
** multiple values, the values are encode to use include type information.
**
** In sha3_agg(), the sequence of bytes that gets hashed for each input
** Y depends on the datatype of Y:
**
**    typeof(Y)='null'         A single "N" is hashed.  (One byte)
**
**    typeof(Y)='integer'      The data hash is the character "I" followed
**                             by an 8-byte big-endian binary of the
**                             64-bit signed integer.  (Nine bytes total.)
**
**    typeof(Y)='real'         The character "F" followed by an 8-byte
**                             big-ending binary of the double.  (Nine
**                             bytes total.)
**
**    typeof(Y)='text'         The hash is over prefix "Tnnn:" followed
**                             by the UTF8 encoding of the text.  The "nnn"
**                             in the prefix is the minimum-length decimal
**                             representation of the octet_length of the text.
**                             Notice the ":" at the end of the prefix, which
**                             is needed to separate the prefix from the
**                             content in cases where the content starts
**                             with a digit.
**
**    typeof(Y)='blob'         The hash is taken over prefix "Bnnn:" followed
**                             by the binary content of the blob.  The "nnn"
**                             in the prefix is the minimum-length decimal
**                             representation of the byte-length of the blob.
**
** According to the rules above, all of the following SELECT statements
** should return TRUE:
**
**    SELECT sha3(1) = sha3('1');
**
**    SELECT sha3('hello') = sha3(x'68656c6c6f');
**
**    WITH a(x) AS (VALUES('xyzzy'))
**      SELECT sha3_agg(x) = sha3('T5:xyzzy')            FROM a;
**
**    WITH a(x) AS (VALUES(x'010203'))
**      SELECT sha3_agg(x) = sha3(x'42333a010203')       FROM a;
**
**    WITH a(x) AS (VALUES(0x123456))
**      SELECT sha3_agg(x) = sha3(x'490000000000123456') FROM a;
**
**    WITH a(x) AS (VALUES(100.015625))
**      SELECT sha3_agg(x) = sha3(x'464059010000000000') FROM a;
**
**    WITH a(x) AS (VALUES(NULL))
**      SELECT sha3_agg(x) = sha3('N') FROM a;
**
**
** In sha3_query(), individual column values are encoded as with
** sha3_agg(), but with the addition that a single "R" character is
** inserted at the start of each row.
**
** Note that sha3_agg() hashes rows for which Y is NULL.  Add a FILTER
** clause if NULL rows should be excluded:
**
**    SELECT sha3_agg(x ORDER BY rowid) FILTER(WHERE x NOT NULL) FROM t1;
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>

#ifndef SQLITE_AMALGAMATION
/* typedef sqlite3_uint64 u64; */
#endif /* SQLITE_AMALGAMATION */

/******************************************************************************
** The Hash Engine
*/

/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros.  If that is unsuccessful, or if
** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
*/

#ifndef SHA3_BYTEORDER
# if defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
     defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
     defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
     defined(__arm__)
#   define SHA3_BYTEORDER    1234
# elif defined(sparc)    || defined(__ppc__)
#   define SHA3_BYTEORDER    4321
# else
#   define SHA3_BYTEORDER 0
# endif
#endif


/*
** State structure for a SHA3 hash in progress
*/

typedef struct SHA3Context SHA3Context;
struct SHA3Context {
  union {
    u64 s[25];                /* Keccak state. 5x5 lines of 64 bits each */
    unsigned char x[1600];    /* ... or 1600 bytes */
  } u;
  unsigned nRate;        /* Bytes of input accepted per Keccak iteration */
  unsigned nLoaded;      /* Input bytes loaded into u.x[] so far this cycle */
  unsigned ixMask;       /* Insert next input into u.x[nLoaded^ixMask]. */
  unsigned iSize;        /* 224, 256, 358, or 512 */
};

/*
** A single step of the Keccak mixing function for a 1600-bit state
*/

static void KeccakF1600Step(SHA3Context *p){
  int i;
  u64 b0, b1, b2, b3, b4;
  u64 c0, c1, c2, c3, c4;
  u64 d0, d1, d2, d3, d4;
  static const u64 RC[] = {
    0x0000000000000001ULL,  0x0000000000008082ULL,
    0x800000000000808aULL,  0x8000000080008000ULL,
    0x000000000000808bULL,  0x0000000080000001ULL,
    0x8000000080008081ULL,  0x8000000000008009ULL,
    0x000000000000008aULL,  0x0000000000000088ULL,
    0x0000000080008009ULL,  0x000000008000000aULL,
    0x000000008000808bULL,  0x800000000000008bULL,
    0x8000000000008089ULL,  0x8000000000008003ULL,
    0x8000000000008002ULL,  0x8000000000000080ULL,
    0x000000000000800aULL,  0x800000008000000aULL,
    0x8000000080008081ULL,  0x8000000000008080ULL,
    0x0000000080000001ULL,  0x8000000080008008ULL
  };
# define a00 (p->u.s[0])
# define a01 (p->u.s[1])
# define a02 (p->u.s[2])
# define a03 (p->u.s[3])
# define a04 (p->u.s[4])
# define a10 (p->u.s[5])
# define a11 (p->u.s[6])
# define a12 (p->u.s[7])
# define a13 (p->u.s[8])
# define a14 (p->u.s[9])
# define a20 (p->u.s[10])
# define a21 (p->u.s[11])
# define a22 (p->u.s[12])
# define a23 (p->u.s[13])
# define a24 (p->u.s[14])
# define a30 (p->u.s[15])
# define a31 (p->u.s[16])
# define a32 (p->u.s[17])
# define a33 (p->u.s[18])
# define a34 (p->u.s[19])
# define a40 (p->u.s[20])
# define a41 (p->u.s[21])
# define a42 (p->u.s[22])
# define a43 (p->u.s[23])
# define a44 (p->u.s[24])
# define ROL64(a,x) ((a<<x)|(a>>(64-x)))

  for(i=0; i<24; i+=4){
    c0 = a00^a10^a20^a30^a40;
    c1 = a01^a11^a21^a31^a41;
    c2 = a02^a12^a22^a32^a42;
    c3 = a03^a13^a23^a33^a43;
    c4 = a04^a14^a24^a34^a44;
    d0 = c4^ROL64(c1, 1);
    d1 = c0^ROL64(c2, 1);
    d2 = c1^ROL64(c3, 1);
    d3 = c2^ROL64(c4, 1);
    d4 = c3^ROL64(c0, 1);

    b0 = (a00^d0);
    b1 = ROL64((a11^d1), 44);
    b2 = ROL64((a22^d2), 43);
    b3 = ROL64((a33^d3), 21);
    b4 = ROL64((a44^d4), 14);
    a00 =   b0 ^((~b1)&  b2 );
    a00 ^= RC[i];
    a11 =   b1 ^((~b2)&  b3 );
    a22 =   b2 ^((~b3)&  b4 );
    a33 =   b3 ^((~b4)&  b0 );
    a44 =   b4 ^((~b0)&  b1 );

    b2 = ROL64((a20^d0), 3);
    b3 = ROL64((a31^d1), 45);
    b4 = ROL64((a42^d2), 61);
    b0 = ROL64((a03^d3), 28);
    b1 = ROL64((a14^d4), 20);
    a20 =   b0 ^((~b1)&  b2 );
    a31 =   b1 ^((~b2)&  b3 );
    a42 =   b2 ^((~b3)&  b4 );
    a03 =   b3 ^((~b4)&  b0 );
    a14 =   b4 ^((~b0)&  b1 );

    b4 = ROL64((a40^d0), 18);
    b0 = ROL64((a01^d1), 1);
    b1 = ROL64((a12^d2), 6);
    b2 = ROL64((a23^d3), 25);
    b3 = ROL64((a34^d4), 8);
    a40 =   b0 ^((~b1)&  b2 );
    a01 =   b1 ^((~b2)&  b3 );
    a12 =   b2 ^((~b3)&  b4 );
    a23 =   b3 ^((~b4)&  b0 );
    a34 =   b4 ^((~b0)&  b1 );

    b1 = ROL64((a10^d0), 36);
    b2 = ROL64((a21^d1), 10);
    b3 = ROL64((a32^d2), 15);
    b4 = ROL64((a43^d3), 56);
    b0 = ROL64((a04^d4), 27);
    a10 =   b0 ^((~b1)&  b2 );
    a21 =   b1 ^((~b2)&  b3 );
    a32 =   b2 ^((~b3)&  b4 );
    a43 =   b3 ^((~b4)&  b0 );
    a04 =   b4 ^((~b0)&  b1 );

    b3 = ROL64((a30^d0), 41);
    b4 = ROL64((a41^d1), 2);
    b0 = ROL64((a02^d2), 62);
    b1 = ROL64((a13^d3), 55);
    b2 = ROL64((a24^d4), 39);
    a30 =   b0 ^((~b1)&  b2 );
    a41 =   b1 ^((~b2)&  b3 );
    a02 =   b2 ^((~b3)&  b4 );
    a13 =   b3 ^((~b4)&  b0 );
    a24 =   b4 ^((~b0)&  b1 );

    c0 = a00^a20^a40^a10^a30;
    c1 = a11^a31^a01^a21^a41;
    c2 = a22^a42^a12^a32^a02;
    c3 = a33^a03^a23^a43^a13;
    c4 = a44^a14^a34^a04^a24;
    d0 = c4^ROL64(c1, 1);
    d1 = c0^ROL64(c2, 1);
    d2 = c1^ROL64(c3, 1);
    d3 = c2^ROL64(c4, 1);
    d4 = c3^ROL64(c0, 1);

    b0 = (a00^d0);
    b1 = ROL64((a31^d1), 44);
    b2 = ROL64((a12^d2), 43);
    b3 = ROL64((a43^d3), 21);
    b4 = ROL64((a24^d4), 14);
    a00 =   b0 ^((~b1)&  b2 );
    a00 ^= RC[i+1];
    a31 =   b1 ^((~b2)&  b3 );
    a12 =   b2 ^((~b3)&  b4 );
    a43 =   b3 ^((~b4)&  b0 );
    a24 =   b4 ^((~b0)&  b1 );

    b2 = ROL64((a40^d0), 3);
    b3 = ROL64((a21^d1), 45);
    b4 = ROL64((a02^d2), 61);
    b0 = ROL64((a33^d3), 28);
    b1 = ROL64((a14^d4), 20);
    a40 =   b0 ^((~b1)&  b2 );
    a21 =   b1 ^((~b2)&  b3 );
    a02 =   b2 ^((~b3)&  b4 );
    a33 =   b3 ^((~b4)&  b0 );
    a14 =   b4 ^((~b0)&  b1 );

    b4 = ROL64((a30^d0), 18);
    b0 = ROL64((a11^d1), 1);
    b1 = ROL64((a42^d2), 6);
    b2 = ROL64((a23^d3), 25);
    b3 = ROL64((a04^d4), 8);
    a30 =   b0 ^((~b1)&  b2 );
    a11 =   b1 ^((~b2)&  b3 );
    a42 =   b2 ^((~b3)&  b4 );
    a23 =   b3 ^((~b4)&  b0 );
    a04 =   b4 ^((~b0)&  b1 );

    b1 = ROL64((a20^d0), 36);
    b2 = ROL64((a01^d1), 10);
    b3 = ROL64((a32^d2), 15);
    b4 = ROL64((a13^d3), 56);
    b0 = ROL64((a44^d4), 27);
    a20 =   b0 ^((~b1)&  b2 );
    a01 =   b1 ^((~b2)&  b3 );
    a32 =   b2 ^((~b3)&  b4 );
    a13 =   b3 ^((~b4)&  b0 );
    a44 =   b4 ^((~b0)&  b1 );

    b3 = ROL64((a10^d0), 41);
    b4 = ROL64((a41^d1), 2);
    b0 = ROL64((a22^d2), 62);
    b1 = ROL64((a03^d3), 55);
    b2 = ROL64((a34^d4), 39);
    a10 =   b0 ^((~b1)&  b2 );
    a41 =   b1 ^((~b2)&  b3 );
    a22 =   b2 ^((~b3)&  b4 );
    a03 =   b3 ^((~b4)&  b0 );
    a34 =   b4 ^((~b0)&  b1 );

    c0 = a00^a40^a30^a20^a10;
    c1 = a31^a21^a11^a01^a41;
    c2 = a12^a02^a42^a32^a22;
    c3 = a43^a33^a23^a13^a03;
    c4 = a24^a14^a04^a44^a34;
    d0 = c4^ROL64(c1, 1);
    d1 = c0^ROL64(c2, 1);
    d2 = c1^ROL64(c3, 1);
    d3 = c2^ROL64(c4, 1);
    d4 = c3^ROL64(c0, 1);

    b0 = (a00^d0);
    b1 = ROL64((a21^d1), 44);
    b2 = ROL64((a42^d2), 43);
    b3 = ROL64((a13^d3), 21);
    b4 = ROL64((a34^d4), 14);
    a00 =   b0 ^((~b1)&  b2 );
    a00 ^= RC[i+2];
    a21 =   b1 ^((~b2)&  b3 );
    a42 =   b2 ^((~b3)&  b4 );
    a13 =   b3 ^((~b4)&  b0 );
    a34 =   b4 ^((~b0)&  b1 );

    b2 = ROL64((a30^d0), 3);
    b3 = ROL64((a01^d1), 45);
    b4 = ROL64((a22^d2), 61);
    b0 = ROL64((a43^d3), 28);
    b1 = ROL64((a14^d4), 20);
    a30 =   b0 ^((~b1)&  b2 );
    a01 =   b1 ^((~b2)&  b3 );
    a22 =   b2 ^((~b3)&  b4 );
    a43 =   b3 ^((~b4)&  b0 );
    a14 =   b4 ^((~b0)&  b1 );

    b4 = ROL64((a10^d0), 18);
    b0 = ROL64((a31^d1), 1);
    b1 = ROL64((a02^d2), 6);
    b2 = ROL64((a23^d3), 25);
    b3 = ROL64((a44^d4), 8);
    a10 =   b0 ^((~b1)&  b2 );
    a31 =   b1 ^((~b2)&  b3 );
    a02 =   b2 ^((~b3)&  b4 );
    a23 =   b3 ^((~b4)&  b0 );
    a44 =   b4 ^((~b0)&  b1 );

    b1 = ROL64((a40^d0), 36);
    b2 = ROL64((a11^d1), 10);
    b3 = ROL64((a32^d2), 15);
    b4 = ROL64((a03^d3), 56);
    b0 = ROL64((a24^d4), 27);
    a40 =   b0 ^((~b1)&  b2 );
    a11 =   b1 ^((~b2)&  b3 );
    a32 =   b2 ^((~b3)&  b4 );
    a03 =   b3 ^((~b4)&  b0 );
    a24 =   b4 ^((~b0)&  b1 );

    b3 = ROL64((a20^d0), 41);
    b4 = ROL64((a41^d1), 2);
    b0 = ROL64((a12^d2), 62);
    b1 = ROL64((a33^d3), 55);
    b2 = ROL64((a04^d4), 39);
    a20 =   b0 ^((~b1)&  b2 );
    a41 =   b1 ^((~b2)&  b3 );
    a12 =   b2 ^((~b3)&  b4 );
    a33 =   b3 ^((~b4)&  b0 );
    a04 =   b4 ^((~b0)&  b1 );

    c0 = a00^a30^a10^a40^a20;
    c1 = a21^a01^a31^a11^a41;
    c2 = a42^a22^a02^a32^a12;
    c3 = a13^a43^a23^a03^a33;
    c4 = a34^a14^a44^a24^a04;
    d0 = c4^ROL64(c1, 1);
    d1 = c0^ROL64(c2, 1);
    d2 = c1^ROL64(c3, 1);
    d3 = c2^ROL64(c4, 1);
    d4 = c3^ROL64(c0, 1);

    b0 = (a00^d0);
    b1 = ROL64((a01^d1), 44);
    b2 = ROL64((a02^d2), 43);
    b3 = ROL64((a03^d3), 21);
    b4 = ROL64((a04^d4), 14);
    a00 =   b0 ^((~b1)&  b2 );
    a00 ^= RC[i+3];
    a01 =   b1 ^((~b2)&  b3 );
    a02 =   b2 ^((~b3)&  b4 );
    a03 =   b3 ^((~b4)&  b0 );
    a04 =   b4 ^((~b0)&  b1 );

    b2 = ROL64((a10^d0), 3);
    b3 = ROL64((a11^d1), 45);
    b4 = ROL64((a12^d2), 61);
    b0 = ROL64((a13^d3), 28);
    b1 = ROL64((a14^d4), 20);
    a10 =   b0 ^((~b1)&  b2 );
    a11 =   b1 ^((~b2)&  b3 );
    a12 =   b2 ^((~b3)&  b4 );
    a13 =   b3 ^((~b4)&  b0 );
    a14 =   b4 ^((~b0)&  b1 );

    b4 = ROL64((a20^d0), 18);
    b0 = ROL64((a21^d1), 1);
    b1 = ROL64((a22^d2), 6);
    b2 = ROL64((a23^d3), 25);
    b3 = ROL64((a24^d4), 8);
    a20 =   b0 ^((~b1)&  b2 );
    a21 =   b1 ^((~b2)&  b3 );
    a22 =   b2 ^((~b3)&  b4 );
    a23 =   b3 ^((~b4)&  b0 );
    a24 =   b4 ^((~b0)&  b1 );

    b1 = ROL64((a30^d0), 36);
    b2 = ROL64((a31^d1), 10);
    b3 = ROL64((a32^d2), 15);
    b4 = ROL64((a33^d3), 56);
    b0 = ROL64((a34^d4), 27);
    a30 =   b0 ^((~b1)&  b2 );
    a31 =   b1 ^((~b2)&  b3 );
    a32 =   b2 ^((~b3)&  b4 );
    a33 =   b3 ^((~b4)&  b0 );
    a34 =   b4 ^((~b0)&  b1 );

    b3 = ROL64((a40^d0), 41);
    b4 = ROL64((a41^d1), 2);
    b0 = ROL64((a42^d2), 62);
    b1 = ROL64((a43^d3), 55);
    b2 = ROL64((a44^d4), 39);
    a40 =   b0 ^((~b1)&  b2 );
    a41 =   b1 ^((~b2)&  b3 );
    a42 =   b2 ^((~b3)&  b4 );
    a43 =   b3 ^((~b4)&  b0 );
    a44 =   b4 ^((~b0)&  b1 );
  }
}

/*
** Initialize a new hash.  iSize determines the size of the hash
** in bits and should be one of 224, 256, 384, or 512.  Or iSize
** can be zero to use the default hash size of 256 bits.
*/

static void SHA3Init(SHA3Context *p, int iSize){
  memset(p, 0, sizeof(*p));
  p->iSize = iSize;
  if( iSize>=128 && iSize<=512 ){
    p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
  }else{
    p->nRate = (1600 - 2*256)/8;
  }
#if SHA3_BYTEORDER==1234
  /* Known to be little-endian at compile-time. No-op */
#elif SHA3_BYTEORDER==4321
  p->ixMask = 7;  /* Big-endian */
#else
  {
    static unsigned int one = 1;
    if( 1==*(unsigned char*)&one ){
      /* Little endian.  No byte swapping. */
      p->ixMask = 0;
    }else{
      /* Big endian.  Byte swap. */
      p->ixMask = 7;
    }
  }
#endif
}

/*
** Make consecutive calls to the SHA3Update function to add new content
** to the hash
*/

static void SHA3Update(
  SHA3Context *p,
  const unsigned char *aData,
  unsigned int nData
){
  unsigned int i = 0;
  if( aData==0 ) return;
#if SHA3_BYTEORDER==1234
  if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
    for(; i+7<nData; i+=8){
      p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
      p->nLoaded += 8;
      if( p->nLoaded>=p->nRate ){
        KeccakF1600Step(p);
        p->nLoaded = 0;
      }
    }
  }
#endif
  for(; i<nData; i++){
#if SHA3_BYTEORDER==1234
    p->u.x[p->nLoaded] ^= aData[i];
#elif SHA3_BYTEORDER==4321
    p->u.x[p->nLoaded^0x07] ^= aData[i];
#else
    p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
#endif
    p->nLoaded++;
    if( p->nLoaded==p->nRate ){
      KeccakF1600Step(p);
      p->nLoaded = 0;
    }
  }
}

/*
** After all content has been added, invoke SHA3Final() to compute
** the final hash.  The function returns a pointer to the binary
** hash value.
*/

static unsigned char *SHA3Final(SHA3Context *p){
  unsigned int i;
  if( p->nLoaded==p->nRate-1 ){
    const unsigned char c1 = 0x86;
    SHA3Update(p, &c1, 1);
  }else{
    const unsigned char c2 = 0x06;
    const unsigned char c3 = 0x80;
    SHA3Update(p, &c2, 1);
    p->nLoaded = p->nRate - 1;
    SHA3Update(p, &c3, 1);
  }
  for(i=0; i<p->nRate; i++){
    p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
  }
  return &p->u.x[p->nRate];
}
/* End of the hashing logic
*****************************************************************************/


/*
** Implementation of the sha3(X,SIZE) function.
**
** Return a BLOB which is the SIZE-bit SHA3 hash of X.  The default
** size is 256.  If X is a BLOB, it is hashed as is.  
** For all other non-NULL types of input, X is converted into a UTF-8 string
** and the string is hashed without the trailing 0x00 terminator.  The hash
** of a NULL value is NULL.
*/

static void sha3Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  SHA3Context cx;
  int eType = sqlite3_value_type(argv[0]);
  int nByte = sqlite3_value_bytes(argv[0]);
  int iSize;
  if( argc==1 ){
    iSize = 256;
  }else{
    iSize = sqlite3_value_int(argv[1]);
    if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
      sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
                                    "384 512", -1);
      return;
    }
  }
  if( eType==SQLITE_NULL ) return;
  SHA3Init(&cx, iSize);
  if( eType==SQLITE_BLOB ){
    SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
  }else{
    SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
  }
  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
}

/* Compute a string using sqlite3_vsnprintf() with a maximum length
** of 50 bytes and add it to the hash.
*/

static void sha3_step_vformat(
  SHA3Context *p,                 /* Add content to this context */
  const char *zFormat,
  ...
){
  va_list ap;
  int n;
  char zBuf[50];
  va_start(ap, zFormat);
  sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
  va_end(ap);
  n = (int)strlen(zBuf);
  SHA3Update(p, (unsigned char*)zBuf, n);
}

/*
** Update a SHA3Context using a single sqlite3_value.
*/

static void sha3UpdateFromValue(SHA3Context *p, sqlite3_value *pVal){
  switch( sqlite3_value_type(pVal) ){
    case SQLITE_NULL: {
      SHA3Update(p, (const unsigned char*)"N",1);
      break;
    }
    case SQLITE_INTEGER: {
      sqlite3_uint64 u;
      int j;
      unsigned char x[9];
      sqlite3_int64 v = sqlite3_value_int64(pVal);
      memcpy(&u, &v, 8);
      for(j=8; j>=1; j--){
        x[j] = u & 0xff;
        u >>= 8;
      }
      x[0] = 'I';
      SHA3Update(p, x, 9);
      break;
    }
    case SQLITE_FLOAT: {
      sqlite3_uint64 u;
      int j;
      unsigned char x[9];
      double r = sqlite3_value_double(pVal);
      memcpy(&u, &r, 8);
      for(j=8; j>=1; j--){
        x[j] = u & 0xff;
        u >>= 8;
      }
      x[0] = 'F';
      SHA3Update(p,x,9);
      break;
    }
    case SQLITE_TEXT: {
      int n2 = sqlite3_value_bytes(pVal);
      const unsigned char *z2 = sqlite3_value_text(pVal);
      sha3_step_vformat(p,"T%d:",n2);
      SHA3Update(p, z2, n2);
      break;
    }
    case SQLITE_BLOB: {
      int n2 = sqlite3_value_bytes(pVal);
      const unsigned char *z2 = sqlite3_value_blob(pVal);
      sha3_step_vformat(p,"B%d:",n2);
      SHA3Update(p, z2, n2);
      break;
    }
  }
}

/*
** Implementation of the sha3_query(SQL,SIZE) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using a SIZE-bit SHA3.  The default
** size is 256.
**
** The format of the byte stream that is hashed is summarized as follows:
**
**       S<n>:<sql>
**       R
**       N
**       I<int>
**       F<ieee-float>
**       B<size>:<bytes>
**       T<size>:<text>
**
** <sql> is the original SQL text for each statement run and <n> is
** the size of that text.  The SQL text is UTF-8.  A single R character
** occurs before the start of each row.  N means a NULL value.
** I mean an 8-byte little-endian integer <int>.  F is a floating point
** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
** B means blobs of <size> bytes.  T means text rendered as <size>
** bytes of UTF-8.  The <n> and <size> values are expressed as an ASCII
** text integers.
**
** For each SQL statement in the X input, there is one S segment.  Each
** S segment is followed by zero or more R segments, one for each row in the
** result set.  After each R, there are one or more N, I, F, B, or T segments,
** one for each column in the result set.  Segments are concatentated directly
** with no delimiters of any kind.
*/

static void sha3QueryFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  sqlite3_stmt *pStmt = 0;
  int nCol;                   /* Number of columns in the result set */
  int i;                      /* Loop counter */
  int rc;
  int n;
  const char *z;
  SHA3Context cx;
  int iSize;

  if( argc==1 ){
    iSize = 256;
  }else{
    iSize = sqlite3_value_int(argv[1]);
    if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
      sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
                                    "384 512", -1);
      return;
    }
  }
  if( zSql==0 ) return;
  SHA3Init(&cx, iSize);
  while( zSql[0] ){
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
    if( rc ){
      char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
                                   zSql, sqlite3_errmsg(db));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    if( !sqlite3_stmt_readonly(pStmt) ){
      char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    nCol = sqlite3_column_count(pStmt);
    z = sqlite3_sql(pStmt);
    if( z ){
      n = (int)strlen(z);
      sha3_step_vformat(&cx,"S%d:",n);
      SHA3Update(&cx,(unsigned char*)z,n);
    }

    /* Compute a hash over the result of the query */
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      SHA3Update(&cx,(const unsigned char*)"R",1);
      for(i=0; i<nCol; i++){
        sha3UpdateFromValue(&cx, sqlite3_column_value(pStmt,i));
      }
    }
    sqlite3_finalize(pStmt);
  }
  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
}

/*
** xStep function for sha3_agg().
*/

static void sha3AggStep(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  SHA3Context *p;
  p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 ) return;
  if( p->nRate==0 ){
    int sz = 256;
    if( argc==2 ){
      sz = sqlite3_value_int(argv[1]);
      if( sz!=224 && sz!=384 && sz!=512 ){
        sz = 256;
      }
    }
    SHA3Init(p, sz);
  }
  sha3UpdateFromValue(p, argv[0]);
}


/*
** xFinal function for sha3_agg().
*/

static void sha3AggFinal(sqlite3_context *context){
  SHA3Context *p;
  p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 ) return;
  if( p->iSize ){
    sqlite3_result_blob(context, SHA3Final(p), p->iSize/8, SQLITE_TRANSIENT);
  }
}



#ifdef _WIN32

#endif
int sqlite3_shathree_init(
  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sha3", 1,
                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                      0, sha3Func, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3", 2,
                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                      0, sha3Func, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_agg", 1,
                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                      0, 0, sha3AggStep, sha3AggFinal);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_agg", 2,
                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                      0, 0, sha3AggStep, sha3AggFinal);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_query", 1,
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                      0, sha3QueryFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_query", 2,
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                      0, sha3QueryFunc, 0, 0);
  }
  return rc;
}

/************************* End ext/misc/shathree.c ********************/
/************************* Begin ext/misc/sha1.c ******************/
/*
** 2017-01-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 SQLite extension implements functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
**     sha1(X)
**     sha1_query(Y)
**
** The sha1(X) function computes the SHA1 hash of the input X, or NULL if
** X is NULL.
**
** The sha1_query(Y) function evalutes all queries in the SQL statements of Y
** and returns a hash of their results.
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>

/******************************************************************************
** The Hash Engine
*/

/* Context for the SHA1 hash */
typedef struct SHA1Context SHA1Context;
struct SHA1Context {
  unsigned int state[5];
  unsigned int count[2];
  unsigned char buffer[64];
};

#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)

#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
    |(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
    ^block[(i+2)&15]^block[i&15],1))

/*
 * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
 *
 * Rl0() for little-endian and Rb0() for big-endian.  Endianness is
 * determined at run-time.
 */

#define Rl0(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
    z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
    z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
    z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);

/*
 * Hash a single 512-bit block. This is the core of the algorithm.
 */

static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
  unsigned int qq[5]; /* a, b, c, d, e; */
  static int one = 1;
  unsigned int block[16];
  memcpy(block, buffer, 64);
  memcpy(qq,state,5*sizeof(unsigned int));

#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]

  /* Copy p->state[] to working vars */
  /*
  a = state[0];
  b = state[1];
  c = state[2];
  d = state[3];
  e = state[4];
  */


  /* 4 rounds of 20 operations each. Loop unrolled. */
  if( 1 == *(unsigned char*)&one ){
    Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
    Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
    Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
    Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
  }else{
    Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
    Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
    Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
    Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
  }
  R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
  R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
  R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
  R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
  R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
  R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
  R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
  R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
  R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
  R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
  R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
  R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
  R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
  R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
  R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
  R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);

  /* Add the working vars back into context.state[] */
  state[0] += a;
  state[1] += b;
  state[2] += c;
  state[3] += d;
  state[4] += e;

#undef a
#undef b
#undef c
#undef d
#undef e
}


/* Initialize a SHA1 context */
static void hash_init(SHA1Context *p){
  /* SHA1 initialization constants */
  p->state[0] = 0x67452301;
  p->state[1] = 0xEFCDAB89;
  p->state[2] = 0x98BADCFE;
  p->state[3] = 0x10325476;
  p->state[4] = 0xC3D2E1F0;
  p->count[0] = p->count[1] = 0;
}

/* Add new content to the SHA1 hash */
static void hash_step(
  SHA1Context *p,                 /* Add content to this context */
  const unsigned char *data,      /* Data to be added */
  unsigned int len                /* Number of bytes in data */
){
  unsigned int i, j;

  j = p->count[0];
  if( (p->count[0] += len << 3) < j ){
    p->count[1] += (len>>29)+1;
  }
  j = (j >> 3) & 63;
  if( (j + len) > 63 ){
    (void)memcpy(&p->buffer[j], data, (i = 64-j));
    SHA1Transform(p->state, p->buffer);
    for(; i + 63 < len; i += 64){
      SHA1Transform(p->state, &data[i]);
    }
    j = 0;
  }else{
    i = 0;
  }
  (void)memcpy(&p->buffer[j], &data[i], len - i);
}

/* Compute a string using sqlite3_vsnprintf() and hash it */
static void hash_step_vformat(
  SHA1Context *p,                 /* Add content to this context */
  const char *zFormat,
  ...
){
  va_list ap;
  int n;
  char zBuf[50];
  va_start(ap, zFormat);
  sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
  va_end(ap);
  n = (int)strlen(zBuf);
  hash_step(p, (unsigned char*)zBuf, n);
}


/* Add padding and compute the message digest.  Render the
** message digest as lower-case hexadecimal and put it into
** zOut[].  zOut[] must be at least 41 bytes long. */

static void hash_finish(
  SHA1Context *p,           /* The SHA1 context to finish and render */
  char *zOut,               /* Store hex or binary hash here */
  int bAsBinary             /* 1 for binary hash, 0 for hex hash */
){
  unsigned int i;
  unsigned char finalcount[8];
  unsigned char digest[20];
  static const char zEncode[] = "0123456789abcdef";

  for (i = 0; i < 8; i++){
    finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
       >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
  }
  hash_step(p, (const unsigned char *)"\200", 1);
  while ((p->count[0] & 504) != 448){
    hash_step(p, (const unsigned char *)"\0", 1);
  }
  hash_step(p, finalcount, 8);  /* Should cause a SHA1Transform() */
  for (i = 0; i < 20; i++){
    digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
  }
  if( bAsBinary ){
    memcpy(zOut, digest, 20);
  }else{
    for(i=0; i<20; i++){
      zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
      zOut[i*2+1] = zEncode[digest[i] & 0xf];
    }
    zOut[i*2]= 0;
  }
}
/* End of the hashing logic
*****************************************************************************/


/*
** Two SQL functions:  sha1(X) and sha1b(X).
**
** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash
** of the argument X.  If X is a BLOB, it is hashed as is.  For all other
** types of input, X is converted into a UTF-8 string and the string
** is hashed without the trailing 0x00 terminator.  The hash of a NULL
** value is NULL.
**
** sha1b(X) is the same except that it returns a 20-byte BLOB containing
** the binary hash instead of a hexadecimal string.
*/

static void sha1Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  SHA1Context cx;
  int eType = sqlite3_value_type(argv[0]);
  int nByte = sqlite3_value_bytes(argv[0]);
  const unsigned char *pData;
  char zOut[44];

  assert( argc==1 );
  if( eType==SQLITE_NULL ) return;
  hash_init(&cx);
  if( eType==SQLITE_BLOB ){
    pData = (const unsigned char*)sqlite3_value_blob(argv[0]);
  }else{
    pData = (const unsigned char*)sqlite3_value_text(argv[0]);
  }
  if( pData==0 ) return;
  hash_step(&cx, pData, nByte);
  if( sqlite3_user_data(context)!=0 ){
    /* sha1b() - binary result */
    hash_finish(&cx, zOut, 1);
    sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
  }else{
    /* sha1() - hexadecimal text result */
    hash_finish(&cx, zOut, 0);
    sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
  }
}

/*
** Implementation of the sha1_query(SQL) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using SHA1 and that hash is returned.
**
** The original SQL text is included as part of the hash.
**
** The hash is not just a concatenation of the outputs.  Each query
** is delimited and each row and value within the query is delimited,
** with all values being marked with their datatypes.
*/

static void sha1QueryFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  sqlite3_stmt *pStmt = 0;
  int nCol;                   /* Number of columns in the result set */
  int i;                      /* Loop counter */
  int rc;
  int n;
  const char *z;
  SHA1Context cx;
  char zOut[44];

  assert( argc==1 );
  if( zSql==0 ) return;
  hash_init(&cx);
  while( zSql[0] ){
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
    if( rc ){
      char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
                                   zSql, sqlite3_errmsg(db));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    if( !sqlite3_stmt_readonly(pStmt) ){
      char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    nCol = sqlite3_column_count(pStmt);
    z = sqlite3_sql(pStmt);
    if( z==0 ) z = "";
    n = (int)strlen(z);
    hash_step_vformat(&cx,"S%d:",n);
    hash_step(&cx,(unsigned char*)z,n);

    /* Compute a hash over the result of the query */
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      hash_step(&cx,(const unsigned char*)"R",1);
      for(i=0; i<nCol; i++){
        switch( sqlite3_column_type(pStmt,i) ){
          case SQLITE_NULL: {
            hash_step(&cx, (const unsigned char*)"N",1);
            break;
          }
          case SQLITE_INTEGER: {
            sqlite3_uint64 u;
            int j;
            unsigned char x[9];
            sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
            memcpy(&u, &v, 8);
            for(j=8; j>=1; j--){
              x[j] = u & 0xff;
              u >>= 8;
            }
            x[0] = 'I';
            hash_step(&cx, x, 9);
            break;
          }
          case SQLITE_FLOAT: {
            sqlite3_uint64 u;
            int j;
            unsigned char x[9];
            double r = sqlite3_column_double(pStmt,i);
            memcpy(&u, &r, 8);
            for(j=8; j>=1; j--){
              x[j] = u & 0xff;
              u >>= 8;
            }
            x[0] = 'F';
            hash_step(&cx,x,9);
            break;
          }
          case SQLITE_TEXT: {
            int n2 = sqlite3_column_bytes(pStmt, i);
            const unsigned char *z2 = sqlite3_column_text(pStmt, i);
            hash_step_vformat(&cx,"T%d:",n2);
            hash_step(&cx, z2, n2);
            break;
          }
          case SQLITE_BLOB: {
            int n2 = sqlite3_column_bytes(pStmt, i);
            const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
            hash_step_vformat(&cx,"B%d:",n2);
            hash_step(&cx, z2, n2);
            break;
          }
        }
      }
    }
    sqlite3_finalize(pStmt);
  }
  hash_finish(&cx, zOut, 0);
  sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}


#ifdef _WIN32

#endif
int sqlite3_sha_init(
  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  static int one = 1;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sha1", 1, 
                       SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                                0, sha1Func, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha1b", 1, 
                       SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                          (void*)&one, sha1Func, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha1_query", 1, 
                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                 sha1QueryFunc, 0, 0);
  }
  return rc;
}

/************************* End ext/misc/sha1.c ********************/
/************************* Begin ext/misc/uint.c ******************/
/*
** 2020-04-14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This SQLite extension implements the UINT collating sequence.
**
** UINT works like BINARY for text, except that embedded strings
** of digits compare in numeric order.
**
**     *   Leading zeros are handled properly, in the sense that
**         they do not mess of the magnitude comparison of embedded
**         strings of digits.  "x00123y" is equal to "x123y".
**
**     *   Only unsigned integers are recognized.  Plus and minus
**         signs are ignored.  Decimal points and exponential notation
**         are ignored.
**
**     *   Embedded integers can be of arbitrary length.  Comparison
**         is *not* limited integers that can be expressed as a
**         64-bit machine integer.
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>

/*
** Compare text in lexicographic order, except strings of digits
** compare in numeric order.
*/

static int uintCollFunc(
  void *notUsed,
  int nKey1, const void *pKey1,
  int nKey2, const void *pKey2
){
  const unsigned char *zA = (const unsigned char*)pKey1;
  const unsigned char *zB = (const unsigned char*)pKey2;
  int i=0, j=0, x;
  (void)notUsed;
  while( i<nKey1 && j<nKey2 ){
    x = zA[i] - zB[j];
    if( isdigit(zA[i]) ){
      int k;
      if( !isdigit(zB[j]) ) return x;
      while( i<nKey1 && zA[i]=='0' ){ i++; }
      while( j<nKey2 && zB[j]=='0' ){ j++; }
      k = 0;
      while( i+k<nKey1 && isdigit(zA[i+k])
             && j+k<nKey2 && isdigit(zB[j+k]) ){
        k++;
      }
      if( i+k<nKey1 && isdigit(zA[i+k]) ){
        return +1;
      }else if( j+k<nKey2 && isdigit(zB[j+k]) ){
        return -1;
      }else{
        x = memcmp(zA+i, zB+j, k);
        if( x ) return x;
        i += k;
        j += k;
      }
    }else if( x ){
      return x;
    }else{
      i++;
      j++;
    }
  }
  return (nKey1 - i) - (nKey2 - j);
}

#ifdef _WIN32

#endif
int sqlite3_uint_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc);
}

/************************* End ext/misc/uint.c ********************/
/************************* Begin ext/misc/decimal.c ******************/
/*
** 2020-06-22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** Routines to implement arbitrary-precision decimal math.
**
** The focus here is on simplicity and correctness, not performance.
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */

#ifndef UNUSED_PARAMETER
# define UNUSED_PARAMETER(X)  (void)(X)
#endif

#ifndef IsSpace
#define IsSpace(X)  isspace((unsigned char)X)
#endif

#ifndef SQLITE_DECIMAL_MAX_DIGIT
# define SQLITE_DECIMAL_MAX_DIGIT 10000000
#endif

/* A decimal object */
typedef struct Decimal Decimal;
struct Decimal {
  char sign;        /* 0 for positive, 1 for negative */
  char oom;         /* True if an OOM is encountered */
  char isNull;      /* True if holds a NULL rather than a number */
  char isInit;      /* True upon initialization */
  int nDigit;       /* Total number of digits */
  int nFrac;        /* Number of digits to the right of the decimal point */
  signed char *a;   /* Array of digits.  Most significant first. */
};

/*
** Release memory held by a Decimal, but do not free the object itself.
*/

static void decimal_clear(Decimal *p){
  sqlite3_free(p->a);
}

/*
** Destroy a Decimal object
*/

static void decimal_free(Decimal *p){
  if( p ){
    decimal_clear(p);
    sqlite3_free(p);
  }
}

/*
** Allocate a new Decimal object initialized to the text in zIn[].
** Return NULL if any kind of error occurs.
*/

static Decimal *decimalNewFromText(const char *zIn, int n){
  Decimal *p = 0;
  int i;
  int iExp = 0;

  if( zIn==0 ) goto new_from_text_failed;
  p = sqlite3_malloc64( sizeof(*p) );
  if( p==0 ) goto new_from_text_failed;
  p->sign = 0;
  p->oom = 0;
  p->isInit = 1;
  p->isNull = 0;
  p->nDigit = 0;
  p->nFrac = 0;
  p->a = sqlite3_malloc64( n+1 );
  if( p->a==0 ) goto new_from_text_failed;
  for(i=0; IsSpace(zIn[i]); i++){}
  if( zIn[i]=='-' ){
    p->sign = 1;
    i++;
  }else if( zIn[i]=='+' ){
    i++;
  }
  while( i<n && zIn[i]=='0' ) i++;
  while( i<n ){
    char c = zIn[i];
    if( c>='0' && c<='9' ){
      p->a[p->nDigit++] = c - '0';
    }else if( c=='.' ){
      p->nFrac = p->nDigit + 1;
    }else if( c=='e' || c=='E' ){
      int j = i+1;
      int neg = 0;
      if( j>=n ) break;
      if( zIn[j]=='-' ){
        neg = 1;
        j++;
      }else if( zIn[j]=='+' ){
        j++;
      }
      while( j<n && iExp<1000000 ){
        if( zIn[j]>='0' && zIn[j]<='9' ){
          iExp = iExp*10 + zIn[j] - '0';
        }
        j++;
      }
      if( neg ) iExp = -iExp;
      break;
    }
    i++;
  }
  if( p->nFrac ){
    p->nFrac = p->nDigit - (p->nFrac - 1);
  }
  if( iExp>0 ){
    if( p->nFrac>0 ){
      if( iExp<=p->nFrac ){
        p->nFrac -= iExp;
        iExp = 0;
      }else{
        iExp -= p->nFrac;
        p->nFrac = 0;
      }
    }
    if( iExp>0 ){   
      signed char *a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit
                                     + (sqlite3_int64)iExp + 1 );
      if( a==0 ) goto new_from_text_failed;
      p->a = a;
      memset(p->a+p->nDigit, 0, iExp);
      p->nDigit += iExp;
    }
  }else if( iExp<0 ){
    int nExtra;
    iExp = -iExp;
    nExtra = p->nDigit - p->nFrac - 1;
    if( nExtra ){
      if( nExtra>=iExp ){
        p->nFrac += iExp;
        iExp  = 0;
      }else{
        iExp -= nExtra;
        p->nFrac = p->nDigit - 1;
      }
    }
    if( iExp>0 ){
      signed char *a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit
                                     + (sqlite3_int64)iExp + 1 );
      if( a==0 ) goto new_from_text_failed;
      p->a = a;
      memmove(p->a+iExp, p->a, p->nDigit);
      memset(p->a, 0, iExp);
      p->nDigit += iExp;
      p->nFrac += iExp;
    }
  }
  if( p->sign ){
    for(i=0; i<p->nDigit && p->a[i]==0; i++){}
    if( i>=p->nDigit ) p->sign = 0;
  }
  if( p->nDigit>SQLITE_DECIMAL_MAX_DIGIT ) goto new_from_text_failed;
  return p;

new_from_text_failed:
  if( p ){
    if( p->a ) sqlite3_free(p->a);
    sqlite3_free(p);
  }
  return 0;
}

/* Forward reference */
static Decimal *decimalFromDouble(double);

/*
** Allocate a new Decimal object from an sqlite3_value.  Return a pointer
** to the new object, or NULL if there is an error.  If the pCtx argument
** is not NULL, then errors are reported on it as well.
**
** If the pIn argument is SQLITE_TEXT or SQLITE_INTEGER, it is converted
** directly into a Decimal.  For SQLITE_FLOAT or for SQLITE_BLOB of length
** 8 bytes, the resulting double value is expanded into its decimal equivalent.
** If pIn is NULL or if it is a BLOB that is not exactly 8 bytes in length,
** then NULL is returned.
*/

static Decimal *decimal_new(
  sqlite3_context *pCtx,       /* Report error here, if not null */
  sqlite3_value *pIn,          /* Construct the decimal object from this */
  int bTextOnly                /* Always interpret pIn as text if true */
){
  Decimal *p = 0;
  int eType = sqlite3_value_type(pIn);
  if( bTextOnly && (eType==SQLITE_FLOAT || eType==SQLITE_BLOB) ){
    eType = SQLITE_TEXT;
  }
  switch( eType ){
    case SQLITE_TEXT:
    case SQLITE_INTEGER: {
      const char *zIn = (const char*)sqlite3_value_text(pIn);
      int n = sqlite3_value_bytes(pIn);
      p = decimalNewFromText(zIn, n);
      if( p==0 ) goto new_failed;
      break;
    }

    case SQLITE_FLOAT: {
      p = decimalFromDouble(sqlite3_value_double(pIn));
      break;
    }

    case SQLITE_BLOB: {
      const unsigned char *x;
      unsigned int i;
      sqlite3_uint64 v = 0;
      double r;

      if( sqlite3_value_bytes(pIn)!=sizeof(r) ) break;
      x = sqlite3_value_blob(pIn);
      for(i=0; i<sizeof(r); i++){
        v = (v<<8) | x[i];
      }
      memcpy(&r, &v, sizeof(r));
      p = decimalFromDouble(r);
      break;
    }

    case SQLITE_NULL: {
      break;
    }
  }
  return p;

new_failed:
  if( pCtx ) sqlite3_result_error_nomem(pCtx);
  sqlite3_free(p);
  return 0;
}

/*
** Make the given Decimal the result.
*/

static void decimal_result(sqlite3_context *pCtx, Decimal *p){
  char *z;
  int i, j;
  int n;
  if( p==0 || p->oom ){
    sqlite3_result_error_nomem(pCtx);
    return;
  }
  if( p->isNull ){
    sqlite3_result_null(pCtx);
    return;
  }
  z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 );
  if( z==0 ){
    sqlite3_result_error_nomem(pCtx);
    return;
  }
  i = 0;
  if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){
    p->sign = 0;
  }
  if( p->sign ){
    z[0] = '-';
    i = 1;
  }
  n = p->nDigit - p->nFrac;
  if( n<=0 ){
    z[i++] = '0';
  }
  j = 0;
  while( n>1 && p->a[j]==0 ){
    j++;
    n--;
  }
  while( n>0  ){
    z[i++] = p->a[j] + '0';
    j++;
    n--;
  }
  if( p->nFrac ){
    z[i++] = '.';
    do{
      z[i++] = p->a[j] + '0';
      j++;
    }while( j<p->nDigit );
  }
  z[i] = 0;
  sqlite3_result_text(pCtx, z, i, sqlite3_free);
}

/*
** Round a decimal value to N significant digits.  N must be positive.
*/

static void decimal_round(Decimal *p, int N){
  int i;
  int nZero;
  if( N<1 ) return;
  if( p==0 ) return;
  if( p->nDigit<=N ) return;
  for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
  N += nZero;
  if( p->nDigit<=N ) return;
  if( p->a[N]>4 ){
    p->a[N-1]++;
    for(i=N-1; i>0 && p->a[i]>9; i--){
      p->a[i] = 0;
      p->a[i-1]++;
    }
    if( p->a[0]>9 ){
      p->a[0] = 1;
      p->nFrac--;
    }
  }
  memset(&p->a[N], 0, p->nDigit - N);
}

/*
** Make the given Decimal the result in an format similar to  '%+#e'.
** In other words, show exponential notation with leading and trailing
** zeros omitted.
*/

static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p, int N){
  char *z;       /* The output buffer */
  int i;         /* Loop counter */
  int nZero;     /* Number of leading zeros */
  int nDigit;    /* Number of digits not counting trailing zeros */
  int nFrac;     /* Digits to the right of the decimal point */
  int exp;       /* Exponent value */
  signed char zero;     /* Zero value */
  signed char *a;       /* Array of digits */

  if( p==0 || p->oom ){
    sqlite3_result_error_nomem(pCtx);
    return;
  }
  if( p->isNull ){
    sqlite3_result_null(pCtx);
    return;
  }
  if( N<1 ) N = 0;
  for(nDigit=p->nDigit; nDigit>N && p->a[nDigit-1]==0; nDigit--){}
  for(nZero=0; nZero<nDigit && p->a[nZero]==0; nZero++){}
  nFrac = p->nFrac + (nDigit - p->nDigit);
  nDigit -= nZero;
  z = sqlite3_malloc64( (sqlite3_int64)nDigit+20 );
  if( z==0 ){
    sqlite3_result_error_nomem(pCtx);
    return;
  }
  if( nDigit==0 ){
    zero = 0;
    a = &zero;
    nDigit = 1;
    nFrac = 0;
  }else{
    a = &p->a[nZero];
  }
  if( p->sign && nDigit>0 ){
    z[0] = '-';
  }else{
    z[0] = '+';
  }
  z[1] = a[0]+'0';
  z[2] = '.';
  if( nDigit==1 ){
    z[3] = '0';
    i = 4;
  }else{
    for(i=1; i<nDigit; i++){
      z[2+i] = a[i]+'0';
    }
    i = nDigit+2;
  }
  exp = nDigit - nFrac - 1;
  sqlite3_snprintf(nDigit+20-i, &z[i], "e%+03d", exp);
  sqlite3_result_text(pCtx, z, -1, sqlite3_free);
}

/*
** Compare to Decimal objects.  Return negative, 0, or positive if the
** first object is less than, equal to, or greater than the second.
**
** Preconditions for this routine:
**
**    pA!=0
**    pA->isNull==0
**    pB!=0
**    pB->isNull==0
*/

static int decimal_cmp(Decimal *pA, Decimal *pB){
  int nASig, nBSig, rc, n;
  while( pA->nFrac>0 && pA->a[pA->nDigit-1]==0 ){
    pA->nDigit--;
    pA->nFrac--;
  }
  while( pB->nFrac>0 && pB->a[pB->nDigit-1]==0 ){
    pB->nDigit--;
    pB->nFrac--;
  }
  if( pA->sign!=pB->sign ){
    return pA->sign ? -1 : +1;
  }
  if( pA->sign ){
    Decimal *pTemp = pA;
    pA = pB;
    pB = pTemp;
  }
  nASig = pA->nDigit - pA->nFrac;
  nBSig = pB->nDigit - pB->nFrac;
  if( nASig!=nBSig ){
    return nASig - nBSig;
  }
  n = pA->nDigit;
  if( n>pB->nDigit ) n = pB->nDigit;
  rc = memcmp(pA->a, pB->a, n);
  if( rc==0 ){
    rc = pA->nDigit - pB->nDigit;
  }
  return rc;
}

/*
** SQL Function:   decimal_cmp(X, Y)
**
** Return negative, zero, or positive if X is less then, equal to, or
** greater than Y.
*/

static void decimalCmpFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = 0, *pB = 0;
  int rc;

  UNUSED_PARAMETER(argc);
  pA = decimal_new(context, argv[0], 1);
  if( pA==0 || pA->isNull ) goto cmp_done;
  pB = decimal_new(context, argv[1], 1);
  if( pB==0 || pB->isNull ) goto cmp_done;
  rc = decimal_cmp(pA, pB);
  if( rc<0 ) rc = -1;
  else if( rc>0 ) rc = +1;
  sqlite3_result_int(context, rc);
cmp_done:
  decimal_free(pA);
  decimal_free(pB);
}

/*
** Expand the Decimal so that it has a least nDigit digits and nFrac
** digits to the right of the decimal point.
*/

static void decimal_expand(Decimal *p, int nDigit, int nFrac){
  int nAddSig;
  int nAddFrac;
  signed char *a;
  if( p==0 ) return;
  nAddFrac = nFrac - p->nFrac;
  nAddSig = (nDigit - p->nDigit) - nAddFrac;
  if( nAddFrac==0 && nAddSig==0 ) return;
  if( nDigit+1>SQLITE_DECIMAL_MAX_DIGIT ){ p->oom = 1; return; }
  a = sqlite3_realloc64(p->a, nDigit+1);
  if( a==0 ){
    p->oom = 1;
    return;
  }
  p->a = a;
  if( nAddSig ){
    memmove(p->a+nAddSig, p->a, p->nDigit);
    memset(p->a, 0, nAddSig);
    p->nDigit += nAddSig;
  }
  if( nAddFrac ){
    memset(p->a+p->nDigit, 0, nAddFrac);
    p->nDigit += nAddFrac;
    p->nFrac += nAddFrac;
  }
}

/*
** Add the value pB into pA.   A := A + B.
**
** Both pA and pB might become denormalized by this routine.
*/

static void decimal_add(Decimal *pA, Decimal *pB){
  int nSig, nFrac, nDigit;
  int i, rc;
  if( pA==0 ){
    return;
  }
  if( pA->oom || pB==0 || pB->oom ){
    pA->oom = 1;
    return;
  }
  if( pA->isNull || pB->isNull ){
    pA->isNull = 1;
    return;
  }
  nSig = pA->nDigit - pA->nFrac;
  if( nSig && pA->a[0]==0 ) nSig--;
  if( nSig<pB->nDigit-pB->nFrac ){
    nSig = pB->nDigit - pB->nFrac;
  }
  nFrac = pA->nFrac;
  if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
  nDigit = nSig + nFrac + 1;
  decimal_expand(pA, nDigit, nFrac);
  decimal_expand(pB, nDigit, nFrac);
  if( pA->oom || pB->oom ){
    pA->oom = 1;
  }else{
    if( pA->sign==pB->sign ){
      int carry = 0;
      for(i=nDigit-1; i>=0; i--){
        int x = pA->a[i] + pB->a[i] + carry;
        if( x>=10 ){
          carry = 1;
          pA->a[i] = x - 10;
        }else{
          carry = 0;
          pA->a[i] = x;
        }
      }
    }else{
      signed char *aA, *aB;
      int borrow = 0;
      rc = memcmp(pA->a, pB->a, nDigit);
      if( rc<0 ){
        aA = pB->a;
        aB = pA->a;
        pA->sign = !pA->sign;
      }else{
        aA = pA->a;
        aB = pB->a;
      }
      for(i=nDigit-1; i>=0; i--){
        int x = aA[i] - aB[i] - borrow;
        if( x<0 ){
          pA->a[i] = x+10;
          borrow = 1;
        }else{
          pA->a[i] = x;
          borrow = 0;
        }
      }
    }
  }
}

/*
** Multiply A by B.   A := A * B
**
** All significant digits after the decimal point are retained.
** Trailing zeros after the decimal point are omitted as long as
** the number of digits after the decimal point is no less than
** either the number of digits in either input.
*/

static void decimalMul(Decimal *pA, Decimal *pB){
  signed char *acc = 0;
  int i, j, k;
  int minFrac;
  sqlite3_int64 sumDigit;

  if( pA==0 || pA->oom || pA->isNull
   || pB==0 || pB->oom || pB->isNull 
  ){
    goto mul_end;
  }
  sumDigit = pA->nDigit;
  sumDigit += pB->nDigit;
  sumDigit += 2;
  if( sumDigit>SQLITE_DECIMAL_MAX_DIGIT ){ pA->oom = 1; return; }
  acc = sqlite3_malloc64( sumDigit );
  if( acc==0 ){
    pA->oom = 1;
    goto mul_end;
  }
  memset(acc, 0, pA->nDigit + pB->nDigit + 2);
  minFrac = pA->nFrac;
  if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
  for(i=pA->nDigit-1; i>=0; i--){
    signed char f = pA->a[i];
    int carry = 0, x;
    for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
      x = acc[k] + f*pB->a[j] + carry;
      acc[k] = x%10;
      carry = x/10;
    }
    x = acc[k] + carry;
    acc[k] = x%10;
    acc[k-1] += x/10;
  }
  sqlite3_free(pA->a);
  pA->a = acc;
  acc = 0;
  pA->nDigit += pB->nDigit + 2;
  pA->nFrac += pB->nFrac;
  pA->sign ^= pB->sign;
  while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
    pA->nFrac--;
    pA->nDigit--;
  }

mul_end:
  sqlite3_free(acc);
}

/*
** Create a new Decimal object that contains an integer power of 2.
*/

static Decimal *decimalPow2(int N){
  Decimal *pA = 0;      /* The result to be returned */
  Decimal *pX = 0;      /* Multiplier */
  if( N<-20000 || N>20000 ) goto pow2_fault;
  pA = decimalNewFromText("1.0", 3);
  if( pA==0 || pA->oom ) goto pow2_fault;
  if( N==0 ) return pA;
  if( N>0 ){
    pX = decimalNewFromText("2.0", 3);
  }else{
    N = -N;
    pX = decimalNewFromText("0.5", 3);
  }
  if( pX==0 || pX->oom ) goto pow2_fault;
  while( 1 /* Exit by break */ ){
    if( N & 1 ){
      decimalMul(pA, pX);
      if( pA->oom ) goto pow2_fault;
    }
    N >>= 1;
    if( N==0 ) break;
    decimalMul(pX, pX);
  }
  decimal_free(pX);
  return pA;

pow2_fault:
  decimal_free(pA);
  decimal_free(pX);
  return 0;
}

/*
** Use an IEEE754 binary64 ("double") to generate a new Decimal object.
*/

static Decimal *decimalFromDouble(double r){
  sqlite3_int64 m, a;
  int e;
  int isNeg;
  Decimal *pA;
  Decimal *pX;
  char zNum[100];
  if( r<0.0 ){
    isNeg = 1;
    r = -r;
  }else{
    isNeg = 0;
  }
  memcpy(&a,&r,sizeof(a));
  if( a==0 || a==(sqlite3_int64)0x8000000000000000LL){
    e = 0;
    m = 0;
  }else{
    e = a>>52;
    m = a & ((((sqlite3_int64)1)<<52)-1);
    if( e==0 ){
      m <<= 1;
    }else{
      m |= ((sqlite3_int64)1)<<52;
    }
    while( e<1075 && m>0 && (m&1)==0 ){
      m >>= 1;
      e++;
    }
    if( isNeg ) m = -m;
    e = e - 1075;
    if( e>971 ){
      return 0;  /* A NaN or an Infinity */
    }
  }

  /* At this point m is the integer significand and e is the exponent */
  sqlite3_snprintf(sizeof(zNum), zNum, "%lld", m);
  pA = decimalNewFromText(zNum, (int)strlen(zNum));
  pX = decimalPow2(e);
  decimalMul(pA, pX);
  decimal_free(pX);
  return pA;
}

/*
** SQL Function:   decimal(X)
** OR:             decimal_exp(X)
**
** Convert input X into decimal and then back into text.
**
** If X is originally a float, then a full decimal expansion of that floating
** point value is done.  Or if X is an 8-byte blob, it is interpreted
** as a float and similarly expanded.
**
** The decimal_exp(X) function returns the result in exponential notation.
** decimal(X) returns a complete decimal, without the e+NNN at the end.
*/

static void decimalFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *p =  decimal_new(context, argv[0], 0);
  int N;
  if( argc==2 ){
    N = sqlite3_value_int(argv[1]);
    if( N>0 ) decimal_round(p, N);
  }else{
    N = 0;
  }
  if( p ){
    if( sqlite3_user_data(context)!=0 ){
      decimal_result_sci(context, p, N);
    }else{
      decimal_result(context, p);
    }
    decimal_free(p);
  }
}

/*
** Compare text in decimal order.
*/

static int decimalCollFunc(
  void *notUsed,
  int nKey1, const void *pKey1,
  int nKey2, const void *pKey2
){
  const unsigned char *zA = (const unsigned char*)pKey1;
  const unsigned char *zB = (const unsigned char*)pKey2;
  Decimal *pA = decimalNewFromText((const char*)zA, nKey1);
  Decimal *pB = decimalNewFromText((const char*)zB, nKey2);
  int rc;
  UNUSED_PARAMETER(notUsed);
  if( pA==0 || pB==0 ){
    rc = 0;
  }else{
    rc = decimal_cmp(pA, pB);
  }
  decimal_free(pA);
  decimal_free(pB);
  return rc;
}


/*
** SQL Function:   decimal_add(X, Y)
**                 decimal_sub(X, Y)
**
** Return the sum or difference of X and Y.
*/

static void decimalAddFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = decimal_new(context, argv[0], 1);
  Decimal *pB = decimal_new(context, argv[1], 1);
  UNUSED_PARAMETER(argc);
  decimal_add(pA, pB);
  decimal_result(context, pA);
  decimal_free(pA);
  decimal_free(pB);
}
static void decimalSubFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = decimal_new(context, argv[0], 1);
  Decimal *pB = decimal_new(context, argv[1], 1);
  UNUSED_PARAMETER(argc);
  if( pB ){
    pB->sign = !pB->sign;
    decimal_add(pA, pB);
    decimal_result(context, pA);
  }
  decimal_free(pA);
  decimal_free(pB);
}

/* Aggregate function:   decimal_sum(X)
**
** Works like sum() except that it uses decimal arithmetic for unlimited
** precision.
*/

static void decimalSumStep(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *p;
  Decimal *pArg;
  UNUSED_PARAMETER(argc);
  p = sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 ) return;
  if( !p->isInit ){
    p->isInit = 1;
    p->a = sqlite3_malloc64(2);
    if( p->a==0 ){
      p->oom = 1;
    }else{
      p->a[0] = 0;
    }
    p->nDigit = 1;
    p->nFrac = 0;
  }
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  pArg = decimal_new(context, argv[0], 1);
  decimal_add(p, pArg);
  decimal_free(pArg);
}
static void decimalSumInverse(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *p;
  Decimal *pArg;
  UNUSED_PARAMETER(argc);
  p = sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 ) return;
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  pArg = decimal_new(context, argv[0], 1);
  if( pArg ) pArg->sign = !pArg->sign;
  decimal_add(p, pArg);
  decimal_free(pArg);
}
static void decimalSumValue(sqlite3_context *context){
  Decimal *p = sqlite3_aggregate_context(context, 0);
  if( p==0 ) return;
  decimal_result(context, p);
}
static void decimalSumFinalize(sqlite3_context *context){
  Decimal *p = sqlite3_aggregate_context(context, 0);
  if( p==0 ) return;
  decimal_result(context, p);
  decimal_clear(p);
}

/*
** SQL Function:   decimal_mul(X, Y)
**
** Return the product of X and Y.
*/

static void decimalMulFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = decimal_new(context, argv[0], 1);
  Decimal *pB = decimal_new(context, argv[1], 1);
  UNUSED_PARAMETER(argc);
  if( pA==0 || pA->oom || pA->isNull
   || pB==0 || pB->oom || pB->isNull 
  ){
    goto mul_end;
  }
  decimalMul(pA, pB);
  if( pA->oom ){
    goto mul_end;
  }
  decimal_result(context, pA);

mul_end:
  decimal_free(pA);
  decimal_free(pB);
}

/*
** SQL Function:   decimal_pow2(N)
**
** Return the N-th power of 2.  N must be an integer.
*/

static void decimalPow2Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
    Decimal *pA = decimalPow2(sqlite3_value_int(argv[0]));
    decimal_result_sci(context, pA, 0);
    decimal_free(pA);
  }
}

#ifdef _WIN32

#endif
int sqlite3_decimal_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  static const struct {
    const char *zFuncName;
    int nArg;
    int iArg;
    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "decimal",       1, 0,  decimalFunc        },
    { "decimal",       2, 0,  decimalFunc        },
    { "decimal_exp",   1, 1,  decimalFunc        },
    { "decimal_exp",   2, 1,  decimalFunc        },
    { "decimal_cmp",   2, 0,  decimalCmpFunc     },
    { "decimal_add",   2, 0,  decimalAddFunc     },
    { "decimal_sub",   2, 0,  decimalSubFunc     },
    { "decimal_mul",   2, 0,  decimalMulFunc     },
    { "decimal_pow2",  1, 0,  decimalPow2Func    },
  };
  unsigned int i;
  (void)pzErrMsg;  /* Unused parameter */

  SQLITE_EXTENSION_INIT2(pApi);

  for(i=0; i<(int)(sizeof(aFunc)/sizeof(aFunc[0])) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                   aFunc[i].iArg ? db : 0, aFunc[i].xFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_window_function(db, "decimal_sum", 1,
                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0,
                   decimalSumStep, decimalSumFinalize,
                   decimalSumValue, decimalSumInverse, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8,
                                  0, decimalCollFunc);
  }
  return rc;
}

/************************* End ext/misc/decimal.c ********************/
/************************* Begin ext/misc/base64.c ******************/
/*
** 2022-11-18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This is a SQLite extension for converting in either direction
** between a (binary) blob and base64 text. Base64 can transit a
** sane USASCII channel unmolested. It also plays nicely in CSV or
** written as TCL brace-enclosed literals or SQL string literals,
** and can be used unmodified in XML-like documents.
**
** This is an independent implementation of conversions specified in
** RFC 4648, done on the above date by the author (Larry Brasfield)
** who thereby has the right to put this into the public domain.
**
** The conversions meet RFC 4648 requirements, provided that this
** C source specifies that line-feeds are included in the encoded
** data to limit visible line lengths to 72 characters and to
** terminate any encoded blob having non-zero length.
**
** Length limitations are not imposed except that the runtime
** SQLite string or blob length limits are respected. Otherwise,
** any length binary sequence can be represented and recovered.
** Generated base64 sequences, with their line-feeds included,
** can be concatenated; the result converted back to binary will
** be the concatenation of the represented binary sequences.
**
** This SQLite3 extension creates a function, base64(x), which
** either: converts text x containing base64 to a returned blob;
** or converts a blob x to returned text containing base64. An
** error will be thrown for other input argument types.
**
** This code relies on UTF-8 encoding only with respect to the
** meaning of the first 128 (7-bit) codes matching that of USASCII.
** It will fail miserably if somehow made to try to convert EBCDIC.
** Because it is table-driven, it could be enhanced to handle that,
** but the world and SQLite have moved on from that anachronism.
**
** To build the extension:
** Set shell variable SQDIR=<your favorite SQLite checkout directory>
** *Nix: gcc -O2 -shared -I$SQDIR -fPIC -o base64.so base64.c
** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR -o base64.dylib base64.c
** Win32: gcc -O2 -shared -I%SQDIR% -o base64.dll base64.c
** Win32: cl /Os -I%SQDIR% base64.c -link -dll -out:base64.dll
*/


#include <assert.h>

/* #include "sqlite3ext.h" */

#ifndef deliberate_fall_through
/* Quiet some compilers about some of our intentional code. */
# if GCC_VERSION>=7000000
#  define deliberate_fall_through __attribute__((fallthrough));
# else
#  define deliberate_fall_through
# endif
#endif

SQLITE_EXTENSION_INIT1;

#define PC 0x80 /* pad character */
#define WS 0x81 /* whitespace */
#define ND 0x82 /* Not above or digit-value */
#define PAD_CHAR '='

#ifndef U8_TYPEDEF
/* typedef unsigned char u8; */
#define U8_TYPEDEF
#endif

/* Decoding table, ASCII (7-bit) value to base 64 digit value or other */
static const u8 b64DigitValues[128] = {
  /*                             HT LF VT  FF CR       */
    ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND,
  /*                                                US */
    ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND,
  /*sp                                  +            / */
    WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63,
  /* 0  1            5            9            =       */
    52,53,54,55, 56,57,58,59, 60,61,ND,ND, ND,PC,ND,ND,
  /*    A                                            O */
    ND, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
  /* P                               Z                 */
    15,16,17,18, 19,20,21,22, 23,24,25,ND, ND,ND,ND,ND,
  /*    a                                            o */
    ND,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
  /* p                               z                 */
    41,42,43,44, 45,46,47,48, 49,50,51,ND, ND,ND,ND,ND
};

static const char b64Numerals[64+1]
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

#define BX_DV_PROTO(c) \
  ((((u8)(c))<0x80)? (u8)(b64DigitValues[(u8)(c)]) : 0x80)
#define IS_BX_DIGIT(bdp) (((u8)(bdp))<0x80)
#define IS_BX_WS(bdp) ((bdp)==WS)
#define IS_BX_PAD(bdp) ((bdp)==PC)
#define BX_NUMERAL(dv) (b64Numerals[(u8)(dv)])
/* Width of base64 lines. Should be an integer multiple of 4. */
#define B64_DARK_MAX 72

/* Encode a byte buffer into base64 text with linefeeds appended to limit
** encoded group lengths to B64_DARK_MAX or to terminate the last group.
*/

static char* toBase64( u8 *pIn, int nbIn, char *pOut ){
  int nCol = 0;
  while( nbIn >= 3 ){
    /* Do the bit-shuffle, exploiting unsigned input to avoid masking. */
    pOut[0] = BX_NUMERAL(pIn[0]>>2);
    pOut[1] = BX_NUMERAL(((pIn[0]<<4)|(pIn[1]>>4))&0x3f);
    pOut[2] = BX_NUMERAL(((pIn[1]&0xf)<<2)|(pIn[2]>>6));
    pOut[3] = BX_NUMERAL(pIn[2]&0x3f);
    pOut += 4;
    nbIn -= 3;
    pIn += 3;
    if( (nCol += 4)>=B64_DARK_MAX || nbIn<=0 ){
      *pOut++ = '\n';
      nCol = 0;
    }
  }
  if( nbIn > 0 ){
    signed char nco = nbIn+1;
    int nbe;
    unsigned long qv = *pIn++;
    for( nbe=1; nbe<3; ++nbe ){
      qv <<= 8;
      if( nbe<nbIn ) qv |= *pIn++;
    }
    for( nbe=3; nbe>=0; --nbe ){
      char ce = (nbe<nco)? BX_NUMERAL((u8)(qv & 0x3f)) : PAD_CHAR;
      qv >>= 6;
      pOut[nbe] = ce;
    }
    pOut += 4;
    *pOut++ = '\n';
  }
  *pOut = 0;
  return pOut;
}

/* Skip over text which is not base64 numeral(s). */
static char * skipNonB64( char *s, int nc ){
  char c;
  while( nc-- > 0 && (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s;
  return s;
}

/* Decode base64 text into a byte buffer. */
static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
  if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
  while( ncIn>0 && *pIn!=PAD_CHAR ){
    static signed char nboi[] = { 0, 0, 1, 2, 3 };
    char *pUse = skipNonB64(pIn, ncIn);
    unsigned long qv = 0L;
    int nti, nbo, nac;
    ncIn -= (pUse - pIn);
    pIn = pUse;
    nti = (ncIn>4)? 4 : ncIn;
    ncIn -= nti;
    nbo = nboi[nti];
    if( nbo==0 ) break;
    for( nac=0; nac<4; ++nac ){
      char c = (nac<nti)? *pIn++ : b64Numerals[0];
      u8 bdp = BX_DV_PROTO(c);
      switch( bdp ){
      case ND:
        /*  Treat dark non-digits as pad, but they terminate decode too. */
        ncIn = 0;
        deliberate_fall_through; /* FALLTHRU */
      case WS:
        /* Treat whitespace as pad and terminate this group.*/
        nti = nac;
        deliberate_fall_through; /* FALLTHRU */
      case PC:
        bdp = 0;
        --nbo;
        deliberate_fall_through; /* FALLTHRU */
      default: /* bdp is the digit value. */
        qv = qv<<6 | bdp;
        break;
      }
    }
    switch( nbo ){
    case 3:
      pOut[2] = (qv) & 0xff;
      deliberate_fall_through; /* FALLTHRU */
    case 2:
      pOut[1] = (qv>>8) & 0xff;
      deliberate_fall_through; /* FALLTHRU */
    case 1:
      pOut[0] = (qv>>16) & 0xff;
      break;
    }
    pOut += nbo;
  }
  return pOut;
}

/* This function does the work for the SQLite base64(x) UDF. */
static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
  sqlite3_int64 nb;
  sqlite3_int64 nv = sqlite3_value_bytes(av[0]);
  sqlite3_int64 nc;
  int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
                            SQLITE_LIMIT_LENGTH, -1);
  char *cBuf;
  u8 *bBuf;
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_BLOB:
    nb = nv;
    nc = 4*((nv+2)/3); /* quads needed */
    nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
    if( nvMax < nc ){
      sqlite3_result_error(context, "blob expanded to base64 too big", -1);
      return;
    }
    bBuf = (u8*)sqlite3_value_blob(av[0]);
    if( !bBuf ){
      if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
        goto memFail;
      }
      sqlite3_result_text(context,"",-1,SQLITE_STATIC);
      break;
    }
    cBuf = sqlite3_malloc64(nc);
    if( !cBuf ) goto memFail;
    nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf);
    sqlite3_result_text(context, cBuf, nc, sqlite3_free);
    break;
  case SQLITE_TEXT:
    nc = nv;
    nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */
    if( nvMax < nb ){
      sqlite3_result_error(context, "blob from base64 may be too big", -1);
      return;
    }else if( nb<1 ){
      nb = 1;
    }
    cBuf = (char *)sqlite3_value_text(av[0]);
    if( !cBuf ){
      if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
        goto memFail;
      }
      sqlite3_result_zeroblob(context, 0);
      break;
    }
    bBuf = sqlite3_malloc64(nb);
    if( !bBuf ) goto memFail;
    nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf);
    sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
    break;
  default:
    sqlite3_result_error(context, "base64 accepts only blob or text", -1);
    return;
  }
  return;
 memFail:
  sqlite3_result_error(context, "base64 OOM", -1);
}

/*
** Establish linkage to running SQLite library.
*/

#ifndef SQLITE_SHELL_EXTFUNCS
#ifdef _WIN32

#endif
int sqlite3_base64_init
#else
static int sqlite3_base64_init
#endif
(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErr;
  return sqlite3_create_function
    (db, "base64", 1,
     SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
     0, base64, 0, 0);
}

/*
** Define some macros to allow this extension to be built into the shell
** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
** allows shell.c, as distributed, to have this extension built in.
*/

#define BASE64_INIT(db) sqlite3_base64_init(db, 0, 0)
#define BASE64_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */

/************************* End ext/misc/base64.c ********************/
/************************* Begin ext/misc/base85.c ******************/
/*
** 2022-11-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 is a utility for converting binary to base85 or vice-versa.
** It can be built as a standalone program or an SQLite3 extension.
**
** Much like base64 representations, base85 can be sent through a
** sane USASCII channel unmolested. It also plays nicely in CSV or
** written as TCL brace-enclosed literals or SQL string literals.
** It is not suited for unmodified use in XML-like documents.
**
** The encoding used resembles Ascii85, but was devised by the author
** (Larry Brasfield) before Mozilla, Adobe, ZMODEM or other Ascii85
** variant sources existed, in the 1984 timeframe on a VAX mainframe.
** Further, this is an independent implementation of a base85 system.
** Hence, the author has rightfully put this into the public domain.
**
** Base85 numerals are taken from the set of 7-bit USASCII codes,
** excluding control characters and Space ! " ' ( ) { | } ~ Del
** in code order representing digit values 0 to 84 (base 10.)
**
** Groups of 4 bytes, interpreted as big-endian 32-bit values,
** are represented as 5-digit base85 numbers with MS to LS digit
** order. Groups of 1-3 bytes are represented with 2-4 digits,
** still big-endian but 8-24 bit values. (Using big-endian yields
** the simplest transition to byte groups smaller than 4 bytes.
** These byte groups can also be considered base-256 numbers.)
** Groups of 0 bytes are represented with 0 digits and vice-versa.
** No pad characters are used; Encoded base85 numeral sequence
** (aka "group") length maps 1-to-1 to the decoded binary length.
**
** Any character not in the base85 numeral set delimits groups.
** When base85 is streamed or stored in containers of indefinite
** size, newline is used to separate it into sub-sequences of no
** more than 80 digits so that fgets() can be used to read it.
**
** Length limitations are not imposed except that the runtime
** SQLite string or blob length limits are respected. Otherwise,
** any length binary sequence can be represented and recovered.
** Base85 sequences can be concatenated by separating them with
** a non-base85 character; the conversion to binary will then
** be the concatenation of the represented binary sequences.

** The standalone program either converts base85 on stdin to create
** a binary file or converts a binary file to base85 on stdout.
** Read or make it blurt its help for invocation details.
**
** The SQLite3 extension creates a function, base85(x), which will
** either convert text base85 to a blob or a blob to text base85
** and return the result (or throw an error for other types.)
** Unless built with OMIT_BASE85_CHECKER defined, it also creates a
** function, is_base85(t), which returns 1 iff the text t contains
** nothing other than base85 numerals and whitespace, or 0 otherwise.
**
** To build the extension:
** Set shell variable SQDIR=<your favorite SQLite checkout directory>
** and variable OPTS to -DOMIT_BASE85_CHECKER if is_base85() unwanted.
** *Nix: gcc -O2 -shared -I$SQDIR $OPTS -fPIC -o base85.so base85.c
** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR $OPTS -o base85.dylib base85.c
** Win32: gcc -O2 -shared -I%SQDIR% %OPTS% -o base85.dll base85.c
** Win32: cl /Os -I%SQDIR% %OPTS% base85.c -link -dll -out:base85.dll
**
** To build the standalone program, define PP symbol BASE85_STANDALONE. Eg.
** *Nix or OSX: gcc -O2 -DBASE85_STANDALONE base85.c -o base85
** Win32: gcc -O2 -DBASE85_STANDALONE -o base85.exe base85.c
** Win32: cl /Os /MD -DBASE85_STANDALONE base85.c
*/


#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <assert.h>
#ifndef OMIT_BASE85_CHECKER
# include <ctype.h>
#endif

#ifndef BASE85_STANDALONE

/* # include "sqlite3ext.h" */

SQLITE_EXTENSION_INIT1;

#else

# ifdef _WIN32
#  include <io.h>
#  include <fcntl.h>
# else
#  define setmode(fd,m)
# endif

static char *zHelp =
  "Usage: base85 <dirFlag> <binFile>\n"
  " <dirFlag> is either -r to read or -w to write <binFile>,\n"
  "   content to be converted to/from base85 on stdout/stdin.\n"
  " <binFile> names a binary file to be rendered or created.\n"
  "   Or, the name '-' refers to the stdin or stdout stream.\n"
  ;

static void sayHelp(){
  printf("%s", zHelp);
}
#endif

#ifndef U8_TYPEDEF
/* typedef unsigned char u8; */
#define U8_TYPEDEF
#endif

/* Classify c according to interval within USASCII set w.r.t. base85
 * Values of 1 and 3 are base85 numerals. Values of 0, 2, or 4 are not.
 */

#define B85_CLASS( c ) (((c)>='#')+((c)>'&')+((c)>='*')+((c)>'z'))

/* Provide digitValue to b85Numeral offset as a function of above class. */
static u8 b85_cOffset[] = { 0, '#', 0, '*'-4, 0 };
#define B85_DNOS( c ) b85_cOffset[B85_CLASS(c)]

/* Say whether c is a base85 numeral. */
#define IS_B85( c ) (B85_CLASS(c) & 1)

#if 0 /* Not used, */
static u8 base85DigitValue( char c ){
  u8 dv = (u8)(c - '#');
  if( dv>87 ) return 0xff;
  return (dv > 3)? dv-3 : dv;
}
#endif

/* Width of base64 lines. Should be an integer multiple of 5. */
#define B85_DARK_MAX 80


static char * skipNonB85( char *s, int nc ){
  char c;
  while( nc-- > 0 && (c = *s) && !IS_B85(c) ) ++s;
  return s;
}

/* Convert small integer, known to be in 0..84 inclusive, to base85 numeral.
 * Do not use the macro form with argument expression having a side-effect.*/

#if 0
static char base85Numeral( u8 b ){
  return (b < 4)? (char)(b + '#') : (char)(b - 4 + '*');
}
#else
# define base85Numeral( dn )\
  ((char)(((dn) < 4)? (char)((dn) + '#') : (char)((dn) - 4 + '*')))
#endif

static char *putcs(char *pc, char *s){
  char c;
  while( (c = *s++)!=0 ) *pc++ = c;
  return pc;
}

/* Encode a byte buffer into base85 text. If pSep!=0, it's a C string
** to be appended to encoded groups to limit their length to B85_DARK_MAX
** or to terminate the last group (to aid concatenation.)
*/

static char* toBase85( u8 *pIn, int nbIn, char *pOut, char *pSep ){
  int nCol = 0;
  while( nbIn >= 4 ){
    int nco = 5;
    unsigned long qbv = (((unsigned long)pIn[0])<<24) |
                        (pIn[1]<<16) | (pIn[2]<<8) | pIn[3];
    while( nco > 0 ){
      unsigned nqv = (unsigned)(qbv/85UL);
      unsigned char dv = qbv - 85UL*nqv;
      qbv = nqv;
      pOut[--nco] = base85Numeral(dv);
    }
    nbIn -= 4;
    pIn += 4;
    pOut += 5;
    if( pSep && (nCol += 5)>=B85_DARK_MAX ){
      pOut = putcs(pOut, pSep);
      nCol = 0;
    }
  }
  if( nbIn > 0 ){
    int nco = nbIn + 1;
    unsigned long qv = *pIn++;
    int nbe = 1;
    while( nbe++ < nbIn ){
      qv = (qv<<8) | *pIn++;
    }
    nCol += nco;
    while( nco > 0 ){
      u8 dv = (u8)(qv % 85);
      qv /= 85;
      pOut[--nco] = base85Numeral(dv);
    }
    pOut += (nbIn+1);
  }
  if( pSep && nCol>0 ) pOut = putcs(pOut, pSep);
  *pOut = 0;
  return pOut;
}

/* Decode base85 text into a byte buffer. */
static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){
  if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
  while( ncIn>0 ){
    static signed char nboi[] = { 0, 0, 1, 2, 3, 4 };
    char *pUse = skipNonB85(pIn, ncIn);
    unsigned long qv = 0L;
    int nti, nbo;
    ncIn -= (pUse - pIn);
    pIn = pUse;
    nti = (ncIn>5)? 5 : ncIn;
    nbo = nboi[nti];
    if( nbo==0 ) break;
    while( nti>0 ){
      char c = *pIn++;
      u8 cdo = B85_DNOS(c);
      --ncIn;
      if( cdo==0 ) break;
      qv = 85 * qv + (c - cdo);
      --nti;
    }
    nbo -= nti; /* Adjust for early (non-digit) end of group. */
    switch( nbo ){
    case 4:
      *pOut++ = (qv >> 24)&0xff;
      /* FALLTHRU */
    case 3:
      *pOut++ = (qv >> 16)&0xff;
      /* FALLTHRU */
    case 2:
      *pOut++ = (qv >> 8)&0xff;
      /* FALLTHRU */
    case 1:
      *pOut++ = qv&0xff;
      /* FALLTHRU */
    case 0:
      break;
    }
  }
  return pOut;
}

#ifndef OMIT_BASE85_CHECKER
/* Say whether input char sequence is all (base85 and/or whitespace).*/
static int allBase85( char *p, int len ){
  char c;
  while( len-- > 0 && (c = *p++) != 0 ){
    if( !IS_B85(c) && !isspace(c) ) return 0;
  }
  return 1;
}
#endif

#ifndef BASE85_STANDALONE

#ifndef OMIT_BASE85_CHECKER
/* This function does the work for the SQLite is_base85(t) UDF. */
static void is_base85(sqlite3_context *context, int na, sqlite3_value *av[]){
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_TEXT:
    {
      int rv = allBase85( (char *)sqlite3_value_text(av[0]),
                          sqlite3_value_bytes(av[0]) );
      sqlite3_result_int(context, rv);
    }
    break;
  case SQLITE_NULL:
    sqlite3_result_null(context);
    break;
  default:
    sqlite3_result_error(context, "is_base85 accepts only text or NULL", -1);
    return;
  }
}
#endif

/* This function does the work for the SQLite base85(x) UDF. */
static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){
  sqlite3_int64 nb, nc, nv = sqlite3_value_bytes(av[0]);
  int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
                            SQLITE_LIMIT_LENGTH, -1);
  char *cBuf;
  u8 *bBuf;
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_BLOB:
    nb = nv;
    /*    ulongs    tail   newlines  tailenc+nul*/
    nc = 5*(nv/4) + nv%4 + nv/64+1 + 2;
    if( nvMax < nc ){
      sqlite3_result_error(context, "blob expanded to base85 too big", -1);
      return;
    }
    bBuf = (u8*)sqlite3_value_blob(av[0]);
    if( !bBuf ){
      if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
        goto memFail;
      }
      sqlite3_result_text(context,"",-1,SQLITE_STATIC);
      break;
    }
    cBuf = sqlite3_malloc64(nc);
    if( !cBuf ) goto memFail;
    nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf);
    sqlite3_result_text(context, cBuf, nc, sqlite3_free);
    break;
  case SQLITE_TEXT:
    nc = nv;
    nb = 4*(nv/5) + nv%5; /* may overestimate */
    if( nvMax < nb ){
      sqlite3_result_error(context, "blob from base85 may be too big", -1);
      return;
    }else if( nb<1 ){
      nb = 1;
    }
    cBuf = (char *)sqlite3_value_text(av[0]);
    if( !cBuf ){
      if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
        goto memFail;
      }
      sqlite3_result_zeroblob(context, 0);
      break;
    }
    bBuf = sqlite3_malloc64(nb);
    if( !bBuf ) goto memFail;
    nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf);
    sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
    break;
  default:
    sqlite3_result_error(context, "base85 accepts only blob or text.", -1);
    return;
  }
  return;
 memFail:
  sqlite3_result_error(context, "base85 OOM", -1);
}

/*
** Establish linkage to running SQLite library.
*/

#ifndef SQLITE_SHELL_EXTFUNCS
#ifdef _WIN32

#endif
int sqlite3_base85_init
#else
static int sqlite3_base85_init
#endif
(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErr;
#ifndef OMIT_BASE85_CHECKER
  {
    int rc = sqlite3_create_function
      (db, "is_base85", 1,
       SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_UTF8,
       0, is_base85, 0, 0);
    if( rc!=SQLITE_OK ) return rc;
  }
#endif
  return sqlite3_create_function
    (db, "base85", 1,
     SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
     0, base85, 0, 0);
}

/*
** Define some macros to allow this extension to be built into the shell
** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
** allows shell.c, as distributed, to have this extension built in.
*/

# define BASE85_INIT(db) sqlite3_base85_init(db, 0, 0)
# define BASE85_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */

#else /* standalone program */

int main(int na, char *av[]){
  int cin;
  int rc = 0;
  u8 bBuf[4*(B85_DARK_MAX/5)];
  char cBuf[5*(sizeof(bBuf)/4)+2];
  size_t nio;
# ifndef OMIT_BASE85_CHECKER
  int b85Clean = 1;
# endif
  char rw;
  FILE *fb = 0, *foc = 0;
  char fmode[3] = "xb";
  if( na < 3 || av[1][0]!='-' || (rw = av[1][1])==0 || (rw!='r' && rw!='w') ){
    sayHelp();
    return 0;
  }
  fmode[0] = rw;
  if( av[2][0]=='-' && av[2][1]==0 ){
    switch( rw ){
    case 'r':
      fb = stdin;
      setmode(fileno(stdin), O_BINARY);
      break;
    case 'w':
      fb = stdout;
      setmode(fileno(stdout), O_BINARY);
      break;
    }
  }else{
    fb = fopen(av[2], fmode);
    foc = fb;
  }
  if( !fb ){
    fprintf(stderr, "Cannot open %s for %c\n", av[2], rw);
    rc = 1;
  }else{
    switch( rw ){
    case 'r':
      while( (nio = fread( bBuf, 1, sizeof(bBuf), fb))>0 ){
        toBase85( bBuf, (int)nio, cBuf, 0 );
        fprintf(stdout, "%s\n", cBuf);
      }
      break;
    case 'w':
      while( 0 != fgets(cBuf, sizeof(cBuf), stdin) ){
        int nc = strlen(cBuf);
        size_t nbo = fromBase85( cBuf, nc, bBuf ) - bBuf;
        if( 1 != fwrite(bBuf, nbo, 1, fb) ) rc = 1;
#ifndef OMIT_BASE85_CHECKER
        b85Clean &= allBase85( cBuf, nc );
#endif
      }
      break;
    default:
      sayHelp();
      rc = 1;
    }
    if( foc ) fclose(foc);
  }
# ifndef OMIT_BASE85_CHECKER
  if( !b85Clean ){
    fprintf(stderr, "Base85 input had non-base85 dark or control content.\n");
  }
# endif
  return rc;
}

#endif

/************************* End ext/misc/base85.c ********************/
/************************* Begin ext/misc/ieee754.c ******************/
/*
** 2013-04-17
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This SQLite extension implements functions for the exact display
** and input of IEEE754 Binary64 floating-point numbers.
**
**   ieee754(X)
**   ieee754(Y,Z)
**
** In the first form, the value X should be a floating-point number.
** The function will return a string of the form 'ieee754(Y,Z)' where
** Y and Z are integers such that X==Y*pow(2,Z).
**
** In the second form, Y and Z are integers which are the mantissa and
** base-2 exponent of a new floating point number.  The function returns
** a floating-point value equal to Y*pow(2,Z).
**
** Examples:
**
**     ieee754(2.0)             ->     'ieee754(2,0)'
**     ieee754(45.25)           ->     'ieee754(181,-2)'
**     ieee754(2, 0)            ->     2.0
**     ieee754(181, -2)         ->     45.25
**
** Two additional functions break apart the one-argument ieee754()
** result into separate integer values:
**
**     ieee754_mantissa(45.25)  ->     181
**     ieee754_exponent(45.25)  ->     -2
**
** These functions convert binary64 numbers into blobs and back again.
**
**     ieee754_from_blob(x'3ff0000000000000')  ->  1.0
**     ieee754_to_blob(1.0)                    ->  x'3ff0000000000000'
**
** In all single-argument functions, if the argument is an 8-byte blob
** then that blob is interpreted as a big-endian binary64 value.
**
**
** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
** -----------------------------------------------
**
** This extension in combination with the separate 'decimal' extension
** can be used to compute the exact decimal representation of binary64
** values.  To begin, first compute a table of exponent values:
**
**    CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
**    WITH RECURSIVE c(x,v) AS (
**      VALUES(0,'1')
**      UNION ALL
**      SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
**    WITH RECURSIVE c(x,v) AS (
**      VALUES(-1,'0.5')
**      UNION ALL
**      SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
**
** Then, to compute the exact decimal representation of a floating
** point value (the value 47.49 is used in the example) do:
**
**    WITH c(n) AS (VALUES(47.49))
**          ---------------^^^^^---- Replace with whatever you want
**    SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
**
** Here is a query to show various boundry values for the binary64
** number format:
**
**    WITH c(name,bin) AS (VALUES
**       ('minimum positive value',        x'0000000000000001'),
**       ('maximum subnormal value',       x'000fffffffffffff'),
**       ('minimum positive normal value', x'0010000000000000'),
**       ('maximum value',                 x'7fefffffffffffff'))
**    SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
**
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */

#ifndef UNUSED_PARAMETER
# define UNUSED_PARAMETER(X)  (void)(X)
#endif

/*
** Implementation of the ieee754() function
*/

static void ieee754func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  if( argc==1 ){
    sqlite3_int64 m, a;
    double r;
    int e;
    int isNeg;
    char zResult[100];
    assert( sizeof(m)==sizeof(r) );
    if( sqlite3_value_type(argv[0])==SQLITE_BLOB
     && sqlite3_value_bytes(argv[0])==sizeof(r)
    ){
      const unsigned char *x = sqlite3_value_blob(argv[0]);
      unsigned int i;
      sqlite3_uint64 v = 0;
      for(i=0; i<sizeof(r); i++){
        v = (v<<8) | x[i];
      }
      memcpy(&r, &v, sizeof(r));
    }else{
      r = sqlite3_value_double(argv[0]);
    }
    if( r<0.0 ){
      isNeg = 1;
      r = -r;
    }else{
      isNeg = 0;
    }
    memcpy(&a,&r,sizeof(a));
    if( a==0 ){
      e = 0;
      m = 0;
    }else if( a==(sqlite3_int64)0x8000000000000000LL ){
      e = -1996;
      m = -1;
    }else{
      e = a>>52;
      m = a & ((((sqlite3_int64)1)<<52)-1);
      if( e==0 ){
        m <<= 1;
      }else{
        m |= ((sqlite3_int64)1)<<52;
      }
      while( e<1075 && m>0 && (m&1)==0 ){
        m >>= 1;
        e++;
      }
      if( isNeg ) m = -m;
    }
    switch( *(int*)sqlite3_user_data(context) ){
      case 0:
        sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
                         m, e-1075);
        sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
        break;
      case 1:
        sqlite3_result_int64(context, m);
        break;
      case 2:
        sqlite3_result_int(context, e-1075);
        break;
    }
  }else{
    sqlite3_int64 m, e, a;
    double r;
    int isNeg = 0;
    m = sqlite3_value_int64(argv[0]);
    e = sqlite3_value_int64(argv[1]);

    /* Limit the range of e.  Ticket 22dea1cfdb9151e4 2021-03-02 */
    if( e>10000 ){
      e = 10000;
    }else if( e<-10000 ){
      e = -10000;
    }

    if( m<0 ){
      if( m<(-9223372036854775807LL) ) return;
      isNeg = 1;
      m = -m;
    }else if( m==0 && e>-1000 && e<1000 ){
      sqlite3_result_double(context, 0.0);
      return;
    }
    while( (m>>32)&0xffe00000 ){
      m >>= 1;
      e++;
    }
    while( m!=0 && ((m>>32)&0xfff00000)==0 ){
      m <<= 1;
      e--;
    }
    e += 1075;
    if( e<=0 ){
      /* Subnormal */
      if( 1-e >= 64 ){
        m = 0;
      }else{
        m >>= 1-e;
      }
      e = 0;
    }else if( e>0x7ff ){
      e = 0x7ff;
    }
    a = m & ((((sqlite3_int64)1)<<52)-1);
    a |= e<<52;
    if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
    memcpy(&r, &a, sizeof(r));
    sqlite3_result_double(context, r);
  }
}

/*
** Functions to convert between blobs and floats.
*/

static void ieee754func_from_blob(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_BLOB
   && sqlite3_value_bytes(argv[0])==sizeof(double)
  ){
    double r;
    const unsigned char *x = sqlite3_value_blob(argv[0]);
    unsigned int i;
    sqlite3_uint64 v = 0;
    for(i=0; i<sizeof(r); i++){
      v = (v<<8) | x[i];
    }
    memcpy(&r, &v, sizeof(r));
    sqlite3_result_double(context, r);
  }
}
static void ieee754func_to_blob(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_FLOAT
   || sqlite3_value_type(argv[0])==SQLITE_INTEGER
  ){
    double r = sqlite3_value_double(argv[0]);
    sqlite3_uint64 v;
    unsigned char a[sizeof(r)];
    unsigned int i;
    memcpy(&v, &r, sizeof(r));
    for(i=1; i<=sizeof(r); i++){
      a[sizeof(r)-i] = v&0xff;
      v >>= 8;
    }
    sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT);
  }
}

/*
** Functions to convert between 64-bit integers and floats.
**
** The bit patterns are copied.  The numeric values are different.
*/

static void ieee754func_from_int(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
    double r;
    sqlite3_int64 v = sqlite3_value_int64(argv[0]);
    memcpy(&r, &v, sizeof(r));
    sqlite3_result_double(context, r);
  }
}
static void ieee754func_to_int(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_FLOAT ){
    double r = sqlite3_value_double(argv[0]);
    sqlite3_uint64 v;
    memcpy(&v, &r, sizeof(v));
    sqlite3_result_int64(context, v);
  }
}

/*
** SQL Function:   ieee754_inc(r,N)
**
** Move the floating point value r by N quantums and return the new
** values.
**
** Behind the scenes: this routine merely casts r into a 64-bit unsigned
** integer, adds N, then casts the value back into float.
**
** Example:  To find the smallest positive number:
**
**     SELECT ieee754_inc(0.0,+1);
*/

static void ieee754inc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  double r;
  sqlite3_int64 N;
  sqlite3_uint64 m1, m2;
  double r2;
  UNUSED_PARAMETER(argc);
  r = sqlite3_value_double(argv[0]);
  N = sqlite3_value_int64(argv[1]);
  memcpy(&m1, &r, 8);
  m2 = m1 + N;
  memcpy(&r2, &m2, 8);
  sqlite3_result_double(context, r2);
}


#ifdef _WIN32

#endif
int sqlite3_ieee_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  static const struct {
    char *zFName;
    int nArg;
    int iAux;
    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "ieee754",           1,   0, ieee754func },
    { "ieee754",           2,   0, ieee754func },
    { "ieee754_mantissa",  1,   1, ieee754func },
    { "ieee754_exponent",  1,   2, ieee754func },
    { "ieee754_to_blob",   1,   0, ieee754func_to_blob },
    { "ieee754_from_blob", 1,   0, ieee754func_from_blob },
    { "ieee754_to_int",    1,   0, ieee754func_to_int },
    { "ieee754_from_int",  1,   0, ieee754func_from_int },
    { "ieee754_inc",       2,   0, ieee754inc  },
  };
  unsigned int i;
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
                               SQLITE_UTF8|SQLITE_INNOCUOUS,
                               (void*)&aFunc[i].iAux,
                               aFunc[i].xFunc, 0, 0);
  }
  return rc;
}

/************************* End ext/misc/ieee754.c ********************/
/************************* Begin ext/misc/series.c ******************/
/*
** 2015-08-18, 2023-04-28
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file demonstrates how to create a table-valued-function using
** a virtual table.  This demo implements the generate_series() function
** which gives the same results as the eponymous function in PostgreSQL,
** within the limitation that its arguments are signed 64-bit integers.
**
** Considering its equivalents to generate_series(start,stop,step): A
** value V[n] sequence is produced for integer n ascending from 0 where
**  ( V[n] == start + n * step  &&  sgn(V[n] - stop) * sgn(step) >= 0 )
** for each produced value (independent of production time ordering.)
**
** All parameters must be either integer or convertable to integer.
** The start parameter is required.
** The stop parameter defaults to (1<<32)-1 (aka 4294967295 or 0xffffffff)
** The step parameter defaults to 1 and 0 is treated as 1.
**
** Examples:
**
**      SELECT * FROM generate_series(0,100,5);
**
** The query above returns integers from 0 through 100 counting by steps
** of 5.  In other words, 0, 5, 10, 15, ..., 90, 95, 100.  There are a total
** of 21 rows.
**
**      SELECT * FROM generate_series(0,100);
**
** Integers from 0 through 100 with a step size of 1.  101 rows.
**
**      SELECT * FROM generate_series(20) LIMIT 10;
**
** Integers 20 through 29.  10 rows.
**
**      SELECT * FROM generate_series(0,-100,-5);
**
** Integers 0 -5 -10 ... -100.  21 rows.
**
**      SELECT * FROM generate_series(0,-1);
**
** Empty sequence.
**
** HOW IT WORKS
**
** The generate_series "function" is really a virtual table with the
** following schema:
**
**     CREATE TABLE generate_series(
**       value,
**       start HIDDEN,
**       stop HIDDEN,
**       step HIDDEN
**     );
**
** The virtual table also has a rowid which is an alias for the value.
**
** Function arguments in queries against this virtual table are translated
** into equality constraints against successive hidden columns.  In other
** words, the following pairs of queries are equivalent to each other:
**
**    SELECT * FROM generate_series(0,100,5);
**    SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
**
**    SELECT * FROM generate_series(0,100);
**    SELECT * FROM generate_series WHERE start=0 AND stop=100;
**
**    SELECT * FROM generate_series(20) LIMIT 10;
**    SELECT * FROM generate_series WHERE start=20 LIMIT 10;
**
** The generate_series virtual table implementation leaves the xCreate method
** set to NULL.  This means that it is not possible to do a CREATE VIRTUAL
** TABLE command with "generate_series" as the USING argument.  Instead, there
** is a single generate_series virtual table that is always available without
** having to be created first.
**
** The xBestIndex method looks for equality constraints against the hidden
** start, stop, and step columns, and if present, it uses those constraints
** to bound the sequence of generated values.  If the equality constraints
** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
** xBestIndex returns a small cost when both start and stop are available,
** and a very large cost if either start or stop are unavailable.  This
** encourages the query planner to order joins such that the bounds of the
** series are well-defined.
**
** Update on 2024-08-22:
** xBestIndex now also looks for equality and inequality constraints against
** the value column and uses those constraints as additional bounds against
** the sequence range.  Thus, a query like this:
**
**     SELECT value FROM generate_series($SA,$EA)
**      WHERE value BETWEEN $SB AND $EB;
**
** Is logically the same as:
**
**     SELECT value FROM generate_series(max($SA,$SB),min($EA,$EB));
**
** Constraints on the value column can server as substitutes for constraints
** on the hidden start and stop columns.  So, the following two queries
** are equivalent:
**
**     SELECT value FROM generate_series($S,$E);
**     SELECT value FROM generate_series WHERE value BETWEEN $S and $E;
**
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <limits.h>
#include <math.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

/* series_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result.
**
** iOBase, iOTerm, and iOStep are the original values of the
** start=, stop=, and step= constraints on the query.  These are
** the values reported by the start, stop, and step columns of the
** virtual table.
**
** iBase, iTerm, iStep, and bDescp are the actual values used to generate
** the sequence.  These might be different from the iOxxxx values.
** For example in
**
**   SELECT value FROM generate_series(1,11,2)
**    WHERE value BETWEEN 4 AND 8;
**
** The iOBase is 1, but the iBase is 5.  iOTerm is 11 but iTerm is 7.
** Another example:
**
**   SELECT value FROM generate_series(1,15,3) ORDER BY value DESC;
**
** The cursor initialization for the above query is:
**
**   iOBase = 1        iBase = 13
**   iOTerm = 15       iTerm = 1
**   iOStep = 3        iStep = 3      bDesc = 1
**
** The actual step size is unsigned so that can have a value of
** +9223372036854775808 which is needed for querys like this:
**
**   SELECT value
**     FROM generate_series(9223372036854775807,
**                          -9223372036854775808,
**                          -9223372036854775808)
**    ORDER BY value ASC;
**
** The setup for the previous query will be:
**
**   iOBase = 9223372036854775807    iBase = -1
**   iOTerm = -9223372036854775808   iTerm = 9223372036854775807
**   iOStep = -9223372036854775808   iStep = 9223372036854775808  bDesc = 0
*/

/* typedef unsigned char u8; */
typedef struct series_cursor series_cursor;
struct series_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  sqlite3_int64 iOBase;      /* Original starting value ("start") */
  sqlite3_int64 iOTerm;      /* Original terminal value ("stop") */
  sqlite3_int64 iOStep;      /* Original step value */
  sqlite3_int64 iBase;       /* Starting value to actually use */
  sqlite3_int64 iTerm;       /* Terminal value to actually use */
  sqlite3_uint64 iStep;      /* The step size */
  sqlite3_int64 iValue;      /* Current value */
  u8 bDesc;                  /* iStep is really negative */
  u8 bDone;                  /* True if stepped past last element */
};

/*
** Computed the difference between two 64-bit signed integers using a
** convoluted computation designed to work around the silly restriction
** against signed integer overflow in C.
*/

static sqlite3_uint64 span64(sqlite3_int64 a, sqlite3_int64 b){
  assert( a>=b );
  return (*(sqlite3_uint64*)&a) - (*(sqlite3_uint64*)&b);
}  

/*
** Add or substract an unsigned 64-bit integer from a signed 64-bit integer
** and return the new signed 64-bit integer.
*/

static sqlite3_int64 add64(sqlite3_int64 a, sqlite3_uint64 b){
  sqlite3_uint64 x = *(sqlite3_uint64*)&a;
  x += b;
  return *(sqlite3_int64*)&x;
}
static sqlite3_int64 sub64(sqlite3_int64 a, sqlite3_uint64 b){
  sqlite3_uint64 x = *(sqlite3_uint64*)&a;
  x -= b;
  return *(sqlite3_int64*)&x;
}

/*
** The seriesConnect() method is invoked to create a new
** series_vtab that describes the generate_series virtual table.
**
** Think of this routine as the constructor for series_vtab objects.
**
** All this routine needs to do is:
**
**    (1) Allocate the series_vtab object and initialize all fields.
**
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
**        result set of queries against generate_series will look like.
*/

static int seriesConnect(
  sqlite3 *db,
  void *pUnused,
  int argcUnused, const char *const*argvUnused,
  sqlite3_vtab **ppVtab,
  char **pzErrUnused
){
  sqlite3_vtab *pNew;
  int rc;

/* Column numbers */
#define SERIES_COLUMN_ROWID (-1)
#define SERIES_COLUMN_VALUE 0
#define SERIES_COLUMN_START 1
#define SERIES_COLUMN_STOP  2
#define SERIES_COLUMN_STEP  3

  (void)pUnused;
  (void)argcUnused;
  (void)argvUnused;
  (void)pzErrUnused;
  rc = sqlite3_declare_vtab(db,
     "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
  if( rc==SQLITE_OK ){
    pNew = *ppVtab = sqlite3_malloc64( sizeof(*pNew) );
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  }
  return rc;
}

/*
** This method is the destructor for series_cursor objects.
*/

static int seriesDisconnect(sqlite3_vtab *pVtab){
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** Constructor for a new series_cursor object.
*/

static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
  series_cursor *pCur;
  (void)pUnused;
  pCur = sqlite3_malloc64( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Destructor for a series_cursor.
*/

static int seriesClose(sqlite3_vtab_cursor *cur){
  sqlite3_free(cur);
  return SQLITE_OK;
}


/*
** Advance a series_cursor to its next row of output.
*/

static int seriesNext(sqlite3_vtab_cursor *cur){
  series_cursor *pCur = (series_cursor*)cur;
  if( pCur->iValue==pCur->iTerm ){
    pCur->bDone = 1;
  }else if( pCur->bDesc ){
    pCur->iValue = sub64(pCur->iValue, pCur->iStep);
    assert( pCur->iValue>=pCur->iTerm );
  }else{
    pCur->iValue = add64(pCur->iValue, pCur->iStep);
    assert( pCur->iValue<=pCur->iTerm );
  }
  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the series_cursor
** is currently pointing.
*/

static int seriesColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  series_cursor *pCur = (series_cursor*)cur;
  sqlite3_int64 x = 0;
  switch( i ){
    case SERIES_COLUMN_START:  x = pCur->iOBase;     break;
    case SERIES_COLUMN_STOP:   x = pCur->iOTerm;     break;
    case SERIES_COLUMN_STEP:   x = pCur->iOStep;     break;
    default:                   x = pCur->iValue;     break;
  }
  sqlite3_result_int64(ctx, x);
  return SQLITE_OK;
}

#ifndef LARGEST_UINT64
#define LARGEST_INT64  ((sqlite3_int64)0x7fffffffffffffffLL)
#define LARGEST_UINT64 ((sqlite3_uint64)0xffffffffffffffffULL)
#define SMALLEST_INT64 ((sqlite3_int64)0x8000000000000000LL)
#endif

/*
** The rowid is the same as the value.
*/

static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  series_cursor *pCur = (series_cursor*)cur;
  *pRowid = pCur->iValue;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/

static int seriesEof(sqlite3_vtab_cursor *cur){
  series_cursor *pCur = (series_cursor*)cur;
  return pCur->bDone;
}

/* True to cause run-time checking of the start=, stop=, and/or step=
** parameters.  The only reason to do this is for testing the
** constraint checking logic for virtual tables in the SQLite core.
*/

#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
#endif

/*
** Return the number of steps between pCur->iBase and pCur->iTerm if
** the step width is pCur->iStep.
*/

static sqlite3_uint64 seriesSteps(series_cursor *pCur){
  if( pCur->bDesc ){
    assert( pCur->iBase >= pCur->iTerm );
    return span64(pCur->iBase, pCur->iTerm)/pCur->iStep;
  }else{
    assert( pCur->iBase <= pCur->iTerm );
    return span64(pCur->iTerm, pCur->iBase)/pCur->iStep;
  }
}

#if defined(SQLITE_ENABLE_MATH_FUNCTIONS) || defined(_WIN32)
/*
** Case 1 (the most common case):
** The standard math library is available so use ceil() and floor() from there.
*/

static double seriesCeil(double r){ return ceil(r); }
static double seriesFloor(double r){ return floor(r); }
#elif defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
/*
** Case 2 (2nd most common): Use GCC/Clang builtins
*/

static double seriesCeil(double r){ return __builtin_ceil(r); }
static double seriesFloor(double r){ return __builtin_floor(r); }
#else
/*
** Case 3 (rarely happens): Use home-grown ceil() and floor() routines.
*/

static double seriesCeil(double r){
  sqlite3_int64 x;
  if( r!=r ) return r;
  if( r<=(-4503599627370496.0) ) return r;
  if( r>=(+4503599627370496.0) ) return r;
  x = (sqlite3_int64)r;
  if( r==(double)x ) return r;
  if( r>(double)x ) x++;
  return (double)x;
}
static double seriesFloor(double r){
  sqlite3_int64 x;
  if( r!=r ) return r;
  if( r<=(-4503599627370496.0) ) return r;
  if( r>=(+4503599627370496.0) ) return r;
  x = (sqlite3_int64)r;
  if( r==(double)x ) return r;
  if( r<(double)x ) x--;
  return (double)x;
}
#endif

/*
** This method is called to "rewind" the series_cursor object back
** to the first row of output.  This method is always called at least
** once prior to any call to seriesColumn() or seriesRowid() or
** seriesEof().
**
** The query plan selected by seriesBestIndex is passed in the idxNum
** parameter.  (idxStr is not used in this implementation.)  idxNum
** is a bitmask showing which constraints are available:
**
**   0x0001:    start=VALUE
**   0x0002:    stop=VALUE
**   0x0004:    step=VALUE
**   0x0008:    descending order
**   0x0010:    ascending order
**   0x0020:    LIMIT  VALUE
**   0x0040:    OFFSET  VALUE
**   0x0080:    value=VALUE
**   0x0100:    value>=VALUE
**   0x0200:    value>VALUE
**   0x1000:    value<=VALUE
**   0x2000:    value<VALUE
**
** This routine should initialize the cursor and position it so that it
** is pointing at the first row, or pointing off the end of the table
** (so that seriesEof() will return true) if the table is empty.
*/

static int seriesFilter(
  sqlite3_vtab_cursor *pVtabCursor,
  int idxNum, const char *idxStrUnused,
  int argc, sqlite3_value **argv
){
  series_cursor *pCur = (series_cursor *)pVtabCursor;
  int iArg = 0;                         /* Arguments used so far */
  int i;                                /* Loop counter */
  sqlite3_int64 iMin = SMALLEST_INT64;  /* Smallest allowed output value */
  sqlite3_int64 iMax = LARGEST_INT64;   /* Largest allowed output value */
  sqlite3_int64 iLimit = 0;             /* if >0, the value of the LIMIT */
  sqlite3_int64 iOffset = 0;            /* if >0, the value of the OFFSET */

  (void)idxStrUnused;

  /* If any constraints have a NULL value, then return no rows.
  ** See ticket https://sqlite.org/src/info/fac496b61722daf2
  */

  for(i=0; i<argc; i++){
    if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
      goto series_no_rows;
    }
  }

  /* Capture the three HIDDEN parameters to the virtual table and insert
  ** default values for any parameters that are omitted.
  */

  if( idxNum & 0x01 ){
    pCur->iOBase = sqlite3_value_int64(argv[iArg++]);
  }else{
    pCur->iOBase = 0;
  }
  if( idxNum & 0x02 ){
    pCur->iOTerm = sqlite3_value_int64(argv[iArg++]);
  }else{
    pCur->iOTerm = 0xffffffff;
  }
  if( idxNum & 0x04 ){
    pCur->iOStep = sqlite3_value_int64(argv[iArg++]);
    if( pCur->iOStep==0 ) pCur->iOStep = 1;
  }else{
    pCur->iOStep = 1;
  }

  /* If there are constraints on the value column but there are
  ** no constraints on  the start, stop, and step columns, then
  ** initialize the default range to be the entire range of 64-bit signed
  ** integers.  This range will contracted by the value column constraints
  ** further below.
  */

  if( (idxNum & 0x05)==0 && (idxNum & 0x0380)!=0 ){
    pCur->iOBase = SMALLEST_INT64;
  }
  if( (idxNum & 0x06)==0 && (idxNum & 0x3080)!=0 ){
    pCur->iOTerm = LARGEST_INT64;
  }
  pCur->iBase = pCur->iOBase;
  pCur->iTerm = pCur->iOTerm;
  if( pCur->iOStep>0 ){  
    pCur->iStep = pCur->iOStep;
  }else if( pCur->iOStep>SMALLEST_INT64 ){
    pCur->iStep = -pCur->iOStep;
  }else{
    pCur->iStep = LARGEST_INT64;
    pCur->iStep++;
  }
  pCur->bDesc = pCur->iOStep<0;
  if( pCur->bDesc==0 && pCur->iBase>pCur->iTerm ){
    goto series_no_rows;
  }
  if( pCur->bDesc!=0 && pCur->iBase<pCur->iTerm ){
    goto series_no_rows;
  }

  /* Extract the LIMIT and OFFSET values, but do not apply them yet.
  ** The range must first be constrained by the limits on value.
  */

  if( idxNum & 0x20 ){
    iLimit = sqlite3_value_int64(argv[iArg++]);
    if( idxNum & 0x40 ){
      iOffset = sqlite3_value_int64(argv[iArg++]);
    }
  }

  /* Narrow the range of iMin and iMax (the minimum and maximum outputs)
  ** based on equality and inequality constraints on the "value" column.
  */

  if( idxNum & 0x3380 ){
    if( idxNum & 0x0080 ){    /* value=X */
      if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
        double r = sqlite3_value_double(argv[iArg++]);
        if( r==seriesCeil(r)
         && r>=(double)SMALLEST_INT64
         && r<=(double)LARGEST_INT64
        ){
          iMin = iMax = (sqlite3_int64)r;
        }else{
          goto series_no_rows;
        }
      }else{
        iMin = iMax = sqlite3_value_int64(argv[iArg++]);
      }
    }else{
      if( idxNum & 0x0300 ){  /* value>X or value>=X */
        if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
          double r = sqlite3_value_double(argv[iArg++]);
          if( r<(double)SMALLEST_INT64 ){
            iMin = SMALLEST_INT64;
          }else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
            iMin = (sqlite3_int64)seriesCeil(r+1.0);
          }else{
            iMin = (sqlite3_int64)seriesCeil(r);
          }
        }else{
          iMin = sqlite3_value_int64(argv[iArg++]);
          if( (idxNum & 0x0200)!=0 ){
            if( iMin==LARGEST_INT64 ){
              goto series_no_rows;
            }else{
              iMin++;
            }
          }
        }
      }
      if( idxNum & 0x3000 ){   /* value<X or value<=X */
        if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
          double r = sqlite3_value_double(argv[iArg++]);
          if( r>(double)LARGEST_INT64 ){
            iMax = LARGEST_INT64;
          }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
            iMax = (sqlite3_int64)(r-1.0);
          }else{
            iMax = (sqlite3_int64)seriesFloor(r);
          }
        }else{
          iMax = sqlite3_value_int64(argv[iArg++]);
          if( idxNum & 0x2000 ){
            if( iMax==SMALLEST_INT64 ){
              goto series_no_rows;
            }else{
              iMax--;
            }
          }
        }
      }
      if( iMin>iMax ){
        goto series_no_rows;
      }
    }

    /* Try to reduce the range of values to be generated based on
    ** constraints on the "value" column.
    */

    if( pCur->bDesc==0 ){
      if( pCur->iBase<iMin ){
        sqlite3_uint64 span = span64(iMin,pCur->iBase);
        pCur->iBase = add64(pCur->iBase, (span/pCur->iStep)*pCur->iStep);
        if( pCur->iBase<iMin ){
          if( pCur->iBase > sub64(LARGEST_INT64, pCur->iStep) ){
            goto series_no_rows;
          }
          pCur->iBase = add64(pCur->iBase, pCur->iStep);
        }
      }
      if( pCur->iTerm>iMax ){
        pCur->iTerm = iMax;
      }
    }else{
      if( pCur->iBase>iMax ){
        sqlite3_uint64 span = span64(pCur->iBase,iMax);
        pCur->iBase = sub64(pCur->iBase, (span/pCur->iStep)*pCur->iStep);
        if( pCur->iBase>iMax ){
          if( pCur->iBase < add64(SMALLEST_INT64, pCur->iStep) ){
            goto series_no_rows;
          }
          pCur->iBase = sub64(pCur->iBase, pCur->iStep);
        }
      }
      if( pCur->iTerm<iMin ){
        pCur->iTerm = iMin;
      }
    }
  }

  /* Adjust iTerm so that it is exactly the last value of the series.
  */

  if( pCur->bDesc==0 ){
    if( pCur->iBase>pCur->iTerm ){
      goto series_no_rows;
    }
    pCur->iTerm = sub64(pCur->iTerm,
                        span64(pCur->iTerm,pCur->iBase) % pCur->iStep);
  }else{
    if( pCur->iBase<pCur->iTerm ){
      goto series_no_rows;
    }
    pCur->iTerm = add64(pCur->iTerm,
                        span64(pCur->iBase,pCur->iTerm) % pCur->iStep);
  }

  /* Transform the series generator to output values in the requested
  ** order.
  */

  if( ((idxNum & 0x0008)!=0 && pCur->bDesc==0)
   || ((idxNum & 0x0010)!=0 && pCur->bDesc!=0)
  ){
    sqlite3_int64 tmp = pCur->iBase;
    pCur->iBase = pCur->iTerm;
    pCur->iTerm = tmp;
    pCur->bDesc = !pCur->bDesc;
  }

  /* Apply LIMIT and OFFSET constraints, if any */
  assert( pCur->iStep!=0 );
  if( idxNum & 0x20 ){
    if( iOffset>0 ){
      if( seriesSteps(pCur) < (sqlite3_uint64)iOffset ){
        goto series_no_rows;
      }else if( pCur->bDesc ){
        pCur->iBase = sub64(pCur->iBase, pCur->iStep*iOffset);
      }else{
        pCur->iBase = add64(pCur->iBase, pCur->iStep*iOffset);
      }
    }
    if( iLimit>=0 && seriesSteps(pCur) > (sqlite3_uint64)iLimit ){
      pCur->iTerm = add64(pCur->iBase, (iLimit - 1)*pCur->iStep);
    }
  }
  pCur->iValue = pCur->iBase;
  pCur->bDone = 0;
  return SQLITE_OK;

series_no_rows:
  pCur->iBase = 0;
  pCur->iTerm = 0;
  pCur->iStep = 1;
  pCur->bDesc = 0;
  pCur->bDone = 1;
  return SQLITE_OK;  
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the generate_series virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** In this implementation idxNum is used to represent the
** query plan.  idxStr is unused.
**
** The query plan is represented by bits in idxNum:
**
**   0x0001  start = $num
**   0x0002  stop = $num
**   0x0004  step = $num
**   0x0008  output is in descending order
**   0x0010  output is in ascending order
**   0x0020  LIMIT $num
**   0x0040  OFFSET $num
**   0x0080  value = $num
**   0x0100  value >= $num
**   0x0200  value > $num
**   0x1000  value <= $num
**   0x2000  value < $num
**
** Only one of 0x0100 or 0x0200 will be returned.  Similarly, only
** one of 0x1000 or 0x2000 will be returned.  If the 0x0080 is set, then
** none of the 0xff00 bits will be set.
**
** The order of parameters passed to xFilter is as follows:
**
**    * The argument to start= if bit 0x0001 is in the idxNum mask
**    * The argument to stop= if bit 0x0002 is in the idxNum mask
**    * The argument to step= if bit 0x0004 is in the idxNum mask
**    * The argument to LIMIT if bit 0x0020 is in the idxNum mask
**    * The argument to OFFSET if bit 0x0040 is in the idxNum mask
**    * The argument to value=, or value>= or value> if any of
**      bits 0x0380 are in the idxNum mask
**    * The argument to value<= or value< if either of bits 0x3000
**      are in the mask
**
*/

static int seriesBestIndex(
  sqlite3_vtab *pVTab,
  sqlite3_index_info *pIdxInfo
){
  int i, j;              /* Loop over constraints */
  int idxNum = 0;        /* The query plan bitmask */
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
  int bStartSeen = 0;    /* EQ constraint seen on the START column */
#endif
  int unusableMask = 0;  /* Mask of unusable constraints */
  int nArg = 0;          /* Number of arguments that seriesFilter() expects */
  int aIdx[7];           /* Constraints on start, stop, step, LIMIT, OFFSET,
                         ** and value.  aIdx[5] covers value=, value>=, and
                         ** value>,  aIdx[6] covers value<= and value< */

  const struct sqlite3_index_constraint *pConstraint;

  /* This implementation assumes that the start, stop, and step columns
  ** are the last three columns in the virtual table. */

  assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
  assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );

  aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = aIdx[5] = aIdx[6] = -1;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    int iCol;    /* 0 for start, 1 for stop, 2 for step */
    int iMask;   /* bitmask for those column */
    int op = pConstraint->op;
    if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
     && op<=SQLITE_INDEX_CONSTRAINT_OFFSET
    ){
      if( pConstraint->usable==0 ){
        /* do nothing */
      }else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
        aIdx[3] = i;
        idxNum |= 0x20;
      }else{
        assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
        aIdx[4] = i;
        idxNum |= 0x40;
      }
      continue;
    }
    if( pConstraint->iColumn<SERIES_COLUMN_START ){
      if( (pConstraint->iColumn==SERIES_COLUMN_VALUE ||
           pConstraint->iColumn==SERIES_COLUMN_ROWID)
       && pConstraint->usable
      ){
        switch( op ){
          case SQLITE_INDEX_CONSTRAINT_EQ:
          case SQLITE_INDEX_CONSTRAINT_IS: {
            idxNum |=  0x0080;
            idxNum &= ~0x3300;
            aIdx[5] = i;
            aIdx[6] = -1;
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
            bStartSeen = 1;
#endif
            break;
          }
          case SQLITE_INDEX_CONSTRAINT_GE: {
            if( idxNum & 0x0080 ) break;
            idxNum |=  0x0100;
            idxNum &= ~0x0200;
            aIdx[5] = i;
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
            bStartSeen = 1;
#endif
            break;
          }
          case SQLITE_INDEX_CONSTRAINT_GT: {
            if( idxNum & 0x0080 ) break;
            idxNum |=  0x0200;
            idxNum &= ~0x0100;
            aIdx[5] = i;
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
            bStartSeen = 1;
#endif
            break;
          }
          case SQLITE_INDEX_CONSTRAINT_LE: {
            if( idxNum & 0x0080 ) break;
            idxNum |=  0x1000;
            idxNum &= ~0x2000;
            aIdx[6] = i;
            break;
          }
          case SQLITE_INDEX_CONSTRAINT_LT: {
            if( idxNum & 0x0080 ) break;
            idxNum |=  0x2000;
            idxNum &= ~0x1000;
            aIdx[6] = i;
            break;
          }
        }
      }
      continue;
    }
    iCol = pConstraint->iColumn - SERIES_COLUMN_START;
    assert( iCol>=0 && iCol<=2 );
    iMask = 1 << iCol;
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
    if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
      bStartSeen = 1;
    }
#endif
    if( pConstraint->usable==0 ){
      unusableMask |=  iMask;
      continue;
    }else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
      idxNum |= iMask;
      aIdx[iCol] = i;
    }
  }
  if( aIdx[3]==0 ){
    /* Ignore OFFSET if LIMIT is omitted */
    idxNum &= ~0x60;
    aIdx[4] = 0;
  }
  for(i=0; i<7; i++){
    if( (j = aIdx[i])>=0 ){
      pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
      pIdxInfo->aConstraintUsage[j].omit =
         !SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
    }
  }
  /* The current generate_column() implementation requires at least one
  ** argument (the START value).  Legacy versions assumed START=0 if the
  ** first argument was omitted.  Compile with -DZERO_ARGUMENT_GENERATE_SERIES
  ** to obtain the legacy behavior */

#ifndef ZERO_ARGUMENT_GENERATE_SERIES
  if( !bStartSeen ){
    sqlite3_free(pVTab->zErrMsg);
    pVTab->zErrMsg = sqlite3_mprintf(
        "first argument to \"generate_series()\" missing or unusable");
    return SQLITE_ERROR;
  }
#endif
  if( (unusableMask & ~idxNum)!=0 ){
    /* The start, stop, and step columns are inputs.  Therefore if there
    ** are unusable constraints on any of start, stop, or step then
    ** this plan is unusable */

    return SQLITE_CONSTRAINT;
  }
  if( (idxNum & 0x03)==0x03 ){
    /* Both start= and stop= boundaries are available.  This is the 
    ** the preferred case */

    pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
    pIdxInfo->estimatedRows = 1000;
    if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
      if( pIdxInfo->aOrderBy[0].desc ){
        idxNum |= 0x08;
      }else{
        idxNum |= 0x10;
      }
      pIdxInfo->orderByConsumed = 1;
    }
  }else if( (idxNum & 0x21)==0x21 ){
    /* We have start= and LIMIT */
    pIdxInfo->estimatedRows = 2500;
  }else{
    /* If either boundary is missing, we have to generate a huge span
    ** of numbers.  Make this case very expensive so that the query
    ** planner will work hard to avoid it. */

    pIdxInfo->estimatedRows = 2147483647;
  }
  pIdxInfo->idxNum = idxNum;
#ifdef SQLITE_INDEX_SCAN_HEX
  pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_HEX;
#endif
  return SQLITE_OK;
}

/*
** This following structure defines all the methods for the 
** generate_series virtual table.
*/

static sqlite3_module seriesModule = {
  0,                         /* iVersion */
  0,                         /* xCreate */
  seriesConnect,             /* xConnect */
  seriesBestIndex,           /* xBestIndex */
  seriesDisconnect,          /* xDisconnect */
  0,                         /* xDestroy */
  seriesOpen,                /* xOpen - open a cursor */
  seriesClose,               /* xClose - close a cursor */
  seriesFilter,              /* xFilter - configure scan constraints */
  seriesNext,                /* xNext - advance a cursor */
  seriesEof,                 /* xEof - check for end of scan */
  seriesColumn,              /* xColumn - read data */
  seriesRowid,               /* xRowid - read data */
  0,                         /* xUpdate */
  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
  0,                         /* xSavepoint */
  0,                         /* xRelease */
  0,                         /* xRollbackTo */
  0,                         /* xShadowName */
  0                          /* xIntegrity */
};

#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifdef _WIN32

#endif
int sqlite3_series_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( sqlite3_libversion_number()<3008012 && pzErrMsg!=0 ){
    *pzErrMsg = sqlite3_mprintf(
        "generate_series() requires SQLite 3.8.12 or later");
    return SQLITE_ERROR;
  }
  rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
#endif
  return rc;
}

/************************* End ext/misc/series.c ********************/
/************************* Begin ext/misc/regexp.c ******************/
/*
** 2012-11-13
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** The code in this file implements a compact but reasonably
** efficient regular-expression matcher for posix extended regular
** expressions against UTF8 text.
**
** This file is an SQLite extension.  It registers a single function
** named "regexp(A,B)" where A is the regular expression and B is the
** string to be matched.  By registering this function, SQLite will also
** then implement the "B regexp A" operator.  Note that with the function
** the regular expression comes first, but with the operator it comes
** second.
**
**  The following regular expression syntax is supported:
**
**     X*      zero or more occurrences of X
**     X+      one or more occurrences of X
**     X?      zero or one occurrences of X
**     X{p,q}  between p and q occurrences of X
**     (X)     match X
**     X|Y     X or Y
**     ^X      X occurring at the beginning of the string
**     X$      X occurring at the end of the string
**     .       Match any single character
**     \c      Character c where c is one of \{}()[]|*+?-.
**     \c      C-language escapes for c in afnrtv.  ex: \t or \n
**     \uXXXX  Where XXXX is exactly 4 hex digits, unicode value XXXX
**     \xXX    Where XX is exactly 2 hex digits, unicode value XX
**     [abc]   Any single character from the set abc
**     [^abc]  Any single character not in the set abc
**     [a-z]   Any single character in the range a-z
**     [^a-z]  Any single character not in the range a-z
**     \b      Word boundary
**     \w      Word character.  [A-Za-z0-9_]
**     \W      Non-word character
**     \d      Digit
**     \D      Non-digit
**     \s      Whitespace character
**     \S      Non-whitespace character
**
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string.  The matcher never
** exhibits exponential behavior.  Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
**
** To help prevent DoS attacks, the maximum size of the NFA is restricted.
*/

#include <string.h>
#include <stdlib.h>
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1

/*
** The following #defines change the names of some functions implemented in
** this file to prevent name collisions with C-library functions of the
** same name.
*/

#define re_match   sqlite3re_match
#define re_compile sqlite3re_compile
#define re_free    sqlite3re_free

/* 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.
*/

#define RE_OP_MATCH       1    /* Match the one character in the argument */
#define RE_OP_ANY         2    /* Match any one character.  (Implements ".") */
#define RE_OP_ANYSTAR     3    /* Special optimized version of .* */
#define RE_OP_FORK        4    /* Continue to both next and opcode at iArg */
#define RE_OP_GOTO        5    /* Jump to opcode at iArg */
#define RE_OP_ACCEPT      6    /* Halt and indicate a successful match */
#define RE_OP_CC_INC      7    /* Beginning of a [...] character class */
#define RE_OP_CC_EXC      8    /* Beginning of a [^...] character class */
#define RE_OP_CC_VALUE    9    /* Single value in a character class */
#define RE_OP_CC_RANGE   10    /* Range of values in a character class */
#define RE_OP_WORD       11    /* Perl word character [A-Za-z0-9_] */
#define RE_OP_NOTWORD    12    /* Not a perl word character */
#define RE_OP_DIGIT      13    /* digit:  [0-9] */
#define RE_OP_NOTDIGIT   14    /* Not a digit */
#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 */

/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;

/* Because this is an NFA and not a DFA, multiple states can be active at
** once.  An instance of the following object records all active states in
** the NFA.  The implementation is optimized for the common case where the
** number of actives states is small.
*/

typedef struct ReStateSet {
  unsigned nState;            /* Number of current states */
  ReStateNumber *aState;      /* Current states */
} ReStateSet;

/* An input string read one character at a time.
*/

typedef struct ReInput ReInput;
struct ReInput {
  const unsigned char *z;  /* All text */
  int i;                   /* Next byte to read */
  int mx;                  /* EOF when i>=mx */
};

/* A compiled NFA (or an NFA that is in the process of being compiled) is
** an instance of the following object.
*/

typedef struct ReCompiled ReCompiled;
struct ReCompiled {
  ReInput sIn;                /* Regular expression text */
  const char *zErr;           /* Error message to return */
  char *aOp;                  /* Operators for the virtual machine */
  int *aArg;                  /* Arguments to each operator */
  unsigned (*xNextChar)(ReInput*);  /* Next character function */
  unsigned char zInit[12];    /* Initial text to match */
  int nInit;                  /* Number of bytes in zInit */
  unsigned nState;            /* Number of entries in aOp[] and aArg[] */
  unsigned nAlloc;            /* Slots allocated for aOp[] and aArg[] */
  unsigned mxAlloc;           /* Complexity limit */
};

/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
  unsigned i;
  for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
  pSet->aState[pSet->nState++] = (ReStateNumber)newState;
}

/* Extract the next unicode character from *pzIn and return it.  Advance
** *pzIn to the first byte past the end of the character returned.  To
** be clear:  this routine converts utf8 to unicode.  This routine is 
** optimized for the common case where the next character is a single byte.
*/

static unsigned re_next_char(ReInput *p){
  unsigned c;
  if( p->i>=p->mx ) return 0;
  c = p->z[p->i++];
  if( c>=0x80 ){
    if( (c&0xe0)==0xc0 && p->i<p->mx && (p->z[p->i]&0xc0)==0x80 ){
      c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f);
      if( c<0x80 ) c = 0xfffd;
    }else if( (c&0xf0)==0xe0 && p->i+1<p->mx && (p->z[p->i]&0xc0)==0x80
           && (p->z[p->i+1]&0xc0)==0x80 ){
      c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
      p->i += 2;
      if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
    }else if( (c&0xf8)==0xf0 && p->i+2<p->mx && (p->z[p->i]&0xc0)==0x80
           && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
      c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
                       | (p->z[p->i+2]&0x3f);
      p->i += 3;
      if( c<=0xffff || c>0x10ffff ) c = 0xfffd;
    }else{
      c = 0xfffd;
    }
  }
  return c;
}
static unsigned re_next_char_nocase(ReInput *p){
  unsigned c = re_next_char(p);
  if( c>='A' && c<='Z' ) c += 'a' - 'A';
  return c;
}

/* Return true if c is a perl "word" character:  [A-Za-z0-9_] */
static int re_word_char(int c){
  return (c>='0' && c<='9') || (c>='a' && c<='z')
      || (c>='A' && c<='Z') || c=='_';
}

/* Return true if c is a "digit" character:  [0-9] */
static int re_digit_char(int c){
  return (c>='0' && c<='9');
}

/* Return true if c is a perl "space" character:  [ \t\r\n\v\f] */
static int re_space_char(int c){
  return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}

/* Run a compiled regular expression on the zero-terminated input
** string zIn[].  Return true on a match and false if there is no match.
*/

static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
  ReStateSet aStateSet[2], *pThis, *pNext;
  ReStateNumber aSpace[100];
  ReStateNumber *pToFree;
  unsigned int i = 0;
  unsigned int iSwap = 0;
  int c = RE_START;
  int cPrev = 0;
  int rc = 0;
  ReInput in;

  in.z = zIn;
  in.i = 0;
  in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);

  /* Look for the initial prefix match, if there is one. */
  if( pRe->nInit ){
    unsigned char x = pRe->zInit[0];
    while( in.i+pRe->nInit<=in.mx 
     && (zIn[in.i]!=x ||
         strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
    ){
      in.i++;
    }
    if( in.i+pRe->nInit>in.mx ) return 0;
    c = RE_START-1;
  }

  if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
    pToFree = 0;
    aStateSet[0].aState = aSpace;
  }else{
    pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState );
    if( pToFree==0 ) return -1;
    aStateSet[0].aState = pToFree;
  }
  aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
  pNext = &aStateSet[1];
  pNext->nState = 0;
  re_add_state(pNext, 0);
  while( c!=RE_EOF && pNext->nState>0 ){
    cPrev = c;
    c = pRe->xNextChar(&in);
    pThis = pNext;
    pNext = &aStateSet[iSwap];
    iSwap = 1 - iSwap;
    pNext->nState = 0;
    for(i=0; i<pThis->nState; i++){
      int x = pThis->aState[i];
      switch( pRe->aOp[x] ){
        case RE_OP_MATCH: {
          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;
        }
        case RE_OP_WORD: {
          if( re_word_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTWORD: {
          if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_DIGIT: {
          if( re_digit_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTDIGIT: {
          if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_SPACE: {
          if( re_space_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTSPACE: {
          if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_BOUNDARY: {
          if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_ANYSTAR: {
          re_add_state(pNext, x);
          re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_FORK: {
          re_add_state(pThis, x+pRe->aArg[x]);
          re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_GOTO: {
          re_add_state(pThis, x+pRe->aArg[x]);
          break;
        }
        case RE_OP_ACCEPT: {
          rc = 1;
          goto re_match_end;
        }
        case RE_OP_CC_EXC: {
          if( c==0 ) break;
          /* fall-through */ goto re_op_cc_inc;
        }
        case RE_OP_CC_INC: re_op_cc_inc: {
          int j = 1;
          int n = pRe->aArg[x];
          int hit = 0;
          for(j=1; j>0 && j<n; j++){
            if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
              if( pRe->aArg[x+j]==c ){
                hit = 1;
                j = -1;
              }
            }else{
              if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){
                hit = 1;
                j = -1;
              }else{
                j++;
              }
            }
          }
          if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
          if( hit ) re_add_state(pNext, x+n);
          break;
        }
      }
    }
  }
  for(i=0; i<pNext->nState; i++){
    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);
  return rc;
}

/* Resize the opcode and argument arrays for an RE under construction.
*/

static int re_resize(ReCompiled *p, unsigned int N){
  char *aOp;
  int *aArg;
  if( N>p->mxAlloc ){ p->zErr = "REGEXP pattern too big"; return 1; }
  aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
  if( aOp==0 ){ p->zErr = "out of memory"; return 1; }
  p->aOp = aOp;
  aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
  if( aArg==0 ){ p->zErr = "out of memory"; return 1; }
  p->aArg = aArg;
  p->nAlloc = N;
  return 0;
}

/* Insert a new opcode and argument into an RE under construction.  The
** insertion point is just prior to existing opcode iBefore.
*/

static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
  int i;
  if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
  for(i=p->nState; i>iBefore; i--){
    p->aOp[i] = p->aOp[i-1];
    p->aArg[i] = p->aArg[i-1];
  }
  p->nState++;
  p->aOp[iBefore] = (char)op;
  p->aArg[iBefore] = arg;
  return iBefore;
}

/* Append a new opcode and argument to the end of the RE under construction.
*/

static int re_append(ReCompiled *p, int op, int arg){
  return re_insert(p, p->nState, op, arg);
}

/* Make a copy of N opcodes starting at iStart onto the end of the RE
** under construction.
*/

static void re_copy(ReCompiled *p, int iStart, unsigned int N){
  if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
  memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
  memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
  p->nState += N;
}

/* Return true if c is a hexadecimal digit character:  [0-9a-fA-F]
** If c is a hex digit, also set *pV = (*pV)*16 + valueof(c).  If
** c is not a hex digit *pV is unchanged.
*/

static int re_hex(int c, int *pV){
  if( c>='0' && c<='9' ){
    c -= '0';
  }else if( c>='a' && c<='f' ){
    c -= 'a' - 10;
  }else if( c>='A' && c<='F' ){
    c -= 'A' - 10;
  }else{
    return 0;
  }
  *pV = (*pV)*16 + (c & 0xff);
  return 1;
}

/* A backslash character has been seen, read the next character and
** return its interpretation.
*/

static unsigned re_esc_char(ReCompiled *p){
  static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-";
  static const char zTrans[] = "\a\f\n\r\t\v";
  int i, v = 0;
  char c;
  if( p->sIn.i>=p->sIn.mx ) return 0;
  c = p->sIn.z[p->sIn.i];
  if( c=='u' && p->sIn.i+4<p->sIn.mx ){
    const unsigned char *zIn = p->sIn.z + p->sIn.i;
    if( re_hex(zIn[1],&v)
     && re_hex(zIn[2],&v)
     && re_hex(zIn[3],&v)
     && re_hex(zIn[4],&v)
    ){
      p->sIn.i += 5;
      return v;
    }
  }
  if( c=='x' && p->sIn.i+2<p->sIn.mx ){
    const unsigned char *zIn = p->sIn.z + p->sIn.i;
    if( re_hex(zIn[1],&v)
     && re_hex(zIn[2],&v)
    ){
      p->sIn.i += 3;
      return v;
    }
  }
  for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
  if( zEsc[i] ){
    if( i<6 ) c = zTrans[i];
    p->sIn.i++;
  }else{
    p->zErr = "unknown \\ escape";
  }
  return c;
}

/* Forward declaration */
static const char *re_subcompile_string(ReCompiled*);

/* Peek at the next byte of input */
static unsigned char rePeek(ReCompiled *p){
  return p->sIn.i<p->sIn.mx ? p->sIn.z[p->sIn.i] : 0;
}

/* Compile RE text into a sequence of opcodes.  Continue up to the
** first unmatched ")" character, then return.  If an error is found,
** return a pointer to the error message string.
*/

static const char *re_subcompile_re(ReCompiled *p){
  const char *zErr;
  int iStart, iEnd, iGoto;
  iStart = p->nState;
  zErr = re_subcompile_string(p);
  if( zErr ) return zErr;
  while( rePeek(p)=='|' ){
    iEnd = p->nState;
    re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart);
    iGoto = re_append(p, RE_OP_GOTO, 0);
    p->sIn.i++;
    zErr = re_subcompile_string(p);
    if( zErr ) return zErr;
    p->aArg[iGoto] = p->nState - iGoto;
  }
  return 0;
}

/* Compile an element of regular expression text (anything that can be
** an operand to the "|" operator).  Return NULL on success or a pointer
** to the error message if there is a problem.
*/

static const char *re_subcompile_string(ReCompiled *p){
  int iPrev = -1;
  int iStart;
  unsigned c;
  const char *zErr;
  while( (c = p->xNextChar(&p->sIn))!=0 ){
    iStart = p->nState;
    switch( c ){
      case '|':
      case ')': {
        p->sIn.i--;
        return 0;
      }
      case '(': {
        zErr = re_subcompile_re(p);
        if( zErr ) return zErr;
        if( rePeek(p)!=')' ) return "unmatched '('";
        p->sIn.i++;
        break;
      }
      case '.': {
        if( rePeek(p)=='*' ){
          re_append(p, RE_OP_ANYSTAR, 0);
          p->sIn.i++;
        }else{
          re_append(p, RE_OP_ANY, 0);
        }
        break;
      }
      case '*': {
        if( iPrev<0 ) return "'*' without operand";
        re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
        re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
        break;
      }
      case '+': {
        if( iPrev<0 ) return "'+' without operand";
        re_append(p, RE_OP_FORK, iPrev - p->nState);
        break;
      }
      case '?': {
        if( iPrev<0 ) return "'?' without operand";
        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 '{': {
        unsigned int m = 0, n = 0;
        unsigned int sz, j;
        if( iPrev<0 ) return "'{m,n}' without operand";
        while( (c=rePeek(p))>='0' && c<='9' ){
          m = m*10 + c - '0';
          if( m*2>p->mxAlloc ) return "REGEXP pattern too big";
          p->sIn.i++;
        }
        n = m;
        if( c==',' ){
          p->sIn.i++;
          n = 0;
          while( (c=rePeek(p))>='0' && c<='9' ){
            n = n*10 + c-'0';
            if( n*2>p->mxAlloc ) return "REGEXP pattern too big";
            p->sIn.i++;
          }
        }
        if( c!='}' ) return "unmatched '{'";
        if( n<m ) return "n less than m in '{m,n}'";
        p->sIn.i++;
        sz = p->nState - iPrev;
        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);
        }
        for(j=m; j<n; j++){
          re_append(p, RE_OP_FORK, sz+1);
          re_copy(p, iPrev, sz);
        }
        if( n==0 && m>0 ){
          re_append(p, RE_OP_FORK, -(int)sz);
        }
        break;
      }
      case '[': {
        unsigned int iFirst = p->nState;
        if( rePeek(p)=='^' ){
          re_append(p, RE_OP_CC_EXC, 0);
          p->sIn.i++;
        }else{
          re_append(p, RE_OP_CC_INC, 0);
        }
        while( (c = p->xNextChar(&p->sIn))!=0 ){
          if( c=='[' && rePeek(p)==':' ){
            return "POSIX character classes not supported";
          }
          if( c=='\\' ) c = re_esc_char(p);
          if( rePeek(p)=='-' ){
            re_append(p, RE_OP_CC_RANGE, c);
            p->sIn.i++;
            c = p->xNextChar(&p->sIn);
            if( c=='\\' ) c = re_esc_char(p);
            re_append(p, RE_OP_CC_RANGE, c);
          }else{
            re_append(p, RE_OP_CC_VALUE, c);
          }
          if( rePeek(p)==']' ){ p->sIn.i++; break; }
        }
        if( c==0 ) return "unclosed '['";
        if( p->nState>iFirst ) p->aArg[iFirst] = p->nState - iFirst;
        break;
      }
      case '\\': {
        int specialOp = 0;
        switch( rePeek(p) ){
          case 'b': specialOp = RE_OP_BOUNDARY;   break;
          case 'd': specialOp = RE_OP_DIGIT;      break;
          case 'D': specialOp = RE_OP_NOTDIGIT;   break;
          case 's': specialOp = RE_OP_SPACE;      break;
          case 'S': specialOp = RE_OP_NOTSPACE;   break;
          case 'w': specialOp = RE_OP_WORD;       break;
          case 'W': specialOp = RE_OP_NOTWORD;    break;
        }
        if( specialOp ){
          p->sIn.i++;
          re_append(p, specialOp, 0);
        }else{
          c = re_esc_char(p);
          re_append(p, RE_OP_MATCH, c);
        }
        break;
      }
      default: {
        re_append(p, RE_OP_MATCH, c);
        break;
      }
    }
    iPrev = iStart;
  }
  return 0;
}

/* Free and reclaim all the memory used by a previously compiled
** regular expression.  Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/

static void re_free(ReCompiled *pRe){
  if( pRe ){
    sqlite3_free(pRe->aOp);
    sqlite3_free(pRe->aArg);
    sqlite3_free(pRe);
  }
}

/*
** Version of re_free() that accepts a pointer of type (void*). Required
** to satisfy sanitizers when the re_free() function is called via a
** function pointer.
*/

static void re_free_voidptr(void *p){
  re_free((ReCompiled*)p);
}

/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_match() and return a pointer to the
** compiled regular expression in *ppRe.  Return NULL on success or an
** error message if something goes wrong.
*/

static const char *re_compile(
  ReCompiled **ppRe,      /* OUT: write compiled NFA here */
  const char *zIn,        /* Input regular expression */
  int mxRe,               /* Complexity limit */
  int noCase              /* True for caseless comparisons */
){
  ReCompiled *pRe;
  const char *zErr;
  int i, j;

  *ppRe = 0;
  pRe = sqlite3_malloc64( sizeof(*pRe) );
  if( pRe==0 ){
    return "out of memory";
  }
  memset(pRe, 0, sizeof(*pRe));
  pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char;
  pRe->mxAlloc = mxRe;
  if( re_resize(pRe, 30) ){
    zErr = pRe->zErr;
    re_free(pRe);
    return zErr;
  }
  if( zIn[0]=='^' ){
    zIn++;
  }else{
    re_append(pRe, RE_OP_ANYSTAR, 0);
  }
  pRe->sIn.z = (unsigned char*)zIn;
  pRe->sIn.i = 0;
  pRe->sIn.mx = (int)strlen(zIn);
  zErr = re_subcompile_re(pRe);
  if( zErr ){
    re_free(pRe);
    return zErr;
  }
  if( pRe->sIn.i>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_ACCEPT, 0);
    *ppRe = pRe;
  }else{
    re_free(pRe);
    return "unrecognized character";
  }

  /* The following is a performance optimization.  If the regex begins with
  ** ".*" (if the input regex lacks an initial "^") and afterwards there are
  ** one or more matching characters, enter those matching characters into
  ** zInit[].  The re_match() routine can then search ahead in the input 
  ** string looking for the initial match without having to run the whole
  ** regex engine over the string.  Do not worry about trying to match
  ** unicode characters beyond plane 0 - those are very rare and this is
  ** just an optimization. */

  if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
    for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
      unsigned x = pRe->aArg[i];
      if( x<=0x7f ){
        pRe->zInit[j++] = (unsigned char)x;
      }else if( x<=0x7ff ){
        pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else if( x<=0xffff ){
        pRe->zInit[j++] = (unsigned char)(0xe0 | (x>>12));
        pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else{
        break;
      }
    }
    if( j>0 && pRe->zInit[j-1]==0 ) j--;
    pRe->nInit = j;
  }
  return pRe->zErr;
}

/*
** The value of LIMIT_MAX_PATTERN_LENGTH.
*/

static int re_maxlen(sqlite3_context *context){
  sqlite3 *db = sqlite3_context_db_handle(context);
  return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1);
}

/*
** Maximum NFA size given a maximum pattern length.
*/

static int re_maxnfa(int mxlen){
  return 75+mxlen/2;
}

/*
** Implementation of the regexp() SQL function.  This function implements
** the build-in REGEXP operator.  The first argument to the function is the
** pattern and the second argument is the string.  So, the SQL statements:
**
**       A REGEXP B
**
** is implemented as regexp(B,A).
*/

static void re_sql_func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  ReCompiled *pRe;          /* Compiled regular expression */
  const char *zPattern;     /* The regular expression */
  const unsigned char *zStr;/* String being searched */
  const char *zErr;         /* Compile error message */
  int setAux = 0;           /* True to invoke sqlite3_set_auxdata() */

  (void)argc;  /* Unused */
  pRe = sqlite3_get_auxdata(context, 0);
  if( pRe==0 ){
    int mxLen = re_maxlen(context);
    int nPattern;
    zPattern = (const char*)sqlite3_value_text(argv[0]);
    if( zPattern==0 ) return;
    nPattern = sqlite3_value_bytes(argv[0]);
    if( nPattern>mxLen ){
      zErr = "REGEXP pattern too big";
    }else{
      zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen),
                        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;
    }
    setAux = 1;
  }
  zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
  if( zStr!=0 ){
    sqlite3_result_int(context, re_match(pRe, zStr, -1));
  }
  if( setAux ){
    sqlite3_set_auxdata(context, 0, pRe, re_free_voidptr);
  }
}

#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;
  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",
  };

  (void)argc;
  zPattern = (const char*)sqlite3_value_text(argv[0]);
  if( zPattern==0 ) return;
  zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)),
                    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.
*/

#ifdef _WIN32

#endif
int sqlite3_regexp_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused */
  rc = sqlite3_create_function(db, "regexp", 2, 
                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                            0, re_sql_func, 0, 0);
  if( rc==SQLITE_OK ){
    /* The regexpi(PATTERN,STRING) function is a case-insensitive version
    ** of regexp(PATTERN,STRING). */

    rc = sqlite3_create_function(db, "regexpi", 2,
                            SQLITE_UTF8|SQLITE_INNOCUOUS|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_FIDDLE
/************************* Begin ext/misc/fileio.c ******************/
/*
** 2014-06-13
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This SQLite extension implements SQL functions readfile() and
** writefile(), and eponymous virtual type "fsdir".
**
** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
**
**   If neither of the optional arguments is present, then this UDF
**   function writes blob DATA to file FILE. If successful, the number
**   of bytes written is returned. If an error occurs, NULL is returned.
**
**   If the first option argument - MODE - is present, then it must
**   be passed an integer value that corresponds to a POSIX mode
**   value (file type + permissions, as returned in the stat.st_mode
**   field by the stat() system call). Three types of files may
**   be written/created:
**
**     regular files:  (mode & 0170000)==0100000
**     symbolic links: (mode & 0170000)==0120000
**     directories:    (mode & 0170000)==0040000
**
**   For a directory, the DATA is ignored. For a symbolic link, it is
**   interpreted as text and used as the target of the link. For a
**   regular file, it is interpreted as a blob and written into the
**   named file. Regardless of the type of file, its permissions are
**   set to (mode & 0777) before returning.
**
**   If the optional MTIME argument is present, then it is interpreted
**   as an integer - the number of seconds since the unix epoch. The
**   modification-time of the target file is set to this value before
**   returning.
**
**   If five or more arguments are passed to this function and an
**   error is encountered, an exception is raised.
**
** READFILE(FILE):
**
**   Read and return the contents of file FILE (type blob) from disk.
**
** FSDIR:
**
**   Used as follows:
**
**     SELECT * FROM fsdir($path [, $dir]);
**
**   Parameter $path is an absolute or relative pathname. If the file that it
**   refers to does not exist, it is an error. If the path refers to a regular
**   file or symbolic link, it returns a single row. Or, if the path refers
**   to a directory, it returns one row for the directory, and one row for each
**   file within the hierarchy rooted at $path.
**
**   Each row has the following columns:
**
**     name:  Path to file or directory (text value).
**     mode:  Value of stat.st_mode for directory entry (an integer).
**     mtime: Value of stat.st_mtime for directory entry (an integer).
**     data:  For a regular file, a blob containing the file data. For a
**            symlink, a text value containing the text of the link. For a
**            directory, NULL.
**     level: Directory hierarchy level.  Topmost is 1.
**
**   If a non-NULL value is specified for the optional $dir parameter and
**   $path is a relative path, then $path is interpreted relative to $dir. 
**   And the paths returned in the "name" column of the table are also 
**   relative to directory $dir.
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if !defined(_WIN32) && !defined(WIN32)
#  include <unistd.h>
#  include <dirent.h>
#  include <utime.h>
#  include <sys/time.h>
#  define STRUCT_STAT struct stat
#  include <limits.h>
#  include <stdlib.h>
#else
/* #  include "windirent.h" */
#  include <direct.h>
#  define STRUCT_STAT struct _stat
#  define chmod(path,mode) fileio_chmod(path,mode)
#  define mkdir(path,mode) fileio_mkdir(path)
   extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
   extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
#endif
#include <time.h>
#include <errno.h>

/* When used as part of the CLI, the sqlite3_stdio.h module will have
** been included before this one. In that case use the sqlite3_stdio.h
** #defines.  If not, create our own for fopen().
*/

#ifndef _SQLITE3_STDIO_H_
# define sqlite3_fopen fopen
#endif

/*
** Structure of the fsdir() table-valued function
*/

                 /*    0    1    2     3    4     5           6          */
#define FSDIR_SCHEMA "(name,mode,mtime,data,level,path HIDDEN,dir HIDDEN)"

#define FSDIR_COLUMN_NAME     0     /* Name of the file */
#define FSDIR_COLUMN_MODE     1     /* Access mode */
#define FSDIR_COLUMN_MTIME    2     /* Last modification time */
#define FSDIR_COLUMN_DATA     3     /* File content */
#define FSDIR_COLUMN_LEVEL    4     /* Level.  Topmost is 1 */
#define FSDIR_COLUMN_PATH     5     /* Path to top of search */
#define FSDIR_COLUMN_DIR      6     /* Path is relative to this directory */

/*
** UTF8 chmod() function for Windows
*/

#if defined(_WIN32) || defined(WIN32)
static int fileio_chmod(const char *zPath, int pmode){
  int rc;
  wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
  if( b1==0 ) return -1;
  rc = _wchmod(b1, pmode);
  sqlite3_free(b1);
  return rc;
}
#endif

/*
** UTF8 mkdir() function for Windows
*/

#if defined(_WIN32) || defined(WIN32)
static int fileio_mkdir(const char *zPath){
  int rc;
  wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
  if( b1==0 ) return -1;
  rc = _wmkdir(b1);
  sqlite3_free(b1);
  return rc;
}
#endif


/*
** Set the result stored by context ctx to a blob containing the 
** contents of file zName.  Or, leave the result unchanged (NULL)
** if the file does not exist or is unreadable.
**
** If the file exceeds the SQLite blob size limit, through an
** SQLITE_TOOBIG error.
**
** Throw an SQLITE_IOERR if there are difficulties pulling the file
** off of disk.
*/

static void readFileContents(sqlite3_context *ctx, const char *zName){
  FILE *in;
  sqlite3_int64 nIn;
  void *pBuf;
  sqlite3 *db;
  int mxBlob;

  in = sqlite3_fopen(zName, "rb");
  if( in==0 ){
    /* File does not exist or is unreadable. Leave the result set to NULL. */
    return;
  }
  fseek(in, 0, SEEK_END);
  nIn = ftell(in);
  rewind(in);
  db = sqlite3_context_db_handle(ctx);
  mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
  if( nIn>mxBlob ){
    sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
    fclose(in);
    return;
  }
  pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
  if( pBuf==0 ){
    sqlite3_result_error_nomem(ctx);
    fclose(in);
    return;
  }
  if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
    sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
  }else{
    sqlite3_result_error_code(ctx, SQLITE_IOERR);
    sqlite3_free(pBuf);
  }
  fclose(in);
}

/*
** Implementation of the "readfile(X)" SQL function.  The entire content
** of the file named X is read and returned as a BLOB.  NULL is returned
** if the file does not exist or is unreadable.
*/

static void readfileFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName;
  (void)(argc);  /* Unused parameter */
  zName = (const char*)sqlite3_value_text(argv[0]);
  if( zName==0 ) return;
  readFileContents(context, zName);
}

/*
** Set the error message contained in context ctx to the results of
** vprintf(zFmt, ...).
*/

static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
  char *zMsg = 0;
  va_list ap;
  va_start(ap, zFmt);
  zMsg = sqlite3_vmprintf(zFmt, ap);
  sqlite3_result_error(ctx, zMsg, -1);
  sqlite3_free(zMsg);
  va_end(ap);
}

#if defined(_WIN32)
/*
** This function is designed to convert a Win32 FILETIME structure into the
** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
*/

static sqlite3_uint64 fileTimeToUnixTime(
  LPFILETIME pFileTime
){
  SYSTEMTIME epochSystemTime;
  ULARGE_INTEGER epochIntervals;
  FILETIME epochFileTime;
  ULARGE_INTEGER fileIntervals;

  memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
  epochSystemTime.wYear = 1970;
  epochSystemTime.wMonth = 1;
  epochSystemTime.wDay = 1;
  SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
  epochIntervals.LowPart = epochFileTime.dwLowDateTime;
  epochIntervals.HighPart = epochFileTime.dwHighDateTime;

  fileIntervals.LowPart = pFileTime->dwLowDateTime;
  fileIntervals.HighPart = pFileTime->dwHighDateTime;

  return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
}
#endif /* _WIN32 */

/*
** This function is used in place of stat().  On Windows, special handling
** is required in order for the included time to be returned as UTC.  On all
** other systems, this function simply calls stat().
*/

static int fileStat(
  const char *zPath,
  STRUCT_STAT *pStatBuf
){
#if defined(_WIN32)
  int rc;
  wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
  if( b1==0 ) return 1;
  rc = _wstat(b1, pStatBuf);
  if( rc==0 ){
    HANDLE hFindFile;
    WIN32_FIND_DATAW fd;
    memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
    hFindFile = FindFirstFileW(b1, &fd);
    if( hFindFile!=NULL ){
      pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
      pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
      pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
      FindClose(hFindFile);
    }
  }
  sqlite3_free(b1);
  return rc;
#else
  return stat(zPath, pStatBuf);
#endif
}

/*
** This function is used in place of lstat().  On Windows, special handling
** is required in order for the included time to be returned as UTC.  On all
** other systems, this function simply calls lstat().
*/

static int fileLinkStat(
  const char *zPath,
  STRUCT_STAT *pStatBuf
){
#if defined(_WIN32)
  return fileStat(zPath, pStatBuf);
#else
  return lstat(zPath, pStatBuf);
#endif
}

/*
** Argument zFile is the name of a file that will be created and/or written
** by SQL function writefile(). This function ensures that the directory
** zFile will be written to exists, creating it if required. The permissions
** for any path components created by this function are set in accordance
** with the current umask.
**
** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
** SQLITE_OK is returned if the directory is successfully created, or
** SQLITE_ERROR otherwise.
*/

static int makeDirectory(
  const char *zFile
){
  char *zCopy = sqlite3_mprintf("%s", zFile);
  int rc = SQLITE_OK;

  if( zCopy==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int nCopy = (int)strlen(zCopy);
    int i = 1;

    while( rc==SQLITE_OK ){
      STRUCT_STAT sStat;
      int rc2;

      for(; zCopy[i]!='/' && i<nCopy; i++);
      if( i==nCopy ) break;
      zCopy[i] = '\0';

      rc2 = fileStat(zCopy, &sStat);
      if( rc2!=0 ){
        if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
      }else{
        if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
      }
      zCopy[i] = '/';
      i++;
    }

    sqlite3_free(zCopy);
  }

  return rc;
}

/*
** This function does the work for the writefile() UDF. Refer to 
** header comments at the top of this file for details.
*/

static int writeFile(
  sqlite3_context *pCtx,          /* Context to return bytes written in */
  const char *zFile,              /* File to write */
  sqlite3_value *pData,           /* Data to write */
  mode_t mode,                    /* MODE parameter passed to writefile() */
  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
){
  if( zFile==0 ) return 1;
#if !defined(_WIN32) && !defined(WIN32)
  if( S_ISLNK(mode) ){
    const char *zTo = (const char*)sqlite3_value_text(pData);
    if( zTo==0 ) return 1;
    unlink(zFile);
    if( symlink(zTo, zFile)<0 ) return 1;
  }else
#endif
  {
    if( S_ISDIR(mode) ){
      if( mkdir(zFile, mode) ){
        /* The mkdir() call to create the directory failed. This might not
        ** be an error though - if there is already a directory at the same
        ** path and either the permissions already match or can be changed
        ** to do so using chmod(), it is not an error.  */

        STRUCT_STAT sStat;
        if( errno!=EEXIST
         || 0!=fileStat(zFile, &sStat)
         || !S_ISDIR(sStat.st_mode)
         || ((sStat.st_mode&0777)!=(mode&>0777) && 0!=chmod(zFile, mode&0777))
        ){
          return 1;
        }
      }
    }else{
      sqlite3_int64 nWrite = 0;
      const char *z;
      int rc = 0;
      FILE *out = sqlite3_fopen(zFile, "wb");
      if( out==0 ) return 1;
      z = (const char*)sqlite3_value_blob(pData);
      if( z ){
        sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
        nWrite = sqlite3_value_bytes(pData);
        if( nWrite!=n ){
          rc = 1;
        }
      }
      fclose(out);
      if( rc==0 && mode && chmod(zFile, mode & 0777) ){
        rc = 1;
      }
      if( rc ) return 2;
      sqlite3_result_int64(pCtx, nWrite);
    }
  }

  if( mtime>=0 ){
#if defined(_WIN32)
    /* Windows */
    FILETIME lastAccess;
    FILETIME lastWrite;
    SYSTEMTIME currentTime;
    LONGLONG intervals;
    HANDLE hFile;
    LPWSTR zUnicodeName;
    extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);

    GetSystemTime(¤tTime);
    SystemTimeToFileTime(¤tTime, &lastAccess);
    intervals = (mtime*10000000) + 116444736000000000;
    lastWrite.dwLowDateTime = (DWORD)intervals;
    lastWrite.dwHighDateTime = intervals >> 32;
    zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
    if( zUnicodeName==0 ){
      return 1;
    }
    hFile = CreateFileW(
      zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS, NULL
    );
    sqlite3_free(zUnicodeName);
    if( hFile!=INVALID_HANDLE_VALUE ){
      BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
      CloseHandle(hFile);
      return !bResult;
    }else{
      return 1;
    }
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
    /* Recent unix */
    struct timespec times[2];
    times[0].tv_nsec = times[1].tv_nsec = 0;
    times[0].tv_sec = time(0);
    times[1].tv_sec = mtime;
    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
      return 1;
    }
#else
    /* Legacy unix. 
    **
    ** Do not use utimes() on a symbolic link - it sees through the link and
    ** modifies the timestamps on the target. Or fails if the target does 
    ** not exist.  */

    if( 0==S_ISLNK(mode) ){
      struct timeval times[2];
      times[0].tv_usec = times[1].tv_usec = 0;
      times[0].tv_sec = time(0);
      times[1].tv_sec = mtime;
      if( utimes(zFile, times) ){
        return 1;
      }
    }
#endif
  }

  return 0;
}

/*
** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.  
** Refer to header comments at the top of this file for details.
*/

static void writefileFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zFile;
  mode_t mode = 0;
  int res;
  sqlite3_int64 mtime = -1;

  if( argc<2 || argc>4 ){
    sqlite3_result_error(context, 
        "wrong number of arguments to function writefile()", -1
    );
    return;
  }

  zFile = (const char*)sqlite3_value_text(argv[0]);
  if( zFile==0 ) return;
  if( argc>=3 ){
    mode = (mode_t)sqlite3_value_int(argv[2]);
  }
  if( argc==4 ){
    mtime = sqlite3_value_int64(argv[3]);
  }

  res = writeFile(context, zFile, argv[1], mode, mtime);
  if( res==1 && errno==ENOENT ){
    if( makeDirectory(zFile)==SQLITE_OK ){
      res = writeFile(context, zFile, argv[1], mode, mtime);
    }
  }

  if( argc>2 && res!=0 ){
    if( S_ISLNK(mode) ){
      ctxErrorMsg(context, "failed to create symlink: %s", zFile);
    }else if( S_ISDIR(mode) ){
      ctxErrorMsg(context, "failed to create directory: %s", zFile);
    }else{
      ctxErrorMsg(context, "failed to write file: %s", zFile);
    }
  }
}

/*
** SQL function:   lsmode(MODE)
**
** Given a numberic st_mode from stat(), convert it into a human-readable
** text string in the style of "ls -l".
*/

static void lsModeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int i;
  int iMode = sqlite3_value_int(argv[0]);
  char z[16];
  (void)argc;
  if( S_ISLNK(iMode) ){
    z[0] = 'l';
  }else if( S_ISREG(iMode) ){
    z[0] = '-';
  }else if( S_ISDIR(iMode) ){
    z[0] = 'd';
  }else{
    z[0] = '?';
  }
  for(i=0; i<3; i++){
    int m = (iMode >> ((2-i)*3));
    char *a = &z[1 + i*3];
    a[0] = (m & 0x4) ? 'r' : '-';
    a[1] = (m & 0x2) ? 'w' : '-';
    a[2] = (m & 0x1) ? 'x' : '-';
  }
  z[10] = '\0';
  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
}

#ifndef SQLITE_OMIT_VIRTUALTABLE

/* 
** Cursor type for recursively iterating through a directory structure.
*/

typedef struct fsdir_cursor fsdir_cursor;
typedef struct FsdirLevel FsdirLevel;

struct FsdirLevel {
  DIR *pDir;                 /* From opendir() */
  char *zDir;                /* Name of directory (nul-terminated) */
};

struct fsdir_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */

  int nLvl;                  /* Number of entries in aLvl[] array */
  int mxLvl;                 /* Maximum level */
  int iLvl;                  /* Index of current entry */
  FsdirLevel *aLvl;          /* Hierarchy of directories being traversed */

  const char *zBase;
  int nBase;

  STRUCT_STAT sStat;         /* Current lstat() results */
  char *zPath;               /* Path to current entry */
  sqlite3_int64 iRowid;      /* Current rowid */
};

typedef struct fsdir_tab fsdir_tab;
struct fsdir_tab {
  sqlite3_vtab base;         /* Base class - must be first */
};

/*
** Construct a new fsdir virtual table object.
*/

static int fsdirConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  fsdir_tab *pNew = 0;
  int rc;
  (void)pAux;
  (void)argc;
  (void)argv;
  (void)pzErr;
  rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
  if( rc==SQLITE_OK ){
    pNew = (fsdir_tab*)sqlite3_malloc64( sizeof(*pNew) );
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
  }
  *ppVtab = (sqlite3_vtab*)pNew;
  return rc;
}

/*
** This method is the destructor for fsdir vtab objects.
*/

static int fsdirDisconnect(sqlite3_vtab *pVtab){
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** Constructor for a new fsdir_cursor object.
*/

static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  fsdir_cursor *pCur;
  (void)p;
  pCur = sqlite3_malloc64( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  pCur->iLvl = -1;
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Reset a cursor back to the state it was in when first returned
** by fsdirOpen().
*/

static void fsdirResetCursor(fsdir_cursor *pCur){
  int i;
  for(i=0; i<=pCur->iLvl; i++){
    FsdirLevel *pLvl = &pCur->aLvl[i];
    if( pLvl->pDir ) closedir(pLvl->pDir);
    sqlite3_free(pLvl->zDir);
  }
  sqlite3_free(pCur->zPath);
  sqlite3_free(pCur->aLvl);
  pCur->aLvl = 0;
  pCur->zPath = 0;
  pCur->zBase = 0;
  pCur->nBase = 0;
  pCur->nLvl = 0;
  pCur->iLvl = -1;
  pCur->iRowid = 1;
}

/*
** Destructor for an fsdir_cursor.
*/

static int fsdirClose(sqlite3_vtab_cursor *cur){
  fsdir_cursor *pCur = (fsdir_cursor*)cur;

  fsdirResetCursor(pCur);
  sqlite3_free(pCur);
  return SQLITE_OK;
}

/*
** Set the error message for the virtual table associated with cursor
** pCur to the results of vprintf(zFmt, ...).
*/

static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
  va_list ap;
  va_start(ap, zFmt);
  pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
  va_end(ap);
}


/*
** Advance an fsdir_cursor to its next row of output.
*/

static int fsdirNext(sqlite3_vtab_cursor *cur){
  fsdir_cursor *pCur = (fsdir_cursor*)cur;
  mode_t m = pCur->sStat.st_mode;

  pCur->iRowid++;
  if( S_ISDIR(m) && pCur->iLvl+3<pCur->mxLvl ){
    /* Descend into this directory */
    int iNew = pCur->iLvl + 1;
    FsdirLevel *pLvl;
    if( iNew>=pCur->nLvl ){
      int nNew = iNew+1;
      sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
      FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
      if( aNew==0 ) return SQLITE_NOMEM;
      memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
      pCur->aLvl = aNew;
      pCur->nLvl = nNew;
    }
    pCur->iLvl = iNew;
    pLvl = &pCur->aLvl[iNew];
    
    pLvl->zDir = pCur->zPath;
    pCur->zPath = 0;
    pLvl->pDir = opendir(pLvl->zDir);
    if( pLvl->pDir==0 ){
      fsdirSetErrmsg(pCur, "cannot read directory: %s", pLvl->zDir);
      return SQLITE_ERROR;
    }
  }

  while( pCur->iLvl>=0 ){
    FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
    struct dirent *pEntry = readdir(pLvl->pDir);
    if( pEntry ){
      if( pEntry->d_name[0]=='.' ){
       if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
       if( pEntry->d_name[1]=='\0' ) continue;
      }
      sqlite3_free(pCur->zPath);
      pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
      if( pCur->zPath==0 ) return SQLITE_NOMEM;
      if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
        fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
        return SQLITE_ERROR;
      }
      return SQLITE_OK;
    }
    closedir(pLvl->pDir);
    sqlite3_free(pLvl->zDir);
    pLvl->pDir = 0;
    pLvl->zDir = 0;
    pCur->iLvl--;
  }

  /* EOF */
  sqlite3_free(pCur->zPath);
  pCur->zPath = 0;
  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the series_cursor
** is currently pointing.
*/

static int fsdirColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  fsdir_cursor *pCur = (fsdir_cursor*)cur;
  switch( i ){
    case FSDIR_COLUMN_NAME: {
      sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
      break;
    }

    case FSDIR_COLUMN_MODE:
      sqlite3_result_int64(ctx, pCur->sStat.st_mode);
      break;

    case FSDIR_COLUMN_MTIME:
      sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
      break;

    case FSDIR_COLUMN_DATA: {
      mode_t m = pCur->sStat.st_mode;
      if( S_ISDIR(m) ){
        sqlite3_result_null(ctx);
#if !defined(_WIN32) && !defined(WIN32)
      }else if( S_ISLNK(m) ){
        char aStatic[64];
        char *aBuf = aStatic;
        sqlite3_int64 nBuf = 64;
        int n;

        while( 1 ){
          n = readlink(pCur->zPath, aBuf, nBuf);
          if( n<nBuf ) break;
          if( aBuf!=aStatic ) sqlite3_free(aBuf);
          nBuf = nBuf*2;
          aBuf = sqlite3_malloc64(nBuf);
          if( aBuf==0 ){
            sqlite3_result_error_nomem(ctx);
            return SQLITE_NOMEM;
          }
        }

        sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
        if( aBuf!=aStatic ) sqlite3_free(aBuf);
#endif
      }else{
        readFileContents(ctx, pCur->zPath);
      }
      break;
    }
    case FSDIR_COLUMN_LEVEL:
      sqlite3_result_int(ctx, pCur->iLvl+2);
      break;
    case FSDIR_COLUMN_PATH:
    default: {
      /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
      ** always return their values as NULL */

      break;
    }
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row. In this implementation, the
** first row returned is assigned rowid value 1, and each subsequent
** row a value 1 more than that of the previous.
*/

static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  fsdir_cursor *pCur = (fsdir_cursor*)cur;
  *pRowid = pCur->iRowid;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/

static int fsdirEof(sqlite3_vtab_cursor *cur){
  fsdir_cursor *pCur = (fsdir_cursor*)cur;
  return (pCur->zPath==0);
}

/*
** xFilter callback.
**
** idxNum bit      Meaning
**     0x01         PATH=N
**     0x02         DIR=N
**     0x04         LEVEL<N
**     0x08         LEVEL<=N  
*/

static int fsdirFilter(
  sqlite3_vtab_cursor *cur, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  const char *zDir = 0;
  fsdir_cursor *pCur = (fsdir_cursor*)cur;
  int i;
  (void)idxStr;
  fsdirResetCursor(pCur);

  if( idxNum==0 ){
    fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
    return SQLITE_ERROR;
  }

  assert( (idxNum & 0x01)!=0 && argc>0 );
  zDir = (const char*)sqlite3_value_text(argv[0]);
  if( zDir==0 ){
    fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
    return SQLITE_ERROR;
  }
  i = 1;
  if( (idxNum & 0x02)!=0 ){
    assert( argc>i );
    pCur->zBase = (const char*)sqlite3_value_text(argv[i++]);
  }
  if( (idxNum & 0x0c)!=0 ){
    assert( argc>i );
    pCur->mxLvl = sqlite3_value_int(argv[i++]);
    if( idxNum & 0x08 ) pCur->mxLvl++;
    if( pCur->mxLvl<=0 ) pCur->mxLvl = 1000000000;
  }else{
    pCur->mxLvl = 1000000000;
  }
  if( pCur->zBase ){
    pCur->nBase = (int)strlen(pCur->zBase)+1;
    pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
  }else{
    pCur->zPath = sqlite3_mprintf("%s", zDir);
  }

  if( pCur->zPath==0 ){
    return SQLITE_NOMEM;
  }
  if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
    fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
    return SQLITE_ERROR;
  }

  return SQLITE_OK;
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the generate_series virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** In this implementation idxNum is used to represent the
** query plan.  idxStr is unused.
**
** The query plan is represented by bits in idxNum:
**
**  0x01  The path value is supplied by argv[0]
**  0x02  dir is in argv[1]
**  0x04  maxdepth is in argv[1] or [2]
*/

static int fsdirBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;                 /* Loop over constraints */
  int idxPath = -1;      /* Index in pIdxInfo->aConstraint of PATH= */
  int idxDir = -1;       /* Index in pIdxInfo->aConstraint of DIR= */
  int idxLevel = -1;     /* Index in pIdxInfo->aConstraint of LEVEL< or <= */
  int idxLevelEQ = 0;    /* 0x08 for LEVEL<= or LEVEL=.  0x04 for LEVEL< */
  int omitLevel = 0;     /* omit the LEVEL constraint */
  int seenPath = 0;      /* True if an unusable PATH= constraint is seen */
  int seenDir = 0;       /* True if an unusable DIR= constraint is seen */
  const struct sqlite3_index_constraint *pConstraint;

  (void)tab;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
      switch( pConstraint->iColumn ){
        case FSDIR_COLUMN_PATH: {
          if( pConstraint->usable ){
            idxPath = i;
            seenPath = 0;
          }else if( idxPath<0 ){
            seenPath = 1;
          }
          break;
        }
        case FSDIR_COLUMN_DIR: {
          if( pConstraint->usable ){
            idxDir = i;
            seenDir = 0;
          }else if( idxDir<0 ){
            seenDir = 1;
          }
          break;
        }
        case FSDIR_COLUMN_LEVEL: {
          if( pConstraint->usable && idxLevel<0 ){
            idxLevel = i;
            idxLevelEQ = 0x08;
            omitLevel = 0;
          }
          break;
        }
      }
    }else
    if( pConstraint->iColumn==FSDIR_COLUMN_LEVEL
     && pConstraint->usable
     && idxLevel<0
    ){
      if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){
        idxLevel = i;
        idxLevelEQ = 0x08;
        omitLevel = 1;
      }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
        idxLevel = i;
        idxLevelEQ = 0x04;
        omitLevel = 1;
      }
    } 
  }
  if( seenPath || seenDir ){
    /* If input parameters are unusable, disallow this plan */
    return SQLITE_CONSTRAINT;
  }

  if( idxPath<0 ){
    pIdxInfo->idxNum = 0;
    /* The pIdxInfo->estimatedCost should have been initialized to a huge
    ** number.  Leave it unchanged. */

    pIdxInfo->estimatedRows = 0x7fffffff;
  }else{
    pIdxInfo->aConstraintUsage[idxPath].omit = 1;
    pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
    pIdxInfo->idxNum = 0x01;
    pIdxInfo->estimatedCost = 1.0e9;
    i = 2;
    if( idxDir>=0 ){
      pIdxInfo->aConstraintUsage[idxDir].omit = 1;
      pIdxInfo->aConstraintUsage[idxDir].argvIndex = i++;
      pIdxInfo->idxNum |= 0x02;
      pIdxInfo->estimatedCost /= 1.0e4;
    }
    if( idxLevel>=0 ){
      pIdxInfo->aConstraintUsage[idxLevel].omit = omitLevel;
      pIdxInfo->aConstraintUsage[idxLevel].argvIndex = i++;
      pIdxInfo->idxNum |= idxLevelEQ;
      pIdxInfo->estimatedCost /= 1.0e4;
    }
  }

  return SQLITE_OK;
}

/*
** Register the "fsdir" virtual table.
*/

static int fsdirRegister(sqlite3 *db){
  static sqlite3_module fsdirModule = {
    0,                         /* iVersion */
    0,                         /* xCreate */
    fsdirConnect,              /* xConnect */
    fsdirBestIndex,            /* xBestIndex */
    fsdirDisconnect,           /* xDisconnect */
    0,                         /* xDestroy */
    fsdirOpen,                 /* xOpen - open a cursor */
    fsdirClose,                /* xClose - close a cursor */
    fsdirFilter,               /* xFilter - configure scan constraints */
    fsdirNext,                 /* xNext - advance a cursor */
    fsdirEof,                  /* xEof - check for end of scan */
    fsdirColumn,               /* xColumn - read data */
    fsdirRowid,                /* xRowid - read data */
    0,                         /* xUpdate */
    0,                         /* xBegin */
    0,                         /* xSync */
    0,                         /* xCommit */
    0,                         /* xRollback */
    0,                         /* xFindMethod */
    0,                         /* xRename */
    0,                         /* xSavepoint */
    0,                         /* xRelease */
    0,                         /* xRollbackTo */
    0,                         /* xShadowName */
    0                          /* xIntegrity */
  };

  int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
  return rc;
}
#else         /* SQLITE_OMIT_VIRTUALTABLE */
# define fsdirRegister(x) SQLITE_OK
#endif

/*
** This version of realpath() works on any system.  The string
** returned is held in memory allocated using sqlite3_malloc64().
** The caller is responsible for calling sqlite3_free().
*/

static char *portable_realpath(const char *zPath){
#if !defined(_WIN32)       /* BEGIN unix */

  char *zOut = 0;          /* Result */
  char *z;                 /* Temporary buffer */
#if defined(PATH_MAX)
  char zBuf[PATH_MAX+1];   /* Space for the temporary buffer */
#endif

  if( zPath==0 ) return 0;
#if defined(PATH_MAX)
  z = realpath(zPath, zBuf);
  if( z ){
    zOut = sqlite3_mprintf("%s", zBuf);
  }
#endif /* defined(PATH_MAX) */
  if( zOut==0 ){
    /* Try POSIX.1-2008 malloc behavior */
    z = realpath(zPath, NULL);
    if( z ){
      zOut = sqlite3_mprintf("%s", z);
      free(z);
    }
  }
  return zOut;

#else /* End UNIX, Begin WINDOWS */

  wchar_t *zPath16;        /* UTF16 translation of zPath */
  char *zOut = 0;          /* Result */
  wchar_t *z = 0;          /* Temporary buffer */

  if( zPath==0 ) return 0;

  zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
  if( zPath16==0 ) return 0;
  z = _wfullpath(NULL, zPath16, 0);
  sqlite3_free(zPath16);
  if( z ){
    zOut = sqlite3_win32_unicode_to_utf8(z);
    free(z);
  }
  return zOut;

#endif /* End WINDOWS, Begin common code */
}

/*
** SQL function:   realpath(X)
**
** Try to convert file or pathname X into its real, absolute pathname.
** Return NULL if unable.
**
** The file or directory X is not required to exist.  The answer is formed
** by calling system realpath() on the prefix of X that does exist and
** appending the tail of X that does not (yet) exist.
*/

static void realpathFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zPath;    /* Original input path */
  char *zCopy;          /* An editable copy of zPath */
  char *zOut;           /* The result */
  char cSep = 0;        /* Separator turned into \000 */
  size_t len;           /* Prefix length before cSep */
#ifdef _WIN32
  const int isWin = 1;
#else
  const int isWin = 0;
#endif

  (void)argc;
  zPath = (const char*)sqlite3_value_text(argv[0]);
  if( zPath==0 ) return;
  if( zPath[0]==0 ) zPath = ".";
  zCopy = sqlite3_mprintf("%s",zPath);
  len = strlen(zCopy);
  while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
    len--;
  }
  zCopy[len] = 0;
  while( 1 /*exit-by-break*/ ){
    zOut = portable_realpath(zCopy);
    zCopy[len] = cSep;
    if( zOut ){
      if( cSep ){
        zOut = sqlite3_mprintf("%z%s",zOut,&zCopy[len]);
      }
      break;
    }else{
      size_t i = len-1;
      while( i>0 ){
        if( zCopy[i]=='/' || (isWin && zCopy[i]=='\\') ) break;
        i--;
      }
      if( i<=0 ){
        if( zCopy[0]=='/' ){
          zOut = zCopy;
          zCopy = 0;
        }else if( (zOut = portable_realpath("."))!=0 ){
          zOut = sqlite3_mprintf("%z/%s", zOut, zCopy);
        }          
        break;
      }
      cSep = zCopy[i];
      zCopy[i] = 0;
      len = i;
    }
  }
  sqlite3_free(zCopy);
  if( zOut ){
    /* Simplify any "/./" or "/../" that might have snuck into the
    ** pathname due to appending of zCopy.  We only have to consider
    ** unix "/" separators, because the _wfilepath() system call on
    ** Windows will have already done this simplification for us. */

    size_t i, j, n;
    n = strlen(zOut);
    for(i=j=0; i<n; i++){
      if( zOut[i]=='/' ){
        if( zOut[i+1]=='/' ) continue;
        if( zOut[i+1]=='.' && i+2<n && zOut[i+2]=='/' ){
          i += 1;
          continue;
        }
        if( zOut[i+1]=='.' && i+3<n && zOut[i+2]=='.' && zOut[i+3]=='/' ){
          while( j>0 && zOut[j-1]!='/' ){ j--; }
          if( j>0 ){ j--; }
          i += 2;
          continue;
        }
      }
      zOut[j++] = zOut[i];
    }
    zOut[j] = 0;

    /* Return the result */
    sqlite3_result_text(context, zOut, -1, sqlite3_free);
  }
}


#ifdef _WIN32

#endif
int sqlite3_fileio_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "readfile", 1, 
                               SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                               readfileFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "writefile", -1,
                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                 writefileFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
                                 lsModeFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = fsdirRegister(db);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "realpath", 1,
                                 SQLITE_UTF8, 0,
                                 realpathFunc, 0, 0);
  }
  return rc;
}

/************************* End ext/misc/fileio.c ********************/
/************************* Begin ext/misc/completion.c ******************/
/*
** 2017-07-10
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements an eponymous virtual table that returns suggested
** completions for a partial SQL input.
**
** Suggested usage:
**
**     SELECT DISTINCT candidate COLLATE nocase
**       FROM completion($prefix,$wholeline)
**      ORDER BY 1;
**
** The two query parameters are optional.  $prefix is the text of the
** current word being typed and that is to be completed.  $wholeline is
** the complete input line, used for context.
**
** The raw completion() table might return the same candidate multiple
** times, for example if the same column name is used to two or more
** tables.  And the candidates are returned in an arbitrary order.  Hence,
** the DISTINCT and ORDER BY are recommended.
**
** This virtual table operates at the speed of human typing, and so there
** is no attempt to make it fast.  Even a slow implementation will be much
** faster than any human can type.
**
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

#ifndef IsAlnum
#define IsAlnum(X)  isalnum((unsigned char)X)
#endif


/* completion_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a completion virtual table
*/

typedef struct completion_vtab completion_vtab;
struct completion_vtab {
  sqlite3_vtab base;  /* Base class - must be first */
  sqlite3 *db;        /* Database connection for this completion vtab */
};

/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/

typedef struct completion_cursor completion_cursor;
struct completion_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  sqlite3 *db;               /* Database connection for this cursor */
  int nPrefix, nLine;        /* Number of bytes in zPrefix and zLine */
  char *zPrefix;             /* The prefix for the word we want to complete */
  char *zLine;               /* The whole that we want to complete */
  const char *zCurrentRow;   /* Current output row */
  int szRow;                 /* Length of the zCurrentRow string */
  sqlite3_stmt *pStmt;       /* Current statement */
  sqlite3_int64 iRowid;      /* The rowid */
  int ePhase;                /* Current phase */
  int j;                     /* inter-phase counter */
};

/* Values for ePhase:
*/

#define COMPLETION_FIRST_PHASE   1
#define COMPLETION_KEYWORDS      1
#define COMPLETION_PRAGMAS       2
#define COMPLETION_FUNCTIONS     3
#define COMPLETION_COLLATIONS    4
#define COMPLETION_INDEXES       5
#define COMPLETION_TRIGGERS      6
#define COMPLETION_DATABASES     7
#define COMPLETION_TABLES        8    /* Also VIEWs and TRIGGERs */
#define COMPLETION_COLUMNS       9
#define COMPLETION_MODULES       10
#define COMPLETION_EOF           11

/*
** The completionConnect() method is invoked to create a new
** completion_vtab that describes the completion virtual table.
**
** Think of this routine as the constructor for completion_vtab objects.
**
** All this routine needs to do is:
**
**    (1) Allocate the completion_vtab object and initialize all fields.
**
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
**        result set of queries against completion will look like.
*/

static int completionConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  completion_vtab *pNew;
  int rc;

  (void)(pAux);    /* Unused parameter */
  (void)(argc);    /* Unused parameter */
  (void)(argv);    /* Unused parameter */
  (void)(pzErr);   /* Unused parameter */

/* Column numbers */
#define COMPLETION_COLUMN_CANDIDATE 0  /* Suggested completion of the input */
#define COMPLETION_COLUMN_PREFIX    1  /* Prefix of the word to be completed */
#define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
#define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */

  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  rc = sqlite3_declare_vtab(db,
      "CREATE TABLE x("
      "  candidate TEXT,"
      "  prefix TEXT HIDDEN,"
      "  wholeline TEXT HIDDEN,"
      "  phase INT HIDDEN"        /* Used for debugging only */
      ")");
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc64( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    pNew->db = db;
  }
  return rc;
}

/*
** This method is the destructor for completion_cursor objects.
*/

static int completionDisconnect(sqlite3_vtab *pVtab){
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** Constructor for a new completion_cursor object.
*/

static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  completion_cursor *pCur;
  pCur = sqlite3_malloc64( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  pCur->db = ((completion_vtab*)p)->db;
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Reset the completion_cursor.
*/

static void completionCursorReset(completion_cursor *pCur){
  sqlite3_free(pCur->zPrefix);   pCur->zPrefix = 0;  pCur->nPrefix = 0;
  sqlite3_free(pCur->zLine);     pCur->zLine = 0;    pCur->nLine = 0;
  sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
  pCur->j = 0;
}

/*
** Destructor for a completion_cursor.
*/

static int completionClose(sqlite3_vtab_cursor *cur){
  completionCursorReset((completion_cursor*)cur);
  sqlite3_free(cur);
  return SQLITE_OK;
}

/*
** Advance a completion_cursor to its next row of output.
**
** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
** record the current state of the scan.  This routine sets ->zCurrentRow
** to the current row of output and then returns.  If no more rows remain,
** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
** table that has reached the end of its scan.
**
** The current implementation just lists potential identifiers and
** keywords and filters them by zPrefix.  Future enhancements should
** take zLine into account to try to restrict the set of identifiers and
** keywords based on what would be legal at the current point of input.
*/

static int completionNext(sqlite3_vtab_cursor *cur){
  completion_cursor *pCur = (completion_cursor*)cur;
  int eNextPhase = 0;  /* Next phase to try if current phase reaches end */
  int iCol = -1;       /* If >=0, step pCur->pStmt and use the i-th column */
  int rc;
  pCur->iRowid++;
  while( pCur->ePhase!=COMPLETION_EOF ){
    switch( pCur->ePhase ){
      case COMPLETION_KEYWORDS: {
        if( pCur->j >= sqlite3_keyword_count() ){
          pCur->zCurrentRow = 0;
          pCur->ePhase = COMPLETION_DATABASES;
        }else{
          sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
        }
        iCol = -1;
        break;
      }
      case COMPLETION_DATABASES: {
        if( pCur->pStmt==0 ){
          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
                             &pCur->pStmt, 0);
        }
        iCol = 1;
        eNextPhase = COMPLETION_TABLES;
        break;
      }
      case COMPLETION_TABLES: {
        if( pCur->pStmt==0 ){
          sqlite3_stmt *pS2;
          sqlite3_str* pStr = sqlite3_str_new(pCur->db);
          char *zSql = 0;
          const char *zSep = "";
          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
          while( sqlite3_step(pS2)==SQLITE_ROW ){
            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
            sqlite3_str_appendf(pStr,
               "%s"
               "SELECT name FROM \"%w\".sqlite_schema",
               zSep, zDb
            );
            zSep = " UNION ";
          }
          rc = sqlite3_finalize(pS2);
          zSql = sqlite3_str_finish(pStr);
          if( zSql==0 ) return SQLITE_NOMEM;
          if( rc==SQLITE_OK ){
            sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
          }
          sqlite3_free(zSql);
          if( rc ) return rc;
        }
        iCol = 0;
        eNextPhase = COMPLETION_COLUMNS;
        break;
      }
      case COMPLETION_COLUMNS: {
        if( pCur->pStmt==0 ){
          sqlite3_stmt *pS2;
          sqlite3_str *pStr = sqlite3_str_new(pCur->db);
          char *zSql = 0;
          const char *zSep = "";
          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
          while( sqlite3_step(pS2)==SQLITE_ROW ){
            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
            sqlite3_str_appendf(pStr,
               "%s"
               "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
                       " JOIN pragma_table_xinfo(sm.name,%Q) AS pti"
               " WHERE sm.type='table'",
               zSep, zDb, zDb
            );
            zSep = " UNION ";
          }
          rc = sqlite3_finalize(pS2);
          zSql = sqlite3_str_finish(pStr);
          if( zSql==0 ) return SQLITE_NOMEM;
          if( rc==SQLITE_OK ){
            sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
          }
          sqlite3_free(zSql);
          if( rc ) return rc;
        }
        iCol = 0;
        eNextPhase = COMPLETION_EOF;
        break;
      }
    }
    if( iCol<0 ){
      /* This case is when the phase presets zCurrentRow */
      if( pCur->zCurrentRow==0 ) continue;
    }else{
      if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
        /* Extract the next row of content */
        pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
        pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
      }else{
        /* When all rows are finished, advance to the next phase */
        rc = sqlite3_finalize(pCur->pStmt);
        pCur->pStmt = 0;
        pCur->ePhase = eNextPhase;
        if( rc ) return rc;
        continue;
      }
    }
    if( pCur->nPrefix==0 ) break;
    if( pCur->nPrefix<=pCur->szRow
     && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
    ){
      break;
    }
  }

  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the completion_cursor
** is currently pointing.
*/

static int completionColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  completion_cursor *pCur = (completion_cursor*)cur;
  switch( i ){
    case COMPLETION_COLUMN_CANDIDATE: {
      sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
      break;
    }
    case COMPLETION_COLUMN_PREFIX: {
      sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
      break;
    }
    case COMPLETION_COLUMN_WHOLELINE: {
      sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
      break;
    }
    case COMPLETION_COLUMN_PHASE: {
      sqlite3_result_int(ctx, pCur->ePhase);
      break;
    }
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.  In this implementation, the
** rowid is the same as the output value.
*/

static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  completion_cursor *pCur = (completion_cursor*)cur;
  *pRowid = pCur->iRowid;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/

static int completionEof(sqlite3_vtab_cursor *cur){
  completion_cursor *pCur = (completion_cursor*)cur;
  return pCur->ePhase >= COMPLETION_EOF;
}

/*
** This method is called to "rewind" the completion_cursor object back
** to the first row of output.  This method is always called at least
** once prior to any call to completionColumn() or completionRowid() or 
** completionEof().
*/

static int completionFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  completion_cursor *pCur = (completion_cursor *)pVtabCursor;
  int iArg = 0;
  (void)(idxStr);   /* Unused parameter */
  (void)(argc);     /* Unused parameter */
  completionCursorReset(pCur);
  if( idxNum & 1 ){
    pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
    if( pCur->nPrefix>0 ){
      pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
      pCur->nPrefix = (int)strlen(pCur->zPrefix);
    }
    iArg = 1;
  }
  if( idxNum & 2 ){
    pCur->nLine = sqlite3_value_bytes(argv[iArg]);
    if( pCur->nLine>0 ){
      pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
      if( pCur->zLine==0 ) return SQLITE_NOMEM;
      pCur->nLine = (int)strlen(pCur->zLine);
    }
  }
  if( pCur->zLine!=0 && pCur->zPrefix==0 ){
    int i = pCur->nLine;
    while( i>0 && (IsAlnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
      i--;
    }
    pCur->nPrefix = pCur->nLine - i;
    if( pCur->nPrefix>0 ){
      pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
      pCur->nPrefix = (int)strlen(pCur->zPrefix);
    }
  }
  pCur->iRowid = 0;
  pCur->ePhase = COMPLETION_FIRST_PHASE;
  return completionNext(pVtabCursor);
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the completion virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** There are two hidden parameters that act as arguments to the table-valued
** function:  "prefix" and "wholeline".  Bit 0 of idxNum is set if "prefix"
** is available and bit 1 is set if "wholeline" is available.
*/

static int completionBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;                 /* Loop over constraints */
  int idxNum = 0;        /* The query plan bitmask */
  int prefixIdx = -1;    /* Index of the start= constraint, or -1 if none */
  int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
  int nArg = 0;          /* Number of arguments that completeFilter() expects */
  const struct sqlite3_index_constraint *pConstraint;

  (void)(tab);    /* Unused parameter */
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    if( pConstraint->usable==0 ) continue;
    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    switch( pConstraint->iColumn ){
      case COMPLETION_COLUMN_PREFIX:
        prefixIdx = i;
        idxNum |= 1;
        break;
      case COMPLETION_COLUMN_WHOLELINE:
        wholelineIdx = i;
        idxNum |= 2;
        break;
    }
  }
  if( prefixIdx>=0 ){
    pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
    pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
  }
  if( wholelineIdx>=0 ){
    pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
    pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
  }
  pIdxInfo->idxNum = idxNum;
  pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
  pIdxInfo->estimatedRows = 500 - 100*nArg;
  return SQLITE_OK;
}

/*
** This following structure defines all the methods for the 
** completion virtual table.
*/

static sqlite3_module completionModule = {
  0,                         /* iVersion */
  0,                         /* xCreate */
  completionConnect,         /* xConnect */
  completionBestIndex,       /* xBestIndex */
  completionDisconnect,      /* xDisconnect */
  0,                         /* xDestroy */
  completionOpen,            /* xOpen - open a cursor */
  completionClose,           /* xClose - close a cursor */
  completionFilter,          /* xFilter - configure scan constraints */
  completionNext,            /* xNext - advance a cursor */
  completionEof,             /* xEof - check for end of scan */
  completionColumn,          /* xColumn - read data */
  completionRowid,           /* xRowid - read data */
  0,                         /* xUpdate */
  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
  0,                         /* xSavepoint */
  0,                         /* xRelease */
  0,                         /* xRollbackTo */
  0,                         /* xShadowName */
  0                          /* xIntegrity */
};

#endif /* SQLITE_OMIT_VIRTUALTABLE */

int sqlite3CompletionVtabInit(sqlite3 *db){
  int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  rc = sqlite3_create_module(db, "completion", &completionModule, 0);
#endif
  return rc;
}

#ifdef _WIN32

#endif
int sqlite3_completion_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)(pzErrMsg);  /* Unused parameter */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  rc = sqlite3CompletionVtabInit(db);
#endif
  return rc;
}

/************************* End ext/misc/completion.c ********************/
/************************* Begin ext/misc/appendvfs.c ******************/
/*
** 2017-10-20
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file implements a VFS shim that allows an SQLite database to be
** appended onto the end of some other file, such as an executable.
**
** A special record must appear at the end of the file that identifies the
** file as an appended database and provides the offset to the first page
** of the exposed content. (Or, it is the length of the content prefix.)
** For best performance page 1 should be located at a disk page boundary,
** though that is not required.
**
** When opening a database using this VFS, the connection might treat
** the file as an ordinary SQLite database, or it might treat it as a
** database appended onto some other file.  The decision is made by
** applying the following rules in order:
**
**  (1)  An empty file is an ordinary database.
**
**  (2)  If the file ends with the appendvfs trailer string
**       "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
**
**  (3)  If the file begins with the standard SQLite prefix string
**       "SQLite format 3", that file is an ordinary database.
**
**  (4)  If none of the above apply and the SQLITE_OPEN_CREATE flag is
**       set, then a new database is appended to the already existing file.
**
**  (5)  Otherwise, SQLITE_CANTOPEN is returned.
**
** To avoid unnecessary complications with the PENDING_BYTE, the size of
** the file containing the database is limited to 1GiB. (1073741824 bytes)
** This VFS will not read or write past the 1GiB mark.  This restriction
** might be lifted in future versions.  For now, if you need a larger
** database, then keep it in a separate file.
**
** If the file being opened is a plain database (not an appended one), then
** this shim is a pass-through into the default underlying VFS. (rule 3)
**/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>

/* The append mark at the end of the database is:
**
**     Start-Of-SQLite3-NNNNNNNN
**     123456789 123456789 12345
**
** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
** the offset to page 1, and also the length of the prefix content.
*/

#define APND_MARK_PREFIX     "Start-Of-SQLite3-"
#define APND_MARK_PREFIX_SZ  17
#define APND_MARK_FOS_SZ      8
#define APND_MARK_SIZE       (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)

/*
** Maximum size of the combined prefix + database + append-mark.  This
** must be less than 0x40000000 to avoid locking issues on Windows.
*/

#define APND_MAX_SIZE  (0x40000000)

/*
** Try to align the database to an even multiple of APND_ROUNDUP bytes.
*/

#ifndef APND_ROUNDUP
#define APND_ROUNDUP 4096
#endif
#define APND_ALIGN_MASK         ((sqlite3_int64)(APND_ROUNDUP-1))
#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)

/*
** Forward declaration of objects used by this utility
*/

typedef struct sqlite3_vfs ApndVfs;
typedef struct ApndFile ApndFile;

/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/

#define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))

/* An open appendvfs file
**
** An instance of this structure describes the appended database file.
** A separate sqlite3_file object is always appended. The appended
** sqlite3_file object (which can be accessed using ORIGFILE()) describes
** the entire file, including the prefix, the database, and the
** append-mark.
**
** The structure of an AppendVFS database is like this:
**
**   +-------------+---------+----------+-------------+
**   | prefix-file | padding | database | append-mark |
**   +-------------+---------+----------+-------------+
**                           ^          ^
**                           |          |
**                         iPgOne      iMark
**
**
** "prefix file" -  file onto which the database has been appended.
** "padding"     -  zero or more bytes inserted so that "database"
**                  starts on an APND_ROUNDUP boundary
** "database"    -  The SQLite database file
** "append-mark" -  The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
**                  the offset from the start of prefix-file to the start
**                  of "database".
**
** The size of the database is iMark - iPgOne.
**
** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
** of iPgOne stored as a big-ending 64-bit integer.
**
** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
** Or, iMark is -1 to indicate that it has not yet been written.
*/

struct ApndFile {
  sqlite3_file base;        /* Subclass.  MUST BE FIRST! */
  sqlite3_int64 iPgOne;     /* Offset to the start of the database */
  sqlite3_int64 iMark;      /* Offset of the append mark.  -1 if unwritten */
  /* Always followed by another sqlite3_file that describes the whole file */
};

/*
** Methods for ApndFile
*/

static int apndClose(sqlite3_file*);
static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
static int apndSync(sqlite3_file*, int flags);
static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int apndLock(sqlite3_file*, int);
static int apndUnlock(sqlite3_file*, int);
static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
static int apndFileControl(sqlite3_file*, int op, void *pArg);
static int apndSectorSize(sqlite3_file*);
static int apndDeviceCharacteristics(sqlite3_file*);
static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
static void apndShmBarrier(sqlite3_file*);
static int apndShmUnmap(sqlite3_file*, int deleteFlag);
static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);

/*
** Methods for ApndVfs
*/

static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
static void apndDlClose(sqlite3_vfs*, void*);
static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int apndSleep(sqlite3_vfs*, int microseconds);
static int apndCurrentTime(sqlite3_vfs*, double*);
static int apndGetLastError(sqlite3_vfs*, int, char *);
static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);

static sqlite3_vfs apnd_vfs = {
  3,                            /* iVersion (set when registered) */
  0,                            /* szOsFile (set when registered) */
  1024,                         /* mxPathname */
  0,                            /* pNext */
  "apndvfs",                    /* zName */
  0,                            /* pAppData (set when registered) */ 
  apndOpen,                     /* xOpen */
  apndDelete,                   /* xDelete */
  apndAccess,                   /* xAccess */
  apndFullPathname,             /* xFullPathname */
  apndDlOpen,                   /* xDlOpen */
  apndDlError,                  /* xDlError */
  apndDlSym,                    /* xDlSym */
  apndDlClose,                  /* xDlClose */
  apndRandomness,               /* xRandomness */
  apndSleep,                    /* xSleep */
  apndCurrentTime,              /* xCurrentTime */
  apndGetLastError,             /* xGetLastError */
  apndCurrentTimeInt64,         /* xCurrentTimeInt64 */
  apndSetSystemCall,            /* xSetSystemCall */
  apndGetSystemCall,            /* xGetSystemCall */
  apndNextSystemCall            /* xNextSystemCall */
};

static const sqlite3_io_methods apnd_io_methods = {
  3,                              /* iVersion */
  apndClose,                      /* xClose */
  apndRead,                       /* xRead */
  apndWrite,                      /* xWrite */
  apndTruncate,                   /* xTruncate */
  apndSync,                       /* xSync */
  apndFileSize,                   /* xFileSize */
  apndLock,                       /* xLock */
  apndUnlock,                     /* xUnlock */
  apndCheckReservedLock,          /* xCheckReservedLock */
  apndFileControl,                /* xFileControl */
  apndSectorSize,                 /* xSectorSize */
  apndDeviceCharacteristics,      /* xDeviceCharacteristics */
  apndShmMap,                     /* xShmMap */
  apndShmLock,                    /* xShmLock */
  apndShmBarrier,                 /* xShmBarrier */
  apndShmUnmap,                   /* xShmUnmap */
  apndFetch,                      /* xFetch */
  apndUnfetch                     /* xUnfetch */
};

/*
** Close an apnd-file.
*/

static int apndClose(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xClose(pFile);
}

/*
** Read data from an apnd-file.
*/

static int apndRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  ApndFile *paf = (ApndFile *)pFile;
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}

/*
** Add the append-mark onto what should become the end of the file.
*  If and only if this succeeds, internal ApndFile.iMark is updated.
*  Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
*/

static int apndWriteMark(
  ApndFile *paf,
  sqlite3_file *pFile,
  sqlite_int64 iWriteEnd
){
  sqlite_int64 iPgOne = paf->iPgOne;
  unsigned char a[APND_MARK_SIZE];
  int i = APND_MARK_FOS_SZ;
  int rc;
  assert(pFile == ORIGFILE(paf));
  memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
  while( --i >= 0 ){
    a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
    iPgOne >>= 8;
  }
  iWriteEnd += paf->iPgOne;
  if( SQLITE_OK==(rc = pFile->pMethods->xWrite
                  (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
    paf->iMark = iWriteEnd;
  }
  return rc;
}

/*
** Write data to an apnd-file.
*/

static int apndWrite(
  sqlite3_file *pFile,
  const void *zBuf,
  int iAmt,
  sqlite_int64 iOfst
){
  ApndFile *paf = (ApndFile *)pFile;
  sqlite_int64 iWriteEnd = iOfst + iAmt;
  if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
  pFile = ORIGFILE(pFile);
  /* If append-mark is absent or will be overwritten, write it. */
  if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
    int rc = apndWriteMark(paf, pFile, iWriteEnd);
    if( SQLITE_OK!=rc ) return rc;
  }
  return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}

/*
** Truncate an apnd-file.
*/

static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
  ApndFile *paf = (ApndFile *)pFile;
  pFile = ORIGFILE(pFile);
  /* The append mark goes out first so truncate failure does not lose it. */
  if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
  /* Truncate underlying file just past append mark */
  return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
}

/*
** Sync an apnd-file.
*/

static int apndSync(sqlite3_file *pFile, int flags){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xSync(pFile, flags);
}

/*
** Return the current file-size of an apnd-file.
** If the append mark is not yet there, the file-size is 0.
*/

static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  ApndFile *paf = (ApndFile *)pFile;
  *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
  return SQLITE_OK;
}

/*
** Lock an apnd-file.
*/

static int apndLock(sqlite3_file *pFile, int eLock){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xLock(pFile, eLock);
}

/*
** Unlock an apnd-file.
*/

static int apndUnlock(sqlite3_file *pFile, int eLock){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xUnlock(pFile, eLock);
}

/*
** Check if another file-handle holds a RESERVED lock on an apnd-file.
*/

static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
}

/*
** File control method. For custom operations on an apnd-file.
*/

static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
  ApndFile *paf = (ApndFile *)pFile;
  int rc;
  pFile = ORIGFILE(pFile);
  if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
  rc = pFile->pMethods->xFileControl(pFile, op, pArg);
  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
    *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
  }
  return rc;
}

/*
** Return the sector-size in bytes for an apnd-file.
*/

static int apndSectorSize(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xSectorSize(pFile);
}

/*
** Return the device characteristic flags supported by an apnd-file.
*/

static int apndDeviceCharacteristics(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xDeviceCharacteristics(pFile);
}

/* Create a shared memory file mapping */
static int apndShmMap(
  sqlite3_file *pFile,
  int iPg,
  int pgsz,
  int bExtend,
  void volatile **pp
){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
}

/* Perform locking on a shared-memory segment */
static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xShmLock(pFile,offset,n,flags);
}

/* Memory barrier operation on shared memory */
static void apndShmBarrier(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  pFile->pMethods->xShmBarrier(pFile);
}

/* Unmap a shared memory segment */
static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
}

/* Fetch a page of a memory-mapped file */
static int apndFetch(
  sqlite3_file *pFile,
  sqlite3_int64 iOfst,
  int iAmt,
  void **pp
){
  ApndFile *p = (ApndFile *)pFile;
  if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
    return SQLITE_IOERR; /* Cannot read what is not yet there. */
  }
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
}

/* Release a memory-mapped page */
static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
  ApndFile *p = (ApndFile *)pFile;
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
}

/*
** Try to read the append-mark off the end of a file.  Return the
** start of the appended database if the append-mark is present.
** If there is no valid append-mark, return -1;
**
** An append-mark is only valid if the NNNNNNNN start-of-database offset
** indicates that the appended database contains at least one page.  The
** start-of-database value must be a multiple of 512.
*/

static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
  int rc, i;
  sqlite3_int64 iMark;
  int msbs = 8 * (APND_MARK_FOS_SZ-1);
  unsigned char a[APND_MARK_SIZE];

  if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
  rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
  if( rc ) return -1;
  if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
  iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
  for(i=1; i<8; i++){
    msbs -= 8;
    iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
  }
  if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
  if( iMark & 0x1ff ) return -1;
  return iMark;
}

static const char apvfsSqliteHdr[] = "SQLite format 3";
/*
** Check to see if the file is an appendvfs SQLite database file.
** Return true iff it is such. Parameter sz is the file's size.
*/

static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
  int rc;
  char zHdr[16];
  sqlite3_int64 iMark = apndReadMark(sz, pFile);
  if( iMark>=0 ){
    /* If file has the correct end-marker, the expected odd size, and the
    ** SQLite DB type marker where the end-marker puts it, then it
    ** is an appendvfs database.
    */

    rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
    if( SQLITE_OK==rc
     && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
     && (sz & 0x1ff) == APND_MARK_SIZE
     && sz>=512+APND_MARK_SIZE
    ){
      return 1; /* It's an appendvfs database */
    }
  }
  return 0;
}

/*
** Check to see if the file is an ordinary SQLite database file.
** Return true iff so. Parameter sz is the file's size.
*/

static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
  char zHdr[16];
  if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
   || (sz & 0x1ff) != 0
   || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
   || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
  ){
    return 0;
  }else{
    return 1;
  }
}

/*
** Open an apnd file handle.
*/

static int apndOpen(
  sqlite3_vfs *pApndVfs,
  const char *zName,
  sqlite3_file *pFile,
  int flags,
  int *pOutFlags
){
  ApndFile *pApndFile = (ApndFile*)pFile;
  sqlite3_file *pBaseFile = ORIGFILE(pFile);
  sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
  int rc;
  sqlite3_int64 sz = 0;
  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
    /* The appendvfs is not to be used for transient or temporary databases.
    ** Just use the base VFS open to initialize the given file object and
    ** open the underlying file. (Appendvfs is then unused for this file.)
    */

    return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
  }
  memset(pApndFile, 0, sizeof(ApndFile));
  pFile->pMethods = &apnd_io_methods;
  pApndFile->iMark = -1;    /* Append mark not yet written */

  rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
  if( rc==SQLITE_OK ){
    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
    if( rc ){
      pBaseFile->pMethods->xClose(pBaseFile);
    }
  }
  if( rc ){
    pFile->pMethods = 0;
    return rc;
  }
  if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
    /* The file being opened appears to be just an ordinary DB. Copy
    ** the base dispatch-table so this instance mimics the base VFS. 
    */

    memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
    return SQLITE_OK;
  }
  pApndFile->iPgOne = apndReadMark(sz, pFile);
  if( pApndFile->iPgOne>=0 ){
    pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
    return SQLITE_OK;
  }
  if( (flags & SQLITE_OPEN_CREATE)==0 ){
    pBaseFile->pMethods->xClose(pBaseFile);
    rc = SQLITE_CANTOPEN;
    pFile->pMethods = 0;
  }else{
    /* Round newly added appendvfs location to #define'd page boundary. 
    ** Note that nothing has yet been written to the underlying file.
    ** The append mark will be written along with first content write.
    ** Until then, paf->iMark value indicates it is not yet written.
    */

    pApndFile->iPgOne = APND_START_ROUNDUP(sz);
  }
  return rc;
}

/*
** Delete an apnd file.
** For an appendvfs, this could mean delete the appendvfs portion,
** leaving the appendee as it was before it gained an appendvfs.
** For now, this code deletes the underlying file too.
*/

static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
}

/*
** All other VFS methods are pass-thrus.
*/

static int apndAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){
  return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
}
static int apndFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
}
static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
}
static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
}
static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
  return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
}
static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
  ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
}
static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
}
static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
  return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
}
static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
}
static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
  return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
}
static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
  return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
}
static int apndSetSystemCall(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_syscall_ptr pCall
){
  return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
}
static sqlite3_syscall_ptr apndGetSystemCall(
  sqlite3_vfs *pVfs,
  const char *zName
){
  return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
}
static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
  return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
}

  
#ifdef _WIN32

#endif
/* 
** This routine is called when the extension is loaded.
** Register the new VFS.
*/

int sqlite3_appendvfs_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  sqlite3_vfs *pOrig;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;
  (void)db;
  pOrig = sqlite3_vfs_find(0);
  if( pOrig==0 ) return SQLITE_ERROR;
  apnd_vfs.iVersion = pOrig->iVersion;
  apnd_vfs.pAppData = pOrig;
  apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
  rc = sqlite3_vfs_register(&apnd_vfs, 0);
#ifdef APPENDVFS_TEST
  if( rc==SQLITE_OK ){
    rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
  }
#endif
  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
  return rc;
}

/************************* End ext/misc/appendvfs.c ********************/
#endif
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ext/misc/zipfile.c ******************/
/*
** 2017-12-26
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file implements a virtual table for reading and writing ZIP archive
** files.
**
** Usage example:
**
**     SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
**
** Current limitations:
**
**    *  No support for encryption
**    *  No support for ZIP archives spanning multiple files
**    *  No support for zip64 extensions
**    *  Only the "inflate/deflate" (zlib) compression method is supported
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifndef SQLITE_NO_STDINT
#  include <stdint.h>
#endif

#include <zlib.h>

/* When used as part of the CLI, the sqlite3_stdio.h module will have
** been included before this one. In that case use the sqlite3_stdio.h
** #defines.  If not, create our own for fopen().
*/

#ifndef _SQLITE3_STDIO_H_
# define sqlite3_fopen fopen
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE

#ifndef SQLITE_AMALGAMATION

#ifndef UINT32_TYPE
# ifdef HAVE_UINT32_T
#  define UINT32_TYPE uint32_t
# else
#  define UINT32_TYPE unsigned int
# endif
#endif
#ifndef UINT16_TYPE
# ifdef HAVE_UINT16_T
#  define UINT16_TYPE uint16_t
# else
#  define UINT16_TYPE unsigned short int
# endif
#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 // */
#define MIN(a,b) ((a)<(b) ? (a) : (b))

#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
# define NEVER(X)       (X)
#endif

#endif   /* SQLITE_AMALGAMATION */

/*
** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
**
** In some ways it would be better to obtain these values from system 
** header files. But, the dependency is undesirable and (a) these
** have been stable for decades, (b) the values are part of POSIX and
** are also made explicit in [man stat], and (c) are part of the 
** file format for zip archives.
*/

#ifndef S_IFDIR
# define S_IFDIR 0040000
#endif
#ifndef S_IFREG
# define S_IFREG 0100000
#endif
#ifndef S_IFLNK
# define S_IFLNK 0120000
#endif

static const char ZIPFILE_SCHEMA[] = 
  "CREATE TABLE y("
    "name PRIMARY KEY,"  /* 0: Name of file in zip archive */
    "mode,"              /* 1: POSIX mode for file */
    "mtime,"             /* 2: Last modification time (secs since 1970)*/
    "sz,"                /* 3: Size of object */
    "rawdata,"           /* 4: Raw data */
    "data,"              /* 5: Uncompressed data */
    "method,"            /* 6: Compression method (integer) */
    "z HIDDEN"           /* 7: Name of zip file */
  ") WITHOUT ROWID;";

#define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
#define ZIPFILE_MX_NAME (250)     /* Windows limitation on filename size */

/*
** The buffer should be large enough to contain 3 65536 byte strings - the
** filename, the extra field and the file comment.
*/

#define ZIPFILE_BUFFER_SIZE (200*1024)


/*
** Magic numbers used to read and write zip files.
**
** ZIPFILE_NEWENTRY_MADEBY:
**   Use this value for the "version-made-by" field in new zip file
**   entries. The upper byte indicates "unix", and the lower byte 
**   indicates that the zip file matches pkzip specification 3.0. 
**   This is what info-zip seems to do.
**
** ZIPFILE_NEWENTRY_REQUIRED:
**   Value for "version-required-to-extract" field of new entries.
**   Version 2.0 is required to support folders and deflate compression.
**
** ZIPFILE_NEWENTRY_FLAGS:
**   Value for "general-purpose-bit-flags" field of new entries. Bit
**   11 means "utf-8 filename and comment".
**
** ZIPFILE_SIGNATURE_CDS:
**   First 4 bytes of a valid CDS record.
**
** ZIPFILE_SIGNATURE_LFH:
**   First 4 bytes of a valid LFH record.
**
** ZIPFILE_SIGNATURE_EOCD
**   First 4 bytes of a valid EOCD record.
*/

#define ZIPFILE_EXTRA_TIMESTAMP   0x5455
#define ZIPFILE_NEWENTRY_MADEBY   ((3<<8) + 30)
#define ZIPFILE_NEWENTRY_REQUIRED 20
#define ZIPFILE_NEWENTRY_FLAGS    0x800
#define ZIPFILE_SIGNATURE_CDS     0x02014b50
#define ZIPFILE_SIGNATURE_LFH     0x04034b50
#define ZIPFILE_SIGNATURE_EOCD    0x06054b50

/*
** The sizes of the fixed-size part of each of the three main data 
** structures in a zip archive.
*/

#define ZIPFILE_LFH_FIXED_SZ      30
#define ZIPFILE_EOCD_FIXED_SZ     22
#define ZIPFILE_CDS_FIXED_SZ      46

/*
*** 4.3.16  End of central directory record:
***
***   end of central dir signature    4 bytes  (0x06054b50)
***   number of this disk             2 bytes
***   number of the disk with the
***   start of the central directory  2 bytes
***   total number of entries in the
***   central directory on this disk  2 bytes
***   total number of entries in
***   the central directory           2 bytes
***   size of the central directory   4 bytes
***   offset of start of central
***   directory with respect to
***   the starting disk number        4 bytes
***   .ZIP file comment length        2 bytes
***   .ZIP file comment       (variable size)
*/

typedef struct ZipfileEOCD ZipfileEOCD;
struct ZipfileEOCD {
  u16 iDisk;
  u16 iFirstDisk;
  u16 nEntry;
  u16 nEntryTotal;
  u32 nSize;
  u32 iOffset;
};

/*
*** 4.3.12  Central directory structure:
***
*** ...
***
***   central file header signature   4 bytes  (0x02014b50)
***   version made by                 2 bytes
***   version needed to extract       2 bytes
***   general purpose bit flag        2 bytes
***   compression method              2 bytes
***   last mod file time              2 bytes
***   last mod file date              2 bytes
***   crc-32                          4 bytes
***   compressed size                 4 bytes
***   uncompressed size               4 bytes
***   file name length                2 bytes
***   extra field length              2 bytes
***   file comment length             2 bytes
***   disk number start               2 bytes
***   internal file attributes        2 bytes
***   external file attributes        4 bytes
***   relative offset of local header 4 bytes
*/

typedef struct ZipfileCDS ZipfileCDS;
struct ZipfileCDS {
  u16 iVersionMadeBy;
  u16 iVersionExtract;
  u16 flags;
  u16 iCompression;
  u16 mTime;
  u16 mDate;
  u32 crc32;
  u32 szCompressed;
  u32 szUncompressed;
  u16 nFile;
  u16 nExtra;
  u16 nComment;
  u16 iDiskStart;
  u16 iInternalAttr;
  u32 iExternalAttr;
  u32 iOffset;
  char *zFile;                    /* Filename (sqlite3_malloc()) */
};

/*
*** 4.3.7  Local file header:
***
***   local file header signature     4 bytes  (0x04034b50)
***   version needed to extract       2 bytes
***   general purpose bit flag        2 bytes
***   compression method              2 bytes
***   last mod file time              2 bytes
***   last mod file date              2 bytes
***   crc-32                          4 bytes
***   compressed size                 4 bytes
***   uncompressed size               4 bytes
***   file name length                2 bytes
***   extra field length              2 bytes
***   
*/

typedef struct ZipfileLFH ZipfileLFH;
struct ZipfileLFH {
  u16 iVersionExtract;
  u16 flags;
  u16 iCompression;
  u16 mTime;
  u16 mDate;
  u32 crc32;
  u32 szCompressed;
  u32 szUncompressed;
  u16 nFile;
  u16 nExtra;
};

typedef struct ZipfileEntry ZipfileEntry;
struct ZipfileEntry {
  ZipfileCDS cds;            /* Parsed CDS record */
  u32 mUnixTime;             /* Modification time, in UNIX format */
  u8 *aExtra;                /* cds.nExtra+cds.nComment bytes of extra data */
  i64 iDataOff;              /* Offset to data in file (if aData==0) */
  u8 *aData;                 /* cds.szCompressed bytes of compressed data */
  ZipfileEntry *pNext;       /* Next element in in-memory CDS */
};

/* 
** Cursor type for zipfile tables.
*/

typedef struct ZipfileCsr ZipfileCsr;
struct ZipfileCsr {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  i64 iId;                   /* Cursor ID */
  u8 bEof;                   /* True when at EOF */
  u8 bNoop;                  /* If next xNext() call is no-op */

  /* Used outside of write transactions */
  FILE *pFile;               /* Zip file */
  i64 iNextOff;              /* Offset of next record in central directory */
  ZipfileEOCD eocd;          /* Parse of central directory record */

  ZipfileEntry *pFreeEntry;  /* Free this list when cursor is closed or reset */
  ZipfileEntry *pCurrent;    /* Current entry */
  ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
};

typedef struct ZipfileTab ZipfileTab;
struct ZipfileTab {
  sqlite3_vtab base;         /* Base class - must be first */
  char *zFile;               /* Zip file this table accesses (may be NULL) */
  sqlite3 *db;               /* Host database connection */
  u8 *aBuffer;               /* Temporary buffer used for various tasks */

  ZipfileCsr *pCsrList;      /* List of cursors */
  i64 iNextCsrid;

  /* The following are used by write transactions only */
  ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
  ZipfileEntry *pLastEntry;  /* Last element in pFirstEntry list */
  FILE *pWriteFd;            /* File handle open on zip archive */
  i64 szCurrent;             /* Current size of zip archive */
  i64 szOrig;                /* Size of archive at start of transaction */
};

/*
** Set the error message contained in context ctx to the results of
** vprintf(zFmt, ...).
*/

static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
  char *zMsg = 0;
  va_list ap;
  va_start(ap, zFmt);
  zMsg = sqlite3_vmprintf(zFmt, ap);
  sqlite3_result_error(ctx, zMsg, -1);
  sqlite3_free(zMsg);
  va_end(ap);
}

/*
** If string zIn is quoted, dequote it in place. Otherwise, if the string
** is not quoted, do nothing.
*/

static void zipfileDequote(char *zIn){
  char q = zIn[0];
  if( q=='"' || q=='\'' || q=='`' || q=='[' ){
    int iIn = 1;
    int iOut = 0;
    if( q=='[' ) q = ']';
    while( ALWAYS(zIn[iIn]) ){
      char c = zIn[iIn++];
      if( c==q && zIn[iIn++]!=q ) break;
      zIn[iOut++] = c;
    }
    zIn[iOut] = '\0';
  }
}

/*
** Construct a new ZipfileTab virtual table object.
** 
**   argv[0]   -> module name  ("zipfile")
**   argv[1]   -> database name
**   argv[2]   -> table name
**   argv[...] -> "column name" and other module argument fields.
*/

static int zipfileConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
  int nFile = 0;
  const char *zFile = 0;
  ZipfileTab *pNew = 0;
  int rc;
  (void)pAux;

  /* If the table name is not "zipfile", require that the argument be
  ** specified. This stops zipfile tables from being created as:
  **
  **   CREATE VIRTUAL TABLE zzz USING zipfile();
  **
  ** It does not prevent:
  **
  **   CREATE VIRTUAL TABLE zipfile USING zipfile();
  */

  assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
  if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
    *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
    return SQLITE_ERROR;
  }

  if( argc>3 ){
    zFile = argv[3];
    nFile = (int)strlen(zFile)+1;
  }

  rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
  if( rc==SQLITE_OK ){
    pNew = (ZipfileTab*)sqlite3_malloc64((i64)nByte+nFile);
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, nByte+nFile);
    pNew->db = db;
    pNew->aBuffer = (u8*)&pNew[1];
    if( zFile ){
      pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
      memcpy(pNew->zFile, zFile, nFile);
      zipfileDequote(pNew->zFile);
    }
  }
  sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
  *ppVtab = (sqlite3_vtab*)pNew;
  return rc;
}

/*
** Free the ZipfileEntry structure indicated by the only argument.
*/

static void zipfileEntryFree(ZipfileEntry *p){
  if( p ){
    sqlite3_free(p->cds.zFile);
    sqlite3_free(p);
  }
}

/*
** Release resources that should be freed at the end of a write 
** transaction.
*/

static void zipfileCleanupTransaction(ZipfileTab *pTab){
  ZipfileEntry *pEntry;
  ZipfileEntry *pNext;

  if( pTab->pWriteFd ){
    fclose(pTab->pWriteFd);
    pTab->pWriteFd = 0;
  }
  for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
    pNext = pEntry->pNext;
    zipfileEntryFree(pEntry);
  }
  pTab->pFirstEntry = 0;
  pTab->pLastEntry = 0;
  pTab->szCurrent = 0;
  pTab->szOrig = 0;
}

/*
** This method is the destructor for zipfile vtab objects.
*/

static int zipfileDisconnect(sqlite3_vtab *pVtab){
  zipfileCleanupTransaction((ZipfileTab*)pVtab);
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** Constructor for a new ZipfileCsr object.
*/

static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
  ZipfileTab *pTab = (ZipfileTab*)p;
  ZipfileCsr *pCsr;
  pCsr = sqlite3_malloc64(sizeof(*pCsr));
  *ppCsr = (sqlite3_vtab_cursor*)pCsr;
  if( pCsr==0 ){
    return SQLITE_NOMEM;
  }
  memset(pCsr, 0, sizeof(*pCsr));
  pCsr->iId = ++pTab->iNextCsrid;
  pCsr->pCsrNext = pTab->pCsrList;
  pTab->pCsrList = pCsr;
  return SQLITE_OK;
}

/*
** Reset a cursor back to the state it was in when first returned
** by zipfileOpen().
*/

static void zipfileResetCursor(ZipfileCsr *pCsr){
  ZipfileEntry *p;
  ZipfileEntry *pNext;

  pCsr->bEof = 0;
  if( pCsr->pFile ){
    fclose(pCsr->pFile);
    pCsr->pFile = 0;
    zipfileEntryFree(pCsr->pCurrent);
    pCsr->pCurrent = 0;
  }

  for(p=pCsr->pFreeEntry; p; p=pNext){
    pNext = p->pNext;
    zipfileEntryFree(p);
  }
}

/*
** Destructor for an ZipfileCsr.
*/

static int zipfileClose(sqlite3_vtab_cursor *cur){
  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
  ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
  ZipfileCsr **pp;
  zipfileResetCursor(pCsr);

  /* Remove this cursor from the ZipfileTab.pCsrList list. */
  for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
  *pp = pCsr->pCsrNext;

  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/*
** Set the error message for the virtual table associated with cursor
** pCsr to the results of vprintf(zFmt, ...).
*/

static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
  va_list ap;
  va_start(ap, zFmt);
  sqlite3_free(pTab->base.zErrMsg);
  pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
  va_end(ap);
}
static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
  va_list ap;
  va_start(ap, zFmt);
  sqlite3_free(pCsr->base.pVtab->zErrMsg);
  pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
  va_end(ap);
}

/*
** Read nRead bytes of data from offset iOff of file pFile into buffer
** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
** otherwise. 
**
** If an error does occur, output variable (*pzErrmsg) may be set to point
** to an English language error message. It is the responsibility of the
** caller to eventually free this buffer using
** sqlite3_free().
*/

static int zipfileReadData(
  FILE *pFile,                    /* Read from this file */
  u8 *aRead,                      /* Read into this buffer */
  i64 nRead,                      /* Number of bytes to read */
  i64 iOff,                       /* Offset to read from */
  char **pzErrmsg                 /* OUT: Error message (from sqlite3_malloc) */
){
  size_t n;
  fseek(pFile, (long)iOff, SEEK_SET);
  n = fread(aRead, 1, (long)nRead, pFile);
  if( n!=(size_t)nRead ){
    sqlite3_free(*pzErrmsg);
    *pzErrmsg = sqlite3_mprintf("error in fread()");
    return SQLITE_ERROR;
  }
  return SQLITE_OK;
}

static int zipfileAppendData(
  ZipfileTab *pTab,
  const u8 *aWrite,
  int nWrite
){
  if( nWrite>0 ){
    size_t n = nWrite;
    fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
    n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
    if( (int)n!=nWrite ){
      zipfileTableErr(pTab,"error in fwrite()");
      return SQLITE_ERROR;
    }
    pTab->szCurrent += nWrite;
  }
  return SQLITE_OK;
}

/*
** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
*/

static u16 zipfileGetU16(const u8 *aBuf){
  return (aBuf[1] << 8) + aBuf[0];
}

/*
** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
*/

static u32 zipfileGetU32(const u8 *aBuf){
  if( aBuf==0 ) return 0;
  return ((u32)(aBuf[3]) << 24)
       + ((u32)(aBuf[2]) << 16)
       + ((u32)(aBuf[1]) <<  8)
       + ((u32)(aBuf[0]) <<  0);
}

/*
** Write a 16-bit little endiate integer into buffer aBuf.
*/

static void zipfilePutU16(u8 *aBuf, u16 val){
  aBuf[0] = val & 0xFF;
  aBuf[1] = (val>>8) & 0xFF;
}

/*
** Write a 32-bit little endiate integer into buffer aBuf.
*/

static void zipfilePutU32(u8 *aBuf, u32 val){
  aBuf[0] = val & 0xFF;
  aBuf[1] = (val>>8) & 0xFF;
  aBuf[2] = (val>>16) & 0xFF;
  aBuf[3] = (val>>24) & 0xFF;
}

#define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
#define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )

#define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
#define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }

/*
** Magic numbers used to read CDS records.
*/

#define ZIPFILE_CDS_NFILE_OFF        28
#define ZIPFILE_CDS_SZCOMPRESSED_OFF 20

/*
** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
** if the record is not well-formed, or SQLITE_OK otherwise.
*/

static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
  u8 *aRead = aBuf;
  u32 sig = zipfileRead32(aRead);
  int rc = SQLITE_OK;
  if( sig!=ZIPFILE_SIGNATURE_CDS ){
    rc = SQLITE_ERROR;
  }else{
    pCDS->iVersionMadeBy = zipfileRead16(aRead);
    pCDS->iVersionExtract = zipfileRead16(aRead);
    pCDS->flags = zipfileRead16(aRead);
    pCDS->iCompression = zipfileRead16(aRead);
    pCDS->mTime = zipfileRead16(aRead);
    pCDS->mDate = zipfileRead16(aRead);
    pCDS->crc32 = zipfileRead32(aRead);
    pCDS->szCompressed = zipfileRead32(aRead);
    pCDS->szUncompressed = zipfileRead32(aRead);
    assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
    pCDS->nFile = zipfileRead16(aRead);
    pCDS->nExtra = zipfileRead16(aRead);
    pCDS->nComment = zipfileRead16(aRead);
    pCDS->iDiskStart = zipfileRead16(aRead);
    pCDS->iInternalAttr = zipfileRead16(aRead);
    pCDS->iExternalAttr = zipfileRead32(aRead);
    pCDS->iOffset = zipfileRead32(aRead);
    assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
  }

  return rc;
}

/*
** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
** if the record is not well-formed, or SQLITE_OK otherwise.
*/

static int zipfileReadLFH(
  u8 *aBuffer,
  ZipfileLFH *pLFH
){
  u8 *aRead = aBuffer;
  int rc = SQLITE_OK;

  u32 sig = zipfileRead32(aRead);
  if( sig!=ZIPFILE_SIGNATURE_LFH ){
    rc = SQLITE_ERROR;
  }else{
    pLFH->iVersionExtract = zipfileRead16(aRead);
    pLFH->flags = zipfileRead16(aRead);
    pLFH->iCompression = zipfileRead16(aRead);
    pLFH->mTime = zipfileRead16(aRead);
    pLFH->mDate = zipfileRead16(aRead);
    pLFH->crc32 = zipfileRead32(aRead);
    pLFH->szCompressed = zipfileRead32(aRead);
    pLFH->szUncompressed = zipfileRead32(aRead);
    pLFH->nFile = zipfileRead16(aRead);
    pLFH->nExtra = zipfileRead16(aRead);
    if( pLFH->nFile>ZIPFILE_MX_NAME ) rc = SQLITE_ERROR;
  }
  return rc;
}


/*
** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
** Scan through this buffer to find an "extra-timestamp" field. If one
** exists, extract the 32-bit modification-timestamp from it and store
** the value in output parameter *pmTime.
**
** Zero is returned if no extra-timestamp record could be found (and so
** *pmTime is left unchanged), or non-zero otherwise.
**
** The general format of an extra field is:
**
**   Header ID    2 bytes
**   Data Size    2 bytes
**   Data         N bytes
*/

static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
  int ret = 0;
  u8 *p = aExtra;
  u8 *pEnd = &aExtra[nExtra];

  /* Stop when there are less than 9 bytes left to scan in the buffer. This
  ** is because the timestamp field requires exactly 9 bytes - 4 bytes of
  ** header fields and 5 bytes of data. If there are less than 9 bytes 
  ** remaining, either it is some other field or else the extra data
  ** is corrupt. Either way, do not process it.  */

  while( p+(2*sizeof(u16) + 1 + sizeof(u32))<=pEnd ){
    u16 id = zipfileRead16(p);
    u16 nByte = zipfileRead16(p);

    switch( id ){
      case ZIPFILE_EXTRA_TIMESTAMP: {
        u8 b = p[0];
        if( b & 0x01 ){     /* 0x01 -> modtime is present */
          *pmTime = zipfileGetU32(&p[1]);
          ret = 1;
        }
        break;
      }
    }

    p += nByte;
  }
  return ret;
}

/*
** Convert the standard MS-DOS timestamp stored in the mTime and mDate
** fields of the CDS structure passed as the only argument to a 32-bit
** UNIX seconds-since-the-epoch timestamp. Return the result.
**
** "Standard" MS-DOS time format:
**
**   File modification time:
**     Bits 00-04: seconds divided by 2
**     Bits 05-10: minute
**     Bits 11-15: hour
**   File modification date:
**     Bits 00-04: day
**     Bits 05-08: month (1-12)
**     Bits 09-15: years from 1980 
**
** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
*/

static u32 zipfileMtime(ZipfileCDS *pCDS){
  int Y,M,D,X1,X2,A,B,sec,min,hr;
  i64 JDsec;
  Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
  M = ((pCDS->mDate >> 5) & 0x0F);
  D = (pCDS->mDate & 0x1F);
  sec = (pCDS->mTime & 0x1F)*2;
  min = (pCDS->mTime >> 5) & 0x3F;
  hr = (pCDS->mTime >> 11) & 0x1F;
  if( M<=2 ){
    Y--;
    M += 12;
  }
  X1 = 36525*(Y+4716)/100;
  X2 = 306001*(M+1)/10000;
  A = Y/100;
  B = 2 - A + (A/4);
  JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
  return (u32)(JDsec - (i64)24405875*(i64)8640);
}

/*
** The opposite of zipfileMtime(). This function populates the mTime and
** mDate fields of the CDS structure passed as the first argument according
** to the UNIX timestamp value passed as the second.
*/

static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
  /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
  i64 JD = (i64)2440588 + mUnixTime / (24*60*60);

  int A, B, C, D, E;
  int yr, mon, day;
  int hr, min, sec;

  A = (int)((JD - 1867216.25)/36524.25);
  A = (int)(JD + 1 + A - (A/4));
  B = A + 1524;
  C = (int)((B - 122.1)/365.25);
  D = (36525*(C&32767))/100;
  E = (int)((B-D)/30.6001);

  day = B - D - (int)(30.6001*E);
  mon = (E<14 ? E-1 : E-13);
  yr = mon>2 ? C-4716 : C-4715;

  hr = (mUnixTime % (24*60*60)) / (60*60);
  min = (mUnixTime % (60*60)) / 60;
  sec = (mUnixTime % 60);

  if( yr>=1980 ){
    pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
    pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
  }else{
    pCds->mDate = pCds->mTime = 0;
  }

  assert( mUnixTime<315507600 
       || mUnixTime==zipfileMtime(pCds) 
       || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds)) 
       /* || (mUnixTime % 2) */
  );
}

/*
** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a 
** generic corruption message and return SQLITE_CORRUPT;
*/

static int zipfileCorrupt(char **pzErr){
  sqlite3_free(*pzErr);
  *pzErr = sqlite3_mprintf("zip archive is corrupt");
  return SQLITE_CORRUPT;
}

/*
** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
** size) containing an entire zip archive image. Or, if aBlob is NULL,
** then pFile is a file-handle open on a zip file. In either case, this
** function creates a ZipfileEntry object based on the zip archive entry
** for which the CDS record is at offset iOff.
**
** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
** the new object. Otherwise, an SQLite error code is returned and the
** final value of (*ppEntry) undefined.
*/

static int zipfileGetEntry(
  ZipfileTab *pTab,               /* Store any error message here */
  const u8 *aBlob,                /* Pointer to in-memory file image */
  i64 nBlob,                      /* Size of aBlob[] in bytes */
  FILE *pFile,                    /* If aBlob==0, read from this file */
  i64 iOff,                       /* Offset of CDS record */
  ZipfileEntry **ppEntry          /* OUT: Pointer to new object */
){
  u8 *aRead;
  char **pzErr = &pTab->base.zErrMsg;
  int rc = SQLITE_OK;

  if( aBlob==0 ){
    aRead = pTab->aBuffer;
    rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
  }else{
    if( (iOff+ZIPFILE_CDS_FIXED_SZ)>nBlob ){
      /* Not enough data for the CDS structure. Corruption. */
      return zipfileCorrupt(pzErr);
    }
    aRead = (u8*)&aBlob[iOff];
  }

  if( rc==SQLITE_OK ){
    sqlite3_int64 nAlloc;
    ZipfileEntry *pNew;

    int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
    int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
    nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);

    nAlloc = sizeof(ZipfileEntry) + nExtra;
    if( aBlob ){
      nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
    }

    pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
    if( pNew==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pNew, 0, sizeof(ZipfileEntry));
      rc = zipfileReadCDS(aRead, &pNew->cds);
      if( rc!=SQLITE_OK ){
        zipfileTableErr(pTab, "failed to read CDS at offset %lld", iOff);
      }else if( aBlob==0 ){
        rc = zipfileReadData(
            pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
        );
      }else{
        aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
        if( (iOff + ZIPFILE_CDS_FIXED_SZ + nFile + nExtra)>nBlob ){
          rc = zipfileCorrupt(pzErr);
        }
      }
    }

    if( rc==SQLITE_OK ){
      u32 *pt = &pNew->mUnixTime;
      pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead); 
      pNew->aExtra = (u8*)&pNew[1];
      memcpy(pNew->aExtra, &aRead[nFile], nExtra);
      if( pNew->cds.zFile==0 ){
        rc = SQLITE_NOMEM;
      }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
        pNew->mUnixTime = zipfileMtime(&pNew->cds);
      }
    }

    if( rc==SQLITE_OK ){
      static const int szFix = ZIPFILE_LFH_FIXED_SZ;
      ZipfileLFH lfh;
      if( pFile ){
        rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
      }else{
        aRead = (u8*)&aBlob[pNew->cds.iOffset];
        if( ((i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){
          rc = zipfileCorrupt(pzErr);
        }
      }

      memset(&lfh, 0, sizeof(lfh));
      if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
      if( rc==SQLITE_OK ){
        pNew->iDataOff =  (i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
        pNew->iDataOff += lfh.nFile + lfh.nExtra;
        if( aBlob && pNew->cds.szCompressed ){
          if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){
            rc = zipfileCorrupt(pzErr);
          }else{
            pNew->aData = &pNew->aExtra[nExtra];
            memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
          }
        }
      }else{
        zipfileTableErr(pTab, "failed to read LFH at offset %d", 
            (int)pNew->cds.iOffset
        );
      }
    }

    if( rc!=SQLITE_OK ){
      zipfileEntryFree(pNew);
    }else{
      *ppEntry = pNew;
    }
  }

  return rc;
}

/*
** Advance an ZipfileCsr to its next row of output.
*/

static int zipfileNext(sqlite3_vtab_cursor *cur){
  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
  int rc = SQLITE_OK;

  if( pCsr->pFile ){
    i64 iEof = (i64)pCsr->eocd.iOffset + (i64)pCsr->eocd.nSize;
    zipfileEntryFree(pCsr->pCurrent);
    pCsr->pCurrent = 0;
    if( pCsr->iNextOff>=iEof ){
      pCsr->bEof = 1;
    }else{
      ZipfileEntry *p = 0;
      ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
      rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
      if( rc==SQLITE_OK ){
        pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
        pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
      }
      pCsr->pCurrent = p;
    }
  }else{
    if( !pCsr->bNoop ){
      pCsr->pCurrent = pCsr->pCurrent->pNext;
    }
    if( pCsr->pCurrent==0 ){
      pCsr->bEof = 1;
    }
  }

  pCsr->bNoop = 0;
  return rc;
}

static void zipfileFree(void *p) { 
  sqlite3_free(p); 
}

/*
** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
** size is nOut bytes. This function uncompresses the data and sets the
** return value in context pCtx to the result (a blob).
**
** If an error occurs, an error code is left in pCtx instead.
*/

static void zipfileInflate(
  sqlite3_context *pCtx,          /* Store result here */
  const u8 *aIn,                  /* Compressed data */
  int nIn,                        /* Size of buffer aIn[] in bytes */
  int nOut                        /* Expected output size */
){
  u8 *aRes = sqlite3_malloc64(nOut);
  if( aRes==0 ){
    sqlite3_result_error_nomem(pCtx);
  }else{
    int err;
    z_stream str;
    memset(&str, 0, sizeof(str));

    str.next_in = (Byte*)aIn;
    str.avail_in = nIn;
    str.next_out = (Byte*)aRes;
    str.avail_out = nOut;

    err = inflateInit2(&str, -15);
    if( err!=Z_OK ){
      zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
    }else{
      err = inflate(&str, Z_NO_FLUSH);
      if( err!=Z_STREAM_END ){
        zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
      }else{
        sqlite3_result_blob(pCtx, aRes, (int)str.total_out, zipfileFree);
        aRes = 0;
      }
    }
    sqlite3_free(aRes);
    inflateEnd(&str);
  }
}

/*
** Buffer aIn (size nIn bytes) contains uncompressed data. This function
** compresses it and sets (*ppOut) to point to a buffer containing the
** compressed data. The caller is responsible for eventually calling
** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) 
** is set to the size of buffer (*ppOut) in bytes.
**
** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
** code is returned and an error message left in virtual-table handle
** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
** case.
*/

static int zipfileDeflate(
  const u8 *aIn, int nIn,         /* Input */
  u8 **ppOut, int *pnOut,         /* Output */
  char **pzErr                    /* OUT: Error message */
){
  int rc = SQLITE_OK;
  sqlite3_int64 nAlloc;
  z_stream str;
  u8 *aOut;

  memset(&str, 0, sizeof(str));
  str.next_in = (Bytef*)aIn;
  str.avail_in = nIn;
  deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);

  nAlloc = deflateBound(&str, nIn);
  aOut = (u8*)sqlite3_malloc64(nAlloc);
  if( aOut==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int res;
    str.next_out = aOut;
    str.avail_out = nAlloc;
    res = deflate(&str, Z_FINISH);
    if( res==Z_STREAM_END ){
      *ppOut = aOut;
      *pnOut = (int)str.total_out;
    }else{
      sqlite3_free(aOut);
      *pzErr = sqlite3_mprintf("zipfile: deflate() error");
      rc = SQLITE_ERROR;
    }
    deflateEnd(&str);
  }

  return rc;
}


/*
** Return values of columns for the row at which the series_cursor
** is currently pointing.
*/

static int zipfileColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
  ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
  int rc = SQLITE_OK;
  switch( i ){
    case 0:   /* name */
      sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
      break;
    case 1:   /* mode */
      /* TODO: Whether or not the following is correct surely depends on
      ** the platform on which the archive was created.  */

      sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
      break;
    case 2: { /* mtime */
      sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
      break;
    }
    case 3: { /* sz */
      if( sqlite3_vtab_nochange(ctx)==0 ){
        sqlite3_result_int64(ctx, pCDS->szUncompressed);
      }
      break;
    }
    case 4:   /* rawdata */
      if( sqlite3_vtab_nochange(ctx) ) break;
    case 5: { /* data */
      if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
        int sz = pCDS->szCompressed;
        int szFinal = pCDS->szUncompressed;
        if( szFinal>0 ){
          u8 *aBuf;
          u8 *aFree = 0;
          if( pCsr->pCurrent->aData ){
            aBuf = pCsr->pCurrent->aData;
          }else{
            aBuf = aFree = sqlite3_malloc64(sz);
            if( aBuf==0 ){
              rc = SQLITE_NOMEM;
            }else{
              FILE *pFile = pCsr->pFile;
              if( pFile==0 ){
                pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
              }
              rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
                  &pCsr->base.pVtab->zErrMsg
              );
            }
          }
          if( rc==SQLITE_OK ){
            if( i==5 && pCDS->iCompression ){
              zipfileInflate(ctx, aBuf, sz, szFinal);
            }else{
              sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
            }
          }
          sqlite3_free(aFree);
        }else{
          /* Figure out if this is a directory or a zero-sized file. Consider
          ** it to be a directory either if the mode suggests so, or if
          ** the final character in the name is '/'.  */

          u32 mode = pCDS->iExternalAttr >> 16;
          if( !(mode & S_IFDIR)
           && pCDS->nFile>=1
           && pCDS->zFile[pCDS->nFile-1]!='/'
          ){
            sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
          }
        }
      }
      break;
    }
    case 6:   /* method */
      sqlite3_result_int(ctx, pCDS->iCompression);
      break;
    default:  /* z */
      assert( i==7 );
      sqlite3_result_int64(ctx, pCsr->iId);
      break;
  }

  return rc;
}

/*
** Return TRUE if the cursor is at EOF.
*/

static int zipfileEof(sqlite3_vtab_cursor *cur){
  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
  return pCsr->bEof;
}

/*
** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
** is guaranteed to be a file-handle open on a zip file.
**
** This function attempts to locate the EOCD record within the zip archive
** and populate *pEOCD with the results of decoding it. SQLITE_OK is
** returned if successful. Otherwise, an SQLite error code is returned and
** an English language error message may be left in virtual-table pTab.
*/

static int zipfileReadEOCD(
  ZipfileTab *pTab,               /* Return errors here */
  const u8 *aBlob,                /* Pointer to in-memory file image */
  i64 nBlob,                      /* Size of aBlob[] in bytes */
  FILE *pFile,                    /* Read from this file if aBlob==0 */
  ZipfileEOCD *pEOCD              /* Object to populate */
){
  u8 *aRead = pTab->aBuffer;      /* Temporary buffer */
  i64 nRead;                      /* Bytes to read from file */
  int rc = SQLITE_OK;

  memset(pEOCD, 0, sizeof(ZipfileEOCD));
  if( aBlob==0 ){
    i64 iOff;                     /* Offset to read from */
    i64 szFile;                   /* Total size of file in bytes */
    fseek(pFile, 0, SEEK_END);
    szFile = (i64)ftell(pFile);
    if( szFile==0 ){
      return SQLITE_OK;
    }
    nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
    iOff = szFile - nRead;
    rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
  }else{
    nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
    aRead = (u8*)&aBlob[nBlob-nRead];
  }

  if( rc==SQLITE_OK ){
    i64 i;

    /* Scan backwards looking for the signature bytes */
    for(i=nRead-20; i>=0; i--){
      if( aRead[i]==0x50 && aRead[i+1]==0x4b 
       && aRead[i+2]==0x05 && aRead[i+3]==0x06 
      ){
        break;
      }
    }
    if( i<0 ){
      zipfileTableErr(pTab, "cannot find end of central directory record");
      return SQLITE_ERROR;
    }

    aRead += i+4;
    pEOCD->iDisk = zipfileRead16(aRead);
    pEOCD->iFirstDisk = zipfileRead16(aRead);
    pEOCD->nEntry = zipfileRead16(aRead);
    pEOCD->nEntryTotal = zipfileRead16(aRead);
    pEOCD->nSize = zipfileRead32(aRead);
    pEOCD->iOffset = zipfileRead32(aRead);
  }

  return rc;
}

/*
** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry 
** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
** to the end of the list. Otherwise, it is added to the list immediately
** before pBefore (which is guaranteed to be a part of said list).
*/

static void zipfileAddEntry(
  ZipfileTab *pTab, 
  ZipfileEntry *pBefore, 
  ZipfileEntry *pNew
){
  assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
  assert( pNew->pNext==0 );
  if( pBefore==0 ){
    if( pTab->pFirstEntry==0 ){
      pTab->pFirstEntry = pTab->pLastEntry = pNew;
    }else{
      assert( pTab->pLastEntry->pNext==0 );
      pTab->pLastEntry->pNext = pNew;
      pTab->pLastEntry = pNew;
    }
  }else{
    ZipfileEntry **pp;
    for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
    pNew->pNext = pBefore;
    *pp = pNew;
  }
}

static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, i64 nBlob){
  ZipfileEOCD eocd;
  int rc;
  int i;
  i64 iOff;

  rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
  iOff = eocd.iOffset;
  for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
    ZipfileEntry *pNew = 0;
    rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);

    if( rc==SQLITE_OK ){
      zipfileAddEntry(pTab, 0, pNew);
      iOff += ZIPFILE_CDS_FIXED_SZ;
      iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
    }
  }
  return rc;
}

/*
** xFilter callback.
*/

static int zipfileFilter(
  sqlite3_vtab_cursor *cur, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
  const char *zFile = 0;          /* Zip file to scan */
  int rc = SQLITE_OK;             /* Return Code */
  int bInMemory = 0;              /* True for an in-memory zipfile */

  (void)idxStr;
  (void)argc;

  zipfileResetCursor(pCsr);

  if( pTab->zFile ){
    zFile = pTab->zFile;
  }else if( idxNum==0 ){
    zipfileCursorErr(pCsr, "zipfile() function requires an argument");
    return SQLITE_ERROR;
  }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
    static const u8 aEmptyBlob = 0;
    const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
    i64 nBlob = sqlite3_value_bytes(argv[0]);
    assert( pTab->pFirstEntry==0 );
    if( aBlob==0 ){
      aBlob = &aEmptyBlob;
      nBlob = 0;
    }
    rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
    pCsr->pFreeEntry = pTab->pFirstEntry;
    pTab->pFirstEntry = pTab->pLastEntry = 0;
    if( rc!=SQLITE_OK ) return rc;
    bInMemory = 1;
  }else{
    zFile = (const char*)sqlite3_value_text(argv[0]);
  }

  if( 0==pTab->pWriteFd && 0==bInMemory ){
    pCsr->pFile = zFile ? sqlite3_fopen(zFile, "rb") : 0;
    if( pCsr->pFile==0 ){
      zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
      rc = SQLITE_ERROR;
    }else{
      rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
      if( rc==SQLITE_OK ){
        if( pCsr->eocd.nEntry==0 ){
          pCsr->bEof = 1;
        }else{
          pCsr->iNextOff = pCsr->eocd.iOffset;
          rc = zipfileNext(cur);
        }
      }
    }
  }else{
    pCsr->bNoop = 1;
    pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
    rc = zipfileNext(cur);
  }

  return rc;
}

/*
** xBestIndex callback.
*/

static int zipfileBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;
  int idx = -1;
  int unusable = 0;
  (void)tab;

  for(i=0; i<pIdxInfo->nConstraint; i++){
    const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
    if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
    if( pCons->usable==0 ){
      unusable = 1;
    }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
      idx = i;
    }
  }
  pIdxInfo->estimatedCost = 1000.0;
  if( idx>=0 ){
    pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
    pIdxInfo->aConstraintUsage[idx].omit = 1;
    pIdxInfo->idxNum = 1;
  }else if( unusable ){
    return SQLITE_CONSTRAINT;
  }
  return SQLITE_OK;
}

static ZipfileEntry *zipfileNewEntry(const char *zPath){
  ZipfileEntry *pNew;
  pNew = sqlite3_malloc64(sizeof(ZipfileEntry));
  if( pNew ){
    memset(pNew, 0, sizeof(ZipfileEntry));
    pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
    if( pNew->cds.zFile==0 ){
      sqlite3_free(pNew);
      pNew = 0;
    }
  }
  return pNew;
}

static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
  ZipfileCDS *pCds = &pEntry->cds;
  u8 *a = aBuf;

  pCds->nExtra = 9;

  /* Write the LFH itself */
  zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
  zipfileWrite16(a, pCds->iVersionExtract);
  zipfileWrite16(a, pCds->flags);
  zipfileWrite16(a, pCds->iCompression);
  zipfileWrite16(a, pCds->mTime);
  zipfileWrite16(a, pCds->mDate);
  zipfileWrite32(a, pCds->crc32);
  zipfileWrite32(a, pCds->szCompressed);
  zipfileWrite32(a, pCds->szUncompressed);
  zipfileWrite16(a, (u16)pCds->nFile);
  zipfileWrite16(a, pCds->nExtra);
  assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );

  /* Add the file name */
  memcpy(a, pCds->zFile, (int)pCds->nFile);
  a += (int)pCds->nFile;

  /* The "extra" data */
  zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
  zipfileWrite16(a, 5);
  *a++ = 0x01;
  zipfileWrite32(a, pEntry->mUnixTime);

  return a-aBuf;
}

static int zipfileAppendEntry(
  ZipfileTab *pTab,
  ZipfileEntry *pEntry,
  const u8 *pData,
  int nData
){
  u8 *aBuf = pTab->aBuffer;
  int nBuf;
  int rc;

  nBuf = zipfileSerializeLFH(pEntry, aBuf);
  rc = zipfileAppendData(pTab, aBuf, nBuf);
  if( rc==SQLITE_OK ){
    pEntry->iDataOff = pTab->szCurrent;
    rc = zipfileAppendData(pTab, pData, nData);
  }

  return rc;
}

static int zipfileGetMode(
  sqlite3_value *pVal, 
  int bIsDir,                     /* If true, default to directory */
  u32 *pMode,                     /* OUT: Mode value */
  char **pzErr                    /* OUT: Error message */
){
  const char *z = (const char*)sqlite3_value_text(pVal);
  u32 mode = 0;
  if( z==0 ){
    mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
  }else if( z[0]>='0' && z[0]<='9' ){
    mode = (unsigned int)sqlite3_value_int(pVal);
  }else{
    const char zTemplate[11] = "-rwxrwxrwx";
    int i;
    if( strlen(z)!=10 ) goto parse_error;
    switch( z[0] ){
      case '-': mode |= S_IFREG; break;
      case 'd': mode |= S_IFDIR; break;
      case 'l': mode |= S_IFLNK; break;
      default: goto parse_error;
    }
    for(i=1; i<10; i++){
      if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
      else if( z[i]!='-' ) goto parse_error;
    }
  }
  if( ((mode & S_IFDIR)==0)==bIsDir ){
    /* The "mode" attribute is a directory, but data has been specified.
    ** Or vice-versa - no data but "mode" is a file or symlink.  */

    *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
    return SQLITE_CONSTRAINT;
  }
  *pMode = mode;
  return SQLITE_OK;

 parse_error:
  *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
  return SQLITE_ERROR;
}

/*
** Both (const char*) arguments point to nul-terminated strings. Argument
** nB is the value of strlen(zB). This function returns 0 if the strings are
** identical, ignoring any trailing '/' character in either path.  */

static int zipfileComparePath(const char *zA, const char *zB, int nB){
  int nA = (int)strlen(zA);
  if( nA>0 && zA[nA-1]=='/' ) nA--;
  if( nB>0 && zB[nB-1]=='/' ) nB--;
  if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
  return 1;
}

static int zipfileBegin(sqlite3_vtab *pVtab){
  ZipfileTab *pTab = (ZipfileTab*)pVtab;
  int rc = SQLITE_OK;

  assert( pTab->pWriteFd==0 );
  if( pTab->zFile==0 || pTab->zFile[0]==0 ){
    zipfileTableErr(pTab, "zipfile: missing filename");
    return SQLITE_ERROR;
  }

  /* Open a write fd on the file. Also load the entire central directory
  ** structure into memory. During the transaction any new file data is 
  ** appended to the archive file, but the central directory is accumulated
  ** in main-memory until the transaction is committed.  */

  pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+");
  if( pTab->pWriteFd==0 ){
    zipfileTableErr(pTab,
      "zipfile: failed to open file %s for writing", pTab->zFile
    );
    rc = SQLITE_ERROR;
  }else{
    fseek(pTab->pWriteFd, 0, SEEK_END);
    pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
    rc = zipfileLoadDirectory(pTab, 0, 0);
  }

  if( rc!=SQLITE_OK ){
    zipfileCleanupTransaction(pTab);
  }

  return rc;
}

/*
** Return the current time as a 32-bit timestamp in UNIX epoch format (like
** time(2)).
*/

static u32 zipfileTime(void){
  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
  u32 ret;
  if( pVfs==0 ) return 0;
  if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
    i64 ms;
    pVfs->xCurrentTimeInt64(pVfs, &ms);
    ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
  }else{
    double day;
    pVfs->xCurrentTime(pVfs, &day);
    ret = (u32)((day - 2440587.5) * 86400);
  }
  return ret;
}

/*
** Return a 32-bit timestamp in UNIX epoch format.
**
** If the value passed as the only argument is either NULL or an SQL NULL,
** return the current time. Otherwise, return the value stored in (*pVal)
** cast to a 32-bit unsigned integer.
*/

static u32 zipfileGetTime(sqlite3_value *pVal){
  if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
    return zipfileTime();
  }
  return (u32)sqlite3_value_int64(pVal);
}

/*
** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
** linked list.  Remove it from the list and free the object.
*/

static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
  if( pOld ){
    if( pTab->pFirstEntry==pOld ){
      pTab->pFirstEntry = pOld->pNext;
      if( pTab->pLastEntry==pOld ) pTab->pLastEntry = 0;
    }else{
      ZipfileEntry *p;
      for(p=pTab->pFirstEntry; p; p=p->pNext){
        if( p->pNext==pOld ){
          p->pNext = pOld->pNext;
          if( pTab->pLastEntry==pOld ) pTab->pLastEntry = p;
          break;
        }
      }
    }
    zipfileEntryFree(pOld);
  }
}

/*
** xUpdate method.
*/

static int zipfileUpdate(
  sqlite3_vtab *pVtab, 
  int nVal, 
  sqlite3_value **apVal, 
  sqlite_int64 *pRowid
){
  ZipfileTab *pTab = (ZipfileTab*)pVtab;
  int rc = SQLITE_OK;             /* Return Code */
  ZipfileEntry *pNew = 0;         /* New in-memory CDS entry */

  u32 mode = 0;                   /* Mode for new entry */
  u32 mTime = 0;                  /* Modification time for new entry */
  i64 sz = 0;                     /* Uncompressed size */
  const char *zPath = 0;          /* Path for new entry */
  int nPath = 0;                  /* strlen(zPath) */
  const u8 *pData = 0;            /* Pointer to buffer containing content */
  int nData = 0;                  /* Size of pData buffer in bytes */
  int iMethod = 0;                /* Compression method for new entry */
  u8 *pFree = 0;                  /* Free this */
  char *zFree = 0;                /* Also free this */
  ZipfileEntry *pOld = 0;
  ZipfileEntry *pOld2 = 0;
  int bUpdate = 0;                /* True for an update that modifies "name" */
  int bIsDir = 0;
  u32 iCrc32 = 0;

  (void)pRowid;

  if( pTab->pWriteFd==0 ){
    rc = zipfileBegin(pVtab);
    if( rc!=SQLITE_OK ) return rc;
  }

  /* If this is a DELETE or UPDATE, find the archive entry to delete. */
  if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
    const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
    int nDelete = (int)strlen(zDelete);
    if( nVal>1 ){
      const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
      if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
        bUpdate = 1;
      }
    }
    for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
      if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
        break;
      }
      assert( pOld->pNext );
    }
  }

  if( nVal>1 ){
    /* Check that "sz" and "rawdata" are both NULL: */
    if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
      zipfileTableErr(pTab, "sz must be NULL");
      rc = SQLITE_CONSTRAINT;
    }
    if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
      zipfileTableErr(pTab, "rawdata must be NULL"); 
      rc = SQLITE_CONSTRAINT;
    }

    if( rc==SQLITE_OK ){
      if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
        /* data=NULL. A directory */
        bIsDir = 1;
      }else{
        /* Value specified for "data", and possibly "method". This must be
        ** a regular file or a symlink. */

        const u8 *aIn = sqlite3_value_blob(apVal[7]);
        int nIn = sqlite3_value_bytes(apVal[7]);
        int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;

        iMethod = sqlite3_value_int(apVal[8]);
        sz = nIn;
        pData = aIn;
        nData = nIn;
        if( iMethod!=0 && iMethod!=8 ){
          zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
          rc = SQLITE_CONSTRAINT;
        }else{
          if( bAuto || iMethod ){
            int nCmp;
            rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
            if( rc==SQLITE_OK ){
              if( iMethod || nCmp<nIn ){
                iMethod = 8;
                pData = pFree;
                nData = nCmp;
              }
            }
          }
          iCrc32 = crc32(0, aIn, nIn);
        }
      }
    }

    if( rc==SQLITE_OK ){
      rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
    }

    if( rc==SQLITE_OK ){
      zPath = (const char*)sqlite3_value_text(apVal[2]);
      if( zPath==0 ) zPath = "";
      nPath = (int)strlen(zPath);
      if( nPath>ZIPFILE_MX_NAME ){
        zipfileTableErr(pTab, "filename too long; max: %d bytes",
                        ZIPFILE_MX_NAME);
        rc = SQLITE_CONSTRAINT;
      }
      mTime = zipfileGetTime(apVal[4]);
    }

    if( rc==SQLITE_OK && bIsDir ){
      /* For a directory, check that the last character in the path is a
      ** '/'. This appears to be required for compatibility with info-zip
      ** (the unzip command on unix). It does not create directories
      ** otherwise.  */

      if( nPath<=0 || zPath[nPath-1]!='/' ){
        zFree = sqlite3_mprintf("%s/", zPath);
        zPath = (const char*)zFree;
        if( zFree==0 ){
          rc = SQLITE_NOMEM;
          nPath = 0;
        }else{
          nPath = (int)strlen(zPath);
        }
      }
    }

    /* Check that we're not inserting a duplicate entry -OR- updating an
    ** entry with a path, thereby making it into a duplicate. */

    if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
      ZipfileEntry *p;
      for(p=pTab->pFirstEntry; p; p=p->pNext){
        if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
          switch( sqlite3_vtab_on_conflict(pTab->db) ){
            case SQLITE_IGNORE: {
              goto zipfile_update_done;
            }
            case SQLITE_REPLACE: {
              pOld2 = p;
              break;
            }
            default: {
              zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
              rc = SQLITE_CONSTRAINT;
              break;
            }
          }
          break;
        }
      }
    }

    if( rc==SQLITE_OK ){
      /* Create the new CDS record. */
      pNew = zipfileNewEntry(zPath);
      if( pNew==0 ){
        rc = SQLITE_NOMEM;
      }else{
        pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
        pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
        pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
        pNew->cds.iCompression = (u16)iMethod;
        zipfileMtimeToDos(&pNew->cds, mTime);
        pNew->cds.crc32 = iCrc32;
        pNew->cds.szCompressed = nData;
        pNew->cds.szUncompressed = (u32)sz;
        pNew->cds.iExternalAttr = (mode<<16);
        pNew->cds.iOffset = (u32)pTab->szCurrent;
        pNew->cds.nFile = (u16)nPath;
        pNew->mUnixTime = (u32)mTime;
        rc = zipfileAppendEntry(pTab, pNew, pData, nData);
        zipfileAddEntry(pTab, pOld, pNew);
      }
    }
  }

  if( rc==SQLITE_OK && (pOld || pOld2) ){
    ZipfileCsr *pCsr;
    for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
      if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
        pCsr->pCurrent = pCsr->pCurrent->pNext;
        pCsr->bNoop = 1;
      }
    }

    zipfileRemoveEntryFromList(pTab, pOld);
    zipfileRemoveEntryFromList(pTab, pOld2);
  }

zipfile_update_done:
  sqlite3_free(pFree);
  sqlite3_free(zFree);
  return rc;
}

static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
  u8 *a = aBuf;
  zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
  zipfileWrite16(a, p->iDisk);
  zipfileWrite16(a, p->iFirstDisk);
  zipfileWrite16(a, p->nEntry);
  zipfileWrite16(a, p->nEntryTotal);
  zipfileWrite32(a, p->nSize);
  zipfileWrite32(a, p->iOffset);
  zipfileWrite16(a, 0);        /* Size of trailing comment in bytes*/

  return a-aBuf;
}

static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
  int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
  assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
  return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
}

/*
** Serialize the CDS structure into buffer aBuf[]. Return the number
** of bytes written.
*/

static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
  u8 *a = aBuf;
  ZipfileCDS *pCDS = &pEntry->cds;

  if( pEntry->aExtra==0 ){
    pCDS->nExtra = 9;
  }

  zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
  zipfileWrite16(a, pCDS->iVersionMadeBy);
  zipfileWrite16(a, pCDS->iVersionExtract);
  zipfileWrite16(a, pCDS->flags);
  zipfileWrite16(a, pCDS->iCompression);
  zipfileWrite16(a, pCDS->mTime);
  zipfileWrite16(a, pCDS->mDate);
  zipfileWrite32(a, pCDS->crc32);
  zipfileWrite32(a, pCDS->szCompressed);
  zipfileWrite32(a, pCDS->szUncompressed);
  assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
  zipfileWrite16(a, pCDS->nFile);
  zipfileWrite16(a, pCDS->nExtra);
  zipfileWrite16(a, pCDS->nComment);
  zipfileWrite16(a, pCDS->iDiskStart);
  zipfileWrite16(a, pCDS->iInternalAttr);
  zipfileWrite32(a, pCDS->iExternalAttr);
  zipfileWrite32(a, pCDS->iOffset);

  memcpy(a, pCDS->zFile, pCDS->nFile);
  a += pCDS->nFile;

  if( pEntry->aExtra ){
    int n = (int)pCDS->nExtra + (int)pCDS->nComment;
    memcpy(a, pEntry->aExtra, n);
    a += n;
  }else{
    assert( pCDS->nExtra==9 );
    zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
    zipfileWrite16(a, 5);
    *a++ = 0x01;
    zipfileWrite32(a, pEntry->mUnixTime);
  }

  return a-aBuf;
}

static int zipfileCommit(sqlite3_vtab *pVtab){
  ZipfileTab *pTab = (ZipfileTab*)pVtab;
  int rc = SQLITE_OK;
  if( pTab->pWriteFd ){
    i64 iOffset = pTab->szCurrent;
    ZipfileEntry *p;
    ZipfileEOCD eocd;
    int nEntry = 0;

    /* Write out all entries */
    for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
      int n = zipfileSerializeCDS(p, pTab->aBuffer);
      rc = zipfileAppendData(pTab, pTab->aBuffer, n);
      nEntry++;
    }

    /* Write out the EOCD record */
    eocd.iDisk = 0;
    eocd.iFirstDisk = 0;
    eocd.nEntry = (u16)nEntry;
    eocd.nEntryTotal = (u16)nEntry;
    eocd.nSize = (u32)(pTab->szCurrent - iOffset);
    eocd.iOffset = (u32)iOffset;
    rc = zipfileAppendEOCD(pTab, &eocd);

    zipfileCleanupTransaction(pTab);
  }
  return rc;
}

static int zipfileRollback(sqlite3_vtab *pVtab){
  return zipfileCommit(pVtab);
}

static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
  ZipfileCsr *pCsr;
  for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
    if( iId==pCsr->iId ) break;
  }
  return pCsr;
}

static void zipfileFunctionCds(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  ZipfileCsr *pCsr;
  ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
  assert( argc>0 );

  pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
  if( pCsr ){
    ZipfileCDS *p = &pCsr->pCurrent->cds;
    char *zRes = sqlite3_mprintf("{"
        "\"version-made-by\" : %u, "
        "\"version-to-extract\" : %u, "
        "\"flags\" : %u, "
        "\"compression\" : %u, "
        "\"time\" : %u, "
        "\"date\" : %u, "
        "\"crc32\" : %u, "
        "\"compressed-size\" : %u, "
        "\"uncompressed-size\" : %u, "
        "\"file-name-length\" : %u, "
        "\"extra-field-length\" : %u, "
        "\"file-comment-length\" : %u, "
        "\"disk-number-start\" : %u, "
        "\"internal-attr\" : %u, "
        "\"external-attr\" : %u, "
        "\"offset\" : %u }",
        (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
        (u32)p->flags, (u32)p->iCompression,
        (u32)p->mTime, (u32)p->mDate,
        (u32)p->crc32, (u32)p->szCompressed,
        (u32)p->szUncompressed, (u32)p->nFile,
        (u32)p->nExtra, (u32)p->nComment,
        (u32)p->iDiskStart, (u32)p->iInternalAttr,
        (u32)p->iExternalAttr, (u32)p->iOffset
    );

    if( zRes==0 ){
      sqlite3_result_error_nomem(context);
    }else{
      sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
      sqlite3_free(zRes);
    }
  }
}

/*
** xFindFunction method.
*/

static int zipfileFindFunction(
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  int nArg,                       /* Number of SQL function arguments */
  const char *zName,              /* Name of SQL function */
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
  void **ppArg                    /* OUT: User data for *pxFunc */
){
  (void)nArg;
  if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
    *pxFunc = zipfileFunctionCds;
    *ppArg = (void*)pVtab;
    return 1;
  }
  return 0;
}

typedef struct ZipfileBuffer ZipfileBuffer;
struct ZipfileBuffer {
  u8 *a;                          /* Pointer to buffer */
  int n;                          /* Size of buffer in bytes */
  int nAlloc;                     /* Byte allocated at a[] */
};

typedef struct ZipfileCtx ZipfileCtx;
struct ZipfileCtx {
  int nEntry;
  ZipfileBuffer body;
  ZipfileBuffer cds;
};

static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
  if( pBuf->n+nByte>pBuf->nAlloc ){
    u8 *aNew;
    sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
    int nReq = pBuf->n + nByte;

    while( nNew<nReq ) nNew = nNew*2;
    aNew = sqlite3_realloc64(pBuf->a, nNew);
    if( aNew==0 ) return SQLITE_NOMEM;
    pBuf->a = aNew;
    pBuf->nAlloc = (int)nNew;
  }
  return SQLITE_OK;
}

/*
** xStep() callback for the zipfile() aggregate. This can be called in
** any of the following ways:
**
**   SELECT zipfile(name,data) ...
**   SELECT zipfile(name,mode,mtime,data) ...
**   SELECT zipfile(name,mode,mtime,data,method) ...
*/

static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
  ZipfileCtx *p;                  /* Aggregate function context */
  ZipfileEntry e;                 /* New entry to add to zip archive */

  sqlite3_value *pName = 0;
  sqlite3_value *pMode = 0;
  sqlite3_value *pMtime = 0;
  sqlite3_value *pData = 0;
  sqlite3_value *pMethod = 0;

  int bIsDir = 0;
  u32 mode;
  int rc = SQLITE_OK;
  char *zErr = 0;

  int iMethod = -1;               /* Compression method to use (0 or 8) */

  const u8 *aData = 0;            /* Possibly compressed data for new entry */
  int nData = 0;                  /* Size of aData[] in bytes */
  int szUncompressed = 0;         /* Size of data before compression */
  u8 *aFree = 0;                  /* Free this before returning */
  u32 iCrc32 = 0;                 /* crc32 of uncompressed data */

  char *zName = 0;                /* Path (name) of new entry */
  int nName = 0;                  /* Size of zName in bytes */
  char *zFree = 0;                /* Free this before returning */
  i64 nByte;

  memset(&e, 0, sizeof(e));
  p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
  if( p==0 ) return;

  /* Martial the arguments into stack variables */
  if( nVal!=2 && nVal!=4 && nVal!=5 ){
    zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
    rc = SQLITE_ERROR;
    goto zipfile_step_out;
  }
  pName = apVal[0];
  if( nVal==2 ){
    pData = apVal[1];
  }else{
    pMode = apVal[1];
    pMtime = apVal[2];
    pData = apVal[3];
    if( nVal==5 ){
      pMethod = apVal[4];
    }
  }

  /* Check that the 'name' parameter looks ok. */
  zName = (char*)sqlite3_value_text(pName);
  nName = sqlite3_value_bytes(pName);
  if( zName==0 ){
    zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
    rc = SQLITE_ERROR;
    goto zipfile_step_out;
  }
  if( nName>ZIPFILE_MX_NAME ){
    zErr = sqlite3_mprintf(
               "filename argument to zipfile() too big; max: %d bytes",
               ZIPFILE_MX_NAME);
    rc = SQLITE_ERROR;
    goto zipfile_step_out;
  }

  /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
  ** deflate compression) or NULL (choose automatically).  */

  if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
    iMethod = (int)sqlite3_value_int64(pMethod);
    if( iMethod!=0 && iMethod!=8 ){
      zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
      rc = SQLITE_ERROR;
      goto zipfile_step_out;
    }
  }

  /* Now inspect the data. If this is NULL, then the new entry must be a
  ** directory.  Otherwise, figure out whether or not the data should
  ** be deflated or simply stored in the zip archive. */

  if( sqlite3_value_type(pData)==SQLITE_NULL ){
    bIsDir = 1;
    iMethod = 0;
  }else{
    aData = sqlite3_value_blob(pData);
    szUncompressed = nData = sqlite3_value_bytes(pData);
    iCrc32 = crc32(0, aData, nData);
    if( iMethod<0 || iMethod==8 ){
      int nOut = 0;
      rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
      if( rc!=SQLITE_OK ){
        goto zipfile_step_out;
      }
      if( iMethod==8 || nOut<nData ){
        aData = aFree;
        nData = nOut;
        iMethod = 8;
      }else{
        iMethod = 0;
      }
    }
  }

  /* Decode the "mode" argument. */
  rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
  if( rc ) goto zipfile_step_out;

  /* Decode the "mtime" argument. */
  e.mUnixTime = zipfileGetTime(pMtime);

  /* If this is a directory entry, ensure that there is exactly one '/'
  ** at the end of the path. Or, if this is not a directory and the path
  ** ends in '/' it is an error. */

  if( bIsDir==0 ){
    if( nName>0 && zName[nName-1]=='/' ){
      zErr = sqlite3_mprintf("non-directory name must not end with /");
      rc = SQLITE_ERROR;
      goto zipfile_step_out;
    }
  }else{
    if( nName==0 || zName[nName-1]!='/' ){
      zName = zFree = sqlite3_mprintf("%s/", zName);
      if( zName==0 ){
        rc = SQLITE_NOMEM;
        goto zipfile_step_out;
      }
      nName = (int)strlen(zName);
    }else{
      while( nName>1 && zName[nName-2]=='/' ) nName--;
    }
  }

  /* Assemble the ZipfileEntry object for the new zip archive entry */
  e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
  e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
  e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
  e.cds.iCompression = (u16)iMethod;
  zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
  e.cds.crc32 = iCrc32;
  e.cds.szCompressed = nData;
  e.cds.szUncompressed = szUncompressed;
  e.cds.iExternalAttr = (mode<<16);
  e.cds.iOffset = p->body.n;
  e.cds.nFile = (u16)nName;
  e.cds.zFile = zName;

  /* Append the LFH to the body of the new archive */
  nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
  if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
  p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);

  /* Append the data to the body of the new archive */
  if( nData>0 ){
    if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
    memcpy(&p->body.a[p->body.n], aData, nData);
    p->body.n += nData;
  }

  /* Append the CDS record to the directory of the new archive */
  nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
  if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
  p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);

  /* Increment the count of entries in the archive */
  p->nEntry++;

 zipfile_step_out:
  sqlite3_free(aFree);
  sqlite3_free(zFree);
  if( rc ){
    if( zErr ){
      sqlite3_result_error(pCtx, zErr, -1);
    }else{
      sqlite3_result_error_code(pCtx, rc);
    }
  }
  sqlite3_free(zErr);
}

/*
** xFinalize() callback for zipfile aggregate function.
*/

static void zipfileFinal(sqlite3_context *pCtx){
  ZipfileCtx *p;
  ZipfileEOCD eocd;
  sqlite3_int64 nZip;
  u8 *aZip;

  p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
  if( p==0 ) return;
  if( p->nEntry>0 ){
    memset(&eocd, 0, sizeof(eocd));
    eocd.nEntry = (u16)p->nEntry;
    eocd.nEntryTotal = (u16)p->nEntry;
    eocd.nSize = p->cds.n;
    eocd.iOffset = p->body.n;

    nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
    aZip = (u8*)sqlite3_malloc64(nZip);
    if( aZip==0 ){
      sqlite3_result_error_nomem(pCtx);
    }else{
      memcpy(aZip, p->body.a, p->body.n);
      memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
      zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
      sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
    }
  }

  sqlite3_free(p->body.a);
  sqlite3_free(p->cds.a);
}


/*
** Register the "zipfile" virtual table.
*/

static int zipfileRegister(sqlite3 *db){
  static sqlite3_module zipfileModule = {
    1,                         /* iVersion */
    zipfileConnect,            /* xCreate */
    zipfileConnect,            /* xConnect */
    zipfileBestIndex,          /* xBestIndex */
    zipfileDisconnect,         /* xDisconnect */
    zipfileDisconnect,         /* xDestroy */
    zipfileOpen,               /* xOpen - open a cursor */
    zipfileClose,              /* xClose - close a cursor */
    zipfileFilter,             /* xFilter - configure scan constraints */
    zipfileNext,               /* xNext - advance a cursor */
    zipfileEof,                /* xEof - check for end of scan */
    zipfileColumn,             /* xColumn - read data */
    0,                         /* xRowid - read data */
    zipfileUpdate,             /* xUpdate */
    zipfileBegin,              /* xBegin */
    0,                         /* xSync */
    zipfileCommit,             /* xCommit */
    zipfileRollback,           /* xRollback */
    zipfileFindFunction,       /* xFindMethod */
    0,                         /* xRename */
    0,                         /* xSavepoint */
    0,                         /* xRelease */
    0,                         /* xRollback */
    0,                         /* xShadowName */
    0                          /* xIntegrity */
  };

  int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
  if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, 
        zipfileStep, zipfileFinal
    );
  }
  assert( sizeof(i64)==8 );
  assert( sizeof(u32)==4 );
  assert( sizeof(u16)==2 );
  assert( sizeof(u8)==1 );
  return rc;
}
#else         /* SQLITE_OMIT_VIRTUALTABLE */
# define zipfileRegister(x) SQLITE_OK
#endif

#ifdef _WIN32

#endif
int sqlite3_zipfile_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  return zipfileRegister(db);
}

/************************* End ext/misc/zipfile.c ********************/
/************************* Begin ext/misc/sqlar.c ******************/
/*
** 2017-12-17
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
** for working with sqlar archives and used by the shell tool's built-in
** sqlar support.
*/

/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <zlib.h>
#include <assert.h>

/*
** Implementation of the "sqlar_compress(X)" SQL function.
**
** If the type of X is SQLITE_BLOB, and compressing that blob using
** zlib utility function compress() yields a smaller blob, return the
** compressed blob. Otherwise, return a copy of X.
**
** SQLar uses the "zlib format" for compressed content.  The zlib format
** contains a two-byte identification header and a four-byte checksum at
** the end.  This is different from ZIP which uses the raw deflate format.
**
** Future enhancements to SQLar might add support for new compression formats.
** If so, those new formats will be identified by alternative headers in the
** compressed data.
*/

static void sqlarCompressFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==1 );
  if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
    const Bytef *pData = sqlite3_value_blob(argv[0]);
    uLong nData = sqlite3_value_bytes(argv[0]);
    uLongf nOut = compressBound(nData);
    Bytef *pOut;

    pOut = (Bytef*)sqlite3_malloc64(nOut);
    if( pOut==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }else{
      if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
        sqlite3_result_error(context, "error in compress()", -1);
      }else if( nOut<nData ){
        sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
      }else{
        sqlite3_result_value(context, argv[0]);
      }
      sqlite3_free(pOut);
    }
  }else{
    sqlite3_result_value(context, argv[0]);
  }
}

/*
** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
**
** Parameter SZ is interpreted as an integer. If it is less than or
** equal to zero, then this function returns a copy of X. Or, if
** SZ is equal to the size of X when interpreted as a blob, also
** return a copy of X. Otherwise, decompress blob X using zlib
** utility function uncompress() and return the results (another
** blob).
*/

static void sqlarUncompressFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  uLong nData;
  sqlite3_int64 sz;

  assert( argc==2 );
  sz = sqlite3_value_int64(argv[1]);

  if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
    sqlite3_result_value(context, argv[0]);
  }else{
    uLongf szf = sz;
    const Bytef *pData= sqlite3_value_blob(argv[0]);
    Bytef *pOut = sqlite3_malloc64(sz);
    if( pOut==0 ){
      sqlite3_result_error_nomem(context);
    }else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
      sqlite3_result_error(context, "error in uncompress()", -1);
    }else{
      sqlite3_result_blob(context, pOut, szf, SQLITE_TRANSIENT);
    }
    sqlite3_free(pOut);
  }
}

#ifdef _WIN32

#endif
int sqlite3_sqlar_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sqlar_compress", 1, 
                               SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                               sqlarCompressFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
                                 SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                 sqlarUncompressFunc, 0, 0);
  }
  return rc;
}

/************************* End ext/misc/sqlar.c ********************/
#endif
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
/************************* Begin ext/expert/sqlite3expert.h ******************/
/*
** 2017 April 07
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/

#if !defined(SQLITEEXPERT_H)
#define SQLITEEXPERT_H 1
/* #include "sqlite3.h" */

typedef struct sqlite3expert sqlite3expert;

/*
** Create a new sqlite3expert object.
**
** If successful, a pointer to the new object is returned and (*pzErr) set
** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
** an English-language error message. In this case it is the responsibility
** of the caller to eventually free the error message buffer using
** sqlite3_free().
*/

sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);

/*
** Configure an sqlite3expert object.
**
** EXPERT_CONFIG_SAMPLE:
**   By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
**   each candidate index. This involves scanning and sorting the entire
**   contents of each user database table once for each candidate index
**   associated with the table. For large databases, this can be 
**   prohibitively slow. This option allows the sqlite3expert object to
**   be configured so that sqlite_stat1 data is instead generated based on a
**   subset of each table, or so that no sqlite_stat1 data is used at all.
**
**   A single integer argument is passed to this option. If the value is less
**   than or equal to zero, then no sqlite_stat1 data is generated or used by
**   the analysis - indexes are recommended based on the database schema only.
**   Or, if the value is 100 or greater, complete sqlite_stat1 data is
**   generated for each candidate index (this is the default). Finally, if the
**   value falls between 0 and 100, then it represents the percentage of user
**   table rows that should be considered when generating sqlite_stat1 data.
**
**   Examples:
**
**     // Do not generate any sqlite_stat1 data
**     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
**
**     // Generate sqlite_stat1 data based on 10% of the rows in each table.
**     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
*/

int sqlite3_expert_config(sqlite3expert *p, int op, ...);

#define EXPERT_CONFIG_SAMPLE 1    /* int */

/*
** Specify zero or more SQL statements to be included in the analysis.
**
** Buffer zSql must contain zero or more complete SQL statements. This
** function parses all statements contained in the buffer and adds them
** to the internal list of statements to analyze. If successful, SQLITE_OK
** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
** may be set to point to an English language error message. In this case
** the caller is responsible for eventually freeing the error message buffer
** using sqlite3_free().
**
** If an error does occur while processing one of the statements in the
** buffer passed as the second argument, none of the statements in the
** buffer are added to the analysis.
**
** This function must be called before sqlite3_expert_analyze(). If a call
** to this function is made on an sqlite3expert object that has already
** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
** immediately and no statements are added to the analysis.
*/

int sqlite3_expert_sql(
  sqlite3expert *p,               /* From a successful sqlite3_expert_new() */
  const char *zSql,               /* SQL statement(s) to add */
  char **pzErr                    /* OUT: Error message (if any) */
);


/*
** This function is called after the sqlite3expert object has been configured
** with all SQL statements using sqlite3_expert_sql() to actually perform
** the analysis. Once this function has been called, it is not possible to
** add further SQL statements to the analysis.
**
** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
** an error occurs, an SQLite error code is returned and (*pzErr) set to 
** point to a buffer containing an English language error message. In this
** case it is the responsibility of the caller to eventually free the buffer
** using sqlite3_free().
**
** If an error does occur within this function, the sqlite3expert object
** is no longer useful for any purpose. At that point it is no longer
** possible to add further SQL statements to the object or to re-attempt
** the analysis. The sqlite3expert object must still be freed using a call
** sqlite3_expert_destroy().
*/

int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);

/*
** Return the total number of statements loaded using sqlite3_expert_sql().
** The total number of SQL statements may be different from the total number
** to calls to sqlite3_expert_sql().
*/

int sqlite3_expert_count(sqlite3expert*);

/*
** Return a component of the report.
**
** This function is called after sqlite3_expert_analyze() to extract the
** results of the analysis. Each call to this function returns either a
** NULL pointer or a pointer to a buffer containing a nul-terminated string.
** The value passed as the third argument must be one of the EXPERT_REPORT_*
** #define constants defined below.
**
** For some EXPERT_REPORT_* parameters, the buffer returned contains 
** information relating to a specific SQL statement. In these cases that
** SQL statement is identified by the value passed as the second argument.
** SQL statements are numbered from 0 in the order in which they are parsed.
** If an out-of-range value (less than zero or equal to or greater than the
** value returned by sqlite3_expert_count()) is passed as the second argument
** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
**
** EXPERT_REPORT_SQL:
**   Return the text of SQL statement iStmt.
**
** EXPERT_REPORT_INDEXES:
**   Return a buffer containing the CREATE INDEX statements for all recommended
**   indexes for statement iStmt. If there are no new recommeded indexes, NULL 
**   is returned.
**
** EXPERT_REPORT_PLAN:
**   Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
**   iStmt after the proposed indexes have been added to the database schema.
**
** EXPERT_REPORT_CANDIDATES:
**   Return a pointer to a buffer containing the CREATE INDEX statements 
**   for all indexes that were tested (for all SQL statements). The iStmt
**   parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
*/

const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);

/*
** Values for the third argument passed to sqlite3_expert_report().
*/

#define EXPERT_REPORT_SQL        1
#define EXPERT_REPORT_INDEXES    2
#define EXPERT_REPORT_PLAN       3
#define EXPERT_REPORT_CANDIDATES 4

/*
** Free an (sqlite3expert*) handle and all associated resources. There 
** should be one call to this function for each successful call to 
** sqlite3-expert_new().
*/

void sqlite3_expert_destroy(sqlite3expert*);

#endif  /* !defined(SQLITEEXPERT_H) */

/************************* End ext/expert/sqlite3expert.h ********************/
/************************* Begin ext/expert/sqlite3expert.c ******************/
/*
** 2017 April 09
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/

/* #include "sqlite3expert.h" */
#include <assert.h>
#include <string.h>
#include <stdio.h>

#if !defined(SQLITE_AMALGAMATION)
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
# define NEVER(X)       (X)
#endif
#endif /* !defined(SQLITE_AMALGAMATION) */


#ifndef SQLITE_OMIT_VIRTUALTABLE

/* typedef sqlite3_int64 i64; */
/* typedef sqlite3_uint64 u64; */

typedef struct IdxColumn IdxColumn;
typedef struct IdxConstraint IdxConstraint;
typedef struct IdxScan IdxScan;
typedef struct IdxStatement IdxStatement;
typedef struct IdxTable IdxTable;
typedef struct IdxWrite IdxWrite;

#define STRLEN  (int)strlen

/*
** A temp table name that we assume no user database will actually use.
** If this assumption proves incorrect triggers on the table with the
** conflicting name will be ignored.
*/

#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"

/*
** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
** any other type of single-ended range constraint on a column).
**
** pLink:
**   Used to temporarily link IdxConstraint objects into lists while
**   creating candidate indexes.
*/

struct IdxConstraint {
  char *zColl;                    /* Collation sequence */
  int bRange;                     /* True for range, false for eq */
  int iCol;                       /* Constrained table column */
  int bFlag;                      /* Used by idxFindCompatible() */
  int bDesc;                      /* True if ORDER BY <expr> DESC */
  IdxConstraint *pNext;           /* Next constraint in pEq or pRange list */
  IdxConstraint *pLink;           /* See above */
};

/*
** A single scan of a single table.
*/

struct IdxScan {
  IdxTable *pTab;                 /* Associated table object */
  int iDb;                        /* Database containing table zTable */
  i64 covering;                   /* Mask of columns required for cov. index */
  IdxConstraint *pOrder;          /* ORDER BY columns */
  IdxConstraint *pEq;             /* List of == constraints */
  IdxConstraint *pRange;          /* List of < constraints */
  IdxScan *pNextScan;             /* Next IdxScan object for same analysis */
};

/*
** Information regarding a single database table. Extracted from 
** "PRAGMA table_info" by function idxGetTableInfo().
*/

struct IdxColumn {
  char *zName;
  char *zColl;
  int iPk;
};
struct IdxTable {
  int nCol;
  char *zName;                    /* Table name */
  IdxColumn *aCol;
  IdxTable *pNext;                /* Next table in linked list of all tables */
};

/*
** An object of the following type is created for each unique table/write-op
** seen. The objects are stored in a singly-linked list beginning at
** sqlite3expert.pWrite.
*/

struct IdxWrite {
  IdxTable *pTab;
  int eOp;                        /* SQLITE_UPDATE, DELETE or INSERT */
  IdxWrite *pNext;
};

/*
** Each statement being analyzed is represented by an instance of this
** structure.
*/

struct IdxStatement {
  int iId;                        /* Statement number */
  char *zSql;                     /* SQL statement */
  char *zIdx;                     /* Indexes */
  char *zEQP;                     /* Plan */
  IdxStatement *pNext;
};


/*
** A hash table for storing strings. With space for a payload string
** with each entry. Methods are:
**
**   idxHashInit()
**   idxHashClear()
**   idxHashAdd()
**   idxHashSearch()
*/

#define IDX_HASH_SIZE 1023
typedef struct IdxHashEntry IdxHashEntry;
typedef struct IdxHash IdxHash;
struct IdxHashEntry {
  char *zKey;                     /* nul-terminated key */
  char *zVal;                     /* nul-terminated value string */
  char *zVal2;                    /* nul-terminated value string 2 */
  IdxHashEntry *pHashNext;        /* Next entry in same hash bucket */
  IdxHashEntry *pNext;            /* Next entry in hash */
};
struct IdxHash {
  IdxHashEntry *pFirst;
  IdxHashEntry *aHash[IDX_HASH_SIZE];
};

/*
** sqlite3expert object.
*/

struct sqlite3expert {
  int iSample;                    /* Percentage of tables to sample for stat1 */
  sqlite3 *db;                    /* User database */
  sqlite3 *dbm;                   /* In-memory db for this analysis */
  sqlite3 *dbv;                   /* Vtab schema for this analysis */
  IdxTable *pTable;               /* List of all IdxTable objects */
  IdxScan *pScan;                 /* List of scan objects */
  IdxWrite *pWrite;               /* List of write objects */
  IdxStatement *pStatement;       /* List of IdxStatement objects */
  int bRun;                       /* True once analysis has run */
  char **pzErrmsg;
  int rc;                         /* Error code from whereinfo hook */
  IdxHash hIdx;                   /* Hash containing all candidate indexes */
  char *zCandidates;              /* For EXPERT_REPORT_CANDIDATES */
};


/*
** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). 
** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
*/

static void *idxMalloc(int *pRc, i64 nByte){
  void *pRet;
  assert( *pRc==SQLITE_OK );
  assert( nByte>0 );
  pRet = sqlite3_malloc64(nByte);
  if( pRet ){
    memset(pRet, 0, nByte);
  }else{
    *pRc = SQLITE_NOMEM;
  }
  return pRet;
}

/*
** Initialize an IdxHash hash table.
*/

static void idxHashInit(IdxHash *pHash){
  memset(pHash, 0, sizeof(IdxHash));
}

/*
** Reset an IdxHash hash table.
*/

static void idxHashClear(IdxHash *pHash){
  int i;
  for(i=0; i<IDX_HASH_SIZE; i++){
    IdxHashEntry *pEntry;
    IdxHashEntry *pNext;
    for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
      pNext = pEntry->pHashNext;
      sqlite3_free(pEntry->zVal2);
      sqlite3_free(pEntry);
    }
  }
  memset(pHash, 0, sizeof(IdxHash));
}

/*
** Return the index of the hash bucket that the string specified by the
** arguments to this function belongs.
*/

static int idxHashString(const char *z, int n){
  unsigned int ret = 0;
  int i;
  for(i=0; i<n; i++){
    ret += (ret<<3) + (unsigned char)(z[i]);
  }
  return (int)(ret % IDX_HASH_SIZE);
}

/*
** If zKey is already present in the hash table, return non-zero and do
** nothing. Otherwise, add an entry with key zKey and payload string zVal to
** the hash table passed as the second argument. 
*/

static int idxHashAdd(
  int *pRc, 
  IdxHash *pHash, 
  const char *zKey,
  const char *zVal
){
  int nKey = STRLEN(zKey);
  int iHash = idxHashString(zKey, nKey);
  int nVal = (zVal ? STRLEN(zVal) : 0);
  IdxHashEntry *pEntry;
  assert( iHash>=0 );
  for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
    if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
      return 1;
    }
  }
  pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + (i64)nKey+1 + (i64)nVal+1);
  if( pEntry ){
    pEntry->zKey = (char*)&pEntry[1];
    memcpy(pEntry->zKey, zKey, nKey);
    if( zVal ){
      pEntry->zVal = &pEntry->zKey[nKey+1];
      memcpy(pEntry->zVal, zVal, nVal);
    }
    pEntry->pHashNext = pHash->aHash[iHash];
    pHash->aHash[iHash] = pEntry;

    pEntry->pNext = pHash->pFirst;
    pHash->pFirst = pEntry;
  }
  return 0;
}

/*
** If zKey/nKey is present in the hash table, return a pointer to the 
** hash-entry object.
*/

static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
  int iHash;
  IdxHashEntry *pEntry;
  if( nKey<0 ) nKey = STRLEN(zKey);
  iHash = idxHashString(zKey, nKey);
  assert( iHash>=0 );
  for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
    if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
      return pEntry;
    }
  }
  return 0;
}

/*
** If the hash table contains an entry with a key equal to the string
** passed as the final two arguments to this function, return a pointer
** to the payload string. Otherwise, if zKey/nKey is not present in the
** hash table, return NULL.
*/

static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
  IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
  if( pEntry ) return pEntry->zVal;
  return 0;
}

/*
** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
** variable to point to a copy of nul-terminated string zColl.
*/

static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
  IdxConstraint *pNew;
  int nColl = STRLEN(zColl);

  assert( *pRc==SQLITE_OK );
  pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
  if( pNew ){
    pNew->zColl = (char*)&pNew[1];
    memcpy(pNew->zColl, zColl, nColl+1);
  }
  return pNew;
}

/*
** An error associated with database handle db has just occurred. Pass
** the error message to callback function xOut.
*/

static void idxDatabaseError(
  sqlite3 *db,                    /* Database handle */
  char **pzErrmsg                 /* Write error here */
){
  *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}

/*
** Prepare an SQL statement.
*/

static int idxPrepareStmt(
  sqlite3 *db,                    /* Database handle to compile against */
  sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
  char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
  const char *zSql                /* SQL statement to compile */
){
  int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
  if( rc!=SQLITE_OK ){
    *ppStmt = 0;
    idxDatabaseError(db, pzErrmsg);
  }
  return rc;
}

/*
** Prepare an SQL statement using the results of a printf() formatting.
*/

static int idxPrintfPrepareStmt(
  sqlite3 *db,                    /* Database handle to compile against */
  sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
  char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
  const char *zFmt,               /* printf() format of SQL statement */
  ...                             /* Trailing printf() arguments */
){
  va_list ap;
  int rc;
  char *zSql;
  va_start(ap, zFmt);
  zSql = sqlite3_vmprintf(zFmt, ap);
  if( zSql==0 ){
    rc = SQLITE_NOMEM;
  }else{
    rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
    sqlite3_free(zSql);
  }
  va_end(ap);
  return rc;
}


/*************************************************************************
** Beginning of virtual table implementation.
*/

typedef struct ExpertVtab ExpertVtab;
struct ExpertVtab {
  sqlite3_vtab base;
  IdxTable *pTab;
  sqlite3expert *pExpert;
};

typedef struct ExpertCsr ExpertCsr;
struct ExpertCsr {
  sqlite3_vtab_cursor base;
  sqlite3_stmt *pData;
};

static char *expertDequote(const char *zIn){
  i64 n = STRLEN(zIn);
  char *zRet = sqlite3_malloc64(n);

  assert( zIn[0]=='\'' );
  assert( zIn[n-1]=='\'' );

  if( zRet ){
    i64 iOut = 0;
    i64 iIn = 0;
    for(iIn=1; iIn<(n-1); iIn++){
      if( zIn[iIn]=='\'' ){
        assert( zIn[iIn+1]=='\'' );
        iIn++;
      }
      zRet[iOut++] = zIn[iIn];
    }
    zRet[iOut] = '\0';
  }

  return zRet;
}

/* 
** This function is the implementation of both the xConnect and xCreate
** methods of the r-tree virtual table.
**
**   argv[0]   -> module name
**   argv[1]   -> database name
**   argv[2]   -> table name
**   argv[...] -> column names...
*/

static int expertConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  sqlite3expert *pExpert = (sqlite3expert*)pAux;
  ExpertVtab *p = 0;
  int rc;

  if( argc!=4 ){
    *pzErr = sqlite3_mprintf("internal error!");
    rc = SQLITE_ERROR;
  }else{
    char *zCreateTable = expertDequote(argv[3]);
    if( zCreateTable ){
      rc = sqlite3_declare_vtab(db, zCreateTable);
      if( rc==SQLITE_OK ){
        p = idxMalloc(&rc, sizeof(ExpertVtab));
      }
      if( rc==SQLITE_OK ){
        p->pExpert = pExpert;
        p->pTab = pExpert->pTable;
        assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
      }
      sqlite3_free(zCreateTable);
    }else{
      rc = SQLITE_NOMEM;
    }
  }

  *ppVtab = (sqlite3_vtab*)p;
  return rc;
}

static int expertDisconnect(sqlite3_vtab *pVtab){
  ExpertVtab *p = (ExpertVtab*)pVtab;
  sqlite3_free(p);
  return SQLITE_OK;
}

static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
  ExpertVtab *p = (ExpertVtab*)pVtab;
  int rc = SQLITE_OK;
  int n = 0;
  IdxScan *pScan;
  const int opmask = 
    SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
    SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
    SQLITE_INDEX_CONSTRAINT_LE;

  pScan = idxMalloc(&rc, sizeof(IdxScan));
  if( pScan ){
    int i;

    /* Link the new scan object into the list */
    pScan->pTab = p->pTab;
    pScan->pNextScan = p->pExpert->pScan;
    p->pExpert->pScan = pScan;

    /* Add the constraints to the IdxScan object */
    for(i=0; i<pIdxInfo->nConstraint; i++){
      struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
      if( pCons->usable 
       && pCons->iColumn>=0 
       && p->pTab->aCol[pCons->iColumn].iPk==0
       && (pCons->op & opmask) 
      ){
        IdxConstraint *pNew;
        const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
        pNew = idxNewConstraint(&rc, zColl);
        if( pNew ){
          pNew->iCol = pCons->iColumn;
          if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
            pNew->pNext = pScan->pEq;
            pScan->pEq = pNew;
          }else{
            pNew->bRange = 1;
            pNew->pNext = pScan->pRange;
            pScan->pRange = pNew;
          }
        }
        n++;
        pIdxInfo->aConstraintUsage[i].argvIndex = n;
      }
    }

    /* Add the ORDER BY to the IdxScan object */
    for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
      int iCol = pIdxInfo->aOrderBy[i].iColumn;
      if( iCol>=0 ){
        IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
        if( pNew ){
          pNew->iCol = iCol;
          pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
          pNew->pNext = pScan->pOrder;
          pNew->pLink = pScan->pOrder;
          pScan->pOrder = pNew;
          n++;
        }
      }
    }
  }

  pIdxInfo->estimatedCost = 1000000.0 / (n+1);
  return rc;
}

static int expertUpdate(
  sqlite3_vtab *pVtab, 
  int nData, 
  sqlite3_value **azData, 
  sqlite_int64 *pRowid
){
  (void)pVtab;
  (void)nData;
  (void)azData;
  (void)pRowid;
  return SQLITE_OK;
}

/* 
** Virtual table module xOpen method.
*/

static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  int rc = SQLITE_OK;
  ExpertCsr *pCsr;
  (void)pVTab;
  pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
  *ppCursor = (sqlite3_vtab_cursor*)pCsr;
  return rc;
}

/* 
** Virtual table module xClose method.
*/

static int expertClose(sqlite3_vtab_cursor *cur){
  ExpertCsr *pCsr = (ExpertCsr*)cur;
  sqlite3_finalize(pCsr->pData);
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/*
** Virtual table module xEof method.
**
** Return non-zero if the cursor does not currently point to a valid 
** record (i.e if the scan has finished), or zero otherwise.
*/

static int expertEof(sqlite3_vtab_cursor *cur){
  ExpertCsr *pCsr = (ExpertCsr*)cur;
  return pCsr->pData==0;
}

/* 
** Virtual table module xNext method.
*/

static int expertNext(sqlite3_vtab_cursor *cur){
  ExpertCsr *pCsr = (ExpertCsr*)cur;
  int rc = SQLITE_OK;

  assert( pCsr->pData );
  rc = sqlite3_step(pCsr->pData);
  if( rc!=SQLITE_ROW ){
    rc = sqlite3_finalize(pCsr->pData);
    pCsr->pData = 0;
  }else{
    rc = SQLITE_OK;
  }

  return rc;
}

/* 
** Virtual table module xRowid method.
*/

static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  (void)cur;
  *pRowid = 0;
  return SQLITE_OK;
}

/* 
** Virtual table module xColumn method.
*/

static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
  ExpertCsr *pCsr = (ExpertCsr*)cur;
  sqlite3_value *pVal;
  pVal = sqlite3_column_value(pCsr->pData, i);
  if( pVal ){
    sqlite3_result_value(ctx, pVal);
  }
  return SQLITE_OK;
}

/* 
** Virtual table module xFilter method.
*/

static int expertFilter(
  sqlite3_vtab_cursor *cur, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  ExpertCsr *pCsr = (ExpertCsr*)cur;
  ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
  sqlite3expert *pExpert = pVtab->pExpert;
  int rc;

  (void)idxNum;
  (void)idxStr;
  (void)argc;
  (void)argv;
  rc = sqlite3_finalize(pCsr->pData);
  pCsr->pData = 0;
  if( rc==SQLITE_OK ){
    rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
        "SELECT * FROM main.%Q WHERE sqlite_expert_sample()", pVtab->pTab->zName
    );
  }

  if( rc==SQLITE_OK ){
    rc = expertNext(cur);
  }
  return rc;
}

static int idxRegisterVtab(sqlite3expert *p){
  static sqlite3_module expertModule = {
    2,                            /* iVersion */
    expertConnect,                /* xCreate - create a table */
    expertConnect,                /* xConnect - connect to an existing table */
    expertBestIndex,              /* xBestIndex - Determine search strategy */
    expertDisconnect,             /* xDisconnect - Disconnect from a table */
    expertDisconnect,             /* xDestroy - Drop a table */
    expertOpen,                   /* xOpen - open a cursor */
    expertClose,                  /* xClose - close a cursor */
    expertFilter,                 /* xFilter - configure scan constraints */
    expertNext,                   /* xNext - advance a cursor */
    expertEof,                    /* xEof */
    expertColumn,                 /* xColumn - read data */
    expertRowid,                  /* xRowid - read data */
    expertUpdate,                 /* xUpdate - write data */
    0,                            /* xBegin - begin transaction */
    0,                            /* xSync - sync transaction */
    0,                            /* xCommit - commit transaction */
    0,                            /* xRollback - rollback transaction */
    0,                            /* xFindFunction - function overloading */
    0,                            /* xRename - rename the table */
    0,                            /* xSavepoint */
    0,                            /* xRelease */
    0,                            /* xRollbackTo */
    0,                            /* xShadowName */
    0,                            /* xIntegrity */
  };

  return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
}
/*
** End of virtual table implementation.
*************************************************************************/

/*
** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
** is called, set it to the return value of sqlite3_finalize() before
** returning. Otherwise, discard the sqlite3_finalize() return value.
*/

static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
  int rc = sqlite3_finalize(pStmt);
  if( *pRc==SQLITE_OK ) *pRc = rc;
}

/*
** Attempt to allocate an IdxTable structure corresponding to table zTab
** in the main database of connection db. If successful, set (*ppOut) to
** point to the new object and return SQLITE_OK. Otherwise, return an
** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
** set to point to an error string.
**
** It is the responsibility of the caller to eventually free either the
** IdxTable object or error message using sqlite3_free().
*/

static int idxGetTableInfo(
  sqlite3 *db,                    /* Database connection to read details from */
  const char *zTab,               /* Table name */
  IdxTable **ppOut,               /* OUT: New object (if successful) */
  char **pzErrmsg                 /* OUT: Error message (if not) */
){
  sqlite3_stmt *p1 = 0;
  int nCol = 0;
  int nTab;
  i64 nByte;
  IdxTable *pNew = 0;
  int rc, rc2;
  char *pCsr = 0;
  int nPk = 0;

  *ppOut = 0;
  if( zTab==0 ) return SQLITE_ERROR;
  nTab = STRLEN(zTab);
  nByte = sizeof(IdxTable) + nTab + 1;
  rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
    const char *zColSeq = 0;
    if( zCol==0 ){
      rc = SQLITE_ERROR;
      break;
    }
    nByte += 1 + STRLEN(zCol);
    rc = sqlite3_table_column_metadata(
        db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
    );
    if( zColSeq==0 ) zColSeq = "binary";
    nByte += 1 + STRLEN(zColSeq);
    nCol++;
    nPk += (sqlite3_column_int(p1, 5)>0);
  }
  rc2 = sqlite3_reset(p1);
  if( rc==SQLITE_OK ) rc = rc2;

  nByte += sizeof(IdxColumn) * nCol;
  if( rc==SQLITE_OK ){
    pNew = idxMalloc(&rc, nByte);
  }
  if( rc==SQLITE_OK ){
    pNew->aCol = (IdxColumn*)&pNew[1];
    pNew->nCol = nCol;
    pCsr = (char*)&pNew->aCol[nCol];
  }

  nCol = 0;
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
    const char *zColSeq = 0;
    int nCopy;
    if( zCol==0 ) continue;
    nCopy = STRLEN(zCol) + 1;
    pNew->aCol[nCol].zName = pCsr;
    pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
    memcpy(pCsr, zCol, nCopy);
    pCsr += nCopy;

    rc = sqlite3_table_column_metadata(
        db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
    );
    if( rc==SQLITE_OK ){
      if( zColSeq==0 ) zColSeq = "binary";
      nCopy = STRLEN(zColSeq) + 1;
      pNew->aCol[nCol].zColl = pCsr;
      memcpy(pCsr, zColSeq, nCopy);
      pCsr += nCopy;
    }

    nCol++;
  }
  idxFinalize(&rc, p1);

  if( rc!=SQLITE_OK ){
    sqlite3_free(pNew);
    pNew = 0;
  }else if( ALWAYS(pNew!=0) ){
    pNew->zName = pCsr;
    if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1);
  }

  *ppOut = pNew;
  return rc;
}

/*
** This function is a no-op if *pRc is set to anything other than 
** SQLITE_OK when it is called.
**
** If *pRc is initially set to SQLITE_OK, then the text specified by
** the printf() style arguments is appended to zIn and the result returned
** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
** zIn before returning.
*/

static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
  va_list ap;
  char *zAppend = 0;
  char *zRet = 0;
  i64 nIn = zIn ? STRLEN(zIn) : 0;
  i64 nAppend = 0;
  va_start(ap, zFmt);
  if( *pRc==SQLITE_OK ){
    zAppend = sqlite3_vmprintf(zFmt, ap);
    if( zAppend ){
      nAppend = STRLEN(zAppend);
      zRet = (char*)sqlite3_malloc64(nIn + nAppend + 1);
    }
    if( zAppend && zRet ){
      if( nIn ) memcpy(zRet, zIn, nIn);
      memcpy(&zRet[nIn], zAppend, nAppend+1);
    }else{
      sqlite3_free(zRet);
      zRet = 0;
      *pRc = SQLITE_NOMEM;
    }
    sqlite3_free(zAppend);
    sqlite3_free(zIn);
  }
  va_end(ap);
  return zRet;
}

/*
** Return true if zId must be quoted in order to use it as an SQL
** identifier, or false otherwise.
*/

static int idxIdentifierRequiresQuotes(const char *zId){
  int i;
  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')
     && !(zId[i]>='a' && zId[i]<='z')
     && !(zId[i]>='A' && zId[i]<='Z')
    ){
      return 1;
    }
  }
  return 0;
}

/*
** This function appends an index column definition suitable for constraint
** pCons to the string passed as zIn and returns the result.
*/

static char *idxAppendColDefn(
  int *pRc,                       /* IN/OUT: Error code */
  char *zIn,                      /* Column defn accumulated so far */
  IdxTable *pTab,                 /* Table index will be created on */
  IdxConstraint *pCons
){
  char *zRet = zIn;
  IdxColumn *p = &pTab->aCol[pCons->iCol];
  if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");

  if( idxIdentifierRequiresQuotes(p->zName) ){
    zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
  }else{
    zRet = idxAppendText(pRc, zRet, "%s", p->zName);
  }

  if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
    if( idxIdentifierRequiresQuotes(pCons->zColl) ){
      zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
    }else{
      zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
    }
  }

  if( pCons->bDesc ){
    zRet = idxAppendText(pRc, zRet, " DESC");
  }
  return zRet;
}

/*
** Search database dbm for an index compatible with the one idxCreateFromCons()
** would create from arguments pScan, pEq and pTail. If no error occurs and 
** such an index is found, return non-zero. Or, if no such index is found,
** return zero.
**
** If an error occurs, set *pRc to an SQLite error code and return zero.
*/

static int idxFindCompatible(
  int *pRc,                       /* OUT: Error code */
  sqlite3* dbm,                   /* Database to search */
  IdxScan *pScan,                 /* Scan for table to search for index on */
  IdxConstraint *pEq,             /* List of == constraints */
  IdxConstraint *pTail            /* List of range constraints */
){
  const char *zTbl = pScan->pTab->zName;
  sqlite3_stmt *pIdxList = 0;
  IdxConstraint *pIter;
  int nEq = 0;                    /* Number of elements in pEq */
  int rc;

  /* Count the elements in list pEq */
  for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;

  rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
  while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
    int bMatch = 1;
    IdxConstraint *pT = pTail;
    sqlite3_stmt *pInfo = 0;
    const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
    if( zIdx==0 ) continue;

    /* Zero the IdxConstraint.bFlag values in the pEq list */
    for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;

    rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
    while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
      int iIdx = sqlite3_column_int(pInfo, 0);
      int iCol = sqlite3_column_int(pInfo, 1);
      const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);

      if( iIdx<nEq ){
        for(pIter=pEq; pIter; pIter=pIter->pLink){
          if( pIter->bFlag ) continue;
          if( pIter->iCol!=iCol ) continue;
          if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
          pIter->bFlag = 1;
          break;
        }
        if( pIter==0 ){
          bMatch = 0;
          break;
        }
      }else{
        if( pT ){
          if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
            bMatch = 0;
            break;
          }
          pT = pT->pLink;
        }
      }
    }
    idxFinalize(&rc, pInfo);

    if( rc==SQLITE_OK && bMatch ){
      sqlite3_finalize(pIdxList);
      return 1;
    }
  }
  idxFinalize(&rc, pIdxList);

  *pRc = rc;
  return 0;
}

/* Callback for sqlite3_exec() with query with leading count(*) column.
 * The first argument is expected to be an int*, referent to be incremented
 * if that leading column is not exactly '0'.
 */

static int countNonzeros(void* pCount, int nc,
                         char* azResults[], char* azColumns[]){
  (void)azColumns;  /* Suppress unused parameter warning */
  if( nc>0 && (azResults[0][0]!='0' || azResults[0][1]!=0) ){
    *((int *)pCount) += 1;
  }
  return 0;
}

static int idxCreateFromCons(
  sqlite3expert *p,
  IdxScan *pScan,
  IdxConstraint *pEq, 
  IdxConstraint *pTail
){
  sqlite3 *dbm = p->dbm;
  int rc = SQLITE_OK;
  if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
    IdxTable *pTab = pScan->pTab;
    char *zCols = 0;
    char *zIdx = 0;
    IdxConstraint *pCons;
    unsigned int h = 0;
    const char *zFmt;

    for(pCons=pEq; pCons; pCons=pCons->pLink){
      zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
    }
    for(pCons=pTail; pCons; pCons=pCons->pLink){
      zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
    }

    if( rc==SQLITE_OK ){
      /* Hash the list of columns to come up with a name for the index */
      const char *zTable = pScan->pTab->zName;
      int quoteTable = idxIdentifierRequiresQuotes(zTable);
      char *zName = 0;          /* Index name */
      int collisions = 0;
      do{
        int i;
        char *zFind;
        for(i=0; zCols[i]; i++){
          h += ((h<<3) + zCols[i]);
        }
        sqlite3_free(zName);
        zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
        if( zName==0 ) break;
        /* Is is unique among table, view and index names? */
        zFmt = "SELECT count(*) FROM sqlite_schema WHERE name=%Q"
          " AND type in ('index','table','view')";
        zFind = sqlite3_mprintf(zFmt, zName);
        i = 0;
        rc = sqlite3_exec(dbm, zFind, countNonzeros, &i, 0);
        assert(rc==SQLITE_OK);
        sqlite3_free(zFind);
        if( i==0 ){
          collisions = 0;
          break;
        }
        ++collisions;
      }while( collisions<50 && zName!=0 );
      if( collisions ){
        /* This return means "Gave up trying to find a unique index name." */
        rc = SQLITE_BUSY_TIMEOUT;
      }else if( zName==0 ){
        rc = SQLITE_NOMEM;
      }else{
        if( quoteTable ){
          zFmt = "CREATE INDEX \"%w\" ON \"%w\"(%s)";
        }else{
          zFmt = "CREATE INDEX %s ON %s(%s)";
        }
        zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
        if( !zIdx ){
          rc = SQLITE_NOMEM;
        }else{
          rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
          if( rc!=SQLITE_OK ){
            rc = SQLITE_BUSY_TIMEOUT;
          }else{
            idxHashAdd(&rc, &p->hIdx, zName, zIdx);
          }
        }
        sqlite3_free(zName);
        sqlite3_free(zIdx);
      }
    }

    sqlite3_free(zCols);
  }
  return rc;
}

/*
** Return true if list pList (linked by IdxConstraint.pLink) contains
** a constraint compatible with *p. Otherwise return false.
*/

static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
  IdxConstraint *pCmp;
  for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
    if( p->iCol==pCmp->iCol ) return 1;
  }
  return 0;
}

static int idxCreateFromWhere(
  sqlite3expert *p, 
  IdxScan *pScan,                 /* Create indexes for this scan */
  IdxConstraint *pTail            /* range/ORDER BY constraints for inclusion */
){
  IdxConstraint *p1 = 0;
  IdxConstraint *pCon;
  int rc;

  /* Gather up all the == constraints. */
  for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
    if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
      pCon->pLink = p1;
      p1 = pCon;
    }
  }

  /* Create an index using the == constraints collected above. And the
  ** range constraint/ORDER BY terms passed in by the caller, if any. */

  rc = idxCreateFromCons(p, pScan, p1, pTail);

  /* If no range/ORDER BY passed by the caller, create a version of the
  ** index for each range constraint.  */

  if( pTail==0 ){
    for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
      assert( pCon->pLink==0 );
      if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
        rc = idxCreateFromCons(p, pScan, p1, pCon);
      }
    }
  }

  return rc;
}

/*
** Create candidate indexes in database [dbm] based on the data in 
** linked-list pScan.
*/

static int idxCreateCandidates(sqlite3expert *p){
  int rc = SQLITE_OK;
  IdxScan *pIter;

  for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
    rc = idxCreateFromWhere(p, pIter, 0);
    if( rc==SQLITE_OK && pIter->pOrder ){
      rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
    }
  }

  return rc;
}

/*
** Free all elements of the linked list starting at pConstraint.
*/

static void idxConstraintFree(IdxConstraint *pConstraint){
  IdxConstraint *pNext;
  IdxConstraint *p;

  for(p=pConstraint; p; p=pNext){
    pNext = p->pNext;
    sqlite3_free(p);
  }
}

/*
** Free all elements of the linked list starting from pScan up until pLast
** (pLast is not freed).
*/

static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
  IdxScan *p;
  IdxScan *pNext;
  for(p=pScan; p!=pLast; p=pNext){
    pNext = p->pNextScan;
    idxConstraintFree(p->pOrder);
    idxConstraintFree(p->pEq);
    idxConstraintFree(p->pRange);
    sqlite3_free(p);
  }
}

/*
** Free all elements of the linked list starting from pStatement up 
** until pLast (pLast is not freed).
*/

static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
  IdxStatement *p;
  IdxStatement *pNext;
  for(p=pStatement; p!=pLast; p=pNext){
    pNext = p->pNext;
    sqlite3_free(p->zEQP);
    sqlite3_free(p->zIdx);
    sqlite3_free(p);
  }
}

/*
** Free the linked list of IdxTable objects starting at pTab.
*/

static void idxTableFree(IdxTable *pTab){
  IdxTable *pIter;
  IdxTable *pNext;
  for(pIter=pTab; pIter; pIter=pNext){
    pNext = pIter->pNext;
    sqlite3_free(pIter);
  }
}

/*
** Free the linked list of IdxWrite objects starting at pTab.
*/

static void idxWriteFree(IdxWrite *pTab){
  IdxWrite *pIter;
  IdxWrite *pNext;
  for(pIter=pTab; pIter; pIter=pNext){
    pNext = pIter->pNext;
    sqlite3_free(pIter);
  }
}



/*
** This function is called after candidate indexes have been created. It
** runs all the queries to see which indexes they prefer, and populates
** IdxStatement.zIdx and IdxStatement.zEQP with the results.
*/

static int idxFindIndexes(
  sqlite3expert *p,
  char **pzErr                         /* OUT: Error message (sqlite3_malloc) */
){
  IdxStatement *pStmt;
  sqlite3 *dbm = p->dbm;
  int rc = SQLITE_OK;

  IdxHash hIdx;
  idxHashInit(&hIdx);

  for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
    IdxHashEntry *pEntry;
    sqlite3_stmt *pExplain = 0;
    idxHashClear(&hIdx);
    rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
        "EXPLAIN QUERY PLAN %s", pStmt->zSql
    );
    while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
      /* int iId = sqlite3_column_int(pExplain, 0); */
      /* int iParent = sqlite3_column_int(pExplain, 1); */
      /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
      const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
      int nDetail;
      int i;

      if( !zDetail ) continue;
      nDetail = STRLEN(zDetail);

      for(i=0; i<nDetail; i++){
        const char *zIdx = 0;
        if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
          zIdx = &zDetail[i+13];
        }else if( i+22<nDetail 
            && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 
        ){
          zIdx = &zDetail[i+22];
        }
        if( zIdx ){
          const char *zSql;
          int nIdx = 0;
          while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
            nIdx++;
          }
          zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
          if( zSql ){
            idxHashAdd(&rc, &hIdx, zSql, 0);
            if( rc ) goto find_indexes_out;
          }
          break;
        }
      }

      if( zDetail[0]!='-' ){
        pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
      }
    }

    for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
      pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
    }

    idxFinalize(&rc, pExplain);
  }

 find_indexes_out:
  idxHashClear(&hIdx);
  return rc;
}

static int idxAuthCallback(
  void *pCtx,
  int eOp,
  const char *z3,
  const char *z4,
  const char *zDb,
  const char *zTrigger
){
  int rc = SQLITE_OK;
  (void)z4;
  (void)zTrigger;
  if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
    if( sqlite3_stricmp(zDb, "main")==0 ){
      sqlite3expert *p = (sqlite3expert*)pCtx;
      IdxTable *pTab;
      for(pTab=p->pTable; pTab; pTab=pTab->pNext){
        if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
      }
      if( pTab ){
        IdxWrite *pWrite;
        for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
          if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
        }
        if( pWrite==0 ){
          pWrite = idxMalloc(&rc, sizeof(IdxWrite));
          if( rc==SQLITE_OK ){
            pWrite->pTab = pTab;
            pWrite->eOp = eOp;
            pWrite->pNext = p->pWrite;
            p->pWrite = pWrite;
          }
        }
      }
    }
  }
  return rc;
}

static int idxProcessOneTrigger(
  sqlite3expert *p, 
  IdxWrite *pWrite, 
  char **pzErr
){
  static const char *zInt = UNIQUE_TABLE_NAME;
  static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
  IdxTable *pTab = pWrite->pTab;
  const char *zTab = pTab->zName;
  const char *zSql = 
    "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
    "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
    "ORDER BY type;";
  sqlite3_stmt *pSelect = 0;
  int rc = SQLITE_OK;
  char *zWrite = 0;

  /* Create the table and its triggers in the temp schema */
  rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
    const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
    if( zCreate==0 ) continue;
    rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
  }
  idxFinalize(&rc, pSelect);

  /* Rename the table in the temp schema to zInt */
  if( rc==SQLITE_OK ){
    char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
    if( z==0 ){
      rc = SQLITE_NOMEM;
    }else{
      rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
      sqlite3_free(z);
    }
  }

  switch( pWrite->eOp ){
    case SQLITE_INSERT: {
      int i;
      zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
      for(i=0; i<pTab->nCol; i++){
        zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
      }
      zWrite = idxAppendText(&rc, zWrite, ")");
      break;
    }
    case SQLITE_UPDATE: {
      int i;
      zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
      for(i=0; i<pTab->nCol; i++){
        zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ", 
            pTab->aCol[i].zName
        );
      }
      break;
    }
    default: {
      assert( pWrite->eOp==SQLITE_DELETE );
      if( rc==SQLITE_OK ){
        zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
        if( zWrite==0 ) rc = SQLITE_NOMEM;
      }
    }
  }

  if( rc==SQLITE_OK ){
    sqlite3_stmt *pX = 0;
    rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
    idxFinalize(&rc, pX);
    if( rc!=SQLITE_OK ){
      idxDatabaseError(p->dbv, pzErr);
    }
  }
  sqlite3_free(zWrite);

  if( rc==SQLITE_OK ){
    rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
  }

  return rc;
}

static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
  int rc = SQLITE_OK;
  IdxWrite *pEnd = 0;
  IdxWrite *pFirst = p->pWrite;

  while( rc==SQLITE_OK && pFirst!=pEnd ){
    IdxWrite *pIter;
    for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
      rc = idxProcessOneTrigger(p, pIter, pzErr);
    }
    pEnd = pFirst;
    pFirst = p->pWrite;
  }

  return rc;
}

/*
** This function tests if the schema of the main database of database handle
** db contains an object named zTab. Assuming no error occurs, output parameter
** (*pbContains) is set to true if zTab exists, or false if it does not.
**
** Or, if an error occurs, an SQLite error code is returned. The final value
** of (*pbContains) is undefined in this case.
*/

static int expertDbContainsObject(
  sqlite3 *db, 
  const char *zTab, 
  int *pbContains                 /* OUT: True if object exists */
){
  const char *zSql = "SELECT 1 FROM sqlite_schema WHERE name = ?";
  sqlite3_stmt *pSql = 0;
  int rc = SQLITE_OK;
  int ret = 0;

  rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
  if( rc==SQLITE_OK ){
    sqlite3_bind_text(pSql, 1, zTab, -1, SQLITE_STATIC);
    if( SQLITE_ROW==sqlite3_step(pSql) ){
      ret = 1;
    }
    rc = sqlite3_finalize(pSql);
  }

  *pbContains = ret;
  return rc;
}

/*
** Execute SQL command zSql using database handle db. If no error occurs,
** set (*pzErr) to NULL and return SQLITE_OK. 
**
** If an error does occur, return an SQLite error code and set (*pzErr) to
** point to a buffer containing an English language error message. Except,
** if the error message begins with "no such module:", then ignore the
** error and return as if the SQL statement had succeeded.
**
** This is used to copy as much of the database schema as possible while 
** ignoring any errors related to missing virtual table modules.
*/

static int expertSchemaSql(sqlite3 *db, const char *zSql, char **pzErr){
  int rc = SQLITE_OK;
  char *zErr = 0;

  rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
  if( rc!=SQLITE_OK && zErr ){
    int nErr = STRLEN(zErr);
    if( nErr>=15 && memcmp(zErr, "no such module:", 15)==0 ){
      sqlite3_free(zErr);
      rc = SQLITE_OK;
      zErr = 0;
    }
  }

  *pzErr = zErr;
  return rc;
}

static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
  int rc = idxRegisterVtab(p);
  sqlite3_stmt *pSchema = 0;

  /* For each table in the main db schema:
  **
  **   1) Add an entry to the p->pTable list, and
  **   2) Create the equivalent virtual table in dbv.
  */

  rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
      "SELECT type, name, sql, 1, "
      "       substr(sql,1,14)=='create virtual' COLLATE nocase "
      "FROM sqlite_schema "
      "WHERE type IN ('table','view') AND "
      "      substr(name,1,7)!='sqlite_' COLLATE nocase "
      " UNION ALL "
      "SELECT type, name, sql, 2, 0 FROM sqlite_schema "
      "WHERE type = 'trigger'"
      "  AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
      "ORDER BY 4, 5 DESC, 1"
  );
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
    const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
    const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
    const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
    int bVirtual = sqlite3_column_int(pSchema, 4);
    int bExists = 0;

    if( zType==0 || zName==0 ) continue;
    rc = expertDbContainsObject(p->dbv, zName, &bExists);
    if( rc || bExists ) continue;

    if( zType[0]=='v' || zType[1]=='r' || bVirtual ){
      /* A view. Or a trigger on a view. */
      if( zSql ) rc = expertSchemaSql(p->dbv, zSql, pzErrmsg);
    }else{
      IdxTable *pTab;
      rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
      if( rc==SQLITE_OK && ALWAYS(pTab!=0) ){
        int i;
        char *zInner = 0;
        char *zOuter = 0;
        pTab->pNext = p->pTable;
        p->pTable = pTab;

        /* The statement the vtab will pass to sqlite3_declare_vtab() */
        zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
        for(i=0; i<pTab->nCol; i++){
          zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s", 
              (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
          );
        }
        zInner = idxAppendText(&rc, zInner, ")");

        /* The CVT statement to create the vtab */
        zOuter = idxAppendText(&rc, 0, 
            "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
        );
        if( rc==SQLITE_OK ){
          rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
        }
        sqlite3_free(zInner);
        sqlite3_free(zOuter);
      }
    }
  }
  idxFinalize(&rc, pSchema);
  return rc;
}

struct IdxSampleCtx {
  int iTarget;
  double target;                  /* Target nRet/nRow value */
  double nRow;                    /* Number of rows seen */
  double nRet;                    /* Number of rows returned */
};

static void idxSampleFunc(
  sqlite3_context *pCtx,
  int argc,
  sqlite3_value **argv
){
  struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
  int bRet;

  (void)argv;
  assert( argc==0 );
  if( p->nRow==0.0 ){
    bRet = 1;
  }else{
    bRet = (p->nRet / p->nRow) <= p->target;
    if( bRet==0 ){
      unsigned short rnd;
      sqlite3_randomness(2, (void*)&rnd);
      bRet = ((int)rnd % 100) <= p->iTarget;
    }
  }

  sqlite3_result_int(pCtx, bRet);
  p->nRow += 1.0;
  p->nRet += (double)bRet;
}

struct IdxRemCtx {
  int nSlot;
  struct IdxRemSlot {
    int eType;                    /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
    i64 iVal;                     /* SQLITE_INTEGER value */
    double rVal;                  /* SQLITE_FLOAT value */
    i64 nByte;                    /* Bytes of space allocated at z */
    i64 n;                        /* Size of buffer z */
    char *z;                      /* SQLITE_TEXT/BLOB value */
  } aSlot[1];
};

/*
** Implementation of scalar function sqlite_expert_rem().
*/

static void idxRemFunc(
  sqlite3_context *pCtx,
  int argc,
  sqlite3_value **argv
){
  struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
  struct IdxRemSlot *pSlot;
  int iSlot;
  assert( argc==2 );

  iSlot = sqlite3_value_int(argv[0]);
  assert( iSlot<p->nSlot );
  pSlot = &p->aSlot[iSlot];

  switch( pSlot->eType ){
    case SQLITE_NULL:
      /* no-op */
      break;

    case SQLITE_INTEGER:
      sqlite3_result_int64(pCtx, pSlot->iVal);
      break;

    case SQLITE_FLOAT:
      sqlite3_result_double(pCtx, pSlot->rVal);
      break;

    case SQLITE_BLOB:
      assert( pSlot->n <= 0x7fffffff );
      sqlite3_result_blob(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT);
      break;

    case SQLITE_TEXT:
      assert( pSlot->n <= 0x7fffffff );
      sqlite3_result_text(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT);
      break;
  }

  pSlot->eType = sqlite3_value_type(argv[1]);
  switch( pSlot->eType ){
    case SQLITE_NULL:
      /* no-op */
      break;

    case SQLITE_INTEGER:
      pSlot->iVal = sqlite3_value_int64(argv[1]);
      break;

    case SQLITE_FLOAT:
      pSlot->rVal = sqlite3_value_double(argv[1]);
      break;

    case SQLITE_BLOB:
    case SQLITE_TEXT: {
      i64 nByte = sqlite3_value_bytes(argv[1]);
      const void *pData = 0;
      if( nByte>pSlot->nByte ){
        char *zNew = (char*)sqlite3_realloc64(pSlot->z, nByte*2);
        if( zNew==0 ){
          sqlite3_result_error_nomem(pCtx);
          return;
        }
        pSlot->nByte = nByte*2;
        pSlot->z = zNew;
      }
      pSlot->n = nByte;
      if( pSlot->eType==SQLITE_BLOB ){
        pData = sqlite3_value_blob(argv[1]);
        if( pData ) memcpy(pSlot->z, pData, nByte);
      }else{
        pData = sqlite3_value_text(argv[1]);
        memcpy(pSlot->z, pData, nByte);
      }
      break;
    }
  }
}

static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
  int rc = SQLITE_OK;
  const char *zMax = 
    "SELECT max(i.seqno) FROM "
    "  sqlite_schema AS s, "
    "  pragma_index_list(s.name) AS l, "
    "  pragma_index_info(l.name) AS i "
    "WHERE s.type = 'table'";
  sqlite3_stmt *pMax = 0;

  *pnMax = 0;
  rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
    *pnMax = sqlite3_column_int(pMax, 0) + 1;
  }
  idxFinalize(&rc, pMax);

  return rc;
}

static int idxPopulateOneStat1(
  sqlite3expert *p,
  sqlite3_stmt *pIndexXInfo,
  sqlite3_stmt *pWriteStat,
  const char *zTab,
  const char *zIdx,
  char **pzErr
){
  char *zCols = 0;
  char *zOrder = 0;
  char *zQuery = 0;
  int nCol = 0;
  int i;
  sqlite3_stmt *pQuery = 0;
  i64 *aStat = 0;
  int rc = SQLITE_OK;

  assert( p->iSample>0 );

  /* Formulate the query text */
  sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
  while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
    const char *zComma = zCols==0 ? "" : ", ";
    const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
    const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
    if( zName==0 ){
      /* This index contains an expression. Ignore it. */
      sqlite3_free(zCols);
      sqlite3_free(zOrder);
      return sqlite3_reset(pIndexXInfo);
    }
    zCols = idxAppendText(&rc, zCols, 
        "%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s", 
        zComma, zName, nCol, zName, zColl
    );
    zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
  }
  sqlite3_reset(pIndexXInfo);
  if( rc==SQLITE_OK ){
    if( p->iSample==100 ){
      zQuery = sqlite3_mprintf(
          "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
      );
    }else{
      zQuery = sqlite3_mprintf(
          "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
      );
    }
  }
  sqlite3_free(zCols);
  sqlite3_free(zOrder);

  /* Formulate the query text */
  if( rc==SQLITE_OK ){
    sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
    rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
  }
  sqlite3_free(zQuery);

  if( rc==SQLITE_OK ){
    aStat = (i64*)idxMalloc(&rc, sizeof(i64)*(nCol+1));
  }
  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
    IdxHashEntry *pEntry;
    char *zStat = 0;
    for(i=0; i<=nCol; i++) aStat[i] = 1;
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
      aStat[0]++;
      for(i=0; i<nCol; i++){
        if( sqlite3_column_int(pQuery, i)==0 ) break;
      }
      for(/*no-op*/; i<nCol; i++){
        aStat[i+1]++;
      }
    }

    if( rc==SQLITE_OK ){
      i64 s0 = aStat[0];
      zStat = sqlite3_mprintf("%lld", s0);
      if( zStat==0 ) rc = SQLITE_NOMEM;
      for(i=1; rc==SQLITE_OK && i<=nCol; i++){
        zStat = idxAppendText(&rc, zStat, " %lld", (s0+aStat[i]/2) / aStat[i]);
      }
    }

    if( rc==SQLITE_OK ){
      sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
      sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
      sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
      sqlite3_step(pWriteStat);
      rc = sqlite3_reset(pWriteStat);
    }

    pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
    if( pEntry ){
      assert( pEntry->zVal2==0 );
      pEntry->zVal2 = zStat;
    }else{
      sqlite3_free(zStat);
    }
  }
  sqlite3_free(aStat);
  idxFinalize(&rc, pQuery);

  return rc;
}

static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
  int rc;
  char *zSql;

  rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
  if( rc!=SQLITE_OK ) return rc;

  zSql = sqlite3_mprintf(
      "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
  );
  if( zSql==0 ) return SQLITE_NOMEM;
  rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
  sqlite3_free(zSql);

  return rc;
}

/*
** This function is called as part of sqlite3_expert_analyze(). Candidate
** indexes have already been created in database sqlite3expert.dbm, this
** function populates sqlite_stat1 table in the same database.
**
** The stat1 data is generated by querying the 
*/

static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
  int rc = SQLITE_OK;
  int nMax =0;
  struct IdxRemCtx *pCtx = 0;
  struct IdxSampleCtx samplectx; 
  int i;
  i64 iPrev = -100000;
  sqlite3_stmt *pAllIndex = 0;
  sqlite3_stmt *pIndexXInfo = 0;
  sqlite3_stmt *pWrite = 0;

  const char *zAllIndex =
    "SELECT s.rowid, s.name, l.name FROM "
    "  sqlite_schema AS s, "
    "  pragma_index_list(s.name) AS l "
    "WHERE s.type = 'table'";
  const char *zIndexXInfo = 
    "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
  const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";

  /* If iSample==0, no sqlite_stat1 data is required. */
  if( p->iSample==0 ) return SQLITE_OK;

  rc = idxLargestIndex(p->dbm, &nMax, pzErr);
  if( nMax<=0 || rc!=SQLITE_OK ) return rc;

  rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);

  if( rc==SQLITE_OK ){
    i64 nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
    pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
  }

  if( rc==SQLITE_OK ){
    sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
    rc = sqlite3_create_function(dbrem, "sqlite_expert_rem", 
        2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
    );
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(p->db, "sqlite_expert_sample", 
        0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
    );
  }

  if( rc==SQLITE_OK ){
    pCtx->nSlot = (i64)nMax+1;
    rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
  }
  if( rc==SQLITE_OK ){
    rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
  }
  if( rc==SQLITE_OK ){
    rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
  }

  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
    i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
    const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
    const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
    if( zTab==0 || zIdx==0 ) continue;
    if( p->iSample<100 && iPrev!=iRowid ){
      samplectx.target = (double)p->iSample / 100.0;
      samplectx.iTarget = p->iSample;
      samplectx.nRow = 0.0;
      samplectx.nRet = 0.0;
      rc = idxBuildSampleTable(p, zTab);
      if( rc!=SQLITE_OK ) break;
    }
    rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
    iPrev = iRowid;
  }
  if( rc==SQLITE_OK && p->iSample<100 ){
    rc = sqlite3_exec(p->dbv, 
        "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
    );
  }

  idxFinalize(&rc, pAllIndex);
  idxFinalize(&rc, pIndexXInfo);
  idxFinalize(&rc, pWrite);

  if( pCtx ){
    for(i=0; i<pCtx->nSlot; i++){
      sqlite3_free(pCtx->aSlot[i].z);
    }
    sqlite3_free(pCtx);
  }

  if( rc==SQLITE_OK ){
    rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
  }

  sqlite3_create_function(p->db, "sqlite_expert_rem", 2, SQLITE_UTF8, 0,0,0,0);
  sqlite3_create_function(p->db, "sqlite_expert_sample", 0,SQLITE_UTF8,0,0,0,0);

  sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
  return rc;
}

/*
** Define and possibly pretend to use a useless collation sequence.
** This pretense allows expert to accept SQL using custom collations.
*/

int dummyCompare(void *up1, int up2, const void *up3, int up4, const void *up5){
  (void)up1;
  (void)up2;
  (void)up3;
  (void)up4;
  (void)up5;
  assert(0); /* VDBE should never be run. */
  return 0;
}
/* And a callback to register above upon actual need */
void useDummyCS(void *up1, sqlite3 *db, int etr, const char *zName){
  (void)up1;
  sqlite3_create_collation_v2(db, zName, etr, 0, dummyCompare, 0);
}

#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) \
  && !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
/*
** dummy functions for no-op implementation of UDFs during expert's work
*/

void dummyUDF(sqlite3_context *up1, int up2, sqlite3_value **up3){
  (void)up1;
  (void)up2;
  (void)up3;
  assert(0); /* VDBE should never be run. */
}
void dummyUDFvalue(sqlite3_context *up1){
  (void)up1;
  assert(0); /* VDBE should never be run. */
}

/*
** Register UDFs from user database with another.
*/

int registerUDFs(sqlite3 *dbSrc, sqlite3 *dbDst){
  sqlite3_stmt *pStmt;
  int rc = sqlite3_prepare_v2(dbSrc,
            "SELECT name,type,enc,narg,flags "
            "FROM pragma_function_list() "
            "WHERE builtin==0", -1, &pStmt, 0);
  if( rc==SQLITE_OK ){
    while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
      int nargs = sqlite3_column_int(pStmt,3);
      int flags = sqlite3_column_int(pStmt,4);
      const char *name = (char*)sqlite3_column_text(pStmt,0);
      const char *type = (char*)sqlite3_column_text(pStmt,1);
      const char *enc = (char*)sqlite3_column_text(pStmt,2);
      if( name==0 || type==0 || enc==0 ){
        /* no-op.  Only happens on OOM */
      }else{
        int ienc = SQLITE_UTF8;
        int rcf = SQLITE_ERROR;
        if( strcmp(enc,"utf16le")==0 ) ienc = SQLITE_UTF16LE;
        else if( strcmp(enc,"utf16be")==0 ) ienc = SQLITE_UTF16BE;
        ienc |= (flags & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY));
        if( strcmp(type,"w")==0 ){
          rcf = sqlite3_create_window_function(dbDst,name,nargs,ienc,0,
                                               dummyUDF,dummyUDFvalue,0,0,0);
        }else if( strcmp(type,"a")==0 ){
          rcf = sqlite3_create_function(dbDst,name,nargs,ienc,0,
                                        0,dummyUDF,dummyUDFvalue);
        }else if( strcmp(type,"s")==0 ){
          rcf = sqlite3_create_function(dbDst,name,nargs,ienc,0,
                                        dummyUDF,0,0);
        }
        if( rcf!=SQLITE_OK ){
          rc = rcf;
          break;
        }
      }
    }
    sqlite3_finalize(pStmt);
    if( rc==SQLITE_DONE ) rc = SQLITE_OK;
  }
  return rc;
}
#endif

/*
** Allocate a new sqlite3expert object.
*/

sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
  int rc = SQLITE_OK;
  sqlite3expert *pNew;

  pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));

  /* Open two in-memory databases to work with. The "vtab database" (dbv)
  ** will contain a virtual table corresponding to each real table in
  ** the user database schema, and a copy of each view. It is used to
  ** collect information regarding the WHERE, ORDER BY and other clauses
  ** of the user's query.
  */

  if( rc==SQLITE_OK ){
    pNew->db = db;
    pNew->iSample = 100;
    rc = sqlite3_open(":memory:", &pNew->dbv);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_open(":memory:", &pNew->dbm);
    if( rc==SQLITE_OK ){
      sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
    }
  }

  /* Allow custom collations to be dealt with through prepare. */
  if( rc==SQLITE_OK ) rc = sqlite3_collation_needed(pNew->dbm,0,useDummyCS);
  if( rc==SQLITE_OK ) rc = sqlite3_collation_needed(pNew->dbv,0,useDummyCS);

#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) \
  && !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
  /* Register UDFs from database [db] with [dbm] and [dbv]. */
  if( rc==SQLITE_OK ){
    rc = registerUDFs(pNew->db, pNew->dbm);
  }
  if( rc==SQLITE_OK ){
    rc = registerUDFs(pNew->db, pNew->dbv);
  }
#endif

  /* Copy the entire schema of database [db] into [dbm]. */
  if( rc==SQLITE_OK ){
    sqlite3_stmt *pSql = 0;
    rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
        "SELECT sql, name, substr(sql,1,14)=='create virtual' COLLATE nocase"
        " FROM sqlite_schema WHERE substr(name,1,7)!='sqlite_' COLLATE nocase"
        " ORDER BY 3 DESC, rowid"
    );
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
      const char *zName = (const char*)sqlite3_column_text(pSql, 1);
      int bExists = 0;
      rc = expertDbContainsObject(pNew->dbm, zName, &bExists);
      if( rc==SQLITE_OK && zSql && bExists==0 ){
        rc = expertSchemaSql(pNew->dbm, zSql, pzErrmsg);
      }
    }
    idxFinalize(&rc, pSql);
  }

  /* Create the vtab schema */
  if( rc==SQLITE_OK ){
    rc = idxCreateVtabSchema(pNew, pzErrmsg);
  }

  /* Register the auth callback with dbv */
  if( rc==SQLITE_OK ){
    sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
  }

  /* If an error has occurred, free the new object and return NULL. Otherwise,
  ** return the new sqlite3expert handle.  */

  if( rc!=SQLITE_OK ){
    sqlite3_expert_destroy(pNew);
    pNew = 0;
  }
  return pNew;
}

/*
** Configure an sqlite3expert object.
*/

int sqlite3_expert_config(sqlite3expert *p, int op, ...){
  int rc = SQLITE_OK;
  va_list ap;
  va_start(ap, op);
  switch( op ){
    case EXPERT_CONFIG_SAMPLE: {
      int iVal = va_arg(ap, int);
      if( iVal<0 ) iVal = 0;
      if( iVal>100 ) iVal = 100;
      p->iSample = iVal;
      break;
    }
    default:
      rc = SQLITE_NOTFOUND;
      break;
  }

  va_end(ap);
  return rc;
}

/*
** Add an SQL statement to the analysis.
*/

int sqlite3_expert_sql(
  sqlite3expert *p,               /* From sqlite3_expert_new() */
  const char *zSql,               /* SQL statement to add */
  char **pzErr                    /* OUT: Error message (if any) */
){
  IdxScan *pScanOrig = p->pScan;
  IdxStatement *pStmtOrig = p->pStatement;
  int rc = SQLITE_OK;
  const char *zStmt = zSql;

  if( p->bRun ) return SQLITE_MISUSE;

  while( rc==SQLITE_OK && zStmt && zStmt[0] ){
    sqlite3_stmt *pStmt = 0;
    /* Ensure that the provided statement compiles against user's DB. */
    rc = idxPrepareStmt(p->db, &pStmt, pzErr, zStmt);
    if( rc!=SQLITE_OK ) break;
    sqlite3_finalize(pStmt);
    rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
    if( rc==SQLITE_OK ){
      if( pStmt ){
        IdxStatement *pNew;
        const char *z = sqlite3_sql(pStmt);
        i64 n = STRLEN(z);
        pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
        if( rc==SQLITE_OK ){
          pNew->zSql = (char*)&pNew[1];
          memcpy(pNew->zSql, z, n+1);
          pNew->pNext = p->pStatement;
          if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
          p->pStatement = pNew;
        }
        sqlite3_finalize(pStmt);
      }
    }else{
      idxDatabaseError(p->dbv, pzErr);
    }
  }

  if( rc!=SQLITE_OK ){
    idxScanFree(p->pScan, pScanOrig);
    idxStatementFree(p->pStatement, pStmtOrig);
    p->pScan = pScanOrig;
    p->pStatement = pStmtOrig;
  }

  return rc;
}

int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
  int rc;
  IdxHashEntry *pEntry;

  /* Do trigger processing to collect any extra IdxScan structures */
  rc = idxProcessTriggers(p, pzErr);

  /* Create candidate indexes within the in-memory database file */
  if( rc==SQLITE_OK ){
    rc = idxCreateCandidates(p);
  }else if ( rc==SQLITE_BUSY_TIMEOUT ){
    if( pzErr )
      *pzErr = sqlite3_mprintf("Cannot find a unique index name to propose.");
    return rc;
  }

  /* Generate the stat1 data */
  if( rc==SQLITE_OK ){
    rc = idxPopulateStat1(p, pzErr);
  }

  /* Formulate the EXPERT_REPORT_CANDIDATES text */
  for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
    p->zCandidates = idxAppendText(&rc, p->zCandidates, 
        "%s;%s%s\n", pEntry->zVal, 
        pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
    );
  }

  /* Figure out which of the candidate indexes are preferred by the query
  ** planner and report the results to the user.  */

  if( rc==SQLITE_OK ){
    rc = idxFindIndexes(p, pzErr);
  }

  if( rc==SQLITE_OK ){
    p->bRun = 1;
  }
  return rc;
}

/*
** Return the total number of statements that have been added to this
** sqlite3expert using sqlite3_expert_sql().
*/

int sqlite3_expert_count(sqlite3expert *p){
  int nRet = 0;
  if( p->pStatement ) nRet = p->pStatement->iId+1;
  return nRet;
}

/*
** Return a component of the report.
*/

const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
  const char *zRet = 0;
  IdxStatement *pStmt;

  if( p->bRun==0 ) return 0;
  for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
  switch( eReport ){
    case EXPERT_REPORT_SQL:
      if( pStmt ) zRet = pStmt->zSql;
      break;
    case EXPERT_REPORT_INDEXES:
      if( pStmt ) zRet = pStmt->zIdx;
      break;
    case EXPERT_REPORT_PLAN:
      if( pStmt ) zRet = pStmt->zEQP;
      break;
    case EXPERT_REPORT_CANDIDATES:
      zRet = p->zCandidates;
      break;
  }
  return zRet;
}

/*
** Free an sqlite3expert object.
*/

void sqlite3_expert_destroy(sqlite3expert *p){
  if( p ){
    sqlite3_close(p->dbm);
    sqlite3_close(p->dbv);
    idxScanFree(p->pScan, 0);
    idxStatementFree(p->pStatement, 0);
    idxTableFree(p->pTable);
    idxWriteFree(p->pWrite);
    idxHashClear(&p->hIdx);
    sqlite3_free(p->zCandidates);
    sqlite3_free(p);
  }
}

#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

/************************* End ext/expert/sqlite3expert.c ********************/
#endif
/************************* Begin ext/intck/sqlite3intck.h ******************/
/*
** 2024-02-08
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/


/*
** Incremental Integrity-Check Extension
** -------------------------------------
**
** This module contains code to check whether or not an SQLite database
** is well-formed or corrupt. This is the same task as performed by SQLite's
** built-in "PRAGMA integrity_check" command. This module differs from
** "PRAGMA integrity_check" in that:
**
**   +  It is less thorough - this module does not detect certain types
**      of corruption that are detected by the PRAGMA command. However,
**      it does detect all kinds of corruption that are likely to cause
**      errors in SQLite applications.
**
**   +  It is slower. Sometimes up to three times slower.
**
**   +  It allows integrity-check operations to be split into multiple
**      transactions, so that the database does not need to be read-locked
**      for the duration of the integrity-check.
**
** One way to use the API to run integrity-check on the "main" database
** of handle db is:
**
**   int rc = SQLITE_OK;
**   sqlite3_intck *p = 0;
**
**   sqlite3_intck_open(db, "main", &p);
**   while( SQLITE_OK==sqlite3_intck_step(p) ){
**     const char *zMsg = sqlite3_intck_message(p);
**     if( zMsg ) printf("corruption: %s\n", zMsg);
**   }
**   rc = sqlite3_intck_error(p, &zErr);
**   if( rc!=SQLITE_OK ){
**     printf("error occured (rc=%d), (errmsg=%s)\n", rc, zErr);
**   }
**   sqlite3_intck_close(p);
**
** Usually, the sqlite3_intck object opens a read transaction within the
** first call to sqlite3_intck_step() and holds it open until the 
** integrity-check is complete. However, if sqlite3_intck_unlock() is
** called, the read transaction is ended and a new read transaction opened
** by the subsequent call to sqlite3_intck_step().
*/


#ifndef _SQLITE_INTCK_H
#define _SQLITE_INTCK_H

/* #include "sqlite3.h" */

#ifdef __cplusplus
extern "C" {
#endif

/*
** An ongoing incremental integrity-check operation is represented by an
** opaque pointer of the following type.
*/

typedef struct sqlite3_intck sqlite3_intck;

/*
** Open a new incremental integrity-check object. If successful, populate
** output variable (*ppOut) with the new object handle and return SQLITE_OK.
** Or, if an error occurs, set (*ppOut) to NULL and return an SQLite error
** code (e.g. SQLITE_NOMEM).
**
** The integrity-check will be conducted on database zDb (which must be "main",
** "temp", or the name of an attached database) of database handle db. Once
** this function has been called successfully, the caller should not use 
** database handle db until the integrity-check object has been destroyed
** using sqlite3_intck_close().
*/

int sqlite3_intck_open(
  sqlite3 *db,                    /* Database handle */
  const char *zDb,                /* Database name ("main", "temp" etc.) */
  sqlite3_intck **ppOut           /* OUT: New sqlite3_intck handle */
);

/*
** Close and release all resources associated with a handle opened by an
** earlier call to sqlite3_intck_open(). The results of using an
** integrity-check handle after it has been passed to this function are
** undefined.
*/

void sqlite3_intck_close(sqlite3_intck *pCk);

/*
** Do the next step of the integrity-check operation specified by the handle
** passed as the only argument. This function returns SQLITE_DONE if the 
** integrity-check operation is finished, or an SQLite error code if
** an error occurs, or SQLITE_OK if no error occurs but the integrity-check
** is not finished. It is not considered an error if database corruption
** is encountered.
**
** Following a successful call to sqlite3_intck_step() (one that returns
** SQLITE_OK), sqlite3_intck_message() returns a non-NULL value if 
** corruption was detected in the db.
**
** If an error occurs and a value other than SQLITE_OK or SQLITE_DONE is
** returned, then the integrity-check handle is placed in an error state.
** In this state all subsequent calls to sqlite3_intck_step() or 
** sqlite3_intck_unlock() will immediately return the same error. The 
** sqlite3_intck_error() method may be used to obtain an English language 
** error message in this case.
*/

int sqlite3_intck_step(sqlite3_intck *pCk);

/*
** If the previous call to sqlite3_intck_step() encountered corruption 
** within the database, then this function returns a pointer to a buffer
** containing a nul-terminated string describing the corruption in 
** English. If the previous call to sqlite3_intck_step() did not encounter
** corruption, or if there was no previous call, this function returns 
** NULL.
*/

const char *sqlite3_intck_message(sqlite3_intck *pCk);

/*
** Close any read-transaction opened by an earlier call to 
** sqlite3_intck_step(). Any subsequent call to sqlite3_intck_step() will
** open a new transaction. Return SQLITE_OK if successful, or an SQLite error
** code otherwise.
**
** If an error occurs, then the integrity-check handle is placed in an error
** state. In this state all subsequent calls to sqlite3_intck_step() or 
** sqlite3_intck_unlock() will immediately return the same error. The 
** sqlite3_intck_error() method may be used to obtain an English language 
** error message in this case.
*/

int sqlite3_intck_unlock(sqlite3_intck *pCk);

/*
** If an error has occurred in an earlier call to sqlite3_intck_step()
** or sqlite3_intck_unlock(), then this method returns the associated 
** SQLite error code. Additionally, if pzErr is not NULL, then (*pzErr)
** may be set to point to a nul-terminated string containing an English
** language error message. Or, if no error message is available, to
** NULL.
**
** If no error has occurred within sqlite3_intck_step() or
** sqlite_intck_unlock() calls on the handle passed as the first argument, 
** then SQLITE_OK is returned and (*pzErr) set to NULL.
*/

int sqlite3_intck_error(sqlite3_intck *pCk, const char **pzErr);

/*
** This API is used for testing only. It returns the full-text of an SQL
** statement used to test object zObj, which may be a table or index.
** The returned buffer is valid until the next call to either this function
** or sqlite3_intck_close() on the same sqlite3_intck handle.
*/

const char *sqlite3_intck_test_sql(sqlite3_intck *pCk, const char *zObj);


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

#endif /* ifndef _SQLITE_INTCK_H */

/************************* End ext/intck/sqlite3intck.h ********************/
/************************* Begin ext/intck/sqlite3intck.c ******************/
/*
** 2024-02-08
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/


/* #include "sqlite3intck.h" */
#include <string.h>
#include <assert.h>

#include <stdio.h>
#include <stdlib.h>

/*
** nKeyVal:
**   The number of values that make up the 'key' for the current pCheck
**   statement.
**
** rc:
**   Error code returned by most recent sqlite3_intck_step() or 
**   sqlite3_intck_unlock() call. This is set to SQLITE_DONE when
**   the integrity-check operation is finished.
**
** zErr:
**   If the object has entered the error state, this is the error message.
**   Is freed using sqlite3_free() when the object is deleted.
**
** zTestSql:
**   The value returned by the most recent call to sqlite3_intck_testsql().
**   Each call to testsql() frees the previous zTestSql value (using
**   sqlite3_free()) and replaces it with the new value it will return.
*/

struct sqlite3_intck {
  sqlite3 *db;
  const char *zDb;                /* Copy of zDb parameter to _open() */
  char *zObj;                     /* Current object. Or NULL. */

  sqlite3_stmt *pCheck;           /* Current check statement */
  char *zKey;
  int nKeyVal;

  char *zMessage;
  int bCorruptSchema;

  int rc;                         /* Error code */
  char *zErr;                     /* Error message */
  char *zTestSql;                 /* Returned by sqlite3_intck_test_sql() */
};


/*
** Some error has occurred while using database p->db. Save the error message
** and error code currently held by the database handle in p->rc and p->zErr.
*/

static void intckSaveErrmsg(sqlite3_intck *p){
  p->rc = sqlite3_errcode(p->db);
  sqlite3_free(p->zErr);
  p->zErr = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
}

/*
** If the handle passed as the first argument is already in the error state,
** then this function is a no-op (returns NULL immediately). Otherwise, if an
** error occurs within this function, it leaves an error in said handle.
**
** Otherwise, this function attempts to prepare SQL statement zSql and
** return the resulting statement handle to the user.
*/

static sqlite3_stmt *intckPrepare(sqlite3_intck *p, const char *zSql){
  sqlite3_stmt *pRet = 0;
  if( p->rc==SQLITE_OK ){
    p->rc = sqlite3_prepare_v2(p->db, zSql, -1, &pRet, 0);
    if( p->rc!=SQLITE_OK ){
      intckSaveErrmsg(p);
      assert( pRet==0 );
    }
  }
  return pRet;
}

/*
** If the handle passed as the first argument is already in the error state,
** then this function is a no-op (returns NULL immediately). Otherwise, if an
** error occurs within this function, it leaves an error in said handle.
**
** Otherwise, this function treats argument zFmt as a printf() style format
** string. It formats it according to the trailing arguments and then 
** attempts to prepare the results and return the resulting prepared
** statement.
*/

static sqlite3_stmt *intckPrepareFmt(sqlite3_intck *p, const char *zFmt, ...){
  sqlite3_stmt *pRet = 0;
  va_list ap;
  char *zSql = 0;
  va_start(ap, zFmt);
  zSql = sqlite3_vmprintf(zFmt, ap);
  if( p->rc==SQLITE_OK && zSql==0 ){
    p->rc = SQLITE_NOMEM;
  }
  pRet = intckPrepare(p, zSql);
  sqlite3_free(zSql);
  va_end(ap);
  return pRet;
}

/*
** Finalize SQL statement pStmt. If an error occurs and the handle passed
** as the first argument does not already contain an error, store the
** error in the handle.
*/

static void intckFinalize(sqlite3_intck *p, sqlite3_stmt *pStmt){
  int rc = sqlite3_finalize(pStmt);
  if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){
    intckSaveErrmsg(p);
  }
}

/*
** If there is already an error in handle p, return it. Otherwise, call
** sqlite3_step() on the statement handle and return that value.
*/

static int intckStep(sqlite3_intck *p, sqlite3_stmt *pStmt){
  if( p->rc ) return p->rc;
  return sqlite3_step(pStmt);
}

/*
** Execute SQL statement zSql. There is no way to obtain any results 
** returned by the statement. This function uses the sqlite3_intck error
** code convention.
*/

static void intckExec(sqlite3_intck *p, const char *zSql){
  sqlite3_stmt *pStmt = 0;
  pStmt = intckPrepare(p, zSql);
  intckStep(p, pStmt);
  intckFinalize(p, pStmt);
}

/*
** A wrapper around sqlite3_mprintf() that uses the sqlite3_intck error
** code convention.
*/

static char *intckMprintf(sqlite3_intck *p, const char *zFmt, ...){
  va_list ap;
  char *zRet = 0;
  va_start(ap, zFmt);
  zRet = sqlite3_vmprintf(zFmt, ap);
  if( p->rc==SQLITE_OK ){
    if( zRet==0 ){
      p->rc = SQLITE_NOMEM;
    }
  }else{
    sqlite3_free(zRet);
    zRet = 0;
  }
  va_end(ap);
  return zRet;
}

/*
** This is used by sqlite3_intck_unlock() to save the vector key value 
** required to restart the current pCheck query as a nul-terminated string 
** in p->zKey.
*/

static void intckSaveKey(sqlite3_intck *p){
  int ii;
  char *zSql = 0;
  sqlite3_stmt *pStmt = 0;
  sqlite3_stmt *pXinfo = 0;
  const char *zDir = 0;

  assert( p->pCheck );
  assert( p->zKey==0 );

  pXinfo = intckPrepareFmt(p, 
      "SELECT group_concat(desc, '') FROM %Q.sqlite_schema s, "
      "pragma_index_xinfo(%Q, %Q) "
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5 in Prozent
C=91 H=91 G=90

¤ Dauer der Verarbeitung: 3.53 Sekunden  (vorverarbeitet am  2026-09-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.