Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
sqlite: update to 3.47.0
Baptiste Daroussin committed 1 year ago
commit 1bbda8811a65ac3d5aba9f703de4cd747b24140e
parent 31c866b
10 files changed +12422 -5626
modified external/linenoise/Makefile.autosetup
@@ -1,6 +1,6 @@
include @builddir@/mk/defs.mk
LIB=	linenoise
-
SRCS=	linenoise.c
+
SRCS=	linenoise.c stringbuf.c utf8.c
VPATH=	$(top_srcdir)/external/linenoise

include $(MK)/static-lib.mk
modified external/linenoise/linenoise.c
@@ -3,15 +3,17 @@
 *
 * You can find the latest source code at:
 *
-
 *   http://github.com/antirez/linenoise
+
 *   http://github.com/msteveb/linenoise
+
 *   (forked from http://github.com/antirez/linenoise)
 *
 * Does a number of crazy assumptions that happen to be true in 99.9999% of
 * the 2010 UNIX computers around.
 *
 * ------------------------------------------------------------------------
 *
-
 * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>
-
 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+
 * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
+
 * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+
 * Copyright (c) 2011, Steve Bennett <steveb at workware dot net dot au>
 *
 * All rights reserved.
 *
@@ -44,207 +46,377 @@
 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
 *
-
 * Todo list:
-
 * - Filter bogus Ctrl+<char> combinations.
-
 * - Win32 support
-
 *
 * Bloat:
-
 * - History search like Ctrl+r in readline?
+
 * - Completion?
 *
+
 * Unix/termios
+
 * ------------
 * List of escape sequences used by this program, we do everything just
-
 * with three sequences. In order to be so cheap we may have some
+
 * a few sequences. In order to be so cheap we may have some
 * flickering effect with some slow terminal, but the lesser sequences
 * the more compatible.
 *
 * EL (Erase Line)
-
 *    Sequence: ESC [ n K
-
 *    Effect: if n is 0 or missing, clear from cursor to end of line
-
 *    Effect: if n is 1, clear from beginning of line to cursor
-
 *    Effect: if n is 2, clear entire line
+
 *    Sequence: ESC [ 0 K
+
 *    Effect: clear from cursor to end of line
 *
 * CUF (CUrsor Forward)
 *    Sequence: ESC [ n C
 *    Effect: moves cursor forward n chars
 *
-
 * CUB (CUrsor Backward)
-
 *    Sequence: ESC [ n D
-
 *    Effect: moves cursor backward n chars
+
 * CR (Carriage Return)
+
 *    Sequence: \r
+
 *    Effect: moves cursor to column 1
 *
-
 * The following is used to get the terminal width if getting
-
 * the width with the TIOCGWINSZ ioctl fails
+
 * The following are used to clear the screen: ESC [ H ESC [ 2 J
+
 * This is actually composed of two sequences:
 *
-
 * DSR (Device Status Report)
-
 *    Sequence: ESC [ 6 n
-
 *    Effect: reports the current cusor position as ESC [ n ; m R
-
 *            where n is the row and m is the column
+
 * cursorhome
+
 *    Sequence: ESC [ H
+
 *    Effect: moves the cursor to upper left corner
 *
-
 * When multi line mode is enabled, we also use an additional escape
-
 * sequence. However multi line editing is disabled by default.
+
 * ED2 (Clear entire screen)
+
 *    Sequence: ESC [ 2 J
+
 *    Effect: clear the whole screen
 *
+
 * == For highlighting control characters, we also use the following two ==
+
 * SO (enter StandOut)
+
 *    Sequence: ESC [ 7 m
+
 *    Effect: Uses some standout mode such as reverse video
+
 *
+
 * SE (Standout End)
+
 *    Sequence: ESC [ 0 m
+
 *    Effect: Exit standout mode
+
 *
+
 * == Only used if TIOCGWINSZ fails ==
+
 * DSR/CPR (Report cursor position)
+
 *    Sequence: ESC [ 6 n
+
 *    Effect: reports current cursor position as ESC [ NNN ; MMM R
+
 *
+
 * == Only used in multiline mode ==
 * CUU (Cursor Up)
 *    Sequence: ESC [ n A
-
 *    Effect: moves cursor up of n chars.
+
 *    Effect: moves cursor up n chars.
 *
 * CUD (Cursor Down)
 *    Sequence: ESC [ n B
-
 *    Effect: moves cursor down of n chars.
-
 *
-
 * When linenoiseClearScreen() is called, two additional escape sequences
-
 * are used in order to clear the screen and position the cursor at home
-
 * position.
-
 *
-
 * CUP (Cursor position)
-
 *    Sequence: ESC [ H
-
 *    Effect: moves the cursor to upper left corner
-
 *
-
 * ED (Erase display)
-
 *    Sequence: ESC [ 2 J
-
 *    Effect: clear the whole screen
+
 *    Effect: moves cursor down n chars.
 *
+
 * win32/console
+
 * -------------
+
 * If __MINGW32__ is defined, the win32 console API is used.
+
 * This could probably be made to work for the msvc compiler too.
+
 * This support based in part on work by Jon Griffiths.
 */

+
#ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
+
#include <windows.h>
+
#include <fcntl.h>
+
#define USE_WINCONSOLE
+
#ifdef __MINGW32__
+
#define HAVE_UNISTD_H
+
#endif
+
#else
#include <termios.h>
+
#include <sys/ioctl.h>
+
#include <poll.h>
+
#define USE_TERMIOS
+
#define HAVE_UNISTD_H
+
#endif
+

+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
+
#endif
#include <stdlib.h>
+
#include <stdarg.h>
#include <stdio.h>
+
#include <assert.h>
#include <errno.h>
#include <string.h>
+
#include <signal.h>
#include <stdlib.h>
-
#include <ctype.h>
-
#include <sys/stat.h>
#include <sys/types.h>
-
#include <sys/ioctl.h>
-
#include <unistd.h>
+

+
#if defined(_WIN32) && !defined(__MINGW32__)
+
/* Microsoft headers don't like old POSIX names */
+
#define strdup _strdup
+
#define snprintf _snprintf
+
#endif
+

#include "linenoise.h"
+
#ifndef STRINGBUF_H
+
#include "stringbuf.h"
+
#endif
+
#ifndef UTF8_UTIL_H
+
#include "utf8.h"
+
#endif

#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
-
#define LINENOISE_MAX_LINE 4096
-
static char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
-
static linenoiseCompletionCallback *completionCallback = NULL;
-
static linenoiseHintsCallback *hintsCallback = NULL;
-
static linenoiseFreeHintsCallback *freeHintsCallback = NULL;

-
static struct termios orig_termios; /* In order to restore at exit.*/
-
static int maskmode = 0; /* Show "***" instead of input. For passwords. */
-
static int rawmode = 0; /* For atexit() function to check if restore is needed*/
-
static int mlmode = 0;  /* Multi line mode. Default is single line. */
-
static int atexit_registered = 0; /* Register atexit just 1 time. */
+
/* ctrl('A') -> 0x01 */
+
#define ctrl(C) ((C) - '@')
+
/* meta('a') ->  0xe1 */
+
#define meta(C) ((C) | 0x80)
+

+
/* Use -ve numbers here to co-exist with normal unicode chars */
+
enum {
+
    SPECIAL_NONE,
+
    /* don't use -1 here since that indicates error */
+
    SPECIAL_UP = -20,
+
    SPECIAL_DOWN = -21,
+
    SPECIAL_LEFT = -22,
+
    SPECIAL_RIGHT = -23,
+
    SPECIAL_DELETE = -24,
+
    SPECIAL_HOME = -25,
+
    SPECIAL_END = -26,
+
    SPECIAL_INSERT = -27,
+
    SPECIAL_PAGE_UP = -28,
+
    SPECIAL_PAGE_DOWN = -29,
+

+
    /* Some handy names for other special keycodes */
+
    CHAR_ESCAPE = 27,
+
    CHAR_DELETE = 127,
+
};
+

static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
static int history_len = 0;
+
static int history_index = 0;
static char **history = NULL;

-
/* The linenoiseState structure represents the state during line editing.
-
 * We pass this state to functions implementing specific editing
-
 * functionalities. */
-
struct linenoiseState {
-
    int ifd;            /* Terminal stdin file descriptor. */
-
    int ofd;            /* Terminal stdout file descriptor. */
-
    char *buf;          /* Edited line buffer. */
-
    size_t buflen;      /* Edited line buffer size. */
-
    const char *prompt; /* Prompt to display. */
-
    size_t plen;        /* Prompt length. */
-
    size_t pos;         /* Current cursor position. */
-
    size_t oldpos;      /* Previous refresh cursor position. */
-
    size_t len;         /* Current edited line length. */
-
    size_t cols;        /* Number of columns in terminal. */
-
    size_t maxrows;     /* Maximum num of rows used so far (multiline mode) */
-
    int history_index;  /* The history index we are currently editing. */
-
};
-

-
enum KEY_ACTION{
-
	KEY_NULL = 0,	    /* NULL */
-
	CTRL_A = 1,         /* Ctrl+a */
-
	CTRL_B = 2,         /* Ctrl-b */
-
	CTRL_C = 3,         /* Ctrl-c */
-
	CTRL_D = 4,         /* Ctrl-d */
-
	CTRL_E = 5,         /* Ctrl-e */
-
	CTRL_F = 6,         /* Ctrl-f */
-
	CTRL_H = 8,         /* Ctrl-h */
-
	TAB = 9,            /* Tab */
-
	CTRL_K = 11,        /* Ctrl+k */
-
	CTRL_L = 12,        /* Ctrl+l */
-
	ENTER = 13,         /* Enter */
-
	CTRL_N = 14,        /* Ctrl-n */
-
	CTRL_P = 16,        /* Ctrl-p */
-
	CTRL_T = 20,        /* Ctrl-t */
-
	CTRL_U = 21,        /* Ctrl+u */
-
	CTRL_W = 23,        /* Ctrl+w */
-
	ESC = 27,           /* Escape */
-
	BACKSPACE =  127    /* Backspace */
+
/* Structure to contain the status of the current (being edited) line */
+
struct current {
+
    stringbuf *buf; /* Current buffer. Always null terminated */
+
    int pos;    /* Cursor position, measured in chars */
+
    int cols;   /* Size of the window, in chars */
+
    int nrows;  /* How many rows are being used in multiline mode (>= 1) */
+
    int rpos;   /* The current row containing the cursor - multiline mode only */
+
    int colsright; /* refreshLine() cached cols for insert_char() optimisation */
+
    int colsleft;  /* refreshLine() cached cols for remove_char() optimisation */
+
    const char *prompt;
+
    stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
+
    stringbuf *output;  /* used only during refreshLine() - output accumulator */
+
#if defined(USE_TERMIOS)
+
    int fd;     /* Terminal fd */
+
#elif defined(USE_WINCONSOLE)
+
    HANDLE outh; /* Console output handle */
+
    HANDLE inh; /* Console input handle */
+
    int rows;   /* Screen rows */
+
    int x;      /* Current column during output */
+
    int y;      /* Current row */
+
#ifdef USE_UTF8
+
    #define UBUF_MAX_CHARS 132
+
    WORD ubuf[UBUF_MAX_CHARS + 1];  /* Accumulates utf16 output - one extra for final surrogate pairs */
+
    int ubuflen;      /* length used in ubuf */
+
    int ubufcols;     /* how many columns are represented by the chars in ubuf? */
+
#endif
+
#endif
};

-
static void linenoiseAtExit(void);
-
int linenoiseHistoryAdd(const char *line);
-
static void refreshLine(struct linenoiseState *l);
-

-
/* Debugging macro. */
-
#if 0
-
FILE *lndebug_fp = NULL;
-
#define lndebug(...) \
-
    do { \
-
        if (lndebug_fp == NULL) { \
-
            lndebug_fp = fopen("/tmp/lndebug.txt","a"); \
-
            fprintf(lndebug_fp, \
-
            "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \
-
            (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \
-
            (int)l->maxrows,old_rows); \
-
        } \
-
        fprintf(lndebug_fp, ", " __VA_ARGS__); \
-
        fflush(lndebug_fp); \
-
    } while (0)
+
static int fd_read(struct current *current);
+
static int getWindowSize(struct current *current);
+
static void cursorDown(struct current *current, int n);
+
static void cursorUp(struct current *current, int n);
+
static void eraseEol(struct current *current);
+
static void refreshLine(struct current *current);
+
static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos);
+
static void setCursorPos(struct current *current, int x);
+
static void setOutputHighlight(struct current *current, const int *props, int nprops);
+
static void set_current(struct current *current, const char *str);
+

+
static int fd_isatty(struct current *current)
+
{
+
#ifdef USE_TERMIOS
+
    return isatty(current->fd);
#else
-
#define lndebug(fmt, ...)
+
    (void)current;
+
    return 0;
#endif
+
}

-
/* ======================= Low level terminal handling ====================== */
+
void linenoiseHistoryFree(void) {
+
    if (history) {
+
        int j;

-
/* Enable "mask mode". When it is enabled, instead of the input that
-
 * the user is typing, the terminal will just display a corresponding
-
 * number of asterisks, like "****". This is useful for passwords and other
-
 * secrets that should not be displayed. */
-
void linenoiseMaskModeEnable(void) {
-
    maskmode = 1;
+
        for (j = 0; j < history_len; j++)
+
            free(history[j]);
+
        free(history);
+
        history = NULL;
+
        history_len = 0;
+
    }
}

-
/* Disable mask mode. */
-
void linenoiseMaskModeDisable(void) {
-
    maskmode = 0;
+
typedef enum {
+
    EP_START,   /* looking for ESC */
+
    EP_ESC,     /* looking for [ */
+
    EP_DIGITS,  /* parsing digits */
+
    EP_PROPS,   /* parsing digits or semicolons */
+
    EP_END,     /* ok */
+
    EP_ERROR,   /* error */
+
} ep_state_t;
+

+
struct esc_parser {
+
    ep_state_t state;
+
    int props[5];   /* properties are stored here */
+
    int maxprops;   /* size of the props[] array */
+
    int numprops;   /* number of properties found */
+
    int termchar;   /* terminator char, or 0 for any alpha */
+
    int current;    /* current (partial) property value */
+
};
+

+
/**
+
 * Initialise the escape sequence parser at *parser.
+
 *
+
 * If termchar is 0 any alpha char terminates ok. Otherwise only the given
+
 * char terminates successfully.
+
 * Run the parser state machine with calls to parseEscapeSequence() for each char.
+
 */
+
static void initParseEscapeSeq(struct esc_parser *parser, int termchar)
+
{
+
    parser->state = EP_START;
+
    parser->maxprops = sizeof(parser->props) / sizeof(*parser->props);
+
    parser->numprops = 0;
+
    parser->current = 0;
+
    parser->termchar = termchar;
}

-
/* Set if to use or not the multi line mode. */
-
void linenoiseSetMultiLine(int ml) {
-
    mlmode = ml;
+
/**
+
 * Pass character 'ch' into the state machine to parse:
+
 *   'ESC' '[' <digits> (';' <digits>)* <termchar>
+
 *
+
 * The first character must be ESC.
+
 * Returns the current state. The state machine is done when it returns either EP_END
+
 * or EP_ERROR.
+
 *
+
 * On EP_END, the "property/attribute" values can be read from parser->props[]
+
 * of length parser->numprops.
+
 */
+
static int parseEscapeSequence(struct esc_parser *parser, int ch)
+
{
+
    switch (parser->state) {
+
        case EP_START:
+
            parser->state = (ch == '\x1b') ? EP_ESC : EP_ERROR;
+
            break;
+
        case EP_ESC:
+
            parser->state = (ch == '[') ? EP_DIGITS : EP_ERROR;
+
            break;
+
        case EP_PROPS:
+
            if (ch == ';') {
+
                parser->state = EP_DIGITS;
+
donedigits:
+
                if (parser->numprops + 1 < parser->maxprops) {
+
                    parser->props[parser->numprops++] = parser->current;
+
                    parser->current = 0;
+
                }
+
                break;
+
            }
+
            /* fall through */
+
        case EP_DIGITS:
+
            if (ch >= '0' && ch <= '9') {
+
                parser->current = parser->current * 10 + (ch - '0');
+
                parser->state = EP_PROPS;
+
                break;
+
            }
+
            /* must be terminator */
+
            if (parser->termchar != ch) {
+
                if (parser->termchar != 0 || !((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))) {
+
                    parser->state = EP_ERROR;
+
                    break;
+
                }
+
            }
+
            parser->state = EP_END;
+
            goto donedigits;
+
        case EP_END:
+
            parser->state = EP_ERROR;
+
            break;
+
        case EP_ERROR:
+
            break;
+
    }
+
    return parser->state;
+
}
+

+
/*#define DEBUG_REFRESHLINE*/
+

+
#ifdef DEBUG_REFRESHLINE
+
#define DRL(ARGS...) fprintf(dfh, ARGS)
+
static FILE *dfh;
+

+
static void DRL_CHAR(int ch)
+
{
+
    if (ch < ' ') {
+
        DRL("^%c", ch + '@');
+
    }
+
    else if (ch > 127) {
+
        DRL("\\u%04x", ch);
+
    }
+
    else {
+
        DRL("%c", ch);
+
    }
}
+
static void DRL_STR(const char *str)
+
{
+
    while (*str) {
+
        int ch;
+
        int n = utf8_tounicode(str, &ch);
+
        str += n;
+
        DRL_CHAR(ch);
+
    }
+
}
+
#else
+
#define DRL(...)
+
#define DRL_CHAR(ch)
+
#define DRL_STR(str)
+
#endif
+

+
#if defined(USE_WINCONSOLE)
+
#include "linenoise-win32.c"
+
#endif
+

+
#if defined(USE_TERMIOS)
+
static void linenoiseAtExit(void);
+
static struct termios orig_termios; /* in order to restore at exit */
+
static int rawmode = 0; /* for atexit() function to check if restore is needed*/
+
static int atexit_registered = 0; /* register atexit just 1 time */
+

+
static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL};

-
/* Return true if the terminal name is in the list of terminals we know are
-
 * not able to understand basic escape sequences. */
static int isUnsupportedTerm(void) {
    char *term = getenv("TERM");
-
    int j;

-
    if (term == NULL) return 0;
-
    for (j = 0; unsupported_term[j]; j++)
-
        if (!strcasecmp(term,unsupported_term[j])) return 1;
+
    if (term) {
+
        int j;
+
        for (j = 0; unsupported_term[j]; j++) {
+
            if (strcmp(term, unsupported_term[j]) == 0) {
+
                return 1;
+
            }
+
        }
+
    }
    return 0;
}

-
/* Raw mode: 1960 magic shit. */
-
static int enableRawMode(int fd) {
+
static int enableRawMode(struct current *current) {
    struct termios raw;

-
    if (!isatty(STDIN_FILENO)) goto fatal;
+
    current->fd = STDIN_FILENO;
+
    current->cols = 0;
+

+
    if (!isatty(current->fd) || isUnsupportedTerm() ||
+
        tcgetattr(current->fd, &orig_termios) == -1) {
+
fatal:
+
        errno = ENOTTY;
+
        return -1;
+
    }
+

    if (!atexit_registered) {
        atexit(linenoiseAtExit);
        atexit_registered = 1;
    }
-
    if (tcgetattr(fd,&orig_termios) == -1) goto fatal;

    raw = orig_termios;  /* modify the original mode */
    /* input modes: no break, no CR to NL, no parity check, no strip char,
     * no start/stop output control. */
    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
-
    /* output modes - disable post processing */
-
    raw.c_oflag &= ~(OPOST);
+
    /* output modes - actually, no need to disable post processing */
+
    /*raw.c_oflag &= ~(OPOST);*/
    /* control modes - set 8 bit chars */
    raw.c_cflag |= (CS8);
    /* local modes - choing off, canonical off, no extended functions,
@@ -255,918 +427,1564 @@ static int enableRawMode(int fd) {
    raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */

    /* put terminal in raw mode after flushing */
-
    if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal;
+
    if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) {
+
        goto fatal;
+
    }
    rawmode = 1;
    return 0;
-

-
fatal:
-
    errno = ENOTTY;
-
    return -1;
}

-
static void disableRawMode(int fd) {
+
static void disableRawMode(struct current *current) {
    /* Don't even check the return value as it's too late. */
-
    if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)
+
    if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1)
        rawmode = 0;
}

-
/* Use the ESC [6n escape sequence to query the horizontal cursor position
-
 * and return it. On error -1 is returned, on success the position of the
-
 * cursor. */
-
static int getCursorPosition(int ifd, int ofd) {
-
    char buf[32];
-
    int cols, rows;
-
    unsigned int i = 0;
+
/* At exit we'll try to fix the terminal to the initial conditions. */
+
static void linenoiseAtExit(void) {
+
    if (rawmode) {
+
        tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios);
+
    }
+
    linenoiseHistoryFree();
+
}
+

+
/* gcc/glibc insists that we care about the return code of write!
+
 * Clarification: This means that a void-cast like "(void) (EXPR)"
+
 * does not work.
+
 */
+
#define IGNORE_RC(EXPR) if (EXPR) {}
+

+
/**
+
 * Output bytes directly, or accumulate output (if current->output is set)
+
 */
+
static void outputChars(struct current *current, const char *buf, int len)
+
{
+
    if (len < 0) {
+
        len = strlen(buf);
+
    }
+
    if (current->output) {
+
        sb_append_len(current->output, buf, len);
+
    }
+
    else {
+
        IGNORE_RC(write(current->fd, buf, len));
+
    }
+
}
+

+
/* Like outputChars, but using printf-style formatting
+
 */
+
static void outputFormatted(struct current *current, const char *format, ...)
+
{
+
    va_list args;
+
    char buf[64];
+
    int n;
+

+
    va_start(args, format);
+
    n = vsnprintf(buf, sizeof(buf), format, args);
+
    /* This will never happen because we are sure to use outputFormatted() only for short sequences */
+
    assert(n < (int)sizeof(buf));
+
    va_end(args);
+
    outputChars(current, buf, n);
+
}

-
    /* Report cursor location */
-
    if (write(ofd, "\x1b[6n", 4) != 4) return -1;
+
static void cursorToLeft(struct current *current)
+
{
+
    outputChars(current, "\r", -1);
+
}

-
    /* Read the response: ESC [ rows ; cols R */
-
    while (i < sizeof(buf)-1) {
-
        if (read(ifd,buf+i,1) != 1) break;
-
        if (buf[i] == 'R') break;
-
        i++;
+
static void setOutputHighlight(struct current *current, const int *props, int nprops)
+
{
+
    outputChars(current, "\x1b[", -1);
+
    while (nprops--) {
+
        outputFormatted(current, "%d%c", *props, (nprops == 0) ? 'm' : ';');
+
        props++;
+
    }
+
}
+

+
static void eraseEol(struct current *current)
+
{
+
    outputChars(current, "\x1b[0K", -1);
+
}
+

+
static void setCursorPos(struct current *current, int x)
+
{
+
    if (x == 0) {
+
        cursorToLeft(current);
+
    }
+
    else {
+
        outputFormatted(current, "\r\x1b[%dC", x);
+
    }
+
}
+

+
static void cursorUp(struct current *current, int n)
+
{
+
    if (n) {
+
        outputFormatted(current, "\x1b[%dA", n);
+
    }
+
}
+

+
static void cursorDown(struct current *current, int n)
+
{
+
    if (n) {
+
        outputFormatted(current, "\x1b[%dB", n);
+
    }
+
}
+

+
void linenoiseClearScreen(void)
+
{
+
    IGNORE_RC(write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7));
+
}
+

+
/**
+
 * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
+
 *
+
 * A timeout of -1 means to wait forever.
+
 *
+
 * Returns -1 if no char is received within the time or an error occurs.
+
 */
+
static int fd_read_char(int fd, int timeout)
+
{
+
    struct pollfd p;
+
    unsigned char c;
+

+
    p.fd = fd;
+
    p.events = POLLIN;
+

+
    if (poll(&p, 1, timeout) == 0) {
+
        /* timeout */
+
        return -1;
+
    }
+
    if (read(fd, &c, 1) != 1) {
+
        return -1;
+
    }
+
    return c;
+
}
+

+
/**
+
 * Reads a complete utf-8 character
+
 * and returns the unicode value, or -1 on error.
+
 */
+
static int fd_read(struct current *current)
+
{
+
#ifdef USE_UTF8
+
    char buf[MAX_UTF8_LEN];
+
    int n;
+
    int i;
+
    int c;
+

+
    if (read(current->fd, &buf[0], 1) != 1) {
+
        return -1;
+
    }
+
    n = utf8_charlen(buf[0]);
+
    if (n < 1) {
+
        return -1;
+
    }
+
    for (i = 1; i < n; i++) {
+
        if (read(current->fd, &buf[i], 1) != 1) {
+
            return -1;
+
        }
    }
-
    buf[i] = '\0';
+
    /* decode and return the character */
+
    utf8_tounicode(buf, &c);
+
    return c;
+
#else
+
    return fd_read_char(current->fd, -1);
+
#endif
+
}
+


-
    /* Parse it. */
-
    if (buf[0] != ESC || buf[1] != '[') return -1;
-
    if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
-
    return cols;
+
/**
+
 * Stores the current cursor column in '*cols'.
+
 * Returns 1 if OK, or 0 if failed to determine cursor pos.
+
 */
+
static int queryCursor(struct current *current, int* cols)
+
{
+
    struct esc_parser parser;
+
    int ch;
+

+
    /* Should not be buffering this output, it needs to go immediately */
+
    assert(current->output == NULL);
+

+
    /* control sequence - report cursor location */
+
    outputChars(current, "\x1b[6n", -1);
+

+
    /* Parse the response: ESC [ rows ; cols R */
+
    initParseEscapeSeq(&parser, 'R');
+
    while ((ch = fd_read_char(current->fd, 100)) > 0) {
+
        switch (parseEscapeSequence(&parser, ch)) {
+
            default:
+
                continue;
+
            case EP_END:
+
                if (parser.numprops == 2 && parser.props[1] < 1000) {
+
                    *cols = parser.props[1];
+
                    return 1;
+
                }
+
                break;
+
            case EP_ERROR:
+
                break;
+
        }
+
        /* failed */
+
        break;
+
    }
+
    return 0;
}

-
/* Try to get the number of columns in the current terminal, or assume 80
-
 * if it fails. */
-
static int getColumns(int ifd, int ofd) {
+
/**
+
 * Updates current->cols with the current window size (width)
+
 */
+
static int getWindowSize(struct current *current)
+
{
    struct winsize ws;

-
    if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
-
        /* ioctl() failed. Try to query the terminal itself. */
-
        int start, cols;
-

-
        /* Get the initial position so we can restore it later. */
-
        start = getCursorPosition(ifd,ofd);
-
        if (start == -1) goto failed;
-

-
        /* Go to right margin and get position. */
-
        if (write(ofd,"\x1b[999C",6) != 6) goto failed;
-
        cols = getCursorPosition(ifd,ofd);
-
        if (cols == -1) goto failed;
-

-
        /* Restore position. */
-
        if (cols > start) {
-
            char seq[32];
-
            snprintf(seq,32,"\x1b[%dD",cols-start);
-
            if (write(ofd,seq,strlen(seq)) == -1) {
-
                /* Can't recover... */
+
    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) {
+
        current->cols = ws.ws_col;
+
        return 0;
+
    }
+

+
    /* Failed to query the window size. Perhaps we are on a serial terminal.
+
     * Try to query the width by sending the cursor as far to the right
+
     * and reading back the cursor position.
+
     * Note that this is only done once per call to linenoise rather than
+
     * every time the line is refreshed for efficiency reasons.
+
     *
+
     * In more detail, we:
+
     * (a) request current cursor position,
+
     * (b) move cursor far right,
+
     * (c) request cursor position again,
+
     * (d) at last move back to the old position.
+
     * This gives us the width without messing with the externally
+
     * visible cursor position.
+
     */
+

+
    if (current->cols == 0) {
+
        int here;
+

+
        /* If anything fails => default 80 */
+
        current->cols = 80;
+

+
        /* (a) */
+
        if (queryCursor (current, &here)) {
+
            /* (b) */
+
            setCursorPos(current, 999);
+

+
            /* (c). Note: If (a) succeeded, then (c) should as well.
+
             * For paranoia we still check and have a fallback action
+
             * for (d) in case of failure..
+
             */
+
            if (queryCursor (current, &current->cols)) {
+
                /* (d) Reset the cursor back to the original location. */
+
                if (current->cols > here) {
+
                    setCursorPos(current, here);
+
                }
            }
        }
-
        return cols;
-
    } else {
-
        return ws.ws_col;
    }

-
failed:
-
    return 80;
+
    return 0;
+
}
+

+
/**
+
 * If CHAR_ESCAPE was received, reads subsequent
+
 * chars to determine if this is a known special key.
+
 *
+
 * Returns SPECIAL_NONE if unrecognised, or -1 if EOF.
+
 *
+
 * If no additional char is received within a short time,
+
 * CHAR_ESCAPE is returned.
+
 */
+
static int check_special(int fd)
+
{
+
    int c = fd_read_char(fd, 50);
+
    int c2;
+

+
    if (c < 0) {
+
        return CHAR_ESCAPE;
+
    }
+
    else if (c >= 'a' && c <= 'z') {
+
        /* esc-a => meta-a */
+
        return meta(c);
+
    }
+

+
    c2 = fd_read_char(fd, 50);
+
    if (c2 < 0) {
+
        return c2;
+
    }
+
    if (c == '[' || c == 'O') {
+
        /* Potential arrow key */
+
        switch (c2) {
+
            case 'A':
+
                return SPECIAL_UP;
+
            case 'B':
+
                return SPECIAL_DOWN;
+
            case 'C':
+
                return SPECIAL_RIGHT;
+
            case 'D':
+
                return SPECIAL_LEFT;
+
            case 'F':
+
                return SPECIAL_END;
+
            case 'H':
+
                return SPECIAL_HOME;
+
        }
+
    }
+
    if (c == '[' && c2 >= '1' && c2 <= '8') {
+
        /* extended escape */
+
        c = fd_read_char(fd, 50);
+
        if (c == '~') {
+
            switch (c2) {
+
                case '2':
+
                    return SPECIAL_INSERT;
+
                case '3':
+
                    return SPECIAL_DELETE;
+
                case '5':
+
                    return SPECIAL_PAGE_UP;
+
                case '6':
+
                    return SPECIAL_PAGE_DOWN;
+
                case '7':
+
                    return SPECIAL_HOME;
+
                case '8':
+
                    return SPECIAL_END;
+
            }
+
        }
+
        while (c != -1 && c != '~') {
+
            /* .e.g \e[12~ or '\e[11;2~   discard the complete sequence */
+
            c = fd_read_char(fd, 50);
+
        }
+
    }
+

+
    return SPECIAL_NONE;
+
}
+
#endif
+

+
static void clearOutputHighlight(struct current *current)
+
{
+
    int nohighlight = 0;
+
    setOutputHighlight(current, &nohighlight, 1);
+
}
+

+
static void outputControlChar(struct current *current, char ch)
+
{
+
    int reverse = 7;
+
    setOutputHighlight(current, &reverse, 1);
+
    outputChars(current, "^", 1);
+
    outputChars(current, &ch, 1);
+
    clearOutputHighlight(current);
}

-
/* Clear the screen. Used to handle ctrl+l */
-
void linenoiseClearScreen(void) {
-
    if (write(STDOUT_FILENO,"\x1b[H\x1b[2J",7) <= 0) {
-
        /* nothing to do, just to avoid warning. */
+
#ifndef utf8_getchars
+
static int utf8_getchars(char *buf, int c)
+
{
+
#ifdef USE_UTF8
+
    return utf8_fromunicode(buf, c);
+
#else
+
    *buf = c;
+
    return 1;
+
#endif
+
}
+
#endif
+

+
/**
+
 * Returns the unicode character at the given offset,
+
 * or -1 if none.
+
 */
+
static int get_char(struct current *current, int pos)
+
{
+
    if (pos >= 0 && pos < sb_chars(current->buf)) {
+
        int c;
+
        int i = utf8_index(sb_str(current->buf), pos);
+
        (void)utf8_tounicode(sb_str(current->buf) + i, &c);
+
        return c;
+
    }
+
    return -1;
+
}
+

+
static int char_display_width(int ch)
+
{
+
    if (ch < ' ') {
+
        /* control chars take two positions */
+
        return 2;
+
    }
+
    else {
+
        return utf8_width(ch);
    }
}

-
/* Beep, used for completion when there is nothing to complete or when all
-
 * the choices were already shown. */
-
static void linenoiseBeep(void) {
+
#ifndef NO_COMPLETION
+
static linenoiseCompletionCallback *completionCallback = NULL;
+
static void *completionUserdata = NULL;
+
static int showhints = 1;
+
static linenoiseHintsCallback *hintsCallback = NULL;
+
static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
+
static void *hintsUserdata = NULL;
+

+
static void beep(void) {
+
#ifdef USE_TERMIOS
    fprintf(stderr, "\x7");
    fflush(stderr);
+
#endif
}

-
/* ============================== Completion ================================ */
-

-
/* Free a list of completion option populated by linenoiseAddCompletion(). */
static void freeCompletions(linenoiseCompletions *lc) {
    size_t i;
    for (i = 0; i < lc->len; i++)
        free(lc->cvec[i]);
-
    if (lc->cvec != NULL)
-
        free(lc->cvec);
+
    free(lc->cvec);
}

-
/* This is an helper function for linenoiseEdit() and is called when the
-
 * user types the <tab> key in order to complete the string currently in the
-
 * input.
-
 *
-
 * The state of the editing is encapsulated into the pointed linenoiseState
-
 * structure as described in the structure definition. */
-
static int completeLine(struct linenoiseState *ls) {
+
static int completeLine(struct current *current) {
    linenoiseCompletions lc = { 0, NULL };
-
    int nread, nwritten;
-
    char c = 0;
+
    int c = 0;

-
    completionCallback(ls->buf,&lc);
+
    completionCallback(sb_str(current->buf),&lc,completionUserdata);
    if (lc.len == 0) {
-
        linenoiseBeep();
+
        beep();
    } else {
        size_t stop = 0, i = 0;

-
        while(!stop) {
-
            /* Show completion or original buffer */
-
            if (i < lc.len) {
-
                struct linenoiseState saved = *ls;
-

-
                ls->len = ls->pos = strlen(lc.cvec[i]);
-
                ls->buf = lc.cvec[i];
-
                refreshLine(ls);
-
                ls->len = saved.len;
-
                ls->pos = saved.pos;
-
                ls->buf = saved.buf;
-
            } else {
-
                refreshLine(ls);
+
        while(!stop) {
+
            /* Show completion or original buffer */
+
            if (i < lc.len) {
+
                int chars = utf8_strlen(lc.cvec[i], -1);
+
                refreshLineAlt(current, current->prompt, lc.cvec[i], chars);
+
            } else {
+
                refreshLine(current);
+
            }
+

+
            c = fd_read(current);
+
            if (c == -1) {
+
                break;
+
            }
+

+
            switch(c) {
+
                case '\t': /* tab */
+
                    i = (i+1) % (lc.len+1);
+
                    if (i == lc.len) beep();
+
                    break;
+
                case CHAR_ESCAPE: /* escape */
+
                    /* Re-show original buffer */
+
                    if (i < lc.len) {
+
                        refreshLine(current);
+
                    }
+
                    stop = 1;
+
                    break;
+
                default:
+
                    /* Update buffer and return */
+
                    if (i < lc.len) {
+
                        set_current(current,lc.cvec[i]);
+
                    }
+
                    stop = 1;
+
                    break;
+
            }
+
        }
+
    }
+

+
    freeCompletions(&lc);
+
    return c; /* Return last read character */
+
}
+

+
/* Register a callback function to be called for tab-completion.
+
   Returns the prior callback so that the caller may (if needed)
+
   restore it when done. */
+
linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn, void *userdata) {
+
    linenoiseCompletionCallback * old = completionCallback;
+
    completionCallback = fn;
+
    completionUserdata = userdata;
+
    return old;
+
}
+

+
void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
+
    lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1));
+
    lc->cvec[lc->len++] = strdup(str);
+
}
+

+
void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata)
+
{
+
    hintsCallback = callback;
+
    hintsUserdata = userdata;
+
}
+

+
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback)
+
{
+
    freeHintsCallback = callback;
+
}
+

+
#endif
+

+

+
static const char *reduceSingleBuf(const char *buf, int availcols, int *cursor_pos)
+
{
+
    /* We have availcols columns available.
+
     * If necessary, strip chars off the front of buf until *cursor_pos
+
     * fits within availcols
+
     */
+
    int needcols = 0;
+
    int pos = 0;
+
    int new_cursor_pos = *cursor_pos;
+
    const char *pt = buf;
+

+
    DRL("reduceSingleBuf: availcols=%d, cursor_pos=%d\n", availcols, *cursor_pos);
+

+
    while (*pt) {
+
        int ch;
+
        int n = utf8_tounicode(pt, &ch);
+
        pt += n;
+

+
        needcols += char_display_width(ch);
+

+
        /* If we need too many cols, strip
+
         * chars off the front of buf to make it fit.
+
         * We keep 3 extra cols to the right of the cursor.
+
         * 2 for possible wide chars, 1 for the last column that
+
         * can't be used.
+
         */
+
        while (needcols >= availcols - 3) {
+
            n = utf8_tounicode(buf, &ch);
+
            buf += n;
+
            needcols -= char_display_width(ch);
+
            DRL_CHAR(ch);
+

+
            /* and adjust the apparent cursor position */
+
            new_cursor_pos--;
+

+
            if (buf == pt) {
+
                /* can't remove more than this */
+
                break;
+
            }
+
        }
+

+
        if (pos++ == *cursor_pos) {
+
            break;
+
        }
+

+
    }
+
    DRL("<snip>");
+
    DRL_STR(buf);
+
    DRL("\nafter reduce, needcols=%d, new_cursor_pos=%d\n", needcols, new_cursor_pos);
+

+
    /* Done, now new_cursor_pos contains the adjusted cursor position
+
     * and buf points to he adjusted start
+
     */
+
    *cursor_pos = new_cursor_pos;
+
    return buf;
+
}
+

+
static int mlmode = 0;
+

+
void linenoiseSetMultiLine(int enableml)
+
{
+
    mlmode = enableml;
+
}
+

+
/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
+
 * to the right of the prompt.
+
 * Returns 1 if a hint was shown, or 0 if not
+
 * If 'display' is 0, does no output. Just returns the appropriate return code.
+
 */
+
static int refreshShowHints(struct current *current, const char *buf, int availcols, int display)
+
{
+
    int rc = 0;
+
    if (showhints && hintsCallback && availcols > 0) {
+
        int bold = 0;
+
        int color = -1;
+
        char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
+
        if (hint) {
+
            rc = 1;
+
            if (display) {
+
                const char *pt;
+
                if (bold == 1 && color == -1) color = 37;
+
                if (bold || color > 0) {
+
                    int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
+
                    setOutputHighlight(current, props, 3);
+
                }
+
                DRL("<hint bold=%d,color=%d>", bold, color);
+
                pt = hint;
+
                while (*pt) {
+
                    int ch;
+
                    int n = utf8_tounicode(pt, &ch);
+
                    int width = char_display_width(ch);
+

+
                    if (width >= availcols) {
+
                        DRL("<hinteol>");
+
                        break;
+
                    }
+
                    DRL_CHAR(ch);
+

+
                    availcols -= width;
+
                    outputChars(current, pt, n);
+
                    pt += n;
+
                }
+
                if (bold || color > 0) {
+
                    clearOutputHighlight(current);
+
                }
+
                /* Call the function to free the hint returned. */
+
                if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
+
            }
+
        }
+
    }
+
    return rc;
+
}
+

+
#ifdef USE_TERMIOS
+
static void refreshStart(struct current *current)
+
{
+
    /* We accumulate all output here */
+
    assert(current->output == NULL);
+
    current->output = sb_alloc();
+
}
+

+
static void refreshEnd(struct current *current)
+
{
+
    /* Output everything at once */
+
    IGNORE_RC(write(current->fd, sb_str(current->output), sb_len(current->output)));
+
    sb_free(current->output);
+
    current->output = NULL;
+
}
+

+
static void refreshStartChars(struct current *current)
+
{
+
    (void)current;
+
}
+

+
static void refreshNewline(struct current *current)
+
{
+
    DRL("<nl>");
+
    outputChars(current, "\n", 1);
+
}
+

+
static void refreshEndChars(struct current *current)
+
{
+
    (void)current;
+
}
+
#endif
+

+
static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos)
+
{
+
    int i;
+
    const char *pt;
+
    int displaycol;
+
    int displayrow;
+
    int visible;
+
    int currentpos;
+
    int notecursor;
+
    int cursorcol = 0;
+
    int cursorrow = 0;
+
    int hint;
+
    struct esc_parser parser;
+

+
#ifdef DEBUG_REFRESHLINE
+
    dfh = fopen("linenoise.debuglog", "a");
+
#endif
+

+
    /* Should intercept SIGWINCH. For now, just get the size every time */
+
    getWindowSize(current);
+

+
    refreshStart(current);
+

+
    DRL("wincols=%d, cursor_pos=%d, nrows=%d, rpos=%d\n", current->cols, cursor_pos, current->nrows, current->rpos);
+

+
    /* Here is the plan:
+
     * (a) move the the bottom row, going down the appropriate number of lines
+
     * (b) move to beginning of line and erase the current line
+
     * (c) go up one line and do the same, until we have erased up to the first row
+
     * (d) output the prompt, counting cols and rows, taking into account escape sequences
+
     * (e) output the buffer, counting cols and rows
+
     *   (e') when we hit the current pos, save the cursor position
+
     * (f) move the cursor to the saved cursor position
+
     * (g) save the current cursor row and number of rows
+
     */
+

+
    /* (a) - The cursor is currently at row rpos */
+
    cursorDown(current, current->nrows - current->rpos - 1);
+
    DRL("<cud=%d>", current->nrows - current->rpos - 1);
+

+
    /* (b), (c) - Erase lines upwards until we get to the first row */
+
    for (i = 0; i < current->nrows; i++) {
+
        if (i) {
+
            DRL("<cup>");
+
            cursorUp(current, 1);
+
        }
+
        DRL("<clearline>");
+
        cursorToLeft(current);
+
        eraseEol(current);
+
    }
+
    DRL("\n");
+

+
    /* (d) First output the prompt. control sequences don't take up display space */
+
    pt = prompt;
+
    displaycol = 0; /* current display column */
+
    displayrow = 0; /* current display row */
+
    visible = 1;
+

+
    refreshStartChars(current);
+

+
    while (*pt) {
+
        int width;
+
        int ch;
+
        int n = utf8_tounicode(pt, &ch);
+

+
        if (visible && ch == CHAR_ESCAPE) {
+
            /* The start of an escape sequence, so not visible */
+
            visible = 0;
+
            initParseEscapeSeq(&parser, 'm');
+
            DRL("<esc-seq-start>");
+
        }
+

+
        if (ch == '\n' || ch == '\r') {
+
            /* treat both CR and NL the same and force wrap */
+
            refreshNewline(current);
+
            displaycol = 0;
+
            displayrow++;
+
        }
+
        else {
+
            width = visible * utf8_width(ch);
+

+
            displaycol += width;
+
            if (displaycol >= current->cols) {
+
                /* need to wrap to the next line because of newline or if it doesn't fit
+
                 * XXX this is a problem in single line mode
+
                 */
+
                refreshNewline(current);
+
                displaycol = width;
+
                displayrow++;
            }

-
            nread = read(ls->ifd,&c,1);
-
            if (nread <= 0) {
-
                freeCompletions(&lc);
-
                return -1;
+
            DRL_CHAR(ch);
+
#ifdef USE_WINCONSOLE
+
            if (visible) {
+
                outputChars(current, pt, n);
            }
-

-
            switch(c) {
-
                case 9: /* tab */
-
                    i = (i+1) % (lc.len+1);
-
                    if (i == lc.len) linenoiseBeep();
-
                    break;
-
                case 27: /* escape */
-
                    /* Re-show original buffer */
-
                    if (i < lc.len) refreshLine(ls);
-
                    stop = 1;
+
#else
+
            outputChars(current, pt, n);
+
#endif
+
        }
+
        pt += n;
+

+
        if (!visible) {
+
            switch (parseEscapeSequence(&parser, ch)) {
+
                case EP_END:
+
                    visible = 1;
+
                    setOutputHighlight(current, parser.props, parser.numprops);
+
                    DRL("<esc-seq-end,numprops=%d>", parser.numprops);
                    break;
-
                default:
-
                    /* Update buffer and return */
-
                    if (i < lc.len) {
-
                        nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]);
-
                        ls->len = ls->pos = nwritten;
-
                    }
-
                    stop = 1;
+
                case EP_ERROR:
+
                    DRL("<esc-seq-err>");
+
                    visible = 1;
                    break;
            }
        }
    }

-
    freeCompletions(&lc);
-
    return c; /* Return last read character */
-
}
+
    /* Now we are at the first line with all lines erased */
+
    DRL("\nafter prompt: displaycol=%d, displayrow=%d\n", displaycol, displayrow);

-
/* Register a callback function to be called for tab-completion. */
-
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
-
    completionCallback = fn;
-
}

-
/* Register a hits function to be called to show hits to the user at the
-
 * right of the prompt. */
-
void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {
-
    hintsCallback = fn;
-
}
+
    /* (e) output the buffer, counting cols and rows */
+
    if (mlmode == 0) {
+
        /* In this mode we may need to trim chars from the start of the buffer until the
+
         * cursor fits in the window.
+
         */
+
        pt = reduceSingleBuf(buf, current->cols - displaycol, &cursor_pos);
+
    }
+
    else {
+
        pt = buf;
+
    }

-
/* Register a function to free the hints returned by the hints callback
-
 * registered with linenoiseSetHintsCallback(). */
-
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
-
    freeHintsCallback = fn;
-
}
+
    currentpos = 0;
+
    notecursor = -1;

-
/* This function is used by the callback function registered by the user
-
 * in order to add completion options given the input string when the
-
 * user typed <tab>. See the example.c source code for a very easy to
-
 * understand example. */
-
void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
-
    size_t len = strlen(str);
-
    char *copy, **cvec;
-

-
    copy = malloc(len+1);
-
    if (copy == NULL) return;
-
    memcpy(copy,str,len+1);
-
    cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
-
    if (cvec == NULL) {
-
        free(copy);
-
        return;
-
    }
-
    lc->cvec = cvec;
-
    lc->cvec[lc->len++] = copy;
-
}
-

-
/* =========================== Line editing ================================= */
-

-
/* We define a very simple "append buffer" structure, that is an heap
-
 * allocated string where we can append to. This is useful in order to
-
 * write all the escape sequences in a buffer and flush them to the standard
-
 * output in a single call, to avoid flickering effects. */
-
struct abuf {
-
    char *b;
-
    int len;
-
};
+
    while (*pt) {
+
        int ch;
+
        int n = utf8_tounicode(pt, &ch);
+
        int width = char_display_width(ch);

-
static void abInit(struct abuf *ab) {
-
    ab->b = NULL;
-
    ab->len = 0;
-
}
+
        if (currentpos == cursor_pos) {
+
            /* (e') wherever we output this character is where we want the cursor */
+
            notecursor = 1;
+
        }

-
static void abAppend(struct abuf *ab, const char *s, int len) {
-
    char *new = realloc(ab->b,ab->len+len);
+
        if (displaycol + width >= current->cols) {
+
            if (mlmode == 0) {
+
                /* In single line mode stop once we print as much as we can on one line */
+
                DRL("<slmode>");
+
                break;
+
            }
+
            /* need to wrap to the next line since it doesn't fit */
+
            refreshNewline(current);
+
            displaycol = 0;
+
            displayrow++;
+
        }

-
    if (new == NULL) return;
-
    memcpy(new+ab->len,s,len);
-
    ab->b = new;
-
    ab->len += len;
-
}
+
        if (notecursor == 1) {
+
            /* (e') Save this position as the current cursor position */
+
            cursorcol = displaycol;
+
            cursorrow = displayrow;
+
            notecursor = 0;
+
            DRL("<cursor>");
+
        }

-
static void abFree(struct abuf *ab) {
-
    free(ab->b);
-
}
+
        displaycol += width;

-
/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
-
 * to the right of the prompt. */
-
void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
-
    char seq[64];
-
    if (hintsCallback && plen+l->len < l->cols) {
-
        int color = -1, bold = 0;
-
        char *hint = hintsCallback(l->buf,&color,&bold);
-
        if (hint) {
-
            int hintlen = strlen(hint);
-
            int hintmaxlen = l->cols-(plen+l->len);
-
            if (hintlen > hintmaxlen) hintlen = hintmaxlen;
-
            if (bold == 1 && color == -1) color = 37;
-
            if (color != -1 || bold != 0)
-
                snprintf(seq,64,"\033[%d;%d;49m",bold,color);
-
            else
-
                seq[0] = '\0';
-
            abAppend(ab,seq,strlen(seq));
-
            abAppend(ab,hint,hintlen);
-
            if (color != -1 || bold != 0)
-
                abAppend(ab,"\033[0m",4);
-
            /* Call the function to free the hint returned. */
-
            if (freeHintsCallback) freeHintsCallback(hint);
+
        if (ch < ' ') {
+
            outputControlChar(current, ch + '@');
+
        }
+
        else {
+
            outputChars(current, pt, n);
+
        }
+
        DRL_CHAR(ch);
+
        if (width != 1) {
+
            DRL("<w=%d>", width);
        }
-
    }
-
}

-
/* Single line low level line refresh.
-
 *
-
 * Rewrite the currently edited line accordingly to the buffer content,
-
 * cursor position, and number of columns of the terminal. */
-
static void refreshSingleLine(struct linenoiseState *l) {
-
    char seq[64];
-
    size_t plen = strlen(l->prompt);
-
    int fd = l->ofd;
-
    char *buf = l->buf;
-
    size_t len = l->len;
-
    size_t pos = l->pos;
-
    struct abuf ab;
-

-
    while((plen+pos) >= l->cols) {
-
        buf++;
-
        len--;
-
        pos--;
-
    }
-
    while (plen+len > l->cols) {
-
        len--;
-
    }
-

-
    abInit(&ab);
-
    /* Cursor to left edge */
-
    snprintf(seq,64,"\r");
-
    abAppend(&ab,seq,strlen(seq));
-
    /* Write the prompt and the current buffer content */
-
    abAppend(&ab,l->prompt,strlen(l->prompt));
-
    if (maskmode == 1) {
-
        while (len--) abAppend(&ab,"*",1);
-
    } else {
-
        abAppend(&ab,buf,len);
+
        pt += n;
+
        currentpos++;
    }
-
    /* Show hits if any. */
-
    refreshShowHints(&ab,l,plen);
-
    /* Erase to right */
-
    snprintf(seq,64,"\x1b[0K");
-
    abAppend(&ab,seq,strlen(seq));
-
    /* Move cursor to original position. */
-
    snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen));
-
    abAppend(&ab,seq,strlen(seq));
-
    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
-
    abFree(&ab);
-
}

-
/* Multi line low level line refresh.
-
 *
-
 * Rewrite the currently edited line accordingly to the buffer content,
-
 * cursor position, and number of columns of the terminal. */
-
static void refreshMultiLine(struct linenoiseState *l) {
-
    char seq[64];
-
    int plen = strlen(l->prompt);
-
    int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */
-
    int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */
-
    int rpos2; /* rpos after refresh. */
-
    int col; /* colum position, zero-based. */
-
    int old_rows = l->maxrows;
-
    int fd = l->ofd, j;
-
    struct abuf ab;
-

-
    /* Update maxrows if needed. */
-
    if (rows > (int)l->maxrows) l->maxrows = rows;
-

-
    /* First step: clear all the lines used before. To do so start by
-
     * going to the last row. */
-
    abInit(&ab);
-
    if (old_rows-rpos > 0) {
-
        lndebug("go down %d", old_rows-rpos);
-
        snprintf(seq,64,"\x1b[%dB", old_rows-rpos);
-
        abAppend(&ab,seq,strlen(seq));
-
    }
-

-
    /* Now for every row clear it, go up. */
-
    for (j = 0; j < old_rows-1; j++) {
-
        lndebug("clear+up");
-
        snprintf(seq,64,"\r\x1b[0K\x1b[1A");
-
        abAppend(&ab,seq,strlen(seq));
-
    }
-

-
    /* Clean the top line. */
-
    lndebug("clear");
-
    snprintf(seq,64,"\r\x1b[0K");
-
    abAppend(&ab,seq,strlen(seq));
-

-
    /* Write the prompt and the current buffer content */
-
    abAppend(&ab,l->prompt,strlen(l->prompt));
-
    if (maskmode == 1) {
-
        unsigned int i;
-
        for (i = 0; i < l->len; i++) abAppend(&ab,"*",1);
-
    } else {
-
        abAppend(&ab,l->buf,l->len);
+
    /* If we didn't see the cursor, it is at the current location */
+
    if (notecursor) {
+
        DRL("<cursor>");
+
        cursorcol = displaycol;
+
        cursorrow = displayrow;
    }

-
    /* Show hits if any. */
-
    refreshShowHints(&ab,l,plen);
+
    DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n", displaycol, displayrow, cursorcol, cursorrow);
+

+
    /* (f) show hints */
+
    hint = refreshShowHints(current, buf, current->cols - displaycol, 1);

-
    /* If we are at the very end of the screen with our prompt, we need to
-
     * emit a newline and move the prompt to the first column. */
-
    if (l->pos &&
-
        l->pos == l->len &&
-
        (l->pos+plen) % l->cols == 0)
-
    {
-
        lndebug("<newline>");
-
        abAppend(&ab,"\n",1);
-
        snprintf(seq,64,"\r");
-
        abAppend(&ab,seq,strlen(seq));
-
        rows++;
-
        if (rows > (int)l->maxrows) l->maxrows = rows;
+
    /* Remember how many many cols are available for insert optimisation */
+
    if (prompt == current->prompt && hint == 0) {
+
        current->colsright = current->cols - displaycol;
+
        current->colsleft = displaycol;
    }
+
    else {
+
        /* Can't optimise */
+
        current->colsright = 0;
+
        current->colsleft = 0;
+
    }
+
    DRL("\nafter hints: colsleft=%d, colsright=%d\n\n", current->colsleft, current->colsright);
+

+
    refreshEndChars(current);

-
    /* Move cursor to right position. */
-
    rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */
-
    lndebug("rpos2 %d", rpos2);
+
    /* (g) move the cursor to the correct place */
+
    cursorUp(current, displayrow - cursorrow);
+
    setCursorPos(current, cursorcol);

-
    /* Go up till we reach the expected positon. */
-
    if (rows-rpos2 > 0) {
-
        lndebug("go-up %d", rows-rpos2);
-
        snprintf(seq,64,"\x1b[%dA", rows-rpos2);
-
        abAppend(&ab,seq,strlen(seq));
+
    /* (h) Update the number of rows if larger, but never reduce this */
+
    if (displayrow >= current->nrows) {
+
        current->nrows = displayrow + 1;
    }
+
    /* And remember the row that the cursor is on */
+
    current->rpos = cursorrow;

-
    /* Set column. */
-
    col = (plen+(int)l->pos) % (int)l->cols;
-
    lndebug("set col %d", 1+col);
-
    if (col)
-
        snprintf(seq,64,"\r\x1b[%dC", col);
-
    else
-
        snprintf(seq,64,"\r");
-
    abAppend(&ab,seq,strlen(seq));
+
    refreshEnd(current);

-
    lndebug("\n");
-
    l->oldpos = l->pos;
+
#ifdef DEBUG_REFRESHLINE
+
    fclose(dfh);
+
#endif
+
}

-
    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
-
    abFree(&ab);
+
static void refreshLine(struct current *current)
+
{
+
    refreshLineAlt(current, current->prompt, sb_str(current->buf), current->pos);
}

-
/* Calls the two low level functions refreshSingleLine() or
-
 * refreshMultiLine() according to the selected mode. */
-
static void refreshLine(struct linenoiseState *l) {
-
    if (mlmode)
-
        refreshMultiLine(l);
-
    else
-
        refreshSingleLine(l);
+
static void set_current(struct current *current, const char *str)
+
{
+
    sb_clear(current->buf);
+
    sb_append(current->buf, str);
+
    current->pos = sb_chars(current->buf);
}

-
/* Insert the character 'c' at cursor current position.
+
/**
+
 * Removes the char at 'pos'.
 *
-
 * On error writing to the terminal -1 is returned, otherwise 0. */
-
int linenoiseEditInsert(struct linenoiseState *l, char c) {
-
    if (l->len < l->buflen) {
-
        if (l->len == l->pos) {
-
            l->buf[l->pos] = c;
-
            l->pos++;
-
            l->len++;
-
            l->buf[l->len] = '\0';
-
            if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
-
                /* Avoid a full update of the line in the
-
                 * trivial case. */
-
                char d = (maskmode==1) ? '*' : c;
-
                if (write(l->ofd,&d,1) == -1) return -1;
-
            } else {
-
                refreshLine(l);
+
 * Returns 1 if the line needs to be refreshed, 2 if not
+
 * and 0 if nothing was removed
+
 */
+
static int remove_char(struct current *current, int pos)
+
{
+
    if (pos >= 0 && pos < sb_chars(current->buf)) {
+
        int offset = utf8_index(sb_str(current->buf), pos);
+
        int nbytes = utf8_index(sb_str(current->buf) + offset, 1);
+
        int rc = 1;
+

+
        /* Now we try to optimise in the simple but very common case that:
+
         * - outputChars() can be used directly (not win32)
+
         * - we are removing the char at EOL
+
         * - the buffer is not empty
+
         * - there are columns available to the left
+
         * - the char being deleted is not a wide or utf-8 character
+
         * - no hints are being shown
+
         */
+
        if (current->output && current->pos == pos + 1 && current->pos == sb_chars(current->buf) && pos > 0) {
+
#ifdef USE_UTF8
+
            /* Could implement utf8_prev_len() but simplest just to not optimise this case */
+
            char last = sb_str(current->buf)[offset];
+
#else
+
            char last = 0;
+
#endif
+
            if (current->colsleft > 0 && (last & 0x80) == 0) {
+
                /* Have cols on the left and not a UTF-8 char or continuation */
+
                /* Yes, can optimise */
+
                current->colsleft--;
+
                current->colsright++;
+
                rc = 2;
+
            }
+
        }
+

+
        sb_delete(current->buf, offset, nbytes);
+

+
        if (current->pos > pos) {
+
            current->pos--;
+
        }
+
        if (rc == 2) {
+
            if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
+
                /* A hint needs to be shown, so can't optimise after all */
+
                rc = 1;
+
            }
+
            else {
+
                /* optimised output */
+
                outputChars(current, "\b \b", 3);
+
            }
+
        }
+
        return rc;
+
        return 1;
+
    }
+
    return 0;
+
}
+

+
/**
+
 * Insert 'ch' at position 'pos'
+
 *
+
 * Returns 1 if the line needs to be refreshed, 2 if not
+
 * and 0 if nothing was inserted (no room)
+
 */
+
static int insert_char(struct current *current, int pos, int ch)
+
{
+
    if (pos >= 0 && pos <= sb_chars(current->buf)) {
+
        char buf[MAX_UTF8_LEN + 1];
+
        int offset = utf8_index(sb_str(current->buf), pos);
+
        int n = utf8_getchars(buf, ch);
+
        int rc = 1;
+

+
        /* null terminate since sb_insert() requires it */
+
        buf[n] = 0;
+

+
        /* Now we try to optimise in the simple but very common case that:
+
         * - outputChars() can be used directly (not win32)
+
         * - we are inserting at EOL
+
         * - there are enough columns available
+
         * - no hints are being shown
+
         */
+
        if (current->output && pos == current->pos && pos == sb_chars(current->buf)) {
+
            int width = char_display_width(ch);
+
            if (current->colsright > width) {
+
                /* Yes, can optimise */
+
                current->colsright -= width;
+
                current->colsleft -= width;
+
                rc = 2;
+
            }
+
        }
+
        sb_insert(current->buf, offset, buf);
+
        if (current->pos >= pos) {
+
            current->pos++;
+
        }
+
        if (rc == 2) {
+
            if (refreshShowHints(current, sb_str(current->buf), current->colsright, 0)) {
+
                /* A hint needs to be shown, so can't optimise after all */
+
                rc = 1;
+
            }
+
            else {
+
                /* optimised output */
+
                outputChars(current, buf, n);
            }
-
        } else {
-
            memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos);
-
            l->buf[l->pos] = c;
-
            l->len++;
-
            l->pos++;
-
            l->buf[l->len] = '\0';
-
            refreshLine(l);
        }
+
        return rc;
    }
    return 0;
}

-
/* Move cursor on the left. */
-
void linenoiseEditMoveLeft(struct linenoiseState *l) {
-
    if (l->pos > 0) {
-
        l->pos--;
-
        refreshLine(l);
+
/**
+
 * Captures up to 'n' characters starting at 'pos' for the cut buffer.
+
 *
+
 * This replaces any existing characters in the cut buffer.
+
 */
+
static void capture_chars(struct current *current, int pos, int nchars)
+
{
+
    if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
+
        int offset = utf8_index(sb_str(current->buf), pos);
+
        int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);
+

+
        if (nbytes > 0) {
+
            if (current->capture) {
+
                sb_clear(current->capture);
+
            }
+
            else {
+
                current->capture = sb_alloc();
+
            }
+
            sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
+
        }
    }
}

-
/* Move cursor on the right. */
-
void linenoiseEditMoveRight(struct linenoiseState *l) {
-
    if (l->pos != l->len) {
-
        l->pos++;
-
        refreshLine(l);
+
/**
+
 * Removes up to 'n' characters at cursor position 'pos'.
+
 *
+
 * Returns 0 if no chars were removed or non-zero otherwise.
+
 */
+
static int remove_chars(struct current *current, int pos, int n)
+
{
+
    int removed = 0;
+

+
    /* First save any chars which will be removed */
+
    capture_chars(current, pos, n);
+

+
    while (n-- && remove_char(current, pos)) {
+
        removed++;
    }
+
    return removed;
}
+
/**
+
 * Inserts the characters (string) 'chars' at the cursor position 'pos'.
+
 *
+
 * Returns 0 if no chars were inserted or non-zero otherwise.
+
 */
+
static int insert_chars(struct current *current, int pos, const char *chars)
+
{
+
    int inserted = 0;

-
/* Move cursor to the start of the line. */
-
void linenoiseEditMoveHome(struct linenoiseState *l) {
-
    if (l->pos != 0) {
-
        l->pos = 0;
-
        refreshLine(l);
+
    while (*chars) {
+
        int ch;
+
        int n = utf8_tounicode(chars, &ch);
+
        if (insert_char(current, pos, ch) == 0) {
+
            break;
+
        }
+
        inserted++;
+
        pos++;
+
        chars += n;
    }
+
    return inserted;
}

-
/* Move cursor to the end of the line. */
-
void linenoiseEditMoveEnd(struct linenoiseState *l) {
-
    if (l->pos != l->len) {
-
        l->pos = l->len;
-
        refreshLine(l);
+
static int skip_space_nonspace(struct current *current, int dir, int check_is_space)
+
{
+
    int moved = 0;
+
    int checkoffset = (dir < 0) ? -1 : 0;
+
    int limit = (dir < 0) ? 0 : sb_chars(current->buf);
+
    while (current->pos != limit && (get_char(current, current->pos + checkoffset) == ' ') == check_is_space) {
+
        current->pos += dir;
+
        moved++;
    }
+
    return moved;
+
}
+

+
static int skip_space(struct current *current, int dir)
+
{
+
    return skip_space_nonspace(current, dir, 1);
+
}
+

+
static int skip_nonspace(struct current *current, int dir)
+
{
+
    return skip_space_nonspace(current, dir, 0);
}

-
/* Substitute the currently edited line with the next or previous history
-
 * entry as specified by 'dir'. */
-
#define LINENOISE_HISTORY_NEXT 0
-
#define LINENOISE_HISTORY_PREV 1
-
void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) {
+
static void set_history_index(struct current *current, int new_index)
+
{
    if (history_len > 1) {
        /* Update the current history entry before to
         * overwrite it with the next one. */
-
        free(history[history_len - 1 - l->history_index]);
-
        history[history_len - 1 - l->history_index] = strdup(l->buf);
+
        free(history[history_len - 1 - history_index]);
+
        history[history_len - 1 - history_index] = strdup(sb_str(current->buf));
        /* Show the new entry */
-
        l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;
-
        if (l->history_index < 0) {
-
            l->history_index = 0;
-
            return;
-
        } else if (l->history_index >= history_len) {
-
            l->history_index = history_len-1;
-
            return;
+
        history_index = new_index;
+
        if (history_index < 0) {
+
            history_index = 0;
+
        } else if (history_index >= history_len) {
+
            history_index = history_len - 1;
+
        } else {
+
            set_current(current, history[history_len - 1 - history_index]);
+
            refreshLine(current);
        }
-
        strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen);
-
        l->buf[l->buflen-1] = '\0';
-
        l->len = l->pos = strlen(l->buf);
-
        refreshLine(l);
    }
}

-
/* Delete the character at the right of the cursor without altering the cursor
-
 * position. Basically this is what happens with the "Delete" keyboard key. */
-
void linenoiseEditDelete(struct linenoiseState *l) {
-
    if (l->len > 0 && l->pos < l->len) {
-
        memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1);
-
        l->len--;
-
        l->buf[l->len] = '\0';
-
        refreshLine(l);
-
    }
-
}
+
/**
+
 * Returns the keycode to process, or 0 if none.
+
 */
+
static int reverseIncrementalSearch(struct current *current)
+
{
+
    /* Display the reverse-i-search prompt and process chars */
+
    char rbuf[50];
+
    char rprompt[80];
+
    int rchars = 0;
+
    int rlen = 0;
+
    int searchpos = history_len - 1;
+
    int c;
+

+
    rbuf[0] = 0;
+
    while (1) {
+
        int n = 0;
+
        const char *p = NULL;
+
        int skipsame = 0;
+
        int searchdir = -1;
+

+
        snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf);
+
        refreshLineAlt(current, rprompt, sb_str(current->buf), current->pos);
+
        c = fd_read(current);
+
        if (c == ctrl('H') || c == CHAR_DELETE) {
+
            if (rchars) {
+
                int p_ind = utf8_index(rbuf, --rchars);
+
                rbuf[p_ind] = 0;
+
                rlen = strlen(rbuf);
+
            }
+
            continue;
+
        }
+
#ifdef USE_TERMIOS
+
        if (c == CHAR_ESCAPE) {
+
            c = check_special(current->fd);
+
        }
+
#endif
+
        if (c == ctrl('R')) {
+
            /* Search for the previous (earlier) match */
+
            if (searchpos > 0) {
+
                searchpos--;
+
            }
+
            skipsame = 1;
+
        }
+
        else if (c == ctrl('S')) {
+
            /* Search for the next (later) match */
+
            if (searchpos < history_len) {
+
                searchpos++;
+
            }
+
            searchdir = 1;
+
            skipsame = 1;
+
        }
+
        else if (c == ctrl('P') || c == SPECIAL_UP) {
+
            /* Exit Ctrl-R mode and go to the previous history line from the current search pos */
+
            set_history_index(current, history_len - searchpos);
+
            c = 0;
+
            break;
+
        }
+
        else if (c == ctrl('N') || c == SPECIAL_DOWN) {
+
            /* Exit Ctrl-R mode and go to the next history line from the current search pos */
+
            set_history_index(current, history_len - searchpos - 2);
+
            c = 0;
+
            break;
+
        }
+
        else if (c >= ' ' && c <= '~') {
+
            /* >= here to allow for null terminator */
+
            if (rlen >= (int)sizeof(rbuf) - MAX_UTF8_LEN) {
+
                continue;
+
            }
+

+
            n = utf8_getchars(rbuf + rlen, c);
+
            rlen += n;
+
            rchars++;
+
            rbuf[rlen] = 0;
+

+
            /* Adding a new char resets the search location */
+
            searchpos = history_len - 1;
+
        }
+
        else {
+
            /* Exit from incremental search mode */
+
            break;
+
        }

-
/* Backspace implementation. */
-
void linenoiseEditBackspace(struct linenoiseState *l) {
-
    if (l->pos > 0 && l->len > 0) {
-
        memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos);
-
        l->pos--;
-
        l->len--;
-
        l->buf[l->len] = '\0';
-
        refreshLine(l);
+
        /* Now search through the history for a match */
+
        for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) {
+
            p = strstr(history[searchpos], rbuf);
+
            if (p) {
+
                /* Found a match */
+
                if (skipsame && strcmp(history[searchpos], sb_str(current->buf)) == 0) {
+
                    /* But it is identical, so skip it */
+
                    continue;
+
                }
+
                /* Copy the matching line and set the cursor position */
+
                history_index = history_len - 1 - searchpos;
+
                set_current(current,history[searchpos]);
+
                current->pos = utf8_strlen(history[searchpos], p - history[searchpos]);
+
                break;
+
            }
+
        }
+
        if (!p && n) {
+
            /* No match, so don't add it */
+
            rchars--;
+
            rlen -= n;
+
            rbuf[rlen] = 0;
+
        }
+
    }
+
    if (c == ctrl('G') || c == ctrl('C')) {
+
        /* ctrl-g terminates the search with no effect */
+
        set_current(current, "");
+
        history_index = 0;
+
        c = 0;
    }
+
    else if (c == ctrl('J')) {
+
        /* ctrl-j terminates the search leaving the buffer in place */
+
        history_index = 0;
+
        c = 0;
+
    }
+
    /* Go process the char normally */
+
    refreshLine(current);
+
    return c;
}

-
/* Delete the previosu word, maintaining the cursor at the start of the
-
 * current word. */
-
void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
-
    size_t old_pos = l->pos;
-
    size_t diff;
+
static int linenoiseEdit(struct current *current) {
+
    history_index = 0;

-
    while (l->pos > 0 && l->buf[l->pos-1] == ' ')
-
        l->pos--;
-
    while (l->pos > 0 && l->buf[l->pos-1] != ' ')
-
        l->pos--;
-
    diff = old_pos - l->pos;
-
    memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);
-
    l->len -= diff;
-
    refreshLine(l);
-
}
+
    refreshLine(current);

-
/* This function is the core of the line editing capability of linenoise.
-
 * It expects 'fd' to be already in "raw mode" so that every key pressed
-
 * will be returned ASAP to read().
-
 *
-
 * The resulting string is put into 'buf' when the user type enter, or
-
 * when ctrl+d is typed.
-
 *
-
 * The function returns the length of the current buffer. */
-
static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)
-
{
-
    struct linenoiseState l;
-

-
    /* Populate the linenoise state that we pass to functions implementing
-
     * specific editing functionalities. */
-
    l.ifd = stdin_fd;
-
    l.ofd = stdout_fd;
-
    l.buf = buf;
-
    l.buflen = buflen;
-
    l.prompt = prompt;
-
    l.plen = strlen(prompt);
-
    l.oldpos = l.pos = 0;
-
    l.len = 0;
-
    l.cols = getColumns(stdin_fd, stdout_fd);
-
    l.maxrows = 0;
-
    l.history_index = 0;
-

-
    /* Buffer starts empty. */
-
    l.buf[0] = '\0';
-
    l.buflen--; /* Make sure there is always space for the nulterm */
-

-
    /* The latest history entry is always our current buffer, that
-
     * initially is just an empty string. */
-
    linenoiseHistoryAdd("");
-

-
    if (write(l.ofd,prompt,l.plen) == -1) return -1;
    while(1) {
-
        char c;
-
        int nread;
-
        char seq[3];
-

-
        nread = read(l.ifd,&c,1);
-
        if (nread <= 0) return l.len;
+
        int c = fd_read(current);

+
#ifndef NO_COMPLETION
        /* Only autocomplete when the callback is set. It returns < 0 when
         * there was an error reading from fd. Otherwise it will return the
         * character that should be handled next. */
-
        if (c == 9 && completionCallback != NULL) {
-
            int cv = completeLine(&l);
+
        if (c == '\t' && current->pos == sb_chars(current->buf) && completionCallback != NULL) {
+
            c = completeLine(current);
+
        }
+
#endif
+
        if (c == ctrl('R')) {
+
            /* reverse incremental search will provide an alternative keycode or 0 for none */
+
            c = reverseIncrementalSearch(current);
+
            /* go on to process the returned char normally */
+
        }
+

+
#ifdef USE_TERMIOS
+
        if (c == CHAR_ESCAPE) {   /* escape sequence */
+
            c = check_special(current->fd);
+
        }
+
#endif
+
        if (c == -1) {
            /* Return on errors */
-
            if (cv < 0) return l.len;
-
            /* char may be unsigned */
-
            c = (char)cv;
-
            /* Read next character when 0 */
-
            if (c == 0) continue;
+
            return sb_len(current->buf);
        }

        switch(c) {
-
        case ENTER:    /* enter */
+
        case SPECIAL_NONE:
+
            break;
+
        case '\r':    /* enter/CR */
+
        case '\n':    /* LF */
            history_len--;
            free(history[history_len]);
-
            if (mlmode) linenoiseEditMoveEnd(&l);
-
            if (hintsCallback) {
-
                /* Force a refresh without hints to leave the previous
-
                 * line as the user typed it after a newline. */
-
                linenoiseHintsCallback *hc = hintsCallback;
-
                hintsCallback = NULL;
-
                refreshLine(&l);
-
                hintsCallback = hc;
+
            current->pos = sb_chars(current->buf);
+
            if (mlmode || hintsCallback) {
+
                showhints = 0;
+
                refreshLine(current);
+
                showhints = 1;
            }
-
            return (int)l.len;
-
        case CTRL_C:     /* ctrl-c */
+
            return sb_len(current->buf);
+
        case ctrl('C'):     /* ctrl-c */
            errno = EAGAIN;
            return -1;
-
        case BACKSPACE:   /* backspace */
-
        case 8:     /* ctrl-h */
-
            linenoiseEditBackspace(&l);
+
        case ctrl('Z'):     /* ctrl-z */
+
#ifdef SIGTSTP
+
            /* send ourselves SIGSUSP */
+
            disableRawMode(current);
+
            raise(SIGTSTP);
+
            /* and resume */
+
            enableRawMode(current);
+
            refreshLine(current);
+
#endif
+
            continue;
+
        case CHAR_DELETE:   /* backspace */
+
        case ctrl('H'):
+
            if (remove_char(current, current->pos - 1) == 1) {
+
                refreshLine(current);
+
            }
            break;
-
        case CTRL_D:     /* ctrl-d, remove char at right of cursor, or if the
-
                            line is empty, act as end-of-file. */
-
            if (l.len > 0) {
-
                linenoiseEditDelete(&l);
-
            } else {
+
        case ctrl('D'):     /* ctrl-d */
+
            if (sb_len(current->buf) == 0) {
+
                /* Empty line, so EOF */
                history_len--;
                free(history[history_len]);
                return -1;
            }
-
            break;
-
        case CTRL_T:    /* ctrl-t, swaps current character with previous. */
-
            if (l.pos > 0 && l.pos < l.len) {
-
                int aux = buf[l.pos-1];
-
                buf[l.pos-1] = buf[l.pos];
-
                buf[l.pos] = aux;
-
                if (l.pos != l.len-1) l.pos++;
-
                refreshLine(&l);
+
            /* Otherwise fall through to delete char to right of cursor */
+
            /* fall-thru */
+
        case SPECIAL_DELETE:
+
            if (remove_char(current, current->pos) == 1) {
+
                refreshLine(current);
            }
            break;
-
        case CTRL_B:     /* ctrl-b */
-
            linenoiseEditMoveLeft(&l);
-
            break;
-
        case CTRL_F:     /* ctrl-f */
-
            linenoiseEditMoveRight(&l);
+
        case SPECIAL_INSERT:
+
            /* Ignore. Expansion Hook.
+
             * Future possibility: Toggle Insert/Overwrite Modes
+
             */
            break;
-
        case CTRL_P:    /* ctrl-p */
-
            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
+
        case meta('b'):    /* meta-b, move word left */
+
            if (skip_nonspace(current, -1)) {
+
                refreshLine(current);
+
            }
+
            else if (skip_space(current, -1)) {
+
                skip_nonspace(current, -1);
+
                refreshLine(current);
+
            }
            break;
-
        case CTRL_N:    /* ctrl-n */
-
            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
+
        case meta('f'):    /* meta-f, move word right */
+
            if (skip_space(current, 1)) {
+
                refreshLine(current);
+
            }
+
            else if (skip_nonspace(current, 1)) {
+
                skip_space(current, 1);
+
                refreshLine(current);
+
            }
            break;
-
        case ESC:    /* escape sequence */
-
            /* Read the next two bytes representing the escape sequence.
-
             * Use two calls to handle slow terminals returning the two
-
             * chars at different times. */
-
            if (read(l.ifd,seq,1) == -1) break;
-
            if (read(l.ifd,seq+1,1) == -1) break;
-

-
            /* ESC [ sequences. */
-
            if (seq[0] == '[') {
-
                if (seq[1] >= '0' && seq[1] <= '9') {
-
                    /* Extended escape, read additional byte. */
-
                    if (read(l.ifd,seq+2,1) == -1) break;
-
                    if (seq[2] == '~') {
-
                        switch(seq[1]) {
-
                        case '3': /* Delete key. */
-
                            linenoiseEditDelete(&l);
-
                            break;
-
                        }
-
                    }
-
                } else {
-
                    switch(seq[1]) {
-
                    case 'A': /* Up */
-
                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
-
                        break;
-
                    case 'B': /* Down */
-
                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
-
                        break;
-
                    case 'C': /* Right */
-
                        linenoiseEditMoveRight(&l);
-
                        break;
-
                    case 'D': /* Left */
-
                        linenoiseEditMoveLeft(&l);
-
                        break;
-
                    case 'H': /* Home */
-
                        linenoiseEditMoveHome(&l);
-
                        break;
-
                    case 'F': /* End*/
-
                        linenoiseEditMoveEnd(&l);
-
                        break;
-
                    }
+
        case ctrl('W'):    /* ctrl-w, delete word at left. save deleted chars */
+
            /* eat any spaces on the left */
+
            {
+
                int pos = current->pos;
+
                while (pos > 0 && get_char(current, pos - 1) == ' ') {
+
                    pos--;
                }
-
            }

-
            /* ESC O sequences. */
-
            else if (seq[0] == 'O') {
-
                switch(seq[1]) {
-
                case 'H': /* Home */
-
                    linenoiseEditMoveHome(&l);
-
                    break;
-
                case 'F': /* End*/
-
                    linenoiseEditMoveEnd(&l);
-
                    break;
+
                /* now eat any non-spaces on the left */
+
                while (pos > 0 && get_char(current, pos - 1) != ' ') {
+
                    pos--;
+
                }
+

+
                if (remove_chars(current, pos, current->pos - pos)) {
+
                    refreshLine(current);
                }
            }
            break;
-
        default:
-
            if (linenoiseEditInsert(&l,c)) return -1;
+
        case ctrl('T'):    /* ctrl-t */
+
            if (current->pos > 0 && current->pos <= sb_chars(current->buf)) {
+
                /* If cursor is at end, transpose the previous two chars */
+
                int fixer = (current->pos == sb_chars(current->buf));
+
                c = get_char(current, current->pos - fixer);
+
                remove_char(current, current->pos - fixer);
+
                insert_char(current, current->pos - 1, c);
+
                refreshLine(current);
+
            }
+
            break;
+
        case ctrl('V'):    /* ctrl-v */
+
            /* Insert the ^V first */
+
            if (insert_char(current, current->pos, c)) {
+
                refreshLine(current);
+
                /* Now wait for the next char. Can insert anything except \0 */
+
                c = fd_read(current);
+

+
                /* Remove the ^V first */
+
                remove_char(current, current->pos - 1);
+
                if (c > 0) {
+
                    /* Insert the actual char, can't be error or null */
+
                    insert_char(current, current->pos, c);
+
                }
+
                refreshLine(current);
+
            }
+
            break;
+
        case ctrl('B'):
+
        case SPECIAL_LEFT:
+
            if (current->pos > 0) {
+
                current->pos--;
+
                refreshLine(current);
+
            }
+
            break;
+
        case ctrl('F'):
+
        case SPECIAL_RIGHT:
+
            if (current->pos < sb_chars(current->buf)) {
+
                current->pos++;
+
                refreshLine(current);
+
            }
+
            break;
+
        case SPECIAL_PAGE_UP: /* move to start of history */
+
          set_history_index(current, history_len - 1);
+
          break;
+
        case SPECIAL_PAGE_DOWN: /* move to 0 == end of history, i.e. current */
+
          set_history_index(current, 0);
+
          break;
+
        case ctrl('P'):
+
        case SPECIAL_UP:
+
            set_history_index(current, history_index + 1);
            break;
-
        case CTRL_U: /* Ctrl+u, delete the whole line. */
-
            buf[0] = '\0';
-
            l.pos = l.len = 0;
-
            refreshLine(&l);
+
        case ctrl('N'):
+
        case SPECIAL_DOWN:
+
            set_history_index(current, history_index - 1);
            break;
-
        case CTRL_K: /* Ctrl+k, delete from current to end of line. */
-
            buf[l.pos] = '\0';
-
            l.len = l.pos;
-
            refreshLine(&l);
+
        case ctrl('A'): /* Ctrl+a, go to the start of the line */
+
        case SPECIAL_HOME:
+
            current->pos = 0;
+
            refreshLine(current);
            break;
-
        case CTRL_A: /* Ctrl+a, go to the start of the line */
-
            linenoiseEditMoveHome(&l);
+
        case ctrl('E'): /* ctrl+e, go to the end of the line */
+
        case SPECIAL_END:
+
            current->pos = sb_chars(current->buf);
+
            refreshLine(current);
+
            break;
+
        case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
+
            if (remove_chars(current, 0, current->pos)) {
+
                refreshLine(current);
+
            }
+
            break;
+
        case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
+
            if (remove_chars(current, current->pos, sb_chars(current->buf) - current->pos)) {
+
                refreshLine(current);
+
            }
            break;
-
        case CTRL_E: /* ctrl+e, go to the end of the line */
-
            linenoiseEditMoveEnd(&l);
+
        case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
+
            if (current->capture && insert_chars(current, current->pos, sb_str(current->capture))) {
+
                refreshLine(current);
+
            }
            break;
-
        case CTRL_L: /* ctrl+l, clear screen */
+
        case ctrl('L'): /* Ctrl+L, clear screen */
            linenoiseClearScreen();
-
            refreshLine(&l);
+
            /* Force recalc of window size for serial terminals */
+
            current->cols = 0;
+
            current->rpos = 0;
+
            refreshLine(current);
            break;
-
        case CTRL_W: /* ctrl+w, delete previous word */
-
            linenoiseEditDeletePrevWord(&l);
+
        default:
+
            if (c >= meta('a') && c <= meta('z')) {
+
                /* Don't insert meta chars that are not bound */
+
                break;
+
            }
+
            /* Only tab is allowed without ^V */
+
            if (c == '\t' || c >= ' ') {
+
                if (insert_char(current, current->pos, c) == 1) {
+
                    refreshLine(current);
+
                }
+
            }
            break;
        }
    }
-
    return l.len;
-
}
-

-
/* This special mode is used by linenoise in order to print scan codes
-
 * on screen for debugging / development purposes. It is implemented
-
 * by the linenoise_example program using the --keycodes option. */
-
void linenoisePrintKeyCodes(void) {
-
    char quit[4];
-

-
    printf("Linenoise key codes debugging mode.\n"
-
            "Press keys to see scan codes. Type 'quit' at any time to exit.\n");
-
    if (enableRawMode(STDIN_FILENO) == -1) return;
-
    memset(quit,' ',4);
-
    while(1) {
-
        char c;
-
        int nread;
-

-
        nread = read(STDIN_FILENO,&c,1);
-
        if (nread <= 0) continue;
-
        memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */
-
        quit[sizeof(quit)-1] = c; /* Insert current char on the right. */
-
        if (memcmp(quit,"quit",sizeof(quit)) == 0) break;
-

-
        printf("'%c' %02x (%d) (type quit to exit)\n",
-
            isprint(c) ? c : '?', (int)c, (int)c);
-
        printf("\r"); /* Go left edge manually, we are in raw mode. */
-
        fflush(stdout);
-
    }
-
    disableRawMode(STDIN_FILENO);
+
    return sb_len(current->buf);
}

-
/* This function calls the line editing function linenoiseEdit() using
-
 * the STDIN file descriptor set in raw mode. */
-
static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
-
    int count;
-

-
    if (buflen == 0) {
-
        errno = EINVAL;
-
        return -1;
-
    }
-

-
    if (enableRawMode(STDIN_FILENO) == -1) return -1;
-
    count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
-
    disableRawMode(STDIN_FILENO);
-
    printf("\n");
-
    return count;
+
int linenoiseColumns(void)
+
{
+
    struct current current;
+
    current.output = NULL;
+
    enableRawMode (&current);
+
    getWindowSize (&current);
+
    disableRawMode (&current);
+
    return current.cols;
}

-
/* This function is called when linenoise() is called with the standard
-
 * input file descriptor not attached to a TTY. So for example when the
-
 * program using linenoise is called in pipe or with a file redirected
-
 * to its standard input. In this case, we want to be able to return the
-
 * line regardless of its length (by default we are limited to 4k). */
-
static char *linenoiseNoTTY(void) {
-
    char *line = NULL;
-
    size_t len = 0, maxlen = 0;
-

-
    while(1) {
-
        if (len == maxlen) {
-
            if (maxlen == 0) maxlen = 16;
-
            maxlen *= 2;
-
            char *oldval = line;
-
            line = realloc(line,maxlen);
-
            if (line == NULL) {
-
                if (oldval) free(oldval);
-
                return NULL;
-
            }
+
/**
+
 * Reads a line from the file handle (without the trailing NL or CRNL)
+
 * and returns it in a stringbuf.
+
 * Returns NULL if no characters are read before EOF or error.
+
 *
+
 * Note that the character count will *not* be correct for lines containing
+
 * utf8 sequences. Do not rely on the character count.
+
 */
+
static stringbuf *sb_getline(FILE *fh)
+
{
+
    stringbuf *sb = sb_alloc();
+
    int c;
+
    int n = 0;
+

+
    while ((c = getc(fh)) != EOF) {
+
        char ch;
+
        n++;
+
        if (c == '\r') {
+
            /* CRLF -> LF */
+
            continue;
        }
-
        int c = fgetc(stdin);
-
        if (c == EOF || c == '\n') {
-
            if (c == EOF && len == 0) {
-
                free(line);
-
                return NULL;
-
            } else {
-
                line[len] = '\0';
-
                return line;
-
            }
-
        } else {
-
            line[len] = c;
-
            len++;
+
        if (c == '\n' || c == '\r') {
+
            break;
        }
+
        ch = c;
+
        /* ignore the effect of character count for partial utf8 sequences */
+
        sb_append_len(sb, &ch, 1);
+
    }
+
    if (n == 0 || sb->data == NULL) {
+
        sb_free(sb);
+
        return NULL;
    }
+
    return sb;
}

-
/* The high level function that is the main API of the linenoise library.
-
 * This function checks if the terminal has basic capabilities, just checking
-
 * for a blacklist of stupid terminals, and later either calls the line
-
 * editing function or uses dummy fgets() so that you will be able to type
-
 * something even in the most desperate of the conditions. */
-
char *linenoise(const char *prompt) {
-
    char buf[LINENOISE_MAX_LINE];
+
char *linenoiseWithInitial(const char *prompt, const char *initial)
+
{
    int count;
+
    struct current current;
+
    stringbuf *sb;

-
    if (!isatty(STDIN_FILENO)) {
-
        /* Not a tty: read from file / pipe. In this mode we don't want any
-
         * limit to the line size, so we call a function to handle that. */
-
        return linenoiseNoTTY();
-
    } else if (isUnsupportedTerm()) {
-
        size_t len;
+
    memset(&current, 0, sizeof(current));

-
        printf("%s",prompt);
+
    if (enableRawMode(&current) == -1) {
+
        printf("%s", prompt);
        fflush(stdout);
-
        if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
-
        len = strlen(buf);
-
        while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
-
            len--;
-
            buf[len] = '\0';
+
        sb = sb_getline(stdin);
+
        if (sb && !fd_isatty(&current)) {
+
            printf("%s\n", sb_str(sb));
+
            fflush(stdout);
        }
-
        return strdup(buf);
-
    } else {
-
        count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
-
        if (count == -1) return NULL;
-
        return strdup(buf);
    }
-
}
+
    else {
+
        current.buf = sb_alloc();
+
        current.pos = 0;
+
        current.nrows = 1;
+
        current.prompt = prompt;

-
/* This is just a wrapper the user may want to call in order to make sure
-
 * the linenoise returned buffer is freed with the same allocator it was
-
 * created with. Useful when the main program is using an alternative
-
 * allocator. */
-
void linenoiseFree(void *ptr) {
-
    free(ptr);
-
}
+
        /* The latest history entry is always our current buffer */
+
        linenoiseHistoryAdd(initial);
+
        set_current(&current, initial);

-
/* ================================ History ================================= */
+
        count = linenoiseEdit(&current);

-
/* Free the history, but does not reset it. Only used when we have to
-
 * exit() to avoid memory leaks are reported by valgrind & co. */
-
static void freeHistory(void) {
-
    if (history) {
-
        int j;
+
        disableRawMode(&current);
+
        printf("\n");

-
        for (j = 0; j < history_len; j++)
-
            free(history[j]);
-
        free(history);
+
        sb_free(current.capture);
+
        if (count == -1) {
+
            sb_free(current.buf);
+
            return NULL;
+
        }
+
        sb = current.buf;
    }
+
    return sb ? sb_to_string(sb) : NULL;
}

-
/* At exit we'll try to fix the terminal to the initial conditions. */
-
static void linenoiseAtExit(void) {
-
    disableRawMode(STDIN_FILENO);
-
    freeHistory();
+
char *linenoise(const char *prompt)
+
{
+
    return linenoiseWithInitial(prompt, "");
}

-
/* This is the API call to add a new entry in the linenoise history.
-
 * It uses a fixed array of char pointers that are shifted (memmoved)
-
 * when the history max length is reached in order to remove the older
-
 * entry and make room for the new one, so it is not exactly suitable for huge
-
 * histories, but will work well for a few hundred of entries.
-
 *
-
 * Using a circular buffer is smarter, but a bit more complex to handle. */
-
int linenoiseHistoryAdd(const char *line) {
-
    char *linecopy;
-

-
    if (history_max_len == 0) return 0;
+
/* Using a circular buffer is smarter, but a bit more complex to handle. */
+
static int linenoiseHistoryAddAllocated(char *line) {

-
    /* Initialization on first call. */
+
    if (history_max_len == 0) {
+
notinserted:
+
        free(line);
+
        return 0;
+
    }
    if (history == NULL) {
-
        history = malloc(sizeof(char*)*history_max_len);
-
        if (history == NULL) return 0;
-
        memset(history,0,(sizeof(char*)*history_max_len));
+
        history = (char **)calloc(sizeof(char*), history_max_len);
    }

-
    /* Don't add duplicated lines. */
-
    if (history_len && !strcmp(history[history_len-1], line)) return 0;
+
    /* do not insert duplicate lines into history */
+
    if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) {
+
        goto notinserted;
+
    }

-
    /* Add an heap allocated copy of the line in the history.
-
     * If we reached the max length, remove the older line. */
-
    linecopy = strdup(line);
-
    if (!linecopy) return 0;
    if (history_len == history_max_len) {
        free(history[0]);
        memmove(history,history+1,sizeof(char*)*(history_max_len-1));
        history_len--;
    }
-
    history[history_len] = linecopy;
+
    history[history_len] = line;
    history_len++;
    return 1;
}

-
/* Set the maximum length for the history. This function can be called even
-
 * if there is already some history, the function will make sure to retain
-
 * just the latest 'len' elements if the new history length value is smaller
-
 * than the amount of items already inside the history. */
+
int linenoiseHistoryAdd(const char *line) {
+
    return linenoiseHistoryAddAllocated(strdup(line));
+
}
+

+
int linenoiseHistoryGetMaxLen(void) {
+
    return history_max_len;
+
}
+

int linenoiseHistorySetMaxLen(int len) {
-
    char **new;
+
    char **newHistory;

    if (len < 1) return 0;
    if (history) {
        int tocopy = history_len;

-
        new = malloc(sizeof(char*)*len);
-
        if (new == NULL) return 0;
+
        newHistory = (char **)calloc(sizeof(char*), len);

        /* If we can't copy everything, free the elements we'll not use. */
        if (len < tocopy) {
@@ -1175,10 +1993,9 @@ int linenoiseHistorySetMaxLen(int len) {
            for (j = 0; j < tocopy-len; j++) free(history[j]);
            tocopy = len;
        }
-
        memset(new,0,sizeof(char*)*len);
-
        memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);
+
        memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy);
        free(history);
-
        history = new;
+
        history = newHistory;
    }
    history_max_len = len;
    if (history_len > history_max_len)
@@ -1189,39 +2006,84 @@ int linenoiseHistorySetMaxLen(int len) {
/* Save the history in the specified file. On success 0 is returned
 * otherwise -1 is returned. */
int linenoiseHistorySave(const char *filename) {
-
    mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
-
    FILE *fp;
+
    FILE *fp = fopen(filename,"w");
    int j;

-
    fp = fopen(filename,"w");
-
    umask(old_umask);
    if (fp == NULL) return -1;
-
    chmod(filename,S_IRUSR|S_IWUSR);
-
    for (j = 0; j < history_len; j++)
-
        fprintf(fp,"%s\n",history[j]);
+
    for (j = 0; j < history_len; j++) {
+
        const char *str = history[j];
+
        /* Need to encode backslash, nl and cr */
+
        while (*str) {
+
            if (*str == '\\') {
+
                fputs("\\\\", fp);
+
            }
+
            else if (*str == '\n') {
+
                fputs("\\n", fp);
+
            }
+
            else if (*str == '\r') {
+
                fputs("\\r", fp);
+
            }
+
            else {
+
                fputc(*str, fp);
+
            }
+
            str++;
+
        }
+
        fputc('\n', fp);
+
    }
+

    fclose(fp);
    return 0;
}

-
/* Load the history from the specified file. If the file does not exist
-
 * zero is returned and no operation is performed.
+
/* Load the history from the specified file.
 *
-
 * If the file exists and the operation succeeded 0 is returned, otherwise
-
 * on error -1 is returned. */
+
 * If the file does not exist or can't be opened, no operation is performed
+
 * and -1 is returned.
+
 * Otherwise 0 is returned.
+
 */
int linenoiseHistoryLoad(const char *filename) {
    FILE *fp = fopen(filename,"r");
-
    char buf[LINENOISE_MAX_LINE];
+
    stringbuf *sb;

    if (fp == NULL) return -1;

-
    while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {
-
        char *p;
+
    while ((sb = sb_getline(fp)) != NULL) {
+
        /* Take the stringbuf and decode backslash escaped values */
+
        char *buf = sb_to_string(sb);
+
        char *dest = buf;
+
        const char *src;
+

+
        for (src = buf; *src; src++) {
+
            char ch = *src;
+

+
            if (ch == '\\') {
+
                src++;
+
                if (*src == 'n') {
+
                    ch = '\n';
+
                }
+
                else if (*src == 'r') {
+
                    ch = '\r';
+
                } else {
+
                    ch = *src;
+
                }
+
            }
+
            *dest++ = ch;
+
        }
+
        *dest = 0;

-
        p = strchr(buf,'\r');
-
        if (!p) p = strchr(buf,'\n');
-
        if (p) *p = '\0';
-
        linenoiseHistoryAdd(buf);
+
        linenoiseHistoryAddAllocated(buf);
    }
    fclose(fp);
    return 0;
}
+

+
/* Provide access to the history buffer.
+
 *
+
 * If 'len' is not NULL, the length is stored in *len.
+
 */
+
char **linenoiseHistory(int *len) {
+
    if (len) {
+
        *len = history_len;
+
    }
+
    return history;
+
}
modified external/linenoise/linenoise.h
@@ -1,14 +1,12 @@
-
/* linenoise.h -- VERSION 1.0
-
 *
-
 * Guerrilla line editing library against the idea that a line editing lib
-
 * needs to be 20,000 lines of C code.
+
/* linenoise.h -- guerrilla line editing library against the idea that a
+
 * line editing lib needs to be 20,000 lines of C code.
 *
 * See linenoise.c for more information.
 *
 * ------------------------------------------------------------------------
 *
-
 * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
-
 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+
 * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
+
 * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
 *
 * All rights reserved.
 *
@@ -43,30 +41,106 @@
extern "C" {
#endif

+
#ifndef NO_COMPLETION
typedef struct linenoiseCompletions {
  size_t len;
  char **cvec;
} linenoiseCompletions;

-
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
-
typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);
-
typedef void(linenoiseFreeHintsCallback)(void *);
-
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
-
void linenoiseSetHintsCallback(linenoiseHintsCallback *);
-
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
-
void linenoiseAddCompletion(linenoiseCompletions *, const char *);
+
/*
+
 * The callback type for tab completion handlers.
+
 */
+
typedef void(linenoiseCompletionCallback)(const char *prefix, linenoiseCompletions *comp, void *userdata);
+

+
/*
+
 * Sets the current tab completion handler and returns the previous one, or NULL
+
 * if no prior one has been set.
+
 */
+
linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *comp, void *userdata);
+

+
/*
+
 * Adds a copy of the given string to the given completion list. The copy is owned
+
 * by the linenoiseCompletions object.
+
 */
+
void linenoiseAddCompletion(linenoiseCompletions *comp, const char *str);
+

+
typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold, void *userdata);
+
typedef void(linenoiseFreeHintsCallback)(void *hint, void *userdata);
+
void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata);
+
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback);
+

+
#endif

+
/*
+
 * Prompts for input using the given string as the input
+
 * prompt. Returns when the user has tapped ENTER or (on an empty
+
 * line) EOF (Ctrl-D on Unix, Ctrl-Z on Windows). Returns either
+
 * a copy of the entered string (for ENTER) or NULL (on EOF).  The
+
 * caller owns the returned string and must eventually free() it.
+
 */
char *linenoise(const char *prompt);
-
void linenoiseFree(void *ptr);
+

+
/**
+
 * Like linenoise() but starts with an initial buffer.
+
 */
+
char *linenoiseWithInitial(const char *prompt, const char *initial);
+

+
/**
+
 * Clear the screen.
+
 */
+
void linenoiseClearScreen(void);
+

+
/*
+
 * Adds a copy of the given line of the command history.
+
 */
int linenoiseHistoryAdd(const char *line);
+

+
/*
+
 * Sets the maximum length of the command history, in lines.
+
 * If the history is currently longer, it will be trimmed,
+
 * retaining only the most recent entries. If len is 0 or less
+
 * then this function does nothing.
+
 */
int linenoiseHistorySetMaxLen(int len);
+

+
/*
+
 * Returns the current maximum length of the history, in lines.
+
 */
+
int linenoiseHistoryGetMaxLen(void);
+

+
/*
+
 * Saves the current contents of the history to the given file.
+
 * Returns 0 on success.
+
 */
int linenoiseHistorySave(const char *filename);
+

+
/*
+
 * Replaces the current history with the contents
+
 * of the given file.  Returns 0 on success.
+
 */
int linenoiseHistoryLoad(const char *filename);
-
void linenoiseClearScreen(void);
-
void linenoiseSetMultiLine(int ml);
-
void linenoisePrintKeyCodes(void);
-
void linenoiseMaskModeEnable(void);
-
void linenoiseMaskModeDisable(void);
+

+
/*
+
 * Frees all history entries, clearing the history.
+
 */
+
void linenoiseHistoryFree(void);
+

+
/*
+
 * Returns a pointer to the list of history entries, writing its
+
 * length to *len if len is not NULL. The memory is owned by linenoise
+
 * and must not be freed.
+
 */
+
char **linenoiseHistory(int *len);
+

+
/*
+
 * Returns the number of display columns in the current terminal.
+
 */
+
int linenoiseColumns(void);
+

+
/**
+
 * Enable or disable multiline mode (disabled by default)
+
 */
+
void linenoiseSetMultiLine(int enableml);

#ifdef __cplusplus
}
added external/linenoise/stringbuf.c
@@ -0,0 +1,173 @@
+
/**
+
 * resizable string buffer
+
 *
+
 * (c) 2017-2020 Steve Bennett <steveb@workware.net.au>
+
 *
+
 * See utf8.c for licence details.
+
 */
+
#include <stdlib.h>
+
#include <string.h>
+
#include <stdio.h>
+
#include <ctype.h>
+
#include <assert.h>
+

+
#ifndef STRINGBUF_H
+
#include "stringbuf.h"
+
#endif
+
#ifdef USE_UTF8
+
#ifndef UTF8_UTIL_H
+
#include "utf8.h"
+
#endif
+
#endif
+

+
#define SB_INCREMENT 200
+

+
stringbuf *sb_alloc(void)
+
{
+
	stringbuf *sb = (stringbuf *)malloc(sizeof(*sb));
+
	sb->remaining = 0;
+
	sb->last = 0;
+
#ifdef USE_UTF8
+
	sb->chars = 0;
+
#endif
+
	sb->data = NULL;
+

+
	return(sb);
+
}
+

+
void sb_free(stringbuf *sb)
+
{
+
	if (sb) {
+
		free(sb->data);
+
	}
+
	free(sb);
+
}
+

+
static void sb_realloc(stringbuf *sb, int newlen)
+
{
+
	sb->data = (char *)realloc(sb->data, newlen);
+
	sb->remaining = newlen - sb->last;
+
}
+

+
void sb_append(stringbuf *sb, const char *str)
+
{
+
	sb_append_len(sb, str, strlen(str));
+
}
+

+
void sb_append_len(stringbuf *sb, const char *str, int len)
+
{
+
	if (sb->remaining < len + 1) {
+
		sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
+
	}
+
	memcpy(sb->data + sb->last, str, len);
+
	sb->data[sb->last + len] = 0;
+

+
	sb->last += len;
+
	sb->remaining -= len;
+
#ifdef USE_UTF8
+
	sb->chars += utf8_strlen(str, len);
+
#endif
+
}
+

+
char *sb_to_string(stringbuf *sb)
+
{
+
	if (sb->data == NULL) {
+
		/* Return an allocated empty string, not null */
+
		return strdup("");
+
	}
+
	else {
+
		/* Just return the data and free the stringbuf structure */
+
		char *pt = sb->data;
+
		free(sb);
+
		return pt;
+
	}
+
}
+

+
/* Insert and delete operations */
+

+
/* Moves up all the data at position 'pos' and beyond by 'len' bytes
+
 * to make room for new data
+
 *
+
 * Note: Does *not* update sb->chars
+
 */
+
static void sb_insert_space(stringbuf *sb, int pos, int len)
+
{
+
	assert(pos <= sb->last);
+

+
	/* Make sure there is enough space */
+
	if (sb->remaining < len) {
+
		sb_realloc(sb, sb->last + len + SB_INCREMENT);
+
	}
+
	/* Now move it up */
+
	memmove(sb->data + pos + len, sb->data + pos, sb->last - pos);
+
	sb->last += len;
+
	sb->remaining -= len;
+
	/* And null terminate */
+
	sb->data[sb->last] = 0;
+
}
+

+
/**
+
 * Move down all the data from pos + len, effectively
+
 * deleting the data at position 'pos' of length 'len'
+
 */
+
static void sb_delete_space(stringbuf *sb, int pos, int len)
+
{
+
	assert(pos < sb->last);
+
	assert(pos + len <= sb->last);
+

+
#ifdef USE_UTF8
+
	sb->chars -= utf8_strlen(sb->data + pos, len);
+
#endif
+

+
	/* Now move it up */
+
	memmove(sb->data + pos, sb->data + pos + len, sb->last - pos - len);
+
	sb->last -= len;
+
	sb->remaining += len;
+
	/* And null terminate */
+
	sb->data[sb->last] = 0;
+
}
+

+
void sb_insert(stringbuf *sb, int index, const char *str)
+
{
+
	if (index >= sb->last) {
+
		/* Inserting after the end of the list appends. */
+
		sb_append(sb, str);
+
	}
+
	else {
+
		int len = strlen(str);
+

+
		sb_insert_space(sb, index, len);
+
		memcpy(sb->data + index, str, len);
+
#ifdef USE_UTF8
+
		sb->chars += utf8_strlen(str, len);
+
#endif
+
	}
+
}
+

+
/**
+
 * Delete the bytes at index 'index' for length 'len'
+
 * Has no effect if the index is past the end of the list.
+
 */
+
void sb_delete(stringbuf *sb, int index, int len)
+
{
+
	if (index < sb->last) {
+
		char *pos = sb->data + index;
+
		if (len < 0) {
+
			len = sb->last;
+
		}
+

+
		sb_delete_space(sb, pos - sb->data, len);
+
	}
+
}
+

+
void sb_clear(stringbuf *sb)
+
{
+
	if (sb->data) {
+
		/* Null terminate */
+
		sb->data[0] = 0;
+
		sb->last = 0;
+
#ifdef USE_UTF8
+
		sb->chars = 0;
+
#endif
+
	}
+
}
added external/linenoise/stringbuf.h
@@ -0,0 +1,137 @@
+
#ifndef STRINGBUF_H
+
#define STRINGBUF_H
+
/**
+
 * resizable string buffer
+
 *
+
 * (c) 2017-2020 Steve Bennett <steveb@workware.net.au>
+
 *
+
 * See utf8.c for licence details.
+
 */
+
#ifdef __cplusplus
+
extern "C" {
+
#endif
+

+
/** @file
+
 * A stringbuf is a resizing, null terminated string buffer.
+
 *
+
 * The buffer is reallocated as necessary.
+
 *
+
 * In general it is *not* OK to call these functions with a NULL pointer
+
 * unless stated otherwise.
+
 *
+
 * If USE_UTF8 is defined, supports utf8.
+
 */
+

+
/**
+
 * The stringbuf structure should not be accessed directly.
+
 * Use the functions below.
+
 */
+
typedef struct {
+
	int remaining;	/**< Allocated, but unused space */
+
	int last;		/**< Index of the null terminator (and thus the length of the string) */
+
#ifdef USE_UTF8
+
	int chars;		/**< Count of characters */
+
#endif
+
	char *data;		/**< Allocated memory containing the string or NULL for empty */
+
} stringbuf;
+

+
/**
+
 * Allocates and returns a new stringbuf with no elements.
+
 */
+
stringbuf *sb_alloc(void);
+

+
/**
+
 * Frees a stringbuf.
+
 * It is OK to call this with NULL.
+
 */
+
void sb_free(stringbuf *sb);
+

+
/**
+
 * Returns an allocated copy of the stringbuf
+
 */
+
stringbuf *sb_copy(stringbuf *sb);
+

+
/**
+
 * Returns the byte length of the buffer.
+
 * 
+
 * Returns 0 for both a NULL buffer and an empty buffer.
+
 */
+
static inline int sb_len(stringbuf *sb) {
+
	return sb->last;
+
}
+

+
/**
+
 * Returns the utf8 character length of the buffer.
+
 * 
+
 * Returns 0 for both a NULL buffer and an empty buffer.
+
 */
+
static inline int sb_chars(stringbuf *sb) {
+
#ifdef USE_UTF8
+
	return sb->chars;
+
#else
+
	return sb->last;
+
#endif
+
}
+

+
/**
+
 * Appends a null terminated string to the stringbuf
+
 */
+
void sb_append(stringbuf *sb, const char *str);
+

+
/**
+
 * Like sb_append() except does not require a null terminated string.
+
 * The length of 'str' is given as 'len'
+
 *
+
 * Note that in utf8 mode, characters will *not* be counted correctly
+
 * if a partial utf8 sequence is added with sb_append_len()
+
 */
+
void sb_append_len(stringbuf *sb, const char *str, int len);
+

+
/**
+
 * Returns a pointer to the null terminated string in the buffer.
+
 *
+
 * Note this pointer only remains valid until the next modification to the
+
 * string buffer.
+
 *
+
 * The returned pointer can be used to update the buffer in-place
+
 * as long as care is taken to not overwrite the end of the buffer.
+
 */
+
static inline char *sb_str(const stringbuf *sb)
+
{
+
	return sb->data;
+
}
+

+
/**
+
 * Inserts the given string *before* (zero-based) byte 'index' in the stringbuf.
+
 * If index is past the end of the buffer, the string is appended,
+
 * just like sb_append()
+
 */
+
void sb_insert(stringbuf *sb, int index, const char *str);
+

+
/**
+
 * Delete 'len' bytes in the string at the given index.
+
 *
+
 * Any bytes past the end of the buffer are ignored.
+
 * The buffer remains null terminated.
+
 *
+
 * If len is -1, deletes to the end of the buffer.
+
 */
+
void sb_delete(stringbuf *sb, int index, int len);
+

+
/**
+
 * Clear to an empty buffer.
+
 */
+
void sb_clear(stringbuf *sb);
+

+
/**
+
 * Return an allocated copy of buffer and frees 'sb'.
+
 *
+
 * If 'sb' is empty, returns an allocated copy of "".
+
 */
+
char *sb_to_string(stringbuf *sb);
+

+
#ifdef __cplusplus
+
}
+
#endif
+

+
#endif
added external/linenoise/utf8.c
@@ -0,0 +1,275 @@
+
/**
+
 * UTF-8 utility functions
+
 *
+
 * (c) 2010-2019 Steve Bennett <steveb@workware.net.au>
+
 *
+
 * All rights reserved.
+
 *
+
 * Redistribution and use in source and binary forms, with or without
+
 * modification, are permitted provided that the following conditions are met:
+
 *
+
 * * Redistributions of source code must retain the above copyright notice,
+
 *   this list of conditions and the following disclaimer.
+
 *
+
 * * Redistributions in binary form must reproduce the above copyright notice,
+
 *   this list of conditions and the following disclaimer in the documentation
+
 *   and/or other materials provided with the distribution.
+
 *
+
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
+

+
#include <ctype.h>
+
#include <stdlib.h>
+
#include <string.h>
+
#include <stdio.h>
+
#ifndef UTF8_UTIL_H
+
#include "utf8.h"
+
#endif
+

+
#ifdef USE_UTF8
+
int utf8_fromunicode(char *p, unsigned uc)
+
{
+
    if (uc <= 0x7f) {
+
        *p = uc;
+
        return 1;
+
    }
+
    else if (uc <= 0x7ff) {
+
        *p++ = 0xc0 | ((uc & 0x7c0) >> 6);
+
        *p = 0x80 | (uc & 0x3f);
+
        return 2;
+
    }
+
    else if (uc <= 0xffff) {
+
        *p++ = 0xe0 | ((uc & 0xf000) >> 12);
+
        *p++ = 0x80 | ((uc & 0xfc0) >> 6);
+
        *p = 0x80 | (uc & 0x3f);
+
        return 3;
+
    }
+
    /* Note: We silently truncate to 21 bits here: 0x1fffff */
+
    else {
+
        *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
+
        *p++ = 0x80 | ((uc & 0x3f000) >> 12);
+
        *p++ = 0x80 | ((uc & 0xfc0) >> 6);
+
        *p = 0x80 | (uc & 0x3f);
+
        return 4;
+
    }
+
}
+

+
int utf8_charlen(int c)
+
{
+
    if ((c & 0x80) == 0) {
+
        return 1;
+
    }
+
    if ((c & 0xe0) == 0xc0) {
+
        return 2;
+
    }
+
    if ((c & 0xf0) == 0xe0) {
+
        return 3;
+
    }
+
    if ((c & 0xf8) == 0xf0) {
+
        return 4;
+
    }
+
    /* Invalid sequence */
+
    return -1;
+
}
+

+
int utf8_strlen(const char *str, int bytelen)
+
{
+
    int charlen = 0;
+
    if (bytelen < 0) {
+
        bytelen = strlen(str);
+
    }
+
    while (bytelen > 0) {
+
        int c;
+
        int l = utf8_tounicode(str, &c);
+
        charlen++;
+
        str += l;
+
        bytelen -= l;
+
    }
+
    return charlen;
+
}
+

+
int utf8_strwidth(const char *str, int charlen)
+
{
+
    int width = 0;
+
    while (charlen) {
+
        int c;
+
        int l = utf8_tounicode(str, &c);
+
        width += utf8_width(c);
+
        str += l;
+
        charlen--;
+
    }
+
    return width;
+
}
+

+
int utf8_index(const char *str, int index)
+
{
+
    const char *s = str;
+
    while (index--) {
+
        int c;
+
        s += utf8_tounicode(s, &c);
+
    }
+
    return s - str;
+
}
+

+
int utf8_tounicode(const char *str, int *uc)
+
{
+
    unsigned const char *s = (unsigned const char *)str;
+

+
    if (s[0] < 0xc0) {
+
        *uc = s[0];
+
        return 1;
+
    }
+
    if (s[0] < 0xe0) {
+
        if ((s[1] & 0xc0) == 0x80) {
+
            *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80);
+
            if (*uc >= 0x80) {
+
                return 2;
+
            }
+
            /* Otherwise this is an invalid sequence */
+
        }
+
    }
+
    else if (s[0] < 0xf0) {
+
        if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) {
+
            *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80);
+
            if (*uc >= 0x800) {
+
                return 3;
+
            }
+
            /* Otherwise this is an invalid sequence */
+
        }
+
    }
+
    else if (s[0] < 0xf8) {
+
        if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80) && ((str[3] & 0xc0) == 0x80)) {
+
            *uc = ((s[0] & ~0xf0) << 18) | ((s[1] & ~0x80) << 12) | ((s[2] & ~0x80) << 6) | (s[3] & ~0x80);
+
            if (*uc >= 0x10000) {
+
                return 4;
+
            }
+
            /* Otherwise this is an invalid sequence */
+
        }
+
    }
+

+
    /* Invalid sequence, so just return the byte */
+
    *uc = *s;
+
    return 1;
+
}
+

+
struct utf8range {
+
    int lower;     /* lower inclusive */
+
    int upper;     /* upper exclusive */
+
};
+

+
/* From http://unicode.org/Public/UNIDATA/UnicodeData.txt */
+
static const struct utf8range unicode_range_combining[] = {
+
        { 0x0300, 0x0370 },     { 0x0483, 0x048a },     { 0x0591, 0x05d0 },     { 0x0610, 0x061b },
+
        { 0x064b, 0x0660 },     { 0x0670, 0x0671 },     { 0x06d6, 0x06dd },     { 0x06df, 0x06e5 },
+
        { 0x06e7, 0x06ee },     { 0x0711, 0x0712 },     { 0x0730, 0x074d },     { 0x07a6, 0x07b1 },
+
        { 0x07eb, 0x07f4 },     { 0x0816, 0x0830 },     { 0x0859, 0x085e },     { 0x08d4, 0x0904 },
+
        { 0x093a, 0x0958 },     { 0x0962, 0x0964 },     { 0x0981, 0x0985 },     { 0x09bc, 0x09ce },
+
        { 0x09d7, 0x09dc },     { 0x09e2, 0x09e6 },     { 0x0a01, 0x0a05 },     { 0x0a3c, 0x0a59 },
+
        { 0x0a70, 0x0a72 },     { 0x0a75, 0x0a85 },     { 0x0abc, 0x0ad0 },     { 0x0ae2, 0x0ae6 },
+
        { 0x0afa, 0x0b05 },     { 0x0b3c, 0x0b5c },     { 0x0b62, 0x0b66 },     { 0x0b82, 0x0b83 },
+
        { 0x0bbe, 0x0bd0 },     { 0x0bd7, 0x0be6 },     { 0x0c00, 0x0c05 },     { 0x0c3e, 0x0c58 },
+
        { 0x0c62, 0x0c66 },     { 0x0c81, 0x0c85 },     { 0x0cbc, 0x0cde },     { 0x0ce2, 0x0ce6 },
+
        { 0x0d00, 0x0d05 },     { 0x0d3b, 0x0d4e },     { 0x0d57, 0x0d58 },     { 0x0d62, 0x0d66 },
+
        { 0x0d82, 0x0d85 },     { 0x0dca, 0x0de6 },     { 0x0df2, 0x0df4 },     { 0x0e31, 0x0e32 },
+
        { 0x0e34, 0x0e3f },     { 0x0e47, 0x0e4f },     { 0x0eb1, 0x0eb2 },     { 0x0eb4, 0x0ebd },
+
        { 0x0ec8, 0x0ed0 },     { 0x0f18, 0x0f1a },     { 0x0f35, 0x0f3a },     { 0x0f3e, 0x0f40 },
+
        { 0x0f71, 0x0f88 },     { 0x0f8d, 0x0fbe },     { 0x0fc6, 0x0fc7 },     { 0x102b, 0x103f },
+
        { 0x1056, 0x105a },     { 0x105e, 0x1065 },     { 0x1067, 0x106e },     { 0x1071, 0x1075 },
+
        { 0x1082, 0x1090 },     { 0x109a, 0x109e },     { 0x135d, 0x1360 },     { 0x1712, 0x1720 },
+
        { 0x1732, 0x1735 },     { 0x1752, 0x1760 },     { 0x1772, 0x1780 },     { 0x17b4, 0x17d4 },
+
        { 0x17dd, 0x17e0 },     { 0x180b, 0x180e },     { 0x1885, 0x1887 },     { 0x18a9, 0x18aa },
+
        { 0x1920, 0x1940 },     { 0x1a17, 0x1a1e },     { 0x1a55, 0x1a80 },     { 0x1ab0, 0x1b05 },
+
        { 0x1b34, 0x1b45 },     { 0x1b6b, 0x1b74 },     { 0x1b80, 0x1b83 },     { 0x1ba1, 0x1bae },
+
        { 0x1be6, 0x1bfc },     { 0x1c24, 0x1c3b },     { 0x1cd0, 0x1ce9 },     { 0x1ced, 0x1cee },
+
        { 0x1cf2, 0x1cf5 },     { 0x1cf7, 0x1d00 },     { 0x1dc0, 0x1e00 },     { 0x20d0, 0x2100 },
+
        { 0x2cef, 0x2cf2 },     { 0x2d7f, 0x2d80 },     { 0x2de0, 0x2e00 },     { 0x302a, 0x3030 },
+
        { 0x3099, 0x309b },     { 0xa66f, 0xa67e },     { 0xa69e, 0xa6a0 },     { 0xa6f0, 0xa6f2 },
+
        { 0xa802, 0xa803 },     { 0xa806, 0xa807 },     { 0xa80b, 0xa80c },     { 0xa823, 0xa828 },
+
        { 0xa880, 0xa882 },     { 0xa8b4, 0xa8ce },     { 0xa8e0, 0xa8f2 },     { 0xa926, 0xa92e },
+
        { 0xa947, 0xa95f },     { 0xa980, 0xa984 },     { 0xa9b3, 0xa9c1 },     { 0xa9e5, 0xa9e6 },
+
        { 0xaa29, 0xaa40 },     { 0xaa43, 0xaa44 },     { 0xaa4c, 0xaa50 },     { 0xaa7b, 0xaa7e },
+
        { 0xaab0, 0xaab5 },     { 0xaab7, 0xaab9 },     { 0xaabe, 0xaac2 },     { 0xaaeb, 0xaaf0 },
+
        { 0xaaf5, 0xab01 },     { 0xabe3, 0xabf0 },     { 0xfb1e, 0xfb1f },     { 0xfe00, 0xfe10 },
+
        { 0xfe20, 0xfe30 },
+
};
+

+
/* From http://unicode.org/Public/UNIDATA/EastAsianWidth.txt */
+
static const struct utf8range unicode_range_wide[] = {
+
        { 0x1100, 0x115f },     { 0x231a, 0x231b },     { 0x2329, 0x232a },     { 0x23e9, 0x23ec },
+
        { 0x23f0, 0x23f0 },     { 0x23f3, 0x23f3 },     { 0x25fd, 0x25fe },     { 0x2614, 0x2615 },
+
        { 0x2648, 0x2653 },     { 0x267f, 0x267f },     { 0x2693, 0x2693 },     { 0x26a1, 0x26a1 },
+
        { 0x26aa, 0x26ab },     { 0x26bd, 0x26be },     { 0x26c4, 0x26c5 },     { 0x26ce, 0x26ce },
+
        { 0x26d4, 0x26d4 },     { 0x26ea, 0x26ea },     { 0x26f2, 0x26f3 },     { 0x26f5, 0x26f5 },
+
        { 0x26fa, 0x26fa },     { 0x26fd, 0x26fd },     { 0x2705, 0x2705 },     { 0x270a, 0x270b },
+
        { 0x2728, 0x2728 },     { 0x274c, 0x274c },     { 0x274e, 0x274e },     { 0x2753, 0x2755 },
+
        { 0x2757, 0x2757 },     { 0x2795, 0x2797 },     { 0x27b0, 0x27b0 },     { 0x27bf, 0x27bf },
+
        { 0x2b1b, 0x2b1c },     { 0x2b50, 0x2b50 },     { 0x2b55, 0x2b55 },     { 0x2e80, 0x2e99 },
+
        { 0x2e9b, 0x2ef3 },     { 0x2f00, 0x2fd5 },     { 0x2ff0, 0x2ffb },     { 0x3001, 0x303e },
+
        { 0x3041, 0x3096 },     { 0x3099, 0x30ff },     { 0x3105, 0x312e },     { 0x3131, 0x318e },
+
        { 0x3190, 0x31ba },     { 0x31c0, 0x31e3 },     { 0x31f0, 0x321e },     { 0x3220, 0x3247 },
+
        { 0x3250, 0x32fe },     { 0x3300, 0x4dbf },     { 0x4e00, 0xa48c },     { 0xa490, 0xa4c6 },
+
        { 0xa960, 0xa97c },     { 0xac00, 0xd7a3 },     { 0xf900, 0xfaff },     { 0xfe10, 0xfe19 },
+
        { 0xfe30, 0xfe52 },     { 0xfe54, 0xfe66 },     { 0xfe68, 0xfe6b },     { 0x16fe0, 0x16fe1 },
+
        { 0x17000, 0x187ec },   { 0x18800, 0x18af2 },   { 0x1b000, 0x1b11e },   { 0x1b170, 0x1b2fb },
+
        { 0x1f004, 0x1f004 },   { 0x1f0cf, 0x1f0cf },   { 0x1f18e, 0x1f18e },   { 0x1f191, 0x1f19a },
+
        { 0x1f200, 0x1f202 },   { 0x1f210, 0x1f23b },   { 0x1f240, 0x1f248 },   { 0x1f250, 0x1f251 },
+
        { 0x1f260, 0x1f265 },   { 0x1f300, 0x1f320 },   { 0x1f32d, 0x1f335 },   { 0x1f337, 0x1f37c },
+
        { 0x1f37e, 0x1f393 },   { 0x1f3a0, 0x1f3ca },   { 0x1f3cf, 0x1f3d3 },   { 0x1f3e0, 0x1f3f0 },
+
        { 0x1f3f4, 0x1f3f4 },   { 0x1f3f8, 0x1f43e },   { 0x1f440, 0x1f440 },   { 0x1f442, 0x1f4fc },
+
        { 0x1f4ff, 0x1f53d },   { 0x1f54b, 0x1f54e },   { 0x1f550, 0x1f567 },   { 0x1f57a, 0x1f57a },
+
        { 0x1f595, 0x1f596 },   { 0x1f5a4, 0x1f5a4 },   { 0x1f5fb, 0x1f64f },   { 0x1f680, 0x1f6c5 },
+
        { 0x1f6cc, 0x1f6cc },   { 0x1f6d0, 0x1f6d2 },   { 0x1f6eb, 0x1f6ec },   { 0x1f6f4, 0x1f6f8 },
+
        { 0x1f910, 0x1f93e },   { 0x1f940, 0x1f94c },   { 0x1f950, 0x1f96b },   { 0x1f980, 0x1f997 },
+
        { 0x1f9c0, 0x1f9c0 },   { 0x1f9d0, 0x1f9e6 },   { 0x20000, 0x2fffd },   { 0x30000, 0x3fffd },
+
};
+

+
#define ARRAYSIZE(A) sizeof(A) / sizeof(*(A))
+

+
static int cmp_range(const void *key, const void *cm)
+
{
+
    const struct utf8range *range = (const struct utf8range *)cm;
+
    int ch = *(int *)key;
+
    if (ch < range->lower) {
+
        return -1;
+
    }
+
    if (ch >= range->upper) {
+
        return 1;
+
    }
+
    return 0;
+
}
+

+
static int utf8_in_range(const struct utf8range *range, int num, int ch)
+
{
+
    const struct utf8range *r =
+
        bsearch(&ch, range, num, sizeof(*range), cmp_range);
+

+
    if (r) {
+
        return 1;
+
    }
+
    return 0;
+
}
+

+
int utf8_width(int ch)
+
{
+
    /* short circuit for common case */
+
    if (isascii(ch)) {
+
        return 1;
+
    }
+
    if (utf8_in_range(unicode_range_combining, ARRAYSIZE(unicode_range_combining), ch)) {
+
        return 0;
+
    }
+
    if (utf8_in_range(unicode_range_wide, ARRAYSIZE(unicode_range_wide), ch)) {
+
        return 2;
+
    }
+
    return 1;
+
}
+
#endif
added external/linenoise/utf8.h
@@ -0,0 +1,107 @@
+
#ifndef UTF8_UTIL_H
+
#define UTF8_UTIL_H
+

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

+
/**
+
 * UTF-8 utility functions
+
 *
+
 * (c) 2010-2019 Steve Bennett <steveb@workware.net.au>
+
 *
+
 * See utf8.c for licence details.
+
 */
+

+
#ifndef USE_UTF8
+
#include <ctype.h>
+

+
#define MAX_UTF8_LEN 1
+

+
/* No utf-8 support. 1 byte = 1 char */
+
#define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B))
+
#define utf8_strwidth(S, B) utf8_strlen((S), (B))
+
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
+
#define utf8_index(C, I) (I)
+
#define utf8_charlen(C) 1
+
 #define utf8_width(C) 1
+

+
#else
+

+
#define MAX_UTF8_LEN 4
+

+
/**
+
 * Converts the given unicode codepoint (0 - 0x1fffff) to utf-8
+
 * and stores the result at 'p'.
+
 *
+
 * Returns the number of utf-8 characters
+
 */
+
int utf8_fromunicode(char *p, unsigned uc);
+

+
/**
+
 * Returns the length of the utf-8 sequence starting with 'c'.
+
 *
+
 * Returns 1-4, or -1 if this is not a valid start byte.
+
 *
+
 * Note that charlen=4 is not supported by the rest of the API.
+
 */
+
int utf8_charlen(int c);
+

+
/**
+
 * Returns the number of characters in the utf-8
+
 * string of the given byte length.
+
 *
+
 * Any bytes which are not part of an valid utf-8
+
 * sequence are treated as individual characters.
+
 *
+
 * The string *must* be null terminated.
+
 *
+
 * Does not support unicode code points > \u1fffff
+
 */
+
int utf8_strlen(const char *str, int bytelen);
+

+
/**
+
 * Calculates the display width of the first 'charlen' characters in 'str'.
+
 * See utf8_width()
+
 */
+
int utf8_strwidth(const char *str, int charlen);
+

+
/**
+
 * Returns the byte index of the given character in the utf-8 string.
+
 *
+
 * The string *must* be null terminated.
+
 *
+
 * This will return the byte length of a utf-8 string
+
 * if given the char length.
+
 */
+
int utf8_index(const char *str, int charindex);
+

+
/**
+
 * Returns the unicode codepoint corresponding to the
+
 * utf-8 sequence 'str'.
+
 *
+
 * Stores the result in *uc and returns the number of bytes
+
 * consumed.
+
 *
+
 * If 'str' is null terminated, then an invalid utf-8 sequence
+
 * at the end of the string will be returned as individual bytes.
+
 *
+
 * If it is not null terminated, the length *must* be checked first.
+
 *
+
 * Does not support unicode code points > \u1fffff
+
 */
+
int utf8_tounicode(const char *str, int *uc);
+

+
/**
+
 * Returns the width (in characters) of the given unicode codepoint.
+
 * This is 1 for normal letters and 0 for combining characters and 2 for wide characters.
+
 */
+
int utf8_width(int ch);
+

+
#endif
+

+
#ifdef __cplusplus
+
}
+
#endif
+

+
#endif
modified external/sqlite/shell.c
@@ -210,8 +210,6 @@ typedef unsigned char u8;
#  ifndef strdup
#   define strdup _strdup
#  endif
-
#  undef popen
-
#  define popen _popen
#  undef pclose
#  define pclose _pclose
# endif
@@ -255,19 +253,9 @@ extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
#endif

-
/* 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
-
#endif
-
/************************* Begin ../ext/consio/console_io.h ******************/
+
/************************* Begin ../ext/misc/sqlite3_stdio.h ******************/
/*
-
** 2023 November 1
+
** 2024-09-24
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
@@ -276,281 +264,56 @@ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
-
********************************************************************************
-
** This file exposes various interfaces used for console and other I/O
-
** by the SQLite project command-line tools. These interfaces are used
-
** at either source conglomeration time, compilation time, or run time.
-
** This source provides for either inclusion into conglomerated,
-
** "single-source" forms or separate compilation then linking.
-
**
-
** Platform dependencies are "hidden" here by various stratagems so
-
** that, provided certain conditions are met, the programs using this
-
** source or object code compiled from it need no explicit conditional
-
** compilation in their source for their console and stream I/O.
-
**
-
** The symbols and functionality exposed here are not a public API.
-
** This code may change in tandem with other project code as needed.
-
**
-
** When this .h file and its companion .c are directly incorporated into
-
** a source conglomeration (such as shell.c), the preprocessor symbol
-
** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O
-
** translation for Windows is effected for the build.
-
*/
-
#define HAVE_CONSOLE_IO_H 1
-
#ifndef SQLITE_INTERNAL_LINKAGE
-
# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
-
# include <stdio.h>
-
#else
-
# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */
-
#endif
-

-
#ifndef SQLITE3_H
-
/* # include "sqlite3.h" */
-
#endif
-

-
#ifndef SQLITE_CIO_NO_CLASSIFY
-

-
/* Define enum for use with following function. */
-
typedef enum StreamsAreConsole {
-
  SAC_NoConsole = 0,
-
  SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4,
-
  SAC_AnyConsole = 0x7
-
} StreamsAreConsole;
-

-
/*
-
** Classify the three standard I/O streams according to whether
-
** they are connected to a console attached to the process.
+
*************************************************************************
**
-
** Returns the bit-wise OR of SAC_{In,Out,Err}Console values,
-
** or SAC_NoConsole if none of the streams reaches a console.
+
** This header file contains definitions of interfaces that provide 
+
** cross-platform I/O for UTF-8 content.
**
-
** This function should be called before any I/O is done with
-
** the given streams. As a side-effect, the given inputs are
-
** recorded so that later I/O operations on them may be done
-
** differently than the C library FILE* I/O would be done,
-
** iff the stream is used for the I/O functions that follow,
-
** and to support the ones that use an implicit stream.
+
** 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.
**
-
** On some platforms, stream or console mode alteration (aka
-
** "Setup") may be made which is undone by consoleRestore().
-
*/
-
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
-
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr );
-
/* A usual call for convenience: */
-
#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr)
-

-
/*
-
** After an initial call to consoleClassifySetup(...), renew
-
** the same setup it effected. (A call not after is an error.)
-
** This will restore state altered by consoleRestore();
+
** 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.
**
-
** Applications which run an inferior (child) process which
-
** inherits the same I/O streams may call this function after
-
** such a process exits to guard against console mode changes.
+
** 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.
*/
-
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void);
+
#ifndef _SQLITE3_STDIO_H_
+
#define _SQLITE3_STDIO_H_ 1
+
#ifdef _WIN32
+
/**** Definitions For Windows ****/
+
#include <stdio.h>
+
#include <windows.h>

-
/*
-
** Undo any side-effects left by consoleClassifySetup(...).
-
**
-
** This should be called after consoleClassifySetup() and
-
** before the process terminates normally. It is suitable
-
** for use with the atexit() C library procedure. After
-
** this call, no console I/O should be done until one of
-
** console{Classify or Renew}Setup(...) is called again.
-
**
-
** Applications which run an inferior (child) process that
-
** inherits the same I/O streams might call this procedure
-
** before so that said process will have a console setup
-
** however users have configured it or come to expect.
-
*/
-
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void );
+
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, ...);
+
void sqlite3_fsetmode(FILE *stream, int mode);

-
#else /* defined(SQLITE_CIO_NO_CLASSIFY) */
-
# define consoleClassifySetup(i,o,e)
-
# define consoleRenewSetup()
-
# define consoleRestore()
-
#endif /* defined(SQLITE_CIO_NO_CLASSIFY) */

-
#ifndef SQLITE_CIO_NO_REDIRECT
-
/*
-
** Set stream to be used for the functions below which write
-
** to "the designated X stream", where X is Output or Error.
-
** Returns the previous value.
-
**
-
** Alternatively, pass the special value, invalidFileStream,
-
** to get the designated stream value without setting it.
-
**
-
** Before the designated streams are set, they default to
-
** those passed to consoleClassifySetup(...), and before
-
** that is called they default to stdout and stderr.
-
**
-
** It is error to close a stream so designated, then, without
-
** designating another, use the corresponding {o,e}Emit(...).
-
*/
-
SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream;
-
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf);
-
# ifdef CONSIO_SET_ERROR_STREAM
-
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf);
-
# endif
#else
-
# define setOutputStream(pf)
-
# define setErrorStream(pf)
-
#endif /* !defined(SQLITE_CIO_NO_REDIRECT) */
-

-
#ifndef SQLITE_CIO_NO_TRANSLATE
-
/*
-
** Emit output like fprintf(). If the output is going to the
-
** console and translation from UTF-8 is necessary, perform
-
** the needed translation. Otherwise, write formatted output
-
** to the provided stream almost as-is, possibly with newline
-
** translation as specified by set{Binary,Text}Mode().
-
*/
-
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...);
-
/* Like fPrintfUtf8 except stream is always the designated output. */
-
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...);
-
/* Like fPrintfUtf8 except stream is always the designated error. */
-
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...);
-

-
/*
-
** Emit output like fputs(). If the output is going to the
-
** console and translation from UTF-8 is necessary, perform
-
** the needed translation. Otherwise, write given text to the
-
** provided stream almost as-is, possibly with newline
-
** translation as specified by set{Binary,Text}Mode().
-
*/
-
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO);
-
/* Like fPutsUtf8 except stream is always the designated output. */
-
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z);
-
/* Like fPutsUtf8 except stream is always the designated error. */
-
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z);
-

-
/*
-
** Emit output like fPutsUtf8(), except that the length of the
-
** accepted char or character sequence is limited by nAccept.
-
**
-
** Returns the number of accepted char values.
-
*/
-
#ifdef CONSIO_SPUTB
-
SQLITE_INTERNAL_LINKAGE int
-
fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept);
-
/* Like fPutbUtf8 except stream is always the designated output. */
-
#endif
-
SQLITE_INTERNAL_LINKAGE int
-
oPutbUtf8(const char *cBuf, int nAccept);
-
/* Like fPutbUtf8 except stream is always the designated error. */
-
#ifdef CONSIO_EPUTB
-
SQLITE_INTERNAL_LINKAGE int
-
ePutbUtf8(const char *cBuf, int nAccept);
-
#endif
-

-
/*
-
** Collect input like fgets(...) with special provisions for input
-
** from the console on platforms that require same. Defers to the
-
** C library fgets() when input is not from the console. Newline
-
** translation may be done as set by set{Binary,Text}Mode(). As a
-
** convenience, pfIn==NULL is treated as stdin.
-
*/
-
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
-
/* Like fGetsUtf8 except stream is always the designated input. */
-
/* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */
-

-
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
-

-
#ifndef SQLITE_CIO_NO_SETMODE
-
/*
-
** Set given stream for binary mode, where newline translation is
-
** not done, or for text mode where, for some platforms, newlines
-
** are translated to the platform's conventional char sequence.
-
** If bFlush true, flush the stream.
-
**
-
** An additional side-effect is that if the stream is one passed
-
** to consoleClassifySetup() as an output, it is flushed first.
-
**
-
** Note that binary/text mode has no effect on console I/O
-
** translation. On all platforms, newline to the console starts
-
** a new line and CR,LF chars from the console become a newline.
-
*/
-
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush);
-
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush);
-
#endif
-

-
#ifdef SQLITE_CIO_PROMPTED_IN
-
typedef struct Prompts {
-
  int numPrompts;
-
  const char **azPrompts;
-
} Prompts;
-

-
/*
-
** Macros for use of a line editor.
-
**
-
** The following macros define operations involving use of a
-
** line-editing library or simple console interaction.
-
** A "T" argument is a text (char *) buffer or filename.
-
** A "N" argument is an integer.
-
**
-
** SHELL_ADD_HISTORY(T) // Record text as line(s) of history.
-
** SHELL_READ_HISTORY(T) // Read history from file named by T.
-
** SHELL_WRITE_HISTORY(T) // Write history to file named by T.
-
** SHELL_STIFLE_HISTORY(N) // Limit history to N entries.
-
**
-
** A console program which does interactive console input is
-
** expected to call:
-
** SHELL_READ_HISTORY(T) before collecting such input;
-
** SHELL_ADD_HISTORY(T) as record-worthy input is taken;
-
** SHELL_STIFLE_HISTORY(N) after console input ceases; then
-
** SHELL_WRITE_HISTORY(T) before the program exits.
-
*/
-

-
/*
-
** Retrieve a single line of input text from an input stream.
-
**
-
** If pfIn is the input stream passed to consoleClassifySetup(),
-
** and azPrompt is not NULL, then a prompt is issued before the
-
** line is collected, as selected by the isContinuation flag.
-
** Array azPrompt[{0,1}] holds the {main,continuation} prompt.
-
**
-
** If zBufPrior is not NULL then it is a buffer from a prior
-
** call to this routine that can be reused, or will be freed.
-
**
-
** The result is stored in space obtained from malloc() and
-
** must either be freed by the caller or else passed back to
-
** this function as zBufPrior for reuse.
-
**
-
** This function may call upon services of a line-editing
-
** library to interactively collect line edited input.
-
*/
-
SQLITE_INTERNAL_LINKAGE char *
-
shellGetLine(FILE *pfIn, char *zBufPrior, int nLen,
-
             short isContinuation, Prompts azPrompt);
-
#endif /* defined(SQLITE_CIO_PROMPTED_IN) */
-
/*
-
** TBD: Define an interface for application(s) to generate
-
** completion candidates for use by the line-editor.
-
**
-
** This may be premature; the CLI is the only application
-
** that does this. Yet, getting line-editing melded into
-
** console I/O is desirable because a line-editing library
-
** may have to establish console operating mode, possibly
-
** in a way that interferes with the above functionality.
-
*/
-

-
#if !(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))
-
/* Skip over as much z[] input char sequence as is valid UTF-8,
-
** limited per nAccept char's or whole characters and containing
-
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
-
** sequence z:return (inclusive:exclusive) is validated UTF-8.
-
** Limit: nAccept>=0 => char count, nAccept<0 => character
-
 */
-
SQLITE_INTERNAL_LINKAGE const char*
-
zSkipValidUtf8(const char *z, int nAccept, long ccm);
+
/**** 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_fsetmode(F,X)   /*no-op*/

#endif
+
#endif /* _SQLITE3_STDIO_H_ */

-
/************************* End ../ext/consio/console_io.h ********************/
-
/************************* Begin ../ext/consio/console_io.c ******************/
+
/************************* End ../ext/misc/sqlite3_stdio.h ********************/
+
/************************* Begin ../ext/misc/sqlite3_stdio.c ******************/
/*
-
** 2023 November 4
+
** 2024-09-24
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
@@ -559,761 +322,318 @@ zSkipValidUtf8(const char *z, int nAccept, long ccm);
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
-
********************************************************************************
-
** This file implements various interfaces used for console and stream I/O
-
** by the SQLite project command-line tools, as explained in console_io.h .
-
** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there.
+
*************************************************************************
+
**
+
** Implementation of standard I/O interfaces for UTF-8 that are missing
+
** on Windows.
*/
-

-
#ifndef SQLITE_CDECL
-
# define SQLITE_CDECL
-
#endif
-

-
#ifndef SHELL_NO_SYSINC
-
# include <stdarg.h>
-
# include <string.h>
-
# include <stdlib.h>
-
# include <limits.h>
-
# include <assert.h>
-
/* # include "sqlite3.h" */
-
#endif
-
#ifndef HAVE_CONSOLE_IO_H
-
# include "console_io.h"
-
#endif
-
#if defined(_MSC_VER)
-
# pragma warning(disable : 4204)
+
#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>

-
#ifndef SQLITE_CIO_NO_TRANSLATE
-
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
-
#  ifndef SHELL_NO_SYSINC
-
#   include <io.h>
-
#   include <fcntl.h>
-
#   undef WIN32_LEAN_AND_MEAN
-
#   define WIN32_LEAN_AND_MEAN
-
#   include <windows.h>
-
#  endif
-
#  define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */
-
# else
-
#  ifndef SHELL_NO_SYSINC
-
#   include <unistd.h>
-
#  endif
-
#  define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */
-
# endif
+
/*
+
** 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.
+
*/
+
#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 CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
-
#endif
-

-
#if CIO_WIN_WC_XLATE
-
static HANDLE handleOfFile(FILE *pf){
-
  int fileDesc = _fileno(pf);
-
  union { intptr_t osfh; HANDLE fh; } fid = {
-
    (fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE
-
  };
-
  return fid.fh;
-
}
+
# define UseWtextForOutput(fd) _isatty(_fileno(fd))
+
# define UseWtextForInput(fd)  _isatty(_fileno(fd))
+
# define IsConsole(fd)         1
#endif

-
#ifndef SQLITE_CIO_NO_TRANSLATE
-
typedef struct PerStreamTags {
-
# if CIO_WIN_WC_XLATE
-
  HANDLE hx;
-
  DWORD consMode;
-
  char acIncomplete[4];
-
# else
-
  short reachesConsole;
-
# endif
-
  FILE *pf;
-
} PerStreamTags;
-

-
/* Define NULL-like value for things which can validly be 0. */
-
# define SHELL_INVALID_FILE_PTR ((FILE *)~0)
-
# if CIO_WIN_WC_XLATE
-
#  define SHELL_INVALID_CONS_MODE 0xFFFF0000
-
# endif
-

-
# if CIO_WIN_WC_XLATE
-
#  define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \
-
      {0,0,0,0}, SHELL_INVALID_FILE_PTR }
-
# else
-
#  define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
-
# endif
-

-
/* Quickly say whether a known output is going to the console. */
-
# if CIO_WIN_WC_XLATE
-
static short pstReachesConsole(PerStreamTags *ppst){
-
  return (ppst->hx != INVALID_HANDLE_VALUE);
-
}
-
# else
-
#  define pstReachesConsole(ppst) 0
-
# 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;

-
# if CIO_WIN_WC_XLATE
-
static void restoreConsoleArb(PerStreamTags *ppst){
-
  if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode);
-
}
-
# else
-
#  define restoreConsoleArb(ppst)
-
# endif

-
/* Say whether FILE* appears to be a console, collect associated info. */
-
static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
-
# if CIO_WIN_WC_XLATE
-
  short rv = 0;
-
  DWORD dwCM = SHELL_INVALID_CONS_MODE;
-
  HANDLE fh = handleOfFile(pf);
-
  ppst->pf = pf;
-
  if( INVALID_HANDLE_VALUE != fh ){
-
    rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM));
-
  }
-
  ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE;
-
  ppst->consMode = dwCM;
-
  return rv;
-
# else
-
  ppst->pf = pf;
-
  ppst->reachesConsole = ( (short)isatty(fileno(pf)) );
-
  return ppst->reachesConsole;
-
# endif
+
/*
+
** 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;
+
  }
}

-
# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
-
#  define ENABLE_VIRTUAL_TERMINAL_PROCESSING  (0x4)
-
# endif
-

-
# if CIO_WIN_WC_XLATE
-
/* Define console modes for use with the Windows Console API. */
-
#  define SHELL_CONI_MODE \
-
  (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
-
  | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
-
#  define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
-
  | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
-
# endif

-
typedef struct ConsoleInfo {
-
  PerStreamTags pstSetup[3];
-
  PerStreamTags pstDesignated[3];
-
  StreamsAreConsole sacSetup;
-
} ConsoleInfo;
+
/*
+
** 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;

-
static short isValidStreamInfo(PerStreamTags *ppst){
-
  return (ppst->pf != SHELL_INVALID_FILE_PTR);
+
  sz1 = (int)strlen(zFilename);
+
  sz2 = (int)strlen(zMode);
+
  b1 = malloc( (sz1+1)*sizeof(b1[0]) );
+
  b2 = malloc( (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);
+
  }
+
  free(b1);
+
  free(b2);
+
  simBinaryOther = 0;
+
  return fp;
}

-
static ConsoleInfo consoleInfo = {
-
  { /* pstSetup */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
-
  { /* pstDesignated[] */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
-
  SAC_NoConsole /* sacSetup */
-
};

-
SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0;
+
/*
+
** 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;

-
# if CIO_WIN_WC_XLATE
-
static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){
-
  if( pstReachesConsole(ppst) ){
-
    DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE;
-
    SetConsoleMode(ppst->hx, cm);
+
  sz1 = (int)strlen(zCommand);
+
  sz2 = (int)strlen(zMode);
+
  b1 = malloc( (sz1+1)*sizeof(b1[0]) );
+
  b2 = malloc( (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);
  }
+
  free(b1);
+
  free(b2);
+
  return fp;
}
-
# else
-
#  define maybeSetupAsConsole(ppst,odir)
-
# endif

-
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){
-
# if CIO_WIN_WC_XLATE
-
  int ix = 0;
-
  while( ix < 6 ){
-
    PerStreamTags *ppst = (ix<3)?
-
      &consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3];
-
    maybeSetupAsConsole(ppst, (ix % 3)>0);
-
    ++ix;
+
/*
+
** 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 = malloc( sz*sizeof(wchar_t) );
+
    if( b1==0 ) return 0;
+
    _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);
  }
-
# endif
}

-
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
-
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){
-
  StreamsAreConsole rv = SAC_NoConsole;
-
  FILE* apf[3] = { pfIn, pfOut, pfErr };
-
  int ix;
-
  for( ix = 2; ix >= 0; --ix ){
-
    PerStreamTags *ppst = &consoleInfo.pstSetup[ix];
-
    if( streamOfConsole(apf[ix], ppst) ){
-
      rv |= (SAC_InConsole<<ix);
+
/*
+
** 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;
    }
-
    consoleInfo.pstDesignated[ix] = *ppst;
-
    if( ix > 0 ) fflush(apf[ix]);
  }
-
  consoleInfo.sacSetup = rv;
-
  consoleRenewSetup();
-
  return rv;
}

-
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){
-
# if CIO_WIN_WC_XLATE
-
  static ConsoleInfo *pci = &consoleInfo;
-
  if( pci->sacSetup ){
-
    int ix;
-
    for( ix=0; ix<3; ++ix ){
-
      if( pci->sacSetup & (SAC_InConsole<<ix) ){
-
        PerStreamTags *ppst = &pci->pstSetup[ix];
-
        SetConsoleMode(ppst->hx, ppst->consMode);
-
      }
+
/*
+
** 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{
+
    /* When writing to the command-prompt in Windows, it is necessary
+
    ** to use O_U8TEXT to render Unicode U+0080 and greater.  Go ahead
+
    ** use O_U8TEXT for everything in text mode.
+
    */
+
    int sz = (int)strlen(z);
+
    wchar_t *b1 = malloc( (sz+1)*sizeof(wchar_t) );
+
    if( b1==0 ) return 0;
+
    sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
+
    b1[sz] = 0;
+
    _setmode(_fileno(out), _O_U8TEXT);
+
    if( UseBinaryWText(out) ){
+
      piecemealOutput(b1, sz, out);
+
    }else{
+
      fputws(b1, out);
    }
+
    sqlite3_free(b1);
+
    return 0;
  }
-
# endif
}
-
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */

-
#ifdef SQLITE_CIO_INPUT_REDIR
-
/* Say whether given FILE* is among those known, via either
-
** consoleClassifySetup() or set{Output,Error}Stream, as
-
** readable, and return an associated PerStreamTags pointer
-
** if so. Otherwise, return 0.
+

+
/*
+
** Work-alike for fprintf() from the standard C library.
*/
-
static PerStreamTags * isKnownReadable(FILE *pf){
-
  static PerStreamTags *apst[] = {
-
    &consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0
-
  };
-
  int ix = 0;
-
  do {
-
    if( apst[ix]->pf == pf ) break;
-
  } while( apst[++ix] != 0 );
-
  return apst[ix];
+
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;
}
-
#endif

-
#ifndef SQLITE_CIO_NO_TRANSLATE
-
/* Say whether given FILE* is among those known, via either
-
** consoleClassifySetup() or set{Output,Error}Stream, as
-
** writable, and return an associated PerStreamTags pointer
-
** if so. Otherwise, return 0.
+
/*
+
** Set the mode for an output stream.  mode argument is typically _O_BINARY or
+
** _O_TEXT.
*/
-
static PerStreamTags * isKnownWritable(FILE *pf){
-
  static PerStreamTags *apst[] = {
-
    &consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2],
-
    &consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0
-
  };
-
  int ix = 0;
-
  do {
-
    if( apst[ix]->pf == pf ) break;
-
  } while( apst[++ix] != 0 );
-
  return apst[ix];
-
}
-

-
static FILE *designateEmitStream(FILE *pf, unsigned chix){
-
  FILE *rv = consoleInfo.pstDesignated[chix].pf;
-
  if( pf == invalidFileStream ) return rv;
-
  else{
-
    /* Setting a possibly new output stream. */
-
    PerStreamTags *ppst = isKnownWritable(pf);
-
    if( ppst != 0 ){
-
      PerStreamTags pst = *ppst;
-
      consoleInfo.pstDesignated[chix] = pst;
-
    }else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]);
+
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);
  }
-
  return rv;
}

-
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){
-
  return designateEmitStream(pf, 1);
-
}
-
# ifdef CONSIO_SET_ERROR_STREAM
-
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){
-
  return designateEmitStream(pf, 2);
-
}
-
# endif
-
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
+
#endif /* defined(_WIN32) */

-
#ifndef SQLITE_CIO_NO_SETMODE
-
# if CIO_WIN_WC_XLATE
-
static void setModeFlushQ(FILE *pf, short bFlush, int mode){
-
  if( bFlush ) fflush(pf);
-
  _setmode(_fileno(pf), mode);
-
}
-
# else
-
#  define setModeFlushQ(f, b, m) if(b) fflush(f)
-
# endif
+
/************************* End ../ext/misc/sqlite3_stdio.c ********************/

-
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){
-
  setModeFlushQ(pf, bFlush, _O_BINARY);
-
}
-
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){
-
  setModeFlushQ(pf, bFlush, _O_TEXT);
-
}
-
# undef setModeFlushQ
-

-
#else /* defined(SQLITE_CIO_NO_SETMODE) */
-
# define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
-
# define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
-
#endif /* defined(SQLITE_CIO_NO_SETMODE) */
-

-
#ifndef SQLITE_CIO_NO_TRANSLATE
-
# if CIO_WIN_WC_XLATE
-
/* Write buffer cBuf as output to stream known to reach console,
-
** limited to ncTake char's. Return ncTake on success, else 0. */
-
static int conZstrEmit(PerStreamTags *ppst, const char *z, int ncTake){
-
  int rv = 0;
-
  if( z!=NULL ){
-
    int nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, 0,0);
-
    if( nwc > 0 ){
-
      WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR));
-
      if( zw!=NULL ){
-
        nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, zw,nwc);
-
        if( nwc > 0 ){
-
          /* Translation from UTF-8 to UTF-16, then WCHARs out. */
-
          if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){
-
            rv = ncTake;
-
          }
-
        }
-
        sqlite3_free(zw);
-
      }
-
    }
-
  }
-
  return rv;
-
}
+
/* Use console I/O package as a direct INCLUDE. */
+
#define SQLITE_INTERNAL_LINKAGE static

-
/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
-
static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){
-
  char *z = sqlite3_vmprintf(zFormat, ap);
-
  if( z ){
-
    int rv = conZstrEmit(ppst, z, (int)strlen(z));
-
    sqlite3_free(z);
-
    return rv;
-
  }else return 0;
-
}
-
# endif /* CIO_WIN_WC_XLATE */
+
#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

-
# ifdef CONSIO_GET_EMIT_STREAM
-
static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix,
-
                                               PerStreamTags *ppst){
-
  PerStreamTags *rv = isKnownWritable(pf);
-
  short isValid = (rv!=0)? isValidStreamInfo(rv) : 0;
-
  if( rv != 0 && isValid ) return rv;
-
  streamOfConsole(pf, ppst);
-
  return ppst;
-
}
-
# endif
+
#define eputz(z) sqlite3_fputs(z,stderr)
+
#define sputz(fp,z) sqlite3_fputs(z,fp)

-
/* Get stream info, either for designated output or error stream when
-
** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
-
** In either case, ppst references a caller-owned PerStreamTags
-
** struct which may be filled in if none of the known writable
-
** streams is being held by consoleInfo. The ppf parameter is a
-
** byref output when chix!=0 and a byref input when chix==0.
-
 */
-
static PerStreamTags *
-
getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
-
                  /* in/out */ FILE **ppf){
-
  PerStreamTags *ppstTry;
-
  FILE *pfEmit;
-
  if( chix > 0 ){
-
    ppstTry = &consoleInfo.pstDesignated[chix];
-
    if( !isValidStreamInfo(ppstTry) ){
-
      ppstTry = &consoleInfo.pstSetup[chix];
-
      pfEmit = ppst->pf;
-
    }else pfEmit = ppstTry->pf;
-
    if( !isValidStreamInfo(ppstTry) ){
-
      pfEmit = (chix > 1)? stderr : stdout;
-
      ppstTry = ppst;
-
      streamOfConsole(pfEmit, ppstTry);
-
    }
-
    *ppf = pfEmit;
-
  }else{
-
    ppstTry = isKnownWritable(*ppf);
-
    if( ppstTry != 0 ) return ppstTry;
-
    streamOfConsole(*ppf, ppst);
-
    return ppst;
-
  }
-
  return ppstTry;
+
/* True if the timer is enabled */
+
static int enableTimer = 0;
+

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

-
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){
-
  va_list ap;
-
  int rv;
-
  FILE *pfOut;
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
# if CIO_WIN_WC_XLATE
-
  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
-
# else
-
  getEmitStreamInfo(1, &pst, &pfOut);
-
# endif
-
  assert(zFormat!=0);
-
  va_start(ap, zFormat);
-
# if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ){
-
    rv = conioVmPrintf(ppst, zFormat, ap);
+
/* Return the current wall-clock time */
+
static sqlite3_int64 timeOfDay(void){
+
  static sqlite3_vfs *clockVfs = 0;
+
  sqlite3_int64 t;
+
  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
+
  if( clockVfs==0 ) return 0;  /* Never actually happens */
+
  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
+
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
  }else{
-
# endif
-
    rv = vfprintf(pfOut, zFormat, ap);
-
# if CIO_WIN_WC_XLATE
+
    double r;
+
    clockVfs->xCurrentTime(clockVfs, &r);
+
    t = (sqlite3_int64)(r*86400000.0);
  }
-
# endif
-
  va_end(ap);
-
  return rv;
-
}
-

-
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){
-
  va_list ap;
-
  int rv;
-
  FILE *pfErr;
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
# if CIO_WIN_WC_XLATE
-
  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
-
# else
-
  getEmitStreamInfo(2, &pst, &pfErr);
-
# endif
-
  assert(zFormat!=0);
-
  va_start(ap, zFormat);
-
# if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ){
-
    rv = conioVmPrintf(ppst, zFormat, ap);
-
  }else{
-
# endif
-
    rv = vfprintf(pfErr, zFormat, ap);
-
# if CIO_WIN_WC_XLATE
-
  }
-
# endif
-
  va_end(ap);
-
  return rv;
-
}
-

-
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){
-
  va_list ap;
-
  int rv;
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
# if CIO_WIN_WC_XLATE
-
  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
-
# else
-
  getEmitStreamInfo(0, &pst, &pfO);
-
# endif
-
  assert(zFormat!=0);
-
  va_start(ap, zFormat);
-
# if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ){
-
    maybeSetupAsConsole(ppst, 1);
-
    rv = conioVmPrintf(ppst, zFormat, ap);
-
    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
-
  }else{
-
# endif
-
    rv = vfprintf(pfO, zFormat, ap);
-
# if CIO_WIN_WC_XLATE
-
  }
-
# endif
-
  va_end(ap);
-
  return rv;
-
}
-

-
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
# if CIO_WIN_WC_XLATE
-
  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
-
# else
-
  getEmitStreamInfo(0, &pst, &pfO);
-
# endif
-
  assert(z!=0);
-
# if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ){
-
    int rv;
-
    maybeSetupAsConsole(ppst, 1);
-
    rv = conZstrEmit(ppst, z, (int)strlen(z));
-
    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
-
    return rv;
-
  }else {
-
# endif
-
    return (fputs(z, pfO)<0)? 0 : (int)strlen(z);
-
# if CIO_WIN_WC_XLATE
-
  }
-
# endif
-
}
-

-
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){
-
  FILE *pfErr;
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
# if CIO_WIN_WC_XLATE
-
  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
-
# else
-
  getEmitStreamInfo(2, &pst, &pfErr);
-
# endif
-
  assert(z!=0);
-
# if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
-
  else {
-
# endif
-
    return (fputs(z, pfErr)<0)? 0 : (int)strlen(z);
-
# if CIO_WIN_WC_XLATE
-
  }
-
# endif
-
}
-

-
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){
-
  FILE *pfOut;
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
# if CIO_WIN_WC_XLATE
-
  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
-
# else
-
  getEmitStreamInfo(1, &pst, &pfOut);
-
# endif
-
  assert(z!=0);
-
# if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
-
  else {
-
# endif
-
    return (fputs(z, pfOut)<0)? 0 : (int)strlen(z);
-
# if CIO_WIN_WC_XLATE
-
  }
-
# endif
-
}
-

-
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
-

-
#if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE))
-
/* Skip over as much z[] input char sequence as is valid UTF-8,
-
** limited per nAccept char's or whole characters and containing
-
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
-
** sequence z:return (inclusive:exclusive) is validated UTF-8.
-
** Limit: nAccept>=0 => char count, nAccept<0 => character
-
 */
-
SQLITE_INTERNAL_LINKAGE const char*
-
zSkipValidUtf8(const char *z, int nAccept, long ccm){
-
  int ng = (nAccept<0)? -nAccept : 0;
-
  const char *pcLimit = (nAccept>=0)? z+nAccept : 0;
-
  assert(z!=0);
-
  while( (pcLimit)? (z<pcLimit) : (ng-- != 0) ){
-
    char c = *z;
-
    if( (c & 0x80) == 0 ){
-
      if( ccm != 0L && c < 0x20 && ((1L<<c) & ccm) != 0 ) return z;
-
      ++z; /* ASCII */
-
    }else if( (c & 0xC0) != 0xC0 ) return z; /* not a lead byte */
-
    else{
-
      const char *zt = z+1; /* Got lead byte, look at trail bytes.*/
-
      do{
-
        if( pcLimit && zt >= pcLimit ) return z;
-
        else{
-
          char ct = *zt++;
-
          if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){
-
            /* Trailing bytes are too few, too many, or invalid. */
-
            return z;
-
          }
-
        }
-
      } while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
-
      z = zt;
-
    }
-
  }
-
  return z;
-
}
-
#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
-

-
#ifndef SQLITE_CIO_NO_TRANSLATE
-
# ifdef CONSIO_SPUTB
-
SQLITE_INTERNAL_LINKAGE int
-
fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){
-
  assert(pfO!=0);
-
#  if CIO_WIN_WC_XLATE
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
-
  if( pstReachesConsole(ppst) ){
-
    int rv;
-
    maybeSetupAsConsole(ppst, 1);
-
    rv = conZstrEmit(ppst, cBuf, nAccept);
-
    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
-
    return rv;
-
  }else {
-
#  endif
-
    return (int)fwrite(cBuf, 1, nAccept, pfO);
-
#  if CIO_WIN_WC_XLATE
-
  }
-
#  endif
-
}
-
# endif
-

-
SQLITE_INTERNAL_LINKAGE int
-
oPutbUtf8(const char *cBuf, int nAccept){
-
  FILE *pfOut;
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
# if CIO_WIN_WC_XLATE
-
  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
-
# else
-
  getEmitStreamInfo(1, &pst, &pfOut);
-
# endif
-
# if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ){
-
    return conZstrEmit(ppst, cBuf, nAccept);
-
  }else {
-
# endif
-
    return (int)fwrite(cBuf, 1, nAccept, pfOut);
-
# if CIO_WIN_WC_XLATE
-
  }
-
# endif
-
}
-

-
# ifdef CONSIO_EPUTB
-
SQLITE_INTERNAL_LINKAGE int
-
ePutbUtf8(const char *cBuf, int nAccept){
-
  FILE *pfErr;
-
  PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
-
  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
-
#  if CIO_WIN_WC_XLATE
-
  if( pstReachesConsole(ppst) ){
-
    return conZstrEmit(ppst, cBuf, nAccept);
-
  }else {
-
#  endif
-
    return (int)fwrite(cBuf, 1, nAccept, pfErr);
-
#  if CIO_WIN_WC_XLATE
-
  }
-
#  endif
-
}
-
# endif /* defined(CONSIO_EPUTB) */
-

-
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
-
  if( pfIn==0 ) pfIn = stdin;
-
# if CIO_WIN_WC_XLATE
-
  if( pfIn == consoleInfo.pstSetup[0].pf
-
      && (consoleInfo.sacSetup & SAC_InConsole)!=0 ){
-
#  if CIO_WIN_WC_XLATE==1
-
#   define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
-
    WCHAR wcBuf[SHELL_GULP+1];
-
    int lend = 0, noc = 0;
-
    if( ncMax > 0 ) cBuf[0] = 0;
-
    while( noc < ncMax-8-1 && !lend ){
-
      /* There is room for at least 2 more characters and a 0-terminator. */
-
      int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4;
-
#   undef SHELL_GULP
-
      DWORD nbr = 0;
-
      BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0);
-
      if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){
-
        /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
-
        DWORD nbrx;
-
        bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0);
-
        if( bRC ) nbr += nbrx;
-
      }
-
      if( !bRC || (noc==0 && nbr==0) ) return 0;
-
      if( nbr > 0 ){
-
        int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0);
-
        if( nmb != 0 && noc+nmb <= ncMax ){
-
          int iseg = noc;
-
          nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0);
-
          noc += nmb;
-
          /* Fixup line-ends as coded by Windows for CR (or "Enter".)
-
          ** This is done without regard for any setMode{Text,Binary}()
-
          ** call that might have been done on the interactive input.
-
          */
-
          if( noc > 0 ){
-
            if( cBuf[noc-1]=='\n' ){
-
              lend = 1;
-
              if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n';
-
            }
-
          }
-
          /* Check for ^Z (anywhere in line) too, to act as EOF. */
-
          while( iseg < noc ){
-
            if( cBuf[iseg]=='\x1a' ){
-
              noc = iseg; /* Chop ^Z and anything following. */
-
              lend = 1; /* Counts as end of line too. */
-
              break;
-
            }
-
            ++iseg;
-
          }
-
        }else break; /* Drop apparent garbage in. (Could assert.) */
-
      }else break;
-
    }
-
    /* If got nothing, (after ^Z chop), must be at end-of-file. */
-
    if( noc > 0 ){
-
      cBuf[noc] = 0;
-
      return cBuf;
-
    }else return 0;
-
#  endif
-
  }else{
-
# endif
-
    return fgets(cBuf, ncMax, pfIn);
-
# if CIO_WIN_WC_XLATE
-
  }
-
# endif
-
}
-
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
-

-
#if defined(_MSC_VER)
-
# pragma warning(default : 4204)
-
#endif
-

-
#undef SHELL_INVALID_FILE_PTR
-

-
/************************* End ../ext/consio/console_io.c ********************/
-

-
#ifndef SQLITE_SHELL_FIDDLE
-

-
/* From here onward, fgets() is redirected to the console_io library. */
-
# define fgets(b,n,f) fGetsUtf8(b,n,f)
-
/*
-
 * Define macros for emitting output text in various ways:
-
 *  sputz(s, z)      => emit 0-terminated string z to given stream s
-
 *  sputf(s, f, ...) => emit varargs per format f to given stream s
-
 *  oputz(z)         => emit 0-terminated string z to default stream
-
 *  oputf(f, ...)    => emit varargs per format f to default stream
-
 *  eputz(z)         => emit 0-terminated string z to error stream
-
 *  eputf(f, ...)    => emit varargs per format f to error stream
-
 *  oputb(b, n)      => emit char buffer b[0..n-1] to default stream
-
 *
-
 * Note that the default stream is whatever has been last set via:
-
 *   setOutputStream(FILE *pf)
-
 * This is normally the stream that CLI normal output goes to.
-
 * For the stand-alone CLI, it is stdout with no .output redirect.
-
 *
-
 * The ?putz(z) forms are required for the Fiddle builds for string literal
-
 * output, in aid of enforcing format string to argument correspondence.
-
 */
-
# define sputz(s,z) fPutsUtf8(z,s)
-
# define sputf fPrintfUtf8
-
# define oputz(z) oPutsUtf8(z)
-
# define oputf oPrintfUtf8
-
# define eputz(z) ePutsUtf8(z)
-
# define eputf ePrintfUtf8
-
# define oputb(buf,na) oPutbUtf8(buf,na)
-

-
#else
-
/* For Fiddle, all console handling and emit redirection is omitted. */
-
/* These next 3 macros are for emitting formatted output. When complaints
-
 * from the WASM build are issued for non-formatted output, (when a mere
-
 * string literal is to be emitted, the ?putz(z) forms should be used.
-
 * (This permits compile-time checking of format string / argument mismatch.)
-
 */
-
# define oputf(fmt, ...) printf(fmt,__VA_ARGS__)
-
# define eputf(fmt, ...) fprintf(stderr,fmt,__VA_ARGS__)
-
# define sputf(fp,fmt, ...) fprintf(fp,fmt,__VA_ARGS__)
-
/* These next 3 macros are for emitting simple string literals. */
-
# define oputz(z) fputs(z,stdout)
-
# define eputz(z) fputs(z,stderr)
-
# define sputz(fp,z) fputs(z,fp)
-
# define oputb(buf,na) fwrite(buf,1,na,stdout)
-
#endif
-

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

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

-
/* Return the current wall-clock time */
-
static sqlite3_int64 timeOfDay(void){
-
  static sqlite3_vfs *clockVfs = 0;
-
  sqlite3_int64 t;
-
  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
-
  if( clockVfs==0 ) return 0;  /* Never actually happens */
-
  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
-
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
-
  }else{
-
    double r;
-
    clockVfs->xCurrentTime(clockVfs, &r);
-
    t = (sqlite3_int64)(r*86400000.0);
-
  }
-
  return t;
+
  return t;
}

#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
@@ -1329,6 +649,7 @@ struct rusage {
#define getrusage(A,B) memset(B,0,sizeof(*B))
#endif

+

/* Saved resource information for the beginning of an operation */
static struct rusage sBegin;  /* CPU time at start */
static sqlite3_int64 iBegin;  /* Wall-clock time at start */
@@ -1352,12 +673,12 @@ static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
/*
** Print the timing results.
*/
-
static void endTimer(void){
+
static void endTimer(FILE *out){
  if( enableTimer ){
    sqlite3_int64 iEnd = timeOfDay();
    struct rusage sEnd;
    getrusage(RUSAGE_SELF, &sEnd);
-
    sputf(stdout, "Run Time: real %.3f user %f sys %f\n",
+
    sqlite3_fprintf(out, "Run Time: real %.3f user %f sys %f\n",
          (iEnd - iBegin)*0.001,
          timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
          timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
@@ -1365,7 +686,7 @@ static void endTimer(void){
}

#define BEGIN_TIMER beginTimer()
-
#define END_TIMER endTimer()
+
#define END_TIMER(X) endTimer(X)
#define HAS_TIMER 1

#elif (defined(_WIN32) || defined(WIN32))
@@ -1431,12 +752,12 @@ static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
/*
** Print the timing results.
*/
-
static void endTimer(void){
+
static void endTimer(FILE *out){
  if( enableTimer && getProcessTimesAddr){
    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
    sqlite3_int64 ftWallEnd = timeOfDay();
    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
-
    sputf(stdout, "Run Time: real %.3f user %f sys %f\n",
+
    sqlite3_fprintf(out, "Run Time: real %.3f user %f sys %f\n",
          (ftWallEnd - ftWallBegin)*0.001,
          timeDiff(&ftUserBegin, &ftUserEnd),
          timeDiff(&ftKernelBegin, &ftKernelEnd));
@@ -1444,12 +765,12 @@ static void endTimer(void){
}

#define BEGIN_TIMER beginTimer()
-
#define END_TIMER endTimer()
+
#define END_TIMER(X) endTimer(X)
#define HAS_TIMER hasTimer()

#else
#define BEGIN_TIMER
-
#define END_TIMER
+
#define END_TIMER(X)  /*no-op*/
#define HAS_TIMER 0
#endif

@@ -1523,6 +844,14 @@ static char *shell_strncpy(char *dest, const char *src, size_t n){
}

/*
+
** strcpy() workalike to squelch an unwarranted link-time warning
+
** from OpenBSD.
+
*/
+
static void shell_strcpy(char *dest, const char *src){
+
  while( (*(dest++) = *(src++))!=0 ){}
+
}
+

+
/*
** Optionally disable dynamic continuation prompt.
** Unless disabled, the continuation prompt shows open SQL lexemes if any,
** or open parentheses level if non-zero, or continuation prompt as set.
@@ -1587,7 +916,7 @@ static char *dynamicContinuePrompt(void){
      size_t ncp = strlen(continuePrompt);
      size_t ndp = strlen(dynPrompt.zScannerAwaits);
      if( ndp > ncp-3 ) return continuePrompt;
-
      strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
+
      shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
      while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' ';
      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
              PROMPT_LEN_MAX-4);
@@ -1642,37 +971,212 @@ static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
  va_start(ap, zFormat);
  z = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
-
  sputf(iotrace, "%s", z);
+
  sqlite3_fprintf(iotrace, "%s", z);
  sqlite3_free(z);
}
#endif

+
/* 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 */
+
} aUWidth[] = {
+
   /* {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, 0x01038},  {0, 0x01039},  {1, 0x0103a},  {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 cli_wcwidth(int c){
+
  int iFirst, iLast;
+

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

+
  /* The general case */
+
  iFirst = 0;
+
  iLast = sizeof(aUWidth)/sizeof(aUWidth[0]) - 1;
+
  while( iFirst<iLast-1 ){
+
    int iMid = (iFirst+iLast)/2;
+
    int cMid = aUWidth[iMid].iFirst;
+
    if( cMid < c ){
+
      iFirst = iMid;
+
    }else if( cMid > c ){
+
      iLast = iMid - 1;
+
    }else{
+
      return aUWidth[iMid].w;
+
    }
+
  }
+
  if( aUWidth[iLast].iFirst > c ) return aUWidth[iFirst].w;
+
  return aUWidth[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.
+
*/
+
static int decodeUtf8(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[4] & 0x3f);
+
    return 4;
+
  }
+
  *pU = 0;
+
  return 1;
+
}
+

+

+
#if 0 /* NOT USED */
+
/*
+
** Return the width, in display columns, of a UTF-8 string.
+
**
+
** Each normal character counts as 1.  Zero-width characters count
+
** as zero, and double-width characters count as 2.
+
*/
+
int cli_wcswidth(const char *z){
+
  const unsigned char *a = (const unsigned char*)z;
+
  int n = 0;
+
  int i = 0;
+
  unsigned char c;
+
  while( (c = a[i])!=0 ){
+
    if( c>=0xc0 ){
+
      int u;
+
      int len = decodeUtf8(&a[i], &u);
+
      i += len;
+
      n += cli_wcwidth(u);
+
    }else if( c>=' ' ){
+
      n++;
+
      i++;
+
    }else{
+
      i++;
+
    }
+
  }
+
  return n;
+
}
+
#endif
+

/*
-
** Output string zUtf to Out stream as w characters.  If w is negative,
+
** Output string zUtf to stdout as w characters.  If w is negative,
** then right-justify the text.  W is the width in UTF-8 characters, not
** in bytes.  This is different from the %*.*s specification in printf
** since with %*.*s the width is measured in bytes, not characters.
+
**
+
** Take into account zero-width and double-width Unicode characters.
+
** In other words, a zero-width character does not count toward the
+
** the w limit.  A double-width character counts as two.
*/
-
static void utf8_width_print(int w, const char *zUtf){
-
  int i;
-
  int n;
+
static void utf8_width_print(FILE *out, int w, const char *zUtf){
+
  const unsigned char *a = (const unsigned char*)zUtf;
+
  unsigned char c;
+
  int i = 0;
+
  int n = 0;
  int aw = w<0 ? -w : w;
  if( zUtf==0 ) zUtf = "";
-
  for(i=n=0; zUtf[i]; i++){
-
    if( (zUtf[i]&0xc0)!=0x80 ){
-
      n++;
-
      if( n==aw ){
-
        do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
+
  while( (c = a[i])!=0 ){
+
    if( (c&0xc0)==0xc0 ){
+
      int u;
+
      int len = decodeUtf8(a+i, &u);
+
      int x = cli_wcwidth(u);
+
      if( x+n>aw ){
        break;
      }
+
      i += len;
+
      n += x;
+
    }else if( n>=aw ){
+
      break;
+
    }else{
+
      n++;
+
      i++;
    }
  }
  if( n>=aw ){
-
    oputf("%.*s", i, zUtf);
+
    sqlite3_fprintf(out, "%.*s", i, zUtf);
  }else if( w<0 ){
-
    oputf("%*s%s", aw-n, "", zUtf);
+
    sqlite3_fprintf(out, "%*s%s", aw-n, "", zUtf);
  }else{
-
    oputf("%s%*s", zUtf, aw-n, "");
+
    sqlite3_fprintf(out, "%s%*s", zUtf, aw-n, "");
  }
}

@@ -1738,7 +1242,7 @@ static FILE * openChrSource(const char *zFile){
  /* On Windows, open first, then check the stream nature. This order
  ** is necessary because _stat() and sibs, when checking a named pipe,
  ** effectively break the pipe as its supplier sees it. */
-
  FILE *rv = fopen(zFile, "rb");
+
  FILE *rv = sqlite3_fopen(zFile, "rb");
  if( rv==0 ) return 0;
  if( _fstat64(_fileno(rv), &x) != 0
      || !STAT_CHR_SRC(x.st_mode)){
@@ -1752,7 +1256,7 @@ static FILE * openChrSource(const char *zFile){
# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
  if( rc!=0 ) return 0;
  if( STAT_CHR_SRC(x.st_mode) ){
-
    return fopen(zFile, "rb");
+
    return sqlite3_fopen(zFile, "rb");
  }else{
    return 0;
  }
@@ -1779,7 +1283,7 @@ static char *local_getline(char *zLine, FILE *in){
      zLine = realloc(zLine, nLine);
      shell_check_oom(zLine);
    }
-
    if( fgets(&zLine[n], nLine - n, in)==0 ){
+
    if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){
      if( n==0 ){
        free(zLine);
        return 0;
@@ -2848,10 +2352,20 @@ int sqlite3PcacheTraceDeactivate(void){
** Two SQL functions are implemented:
**
**     sha3(X,SIZE)
-
**     sha3_query(Y,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.
+
** 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.
@@ -2859,6 +2373,68 @@ int sqlite3PcacheTraceDeactivate(void){
** 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 mimimum-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
@@ -2908,6 +2484,7 @@ struct SHA3Context {
  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 */
};

/*
@@ -3237,6 +2814,7 @@ static void KeccakF1600Step(SHA3Context *p){
*/
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{
@@ -3381,6 +2959,60 @@ static void sha3_step_vformat(
}

/*
+
** 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
@@ -3469,12 +3101,428 @@ static void sha3QueryFunc(
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      SHA3Update(&cx,(const unsigned char*)"R",1);
      for(i=0; i<nCol; i++){
-
        switch( sqlite3_column_type(pStmt,i) ){
-
          case SQLITE_NULL: {
-
            SHA3Update(&cx, (const unsigned char*)"N",1);
-
            break;
-
          }
-
          case SQLITE_INTEGER: {
+
        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
+
*****************************************************************************/
+

+
/*
+
** Implementation of the sha1(X) function.
+
**
+
** Return 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 hash without the trailing 0x00 terminator.  The hash of a NULL
+
** value is NULL.
+
*/
+
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]);
+
  char zOut[44];
+

+
  assert( argc==1 );
+
  if( eType==SQLITE_NULL ) return;
+
  hash_init(&cx);
+
  if( eType==SQLITE_BLOB ){
+
    hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
+
  }else{
+
    hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
+
  }
+
  if( sqlite3_user_data(context)!=0 ){
+
    hash_finish(&cx, zOut, 1);
+
    sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
+
  }else{
+
    hash_finish(&cx, zOut, 0);
+
    sqlite3_result_blob(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);
+
    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];
@@ -3485,7 +3533,7 @@ static void sha3QueryFunc(
              u >>= 8;
            }
            x[0] = 'I';
-
            SHA3Update(&cx, x, 9);
+
            hash_step(&cx, x, 9);
            break;
          }
          case SQLITE_FLOAT: {
@@ -3499,21 +3547,21 @@ static void sha3QueryFunc(
              u >>= 8;
            }
            x[0] = 'F';
-
            SHA3Update(&cx,x,9);
+
            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);
-
            sha3_step_vformat(&cx,"T%d:",n2);
-
            SHA3Update(&cx, z2, n2);
+
            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);
-
            sha3_step_vformat(&cx,"B%d:",n2);
-
            SHA3Update(&cx, z2, n2);
+
            hash_step_vformat(&cx,"B%d:",n2);
+
            hash_step(&cx, z2, n2);
            break;
          }
        }
@@ -3521,43 +3569,40 @@ static void sha3QueryFunc(
    }
    sqlite3_finalize(pStmt);
  }
-
  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
+
  hash_finish(&cx, zOut, 0);
+
  sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}


#ifdef _WIN32

#endif
-
int sqlite3_shathree_init(
+
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, "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);
-
  }
+
  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, "sha3_query", 1,
-
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
-
                      0, sha3QueryFunc, 0, 0);
+
    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, "sha3_query", 2,
-
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
-
                      0, sha3QueryFunc, 0, 0);
+
    rc = sqlite3_create_function(db, "sha1_query", 1, 
+
                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
+
                                 sha1QueryFunc, 0, 0);
  }
  return rc;
}

-
/************************* End ../ext/misc/shathree.c ********************/
+
/************************* End ../ext/misc/sha1.c ********************/
/************************* Begin ../ext/misc/uint.c ******************/
/*
** 2020-04-14
@@ -4540,11 +4585,9 @@ int sqlite3_decimal_init(
}

/************************* End ../ext/misc/decimal.c ********************/
-
#undef sqlite3_base_init
-
#define sqlite3_base_init sqlite3_base64_init
-
/************************* Begin ../ext/misc/base64.c ******************/
+
/************************* Begin ../ext/misc/percentile.c ******************/
/*
-
** 2022-11-18
+
** 2013-05-28
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
@@ -4553,36 +4596,544 @@ int sqlite3_decimal_init(
**    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 file contains code to implement the percentile(Y,P) SQL function
+
** and similar as described below:
**
-
** 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.
+
**   (1)  The percentile(Y,P) function is an aggregate function taking
+
**        exactly two arguments.
**
-
** 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.
+
**   (2)  If the P argument to percentile(Y,P) is not the same for every
+
**        row in the aggregate then an error is thrown.  The word "same"
+
**        in the previous sentence means that the value differ by less
+
**        than 0.001.
**
-
** 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.
+
**   (3)  If the P argument to percentile(Y,P) evaluates to anything other
+
**        than a number in the range of 0.0 to 100.0 inclusive then an
+
**        error is thrown.
**
-
** 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.
+
**   (4)  If any Y argument to percentile(Y,P) evaluates to a value that
+
**        is not NULL and is not numeric then an error is thrown.
**
-
** This code relies on UTF-8 encoding only with respect to the
+
**   (5)  If any Y argument to percentile(Y,P) evaluates to plus or minus
+
**        infinity then an error is thrown.  (SQLite always interprets NaN
+
**        values as NULL.)
+
**
+
**   (6)  Both Y and P in percentile(Y,P) can be arbitrary expressions,
+
**        including CASE WHEN expressions.
+
**
+
**   (7)  The percentile(Y,P) aggregate is able to handle inputs of at least
+
**        one million (1,000,000) rows.
+
**
+
**   (8)  If there are no non-NULL values for Y, then percentile(Y,P)
+
**        returns NULL.
+
**
+
**   (9)  If there is exactly one non-NULL value for Y, the percentile(Y,P)
+
**        returns the one Y value.
+
**
+
**  (10)  If there N non-NULL values of Y where N is two or more and
+
**        the Y values are ordered from least to greatest and a graph is
+
**        drawn from 0 to N-1 such that the height of the graph at J is
+
**        the J-th Y value and such that straight lines are drawn between
+
**        adjacent Y values, then the percentile(Y,P) function returns
+
**        the height of the graph at P*(N-1)/100.
+
**
+
**  (11)  The percentile(Y,P) function always returns either a floating
+
**        point number or NULL.
+
**
+
**  (12)  The percentile(Y,P) is implemented as a single C99 source-code
+
**        file that compiles into a shared-library or DLL that can be loaded
+
**        into SQLite using the sqlite3_load_extension() interface.
+
**
+
**  (13)  A separate median(Y) function is the equivalent percentile(Y,50).
+
**
+
**  (14)  A separate percentile_cont(Y,P) function is equivalent to
+
**        percentile(Y,P/100.0).  In other words, the fraction value in
+
**        the second argument is in the range of 0 to 1 instead of 0 to 100.
+
**
+
**  (15)  A separate percentile_disc(Y,P) function is like
+
**        percentile_cont(Y,P) except that instead of returning the weighted
+
**        average of the nearest two input values, it returns the next lower
+
**        value.  So the percentile_disc(Y,P) will always return a value
+
**        that was one of the inputs.
+
**
+
**  (16)  All of median(), percentile(Y,P), percentile_cont(Y,P) and
+
**        percentile_disc(Y,P) can be used as window functions.
+
**
+
** Differences from standard SQL:
+
**
+
**  *  The percentile_cont(X,P) function is equivalent to the following in
+
**     standard SQL:
+
**
+
**         (percentile_cont(P) WITHIN GROUP (ORDER BY X))
+
**
+
**     The SQLite syntax is much more compact.  The standard SQL syntax
+
**     is also supported if SQLite is compiled with the
+
**     -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option.
+
**
+
**  *  No median(X) function exists in the SQL standard.  App developers
+
**     are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)".
+
**
+
**  *  No percentile(Y,P) function exists in the SQL standard.  Instead of
+
**     percential(Y,P), developers must write this:
+
**     "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)".  Note that
+
**     the fraction parameter to percentile() goes from 0 to 100 whereas
+
**     the fraction parameter in SQL standard percentile_cont() goes from
+
**     0 to 1.
+
**
+
** Implementation notes as of 2024-08-31:
+
**
+
**  *  The regular aggregate-function versions of these routines work
+
**     by accumulating all values in an array of doubles, then sorting
+
**     that array using quicksort before computing the answer. Thus
+
**     the runtime is O(NlogN) where N is the number of rows of input.
+
**
+
**  *  For the window-function versions of these routines, the array of
+
**     inputs is sorted as soon as the first value is computed.  Thereafter,
+
**     the array is kept in sorted order using an insert-sort.  This
+
**     results in O(N*K) performance where K is the size of the window.
+
**     One can imagine alternative implementations that give O(N*logN*logK)
+
**     performance, but they require more complex logic and data structures.
+
**     The developers have elected to keep the asymptotically slower
+
**     algorithm for now, for simplicity, under the theory that window
+
**     functions are seldom used and when they are, the window size K is
+
**     often small.  The developers might revisit that decision later,
+
**     should the need arise.
+
*/
+
#if defined(SQLITE3_H)
+
  /* no-op */
+
#elif defined(SQLITE_STATIC_PERCENTILE)
+
/* #  include "sqlite3.h" */
+
#else
+
/* #  include "sqlite3ext.h" */
+
   SQLITE_EXTENSION_INIT1
+
#endif
+
#include <assert.h>
+
#include <string.h>
+
#include <stdlib.h>
+

+
/* The following object is the group context for a single percentile()
+
** aggregate.  Remember all input Y values until the very end.
+
** Those values are accumulated in the Percentile.a[] array.
+
*/
+
typedef struct Percentile Percentile;
+
struct Percentile {
+
  unsigned nAlloc;     /* Number of slots allocated for a[] */
+
  unsigned nUsed;      /* Number of slots actually used in a[] */
+
  char bSorted;        /* True if a[] is already in sorted order */
+
  char bKeepSorted;    /* True if advantageous to keep a[] sorted */
+
  char bPctValid;      /* True if rPct is valid */
+
  double rPct;         /* Fraction.  0.0 to 1.0 */
+
  double *a;           /* Array of Y values */
+
};
+

+
/* Details of each function in the percentile family */
+
typedef struct PercentileFunc PercentileFunc;
+
struct PercentileFunc {
+
  const char *zName;   /* Function name */
+
  char nArg;           /* Number of arguments */
+
  char mxFrac;         /* Maximum value of the "fraction" input */
+
  char bDiscrete;      /* True for percentile_disc() */
+
};
+
static const PercentileFunc aPercentFunc[] = {
+
  { "median",           1,   1, 0 },
+
  { "percentile",       2, 100, 0 },
+
  { "percentile_cont",  2,   1, 0 },
+
  { "percentile_disc",  2,   1, 1 },
+
};
+

+
/*
+
** Return TRUE if the input floating-point number is an infinity.
+
*/
+
static int percentIsInfinity(double r){
+
  sqlite3_uint64 u;
+
  assert( sizeof(u)==sizeof(r) );
+
  memcpy(&u, &r, sizeof(u));
+
  return ((u>>52)&0x7ff)==0x7ff;
+
}
+

+
/*
+
** Return TRUE if two doubles differ by 0.001 or less.
+
*/
+
static int percentSameValue(double a, double b){
+
  a -= b;
+
  return a>=-0.001 && a<=0.001;
+
}
+

+
/*
+
** Search p (which must have p->bSorted) looking for an entry with
+
** value y.  Return the index of that entry.
+
**
+
** If bExact is true, return -1 if the entry is not found.
+
**
+
** If bExact is false, return the index at which a new entry with
+
** value y should be insert in order to keep the values in sorted
+
** order.  The smallest return value in this case will be 0, and
+
** the largest return value will be p->nUsed.
+
*/
+
static int percentBinarySearch(Percentile *p, double y, int bExact){
+
  int iFirst = 0;              /* First element of search range */
+
  int iLast = p->nUsed - 1;    /* Last element of search range */
+
  while( iLast>=iFirst ){
+
    int iMid = (iFirst+iLast)/2;
+
    double x = p->a[iMid];
+
    if( x<y ){
+
      iFirst = iMid + 1;
+
    }else if( x>y ){
+
      iLast = iMid - 1;
+
    }else{
+
      return iMid;
+
    }
+
  }
+
  if( bExact ) return -1;
+
  return iFirst;
+
}
+

+
/*
+
** Generate an error for a percentile function.
+
**
+
** The error format string must have exactly one occurrance of "%%s()"
+
** (with two '%' characters).  That substring will be replaced by the name
+
** of the function.
+
*/
+
static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){
+
  PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
+
  char *zMsg1;
+
  char *zMsg2;
+
  va_list ap;
+

+
  va_start(ap, zFormat);
+
  zMsg1 = sqlite3_vmprintf(zFormat, ap);
+
  va_end(ap);
+
  zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0;
+
  sqlite3_result_error(pCtx, zMsg2, -1);
+
  sqlite3_free(zMsg1);
+
  sqlite3_free(zMsg2);
+
}
+

+
/*
+
** The "step" function for percentile(Y,P) is called once for each
+
** input row.
+
*/
+
static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
+
  Percentile *p;
+
  double rPct;
+
  int eType;
+
  double y;
+
  assert( argc==2 || argc==1 );
+

+
  if( argc==1 ){
+
    /* Requirement 13:  median(Y) is the same as percentile(Y,50). */
+
    rPct = 0.5;
+
  }else{
+
    /* Requirement 3:  P must be a number between 0 and 100 */
+
    PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
+
    eType = sqlite3_value_numeric_type(argv[1]);
+
    rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac;
+
    if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
+
     || rPct<0.0 || rPct>1.0
+
    ){
+
      percentError(pCtx, "the fraction argument to %%s()"
+
                        " is not between 0.0 and %.1f",
+
                        (double)pFunc->mxFrac);
+
      return;
+
    }
+
  }
+

+
  /* Allocate the session context. */
+
  p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+
  if( p==0 ) return;
+

+
  /* Remember the P value.  Throw an error if the P value is different
+
  ** from any prior row, per Requirement (2). */
+
  if( !p->bPctValid ){
+
    p->rPct = rPct;
+
    p->bPctValid = 1;
+
  }else if( !percentSameValue(p->rPct,rPct) ){
+
    percentError(pCtx, "the fraction argument to %%s()"
+
                      " is not the same for all input rows");
+
    return;
+
  }
+

+
  /* Ignore rows for which Y is NULL */
+
  eType = sqlite3_value_type(argv[0]);
+
  if( eType==SQLITE_NULL ) return;
+

+
  /* If not NULL, then Y must be numeric.  Otherwise throw an error.
+
  ** Requirement 4 */
+
  if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
+
    percentError(pCtx, "input to %%s() is not numeric");
+
    return;
+
  }
+

+
  /* Throw an error if the Y value is infinity or NaN */
+
  y = sqlite3_value_double(argv[0]);
+
  if( percentIsInfinity(y) ){
+
    percentError(pCtx, "Inf input to %%s()");
+
    return;
+
  }
+

+
  /* Allocate and store the Y */
+
  if( p->nUsed>=p->nAlloc ){
+
    unsigned n = p->nAlloc*2 + 250;
+
    double *a = sqlite3_realloc64(p->a, sizeof(double)*n);
+
    if( a==0 ){
+
      sqlite3_free(p->a);
+
      memset(p, 0, sizeof(*p));
+
      sqlite3_result_error_nomem(pCtx);
+
      return;
+
    }
+
    p->nAlloc = n;
+
    p->a = a;
+
  }
+
  if( p->nUsed==0 ){
+
    p->a[p->nUsed++] = y;
+
    p->bSorted = 1;
+
  }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
+
    p->a[p->nUsed++] = y;
+
  }else if( p->bKeepSorted ){
+
    int i;
+
    i = percentBinarySearch(p, y, 0);
+
    if( i<(int)p->nUsed ){
+
      memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
+
    }
+
    p->a[i] = y;
+
    p->nUsed++;
+
  }else{
+
    p->a[p->nUsed++] = y;
+
    p->bSorted = 0;
+
  }
+
}
+

+
/*
+
** Interchange two doubles.
+
*/
+
#define SWAP_DOUBLE(X,Y)  {double ttt=(X);(X)=(Y);(Y)=ttt;}
+

+
/*
+
** Sort an array of doubles.
+
**
+
** Algorithm: quicksort
+
**
+
** This is implemented separately rather than using the qsort() routine
+
** from the standard library because:
+
**
+
**    (1)  To avoid a dependency on qsort()
+
**    (2)  To avoid the function call to the comparison routine for each
+
**         comparison.
+
*/
+
static void percentSort(double *a, unsigned int n){
+
  int iLt;  /* Entries before a[iLt] are less than rPivot */
+
  int iGt;  /* Entries at or after a[iGt] are greater than rPivot */
+
  int i;         /* Loop counter */
+
  double rPivot; /* The pivot value */
+
  
+
  assert( n>=2 );
+
  if( a[0]>a[n-1] ){
+
    SWAP_DOUBLE(a[0],a[n-1])
+
  }
+
  if( n==2 ) return;
+
  iGt = n-1;
+
  i = n/2;
+
  if( a[0]>a[i] ){
+
    SWAP_DOUBLE(a[0],a[i])
+
  }else if( a[i]>a[iGt] ){
+
    SWAP_DOUBLE(a[i],a[iGt])
+
  }
+
  if( n==3 ) return;
+
  rPivot = a[i];
+
  iLt = i = 1;
+
  do{
+
    if( a[i]<rPivot ){
+
      if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
+
      iLt++;
+
      i++;
+
    }else if( a[i]>rPivot ){
+
      do{
+
        iGt--;
+
      }while( iGt>i && a[iGt]>rPivot );
+
      SWAP_DOUBLE(a[i],a[iGt])
+
    }else{
+
      i++;
+
    }
+
  }while( i<iGt );
+
  if( iLt>=2 ) percentSort(a, iLt);
+
  if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
+
    
+
/* Uncomment for testing */
+
#if 0
+
  for(i=0; i<n-1; i++){
+
    assert( a[i]<=a[i+1] );
+
  }
+
#endif
+
}
+

+

+
/*
+
** The "inverse" function for percentile(Y,P) is called to remove a
+
** row that was previously inserted by "step".
+
*/
+
static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
+
  Percentile *p;
+
  int eType;
+
  double y;
+
  int i;
+
  assert( argc==2 || argc==1 );
+

+
  /* Allocate the session context. */
+
  p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+
  assert( p!=0 );
+

+
  /* Ignore rows for which Y is NULL */
+
  eType = sqlite3_value_type(argv[0]);
+
  if( eType==SQLITE_NULL ) return;
+

+
  /* If not NULL, then Y must be numeric.  Otherwise throw an error.
+
  ** Requirement 4 */
+
  if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
+
    return;
+
  }
+

+
  /* Ignore the Y value if it is infinity or NaN */
+
  y = sqlite3_value_double(argv[0]);
+
  if( percentIsInfinity(y) ){
+
    return;
+
  }
+
  if( p->bSorted==0 ){
+
    assert( p->nUsed>1 );
+
    percentSort(p->a, p->nUsed);
+
    p->bSorted = 1;
+
  }
+
  p->bKeepSorted = 1;
+

+
  /* Find and remove the row */
+
  i = percentBinarySearch(p, y, 1);
+
  if( i>=0 ){
+
    p->nUsed--;
+
    if( i<(int)p->nUsed ){
+
      memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
+
    }
+
  }
+
}
+

+
/*
+
** Compute the final output of percentile().  Clean up all allocated
+
** memory if and only if bIsFinal is true.
+
*/
+
static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
+
  Percentile *p;
+
  PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
+
  unsigned i1, i2;
+
  double v1, v2;
+
  double ix, vx;
+
  p = (Percentile*)sqlite3_aggregate_context(pCtx, 0);
+
  if( p==0 ) return;
+
  if( p->a==0 ) return;
+
  if( p->nUsed ){
+
    if( p->bSorted==0 ){
+
      assert( p->nUsed>1 );
+
      percentSort(p->a, p->nUsed);
+
      p->bSorted = 1;
+
    }
+
    ix = p->rPct*(p->nUsed-1);
+
    i1 = (unsigned)ix;
+
    if( pFunc->bDiscrete ){
+
      vx = p->a[i1];
+
    }else{
+
      i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
+
      v1 = p->a[i1];
+
      v2 = p->a[i2];
+
      vx = v1 + (v2-v1)*(ix-i1);
+
    }
+
    sqlite3_result_double(pCtx, vx);
+
  }
+
  if( bIsFinal ){
+
    sqlite3_free(p->a);
+
    memset(p, 0, sizeof(*p));
+
  }else{
+
    p->bKeepSorted = 1;
+
  }
+
}
+
static void percentFinal(sqlite3_context *pCtx){
+
  percentCompute(pCtx, 1);
+
}
+
static void percentValue(sqlite3_context *pCtx){
+
  percentCompute(pCtx, 0);
+
}
+

+
#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE)
+

+
#endif
+
int sqlite3_percentile_init(
+
  sqlite3 *db, 
+
  char **pzErrMsg, 
+
  const sqlite3_api_routines *pApi
+
){
+
  int rc = SQLITE_OK;
+
  unsigned int i;
+
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
+
  (void)pApi;      /* Unused parameter */
+
#else
+
  SQLITE_EXTENSION_INIT2(pApi);
+
#endif
+
  (void)pzErrMsg;  /* Unused parameter */
+
  for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
+
    rc = sqlite3_create_window_function(db,
+
            aPercentFunc[i].zName,
+
            aPercentFunc[i].nArg,
+
            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_SELFORDER1,
+
            (void*)&aPercentFunc[i],
+
            percentStep, percentFinal, percentValue, percentInverse, 0);
+
    if( rc ) break;
+
  }
+
  return rc;
+
}
+

+
/************************* End ../ext/misc/percentile.c ********************/
+
#undef sqlite3_base_init
+
#define sqlite3_base_init sqlite3_base64_init
+
/************************* 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,
@@ -5713,6 +6264,26 @@ int sqlite3_ieee_init(
** 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
@@ -5754,8 +6325,10 @@ static sqlite3_int64 genSeqMember(
/* typedef unsigned char u8; */

typedef struct SequenceSpec {
-
  sqlite3_int64 iBase;         /* Starting value ("start") */
-
  sqlite3_int64 iTerm;         /* Given terminal value ("stop") */
+
  sqlite3_int64 iOBase;        /* Original starting value ("start") */
+
  sqlite3_int64 iOTerm;        /* Original terminal value ("stop") */
+
  sqlite3_int64 iBase;         /* Starting value to actually use */
+
  sqlite3_int64 iTerm;         /* Terminal value to actually use */
  sqlite3_int64 iStep;         /* Increment ("step") */
  sqlite3_uint64 uSeqIndexMax; /* maximum sequence index (aka "n") */
  sqlite3_uint64 uSeqIndexNow; /* Current index during generation */
@@ -5948,9 +6521,9 @@ static int seriesColumn(
  series_cursor *pCur = (series_cursor*)cur;
  sqlite3_int64 x = 0;
  switch( i ){
-
    case SERIES_COLUMN_START:  x = pCur->ss.iBase; break;
-
    case SERIES_COLUMN_STOP:   x = pCur->ss.iTerm; break;
-
    case SERIES_COLUMN_STEP:   x = pCur->ss.iStep;   break;
+
    case SERIES_COLUMN_START:  x = pCur->ss.iOBase;     break;
+
    case SERIES_COLUMN_STOP:   x = pCur->ss.iOTerm;     break;
+
    case SERIES_COLUMN_STEP:   x = pCur->ss.iStep;      break;
    default:                   x = pCur->ss.iValueNow;  break;
  }
  sqlite3_result_int64(ctx, x);
@@ -5958,7 +6531,9 @@ static int seriesColumn(
}

#ifndef LARGEST_UINT64
+
#define LARGEST_INT64  (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
#define LARGEST_UINT64 (0xffffffff|(((sqlite3_uint64)0xffffffff)<<32))
+
#define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif

/*
@@ -5999,13 +6574,18 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
** parameter.  (idxStr is not used in this implementation.)  idxNum
** is a bitmask showing which constraints are available:
**
-
**   0x01:    start=VALUE
-
**   0x02:    stop=VALUE
-
**   0x04:    step=VALUE
-
**   0x08:    descending order
-
**   0x10:    ascending order
-
**   0x20:    LIMIT  VALUE
-
**   0x40:    OFFSET  VALUE
+
**   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
@@ -6018,6 +6598,12 @@ static int seriesFilter(
){
  series_cursor *pCur = (series_cursor *)pVtabCursor;
  int i = 0;
+
  int returnNoRows = 0;
+
  sqlite3_int64 iMin = SMALLEST_INT64;
+
  sqlite3_int64 iMax = LARGEST_INT64;
+
  sqlite3_int64 iLimit = 0;
+
  sqlite3_int64 iOffset = 0;
+

  (void)idxStrUnused;
  if( idxNum & 0x01 ){
    pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
@@ -6039,16 +6625,98 @@ static int seriesFilter(
  }else{
    pCur->ss.iStep = 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->ss.iBase = SMALLEST_INT64;
+
  }
+
  if( (idxNum & 0x06)==0 && (idxNum & 0x3080)!=0 ){
+
    pCur->ss.iTerm = LARGEST_INT64;
+
  }
+
  pCur->ss.iOBase = pCur->ss.iBase;
+
  pCur->ss.iOTerm = pCur->ss.iTerm;
+

+
  /* 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 ){
-
    sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
-
    sqlite3_int64 iTerm;
+
    iLimit = sqlite3_value_int64(argv[i++]);
    if( idxNum & 0x40 ){
-
      sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
-
      if( iOffset>0 ){
-
        pCur->ss.iBase += pCur->ss.iStep*iOffset;
+
      iOffset = sqlite3_value_int64(argv[i++]);
+
    }
+
  }
+

+
  if( idxNum & 0x3380 ){
+
    /* Extract the maximum range of output values determined by
+
    ** constraints on the "value" column.
+
    */
+
    if( idxNum & 0x0080 ){
+
      iMin = iMax = sqlite3_value_int64(argv[i++]);
+
    }else{
+
      if( idxNum & 0x0300 ){
+
        iMin = sqlite3_value_int64(argv[i++]);
+
        if( idxNum & 0x0200 ){
+
          if( iMin==LARGEST_INT64 ){
+
            returnNoRows = 1;
+
          }else{
+
            iMin++;
+
          }
+
        }
+
      }
+
      if( idxNum & 0x3000 ){
+
        iMax = sqlite3_value_int64(argv[i++]);
+
        if( idxNum & 0x2000 ){
+
          if( iMax==SMALLEST_INT64 ){
+
            returnNoRows = 1;
+
          }else{
+
            iMax--;
+
          }
+
        }
+
      }
+
      if( iMin>iMax ){
+
        returnNoRows = 1;
+
      }
+
    }
+

+
    /* Try to reduce the range of values to be generated based on
+
    ** constraints on the "value" column.
+
    */
+
    if( pCur->ss.iStep>0 ){
+
      sqlite3_int64 szStep = pCur->ss.iStep;
+
      if( pCur->ss.iBase<iMin ){
+
        sqlite3_uint64 d = iMin - pCur->ss.iBase;
+
        pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
+
      }
+
      if( pCur->ss.iTerm>iMax ){
+
        sqlite3_uint64 d = pCur->ss.iTerm - iMax;
+
        pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
      }
+
    }else{
+
      sqlite3_int64 szStep = -pCur->ss.iStep;
+
      assert( szStep>0 );
+
      if( pCur->ss.iBase>iMax ){
+
        sqlite3_uint64 d = pCur->ss.iBase - iMax;
+
        pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
+
      }
+
      if( pCur->ss.iTerm<iMin ){
+
        sqlite3_uint64 d = iMin - pCur->ss.iTerm;
+
        pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
+
      }
+
    }
+
  }
+

+
  /* Apply LIMIT and OFFSET constraints, if any */
+
  if( idxNum & 0x20 ){
+
    if( iOffset>0 ){
+
      pCur->ss.iBase += pCur->ss.iStep*iOffset;
    }
    if( iLimit>=0 ){
+
      sqlite3_int64 iTerm;
      iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
      if( pCur->ss.iStep<0 ){
        if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
@@ -6057,16 +6725,21 @@ static int seriesFilter(
      }
    }
  }
+

+

  for(i=0; i<argc; i++){
    if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
      /* If any of the constraints have a NULL value, then return no rows.
      ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
-
      pCur->ss.iBase = 1;
-
      pCur->ss.iTerm = 0;
-
      pCur->ss.iStep = 1;
+
      returnNoRows = 1;
      break;
    }
  }
+
  if( returnNoRows ){
+
    pCur->ss.iBase = 1;
+
    pCur->ss.iTerm = 0;
+
    pCur->ss.iStep = 1;
+
  }
  if( idxNum & 0x08 ){
    pCur->ss.isReversing = pCur->ss.iStep > 0;
  }else{
@@ -6087,13 +6760,35 @@ static int seriesFilter(
**
** The query plan is represented by bits in idxNum:
**
-
**   0x01  start = $value  -- constraint exists
-
**   0x02  stop = $value   -- constraint exists
-
**   0x04  step = $value   -- constraint exists
-
**   0x08  output is in descending order
-
**   0x10  output is in ascending order
-
**   0x20  LIMIT $value    -- constraint exists
-
**   0x40  OFFSET $value   -- constraint exists
+
**   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,
@@ -6106,7 +6801,9 @@ static int seriesBestIndex(
#endif
  int unusableMask = 0;  /* Mask of unusable constraints */
  int nArg = 0;          /* Number of arguments that seriesFilter() expects */
-
  int aIdx[5];           /* Constraints on start, stop, step, LIMIT, OFFSET */
+
  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
@@ -6114,7 +6811,7 @@ static int seriesBestIndex(
  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] = -1;
+
  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 */
@@ -6135,14 +6832,59 @@ static int seriesBestIndex(
      }
      continue;
    }
-
    if( pConstraint->iColumn<SERIES_COLUMN_START ) 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;
-
    }
+
    if( pConstraint->iColumn<SERIES_COLUMN_START ){
+
      if( pConstraint->iColumn==SERIES_COLUMN_VALUE ){
+
        switch( op ){
+
          case SQLITE_INDEX_CONSTRAINT_EQ:
+
          case SQLITE_INDEX_CONSTRAINT_IS: {
+
            idxNum |=  0x0080;
+
            idxNum &= ~0x3300;
+
            aIdx[5] = i;
+
            aIdx[6] = -1;
+
            bStartSeen = 1;
+
            break;
+
          }
+
          case SQLITE_INDEX_CONSTRAINT_GE: {
+
            if( idxNum & 0x0080 ) break;
+
            idxNum |=  0x0100;
+
            idxNum &= ~0x0200;
+
            aIdx[5] = i;
+
            bStartSeen = 1;
+
            break;
+
          }
+
          case SQLITE_INDEX_CONSTRAINT_GT: {
+
            if( idxNum & 0x0080 ) break;
+
            idxNum |=  0x0200;
+
            idxNum &= ~0x0100;
+
            aIdx[5] = i;
+
            bStartSeen = 1;
+
            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;
@@ -6157,7 +6899,7 @@ static int seriesBestIndex(
    idxNum &= ~0x60;
    aIdx[4] = 0;
  }
-
  for(i=0; i<5; i++){
+
  for(i=0; i<7; i++){
    if( (j = aIdx[i])>=0 ){
      pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
      pIdxInfo->aConstraintUsage[j].omit =
@@ -6205,6 +6947,9 @@ static int seriesBestIndex(
    pIdxInfo->estimatedRows = 2147483647;
  }
  pIdxInfo->idxNum = idxNum;
+
#ifdef SQLITE_INDEX_SCAN_HEX
+
  pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_HEX;
+
#endif
  return SQLITE_OK;
}

@@ -7192,7 +7937,7 @@ int sqlite3_regexp_init(
**   modification-time of the target file is set to this value before
**   returning.
**
-
**   If three or more arguments are passed to this function and an
+
**   If five or more arguments are passed to this function and an
**   error is encountered, an exception is raised.
**
** READFILE(FILE):
@@ -7262,6 +8007,13 @@ SQLITE_EXTENSION_INIT1
#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
@@ -7294,7 +8046,7 @@ static void readFileContents(sqlite3_context *ctx, const char *zName){
  sqlite3 *db;
  int mxBlob;

-
  in = fopen(zName, "rb");
+
  in = sqlite3_fopen(zName, "rb");
  if( in==0 ){
    /* File does not exist or is unreadable. Leave the result set to NULL. */
    return;
@@ -7549,7 +8301,7 @@ static int writeFile(
      sqlite3_int64 nWrite = 0;
      const char *z;
      int rc = 0;
-
      FILE *out = fopen(zFile, "wb");
+
      FILE *out = sqlite3_fopen(zFile, "wb");
      if( out==0 ) return 1;
      z = (const char*)sqlite3_value_blob(pData);
      if( z ){
@@ -8445,7 +9197,7 @@ static int completionNext(sqlite3_vtab_cursor *cur){
            zSql = sqlite3_mprintf(
               "%z%s"
               "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
-
                       " JOIN pragma_table_info(sm.name,%Q) AS pti"
+
                       " JOIN pragma_table_xinfo(sm.name,%Q) AS pti"
               " WHERE sm.type='table'",
               zSql, zSep, zDb, zDb
            );
@@ -9405,10 +10157,20 @@ SQLITE_EXTENSION_INIT1
#include <stdio.h>
#include <string.h>
#include <assert.h>
-
#include <stdint.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
@@ -10665,7 +11427,7 @@ static int zipfileFilter(
  }

  if( 0==pTab->pWriteFd && 0==bInMemory ){
-
    pCsr->pFile = zFile ? fopen(zFile, "rb") : 0;
+
    pCsr->pFile = zFile ? sqlite3_fopen(zFile, "rb") : 0;
    if( pCsr->pFile==0 ){
      zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
      rc = SQLITE_ERROR;
@@ -10855,7 +11617,7 @@ static int zipfileBegin(sqlite3_vtab *pVtab){
  ** structure into memory. During the transaction any new file data is 
  ** appended to the archive file, but the central directory is accumulated
  ** in main-memory until the transaction is committed.  */
-
  pTab->pWriteFd = fopen(pTab->zFile, "ab+");
+
  pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+");
  if( pTab->pWriteFd==0 ){
    pTab->base.zErrMsg = sqlite3_mprintf(
        "zipfile: failed to open file %s for writing", pTab->zFile
@@ -13308,6 +14070,66 @@ static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
  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);
@@ -13319,22 +14141,31 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
  **   2) Create the equivalent virtual table in dbv.
  */
  rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
-
      "SELECT type, name, sql, 1 FROM sqlite_schema "
-
      "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
+
      "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 FROM sqlite_schema "
+
      "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, 1"
+
      "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;
-
    if( zType[0]=='v' || zType[1]=='r' ){
-
      if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
+
    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);
@@ -13539,6 +14370,12 @@ static int idxPopulateOneStat1(
    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
@@ -13867,12 +14704,18 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
  if( rc==SQLITE_OK ){
    sqlite3_stmt *pSql = 0;
    rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
-
        "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
-
        " AND sql NOT LIKE 'CREATE VIRTUAL %%' ORDER BY rowid"
+
        "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);
-
      if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
+
      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);
  }
@@ -14069,7 +14912,6 @@ void sqlite3_expert_destroy(sqlite3expert *p){
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

/************************* End ../ext/expert/sqlite3expert.c ********************/
-

/************************* Begin ../ext/intck/sqlite3intck.h ******************/
/*
** 2024-02-08
@@ -15074,119 +15916,1209 @@ void sqlite3_intck_close(sqlite3_intck *p){
}

/*
-
** Step the integrity-check object.
+
** Step the integrity-check object.
+
*/
+
int sqlite3_intck_step(sqlite3_intck *p){
+
  if( p->rc==SQLITE_OK ){
+

+
    if( p->zMessage ){
+
      sqlite3_free(p->zMessage);
+
      p->zMessage = 0;
+
    }
+

+
    if( p->bCorruptSchema ){
+
      p->rc = SQLITE_DONE;
+
    }else
+
    if( p->pCheck==0 ){
+
      intckFindObject(p);
+
      if( p->rc==SQLITE_OK ){
+
        if( p->zObj ){
+
          char *zSql = 0;
+
          zSql = intckCheckObjectSql(p, p->zObj, p->zKey, &p->nKeyVal);
+
          p->pCheck = intckPrepare(p, zSql);
+
          sqlite3_free(zSql);
+
          sqlite3_free(p->zKey);
+
          p->zKey = 0;
+
        }else{
+
          p->rc = SQLITE_DONE;
+
        }
+
      }else if( p->rc==SQLITE_CORRUPT ){
+
        p->rc = SQLITE_OK;
+
        p->zMessage = intckMprintf(p, "%s",
+
            "corruption found while reading database schema"
+
        );
+
        p->bCorruptSchema = 1;
+
      }
+
    }
+

+
    if( p->pCheck ){
+
      assert( p->rc==SQLITE_OK );
+
      if( sqlite3_step(p->pCheck)==SQLITE_ROW ){
+
        /* Normal case, do nothing. */
+
      }else{
+
        intckFinalize(p, p->pCheck);
+
        p->pCheck = 0;
+
        p->nKeyVal = 0;
+
        if( p->rc==SQLITE_CORRUPT ){
+
          p->rc = SQLITE_OK;
+
          p->zMessage = intckMprintf(p, 
+
              "corruption found while scanning database object %s", p->zObj
+
          );
+
        }
+
      }
+
    }
+
  }
+

+
  return p->rc;
+
}
+

+
/*
+
** Return a message describing the corruption encountered by the most recent
+
** call to sqlite3_intck_step(), or NULL if no corruption was encountered.
+
*/
+
const char *sqlite3_intck_message(sqlite3_intck *p){
+
  assert( p->pCheck==0 || p->zMessage==0 );
+
  if( p->zMessage ){
+
    return p->zMessage;
+
  }
+
  if( p->pCheck ){
+
    return (const char*)sqlite3_column_text(p->pCheck, 0);
+
  }
+
  return 0;
+
}
+

+
/*
+
** Return the error code and message.
+
*/
+
int sqlite3_intck_error(sqlite3_intck *p, const char **pzErr){
+
  if( pzErr ) *pzErr = p->zErr;
+
  return (p->rc==SQLITE_DONE ? SQLITE_OK : p->rc);
+
}
+

+
/*
+
** Close any read transaction the integrity-check object is holding open
+
** on the database.
+
*/
+
int sqlite3_intck_unlock(sqlite3_intck *p){
+
  if( p->rc==SQLITE_OK && p->pCheck ){
+
    assert( p->zKey==0 && p->nKeyVal>0 );
+
    intckSaveKey(p);
+
    intckFinalize(p, p->pCheck);
+
    p->pCheck = 0;
+
  }
+
  return p->rc;
+
}
+

+
/*
+
** Return the SQL statement used to check object zObj. Or, if zObj is 
+
** NULL, the current SQL statement.
+
*/
+
const char *sqlite3_intck_test_sql(sqlite3_intck *p, const char *zObj){
+
  sqlite3_free(p->zTestSql);
+
  if( zObj ){
+
    p->zTestSql = intckCheckObjectSql(p, zObj, 0, 0);
+
  }else{
+
    if( p->zObj ){
+
      p->zTestSql = intckCheckObjectSql(p, p->zObj, p->zKey, 0);
+
    }else{
+
      sqlite3_free(p->zTestSql);
+
      p->zTestSql = 0;
+
    }
+
  }
+
  return p->zTestSql;
+
}
+

+
/************************* End ../ext/intck/sqlite3intck.c ********************/
+
/************************* Begin ../ext/misc/stmtrand.c ******************/
+
/*
+
** 2024-05-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.
+
**
+
******************************************************************************
+
**
+
** An SQL function that return pseudo-random non-negative integers.
+
**
+
**      SELECT stmtrand(123);
+
**
+
** A special feature of this function is that the same sequence of random
+
** integers is returned for each invocation of the statement.  This makes
+
** the results repeatable, and hence useful for testing.  The argument is
+
** an integer which is the seed for the random number sequence.  The seed
+
** is used by the first invocation of this function only and is ignored
+
** for all subsequent calls within the same statement.
+
**
+
** Resetting a statement (sqlite3_reset()) also resets the random number
+
** sequence.
+
*/
+
/* #include "sqlite3ext.h" */
+
SQLITE_EXTENSION_INIT1
+
#include <assert.h>
+
#include <string.h>
+

+
/* State of the pseudo-random number generator */
+
typedef struct Stmtrand {
+
  unsigned int x, y;
+
} Stmtrand;
+

+
/* auxdata key */
+
#define STMTRAND_KEY  (-4418371)
+

+
/*
+
** Function:     stmtrand(SEED)
+
**
+
** Return a pseudo-random number.
+
*/
+
static void stmtrandFunc(
+
  sqlite3_context *context,
+
  int argc,
+
  sqlite3_value **argv
+
){
+
  Stmtrand *p;
+

+
  p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
+
  if( p==0 ){
+
    unsigned int seed;
+
    p = sqlite3_malloc( sizeof(*p) );
+
    if( p==0 ){
+
      sqlite3_result_error_nomem(context);
+
      return;
+
    }
+
    if( argc>=1 ){
+
      seed = (unsigned int)sqlite3_value_int(argv[0]);
+
    }else{
+
      seed = 0;
+
    }
+
    p->x = seed | 1;
+
    p->y = seed;
+
    sqlite3_set_auxdata(context, STMTRAND_KEY, p, sqlite3_free);
+
    p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
+
    if( p==0 ){
+
      sqlite3_result_error_nomem(context);
+
      return;
+
    }
+
  }
+
  p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
+
  p->y = p->y*1103515245 + 12345;
+
  sqlite3_result_int(context, (int)((p->x ^ p->y)&0x7fffffff));
+
}
+

+
#ifdef _WIN32
+

+
#endif
+
int sqlite3_stmtrand_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, "stmtrand", 1, SQLITE_UTF8, 0,
+
                               stmtrandFunc, 0, 0);
+
  if( rc==SQLITE_OK ){
+
    rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
+
                                 stmtrandFunc, 0, 0);
+
  }
+
  return rc;
+
}
+

+
/************************* End ../ext/misc/stmtrand.c ********************/
+
/************************* Begin ../ext/misc/vfstrace.c ******************/
+
/*
+
** 2011 March 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 file contains code implements a VFS shim that writes diagnostic
+
** output for each VFS call, similar to "strace".
+
**
+
** USAGE:
+
**
+
** This source file exports a single symbol which is the name of a
+
** function:
+
**
+
**   int vfstrace_register(
+
**     const char *zTraceName,         // Name of the newly constructed VFS
+
**     const char *zOldVfsName,        // Name of the underlying VFS
+
**     int (*xOut)(const char*,void*), // Output routine.  ex: fputs
+
**     void *pOutArg,                  // 2nd argument to xOut.  ex: stderr
+
**     int makeDefault                 // Make the new VFS the default
+
**   );
+
**
+
** Applications that want to trace their VFS usage must provide a callback
+
** function with this prototype:
+
**
+
**   int traceOutput(const char *zMessage, void *pAppData);
+
**
+
** This function will "output" the trace messages, where "output" can
+
** mean different things to different applications.  The traceOutput function
+
** for the command-line shell (see shell.c) is "fputs" from the standard
+
** library, which means that all trace output is written on the stream
+
** specified by the second argument.  In the case of the command-line shell
+
** the second argument is stderr.  Other applications might choose to output
+
** trace information to a file, over a socket, or write it into a buffer.
+
**
+
** The vfstrace_register() function creates a new "shim" VFS named by
+
** the zTraceName parameter.  A "shim" VFS is an SQLite backend that does
+
** not really perform the duties of a true backend, but simply filters or
+
** interprets VFS calls before passing them off to another VFS which does
+
** the actual work.  In this case the other VFS - the one that does the
+
** real work - is identified by the second parameter, zOldVfsName.  If
+
** the 2nd parameter is NULL then the default VFS is used.  The common
+
** case is for the 2nd parameter to be NULL.
+
**
+
** The third and fourth parameters are the pointer to the output function
+
** and the second argument to the output function.  For the SQLite
+
** command-line shell, when the -vfstrace option is used, these parameters
+
** are fputs and stderr, respectively.
+
**
+
** The fifth argument is true (non-zero) to cause the newly created VFS
+
** to become the default VFS.  The common case is for the fifth parameter
+
** to be true.
+
**
+
** The call to vfstrace_register() simply creates the shim VFS that does
+
** tracing.  The application must also arrange to use the new VFS for
+
** all database connections that are created and for which tracing is 
+
** desired.  This can be done by specifying the trace VFS using URI filename
+
** notation, or by specifying the trace VFS as the 4th parameter to
+
** sqlite3_open_v2() or by making the trace VFS be the default (by setting
+
** the 5th parameter of vfstrace_register() to 1).
+
**
+
**
+
** ENABLING VFSTRACE IN A COMMAND-LINE SHELL
+
**
+
** The SQLite command line shell implemented by the shell.c source file
+
** can be used with this module.  To compile in -vfstrace support, first
+
** gather this file (test_vfstrace.c), the shell source file (shell.c),
+
** and the SQLite amalgamation source files (sqlite3.c, sqlite3.h) into
+
** the working directory.  Then compile using a command like the following:
+
**
+
**    gcc -o sqlite3 -Os -I. -DSQLITE_ENABLE_VFSTRACE \
+
**        -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
+
**        -DHAVE_READLINE -DHAVE_USLEEP=1 \
+
**        shell.c test_vfstrace.c sqlite3.c -ldl -lreadline -lncurses
+
**
+
** The gcc command above works on Linux and provides (in addition to the
+
** -vfstrace option) support for FTS3 and FTS4, RTREE, and command-line
+
** editing using the readline library.  The command-line shell does not
+
** use threads so we added -DSQLITE_THREADSAFE=0 just to make the code
+
** run a little faster.   For compiling on a Mac, you'll probably need
+
** to omit the -DHAVE_READLINE, the -lreadline, and the -lncurses options.
+
** The compilation could be simplified to just this:
+
**
+
**    gcc -DSQLITE_ENABLE_VFSTRACE \
+
**         shell.c test_vfstrace.c sqlite3.c -ldl -lpthread
+
**
+
** In this second example, all unnecessary options have been removed
+
** Note that since the code is now threadsafe, we had to add the -lpthread
+
** option to pull in the pthreads library.
+
**
+
** To cross-compile for windows using MinGW, a command like this might
+
** work:
+
**
+
**    /opt/mingw/bin/i386-mingw32msvc-gcc -o sqlite3.exe -Os -I \
+
**         -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_VFSTRACE \
+
**         shell.c test_vfstrace.c sqlite3.c
+
**
+
** Similar compiler commands will work on different systems.  The key
+
** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
+
** the shell.c source file will know to include the -vfstrace command-line
+
** option and (2) you must compile and link the three source files
+
** shell,c, test_vfstrace.c, and sqlite3.c.  
+
*/
+
#include <stdlib.h>
+
#include <string.h>
+
/* #include "sqlite3.h" */
+

+
/*
+
** An instance of this structure is attached to the each trace VFS to
+
** provide auxiliary information.
+
*/
+
typedef struct vfstrace_info vfstrace_info;
+
struct vfstrace_info {
+
  sqlite3_vfs *pRootVfs;              /* The underlying real VFS */
+
  int (*xOut)(const char*, void*);    /* Send output here */
+
  void *pOutArg;                      /* First argument to xOut */
+
  const char *zVfsName;               /* Name of this trace-VFS */
+
  sqlite3_vfs *pTraceVfs;             /* Pointer back to the trace VFS */
+
};
+

+
/*
+
** The sqlite3_file object for the trace VFS
+
*/
+
typedef struct vfstrace_file vfstrace_file;
+
struct vfstrace_file {
+
  sqlite3_file base;        /* Base class.  Must be first */
+
  vfstrace_info *pInfo;     /* The trace-VFS to which this file belongs */
+
  const char *zFName;       /* Base name of the file */
+
  sqlite3_file *pReal;      /* The real underlying file */
+
};
+

+
/*
+
** Method declarations for vfstrace_file.
+
*/
+
static int vfstraceClose(sqlite3_file*);
+
static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+
static int vfstraceWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
+
static int vfstraceTruncate(sqlite3_file*, sqlite3_int64 size);
+
static int vfstraceSync(sqlite3_file*, int flags);
+
static int vfstraceFileSize(sqlite3_file*, sqlite3_int64 *pSize);
+
static int vfstraceLock(sqlite3_file*, int);
+
static int vfstraceUnlock(sqlite3_file*, int);
+
static int vfstraceCheckReservedLock(sqlite3_file*, int *);
+
static int vfstraceFileControl(sqlite3_file*, int op, void *pArg);
+
static int vfstraceSectorSize(sqlite3_file*);
+
static int vfstraceDeviceCharacteristics(sqlite3_file*);
+
static int vfstraceShmLock(sqlite3_file*,int,int,int);
+
static int vfstraceShmMap(sqlite3_file*,int,int,int, void volatile **);
+
static void vfstraceShmBarrier(sqlite3_file*);
+
static int vfstraceShmUnmap(sqlite3_file*,int);
+

+
/*
+
** Method declarations for vfstrace_vfs.
+
*/
+
static int vfstraceOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
+
static int vfstraceDelete(sqlite3_vfs*, const char *zName, int syncDir);
+
static int vfstraceAccess(sqlite3_vfs*, const char *zName, int flags, int *);
+
static int vfstraceFullPathname(sqlite3_vfs*, const char *zName, int, char *);
+
static void *vfstraceDlOpen(sqlite3_vfs*, const char *zFilename);
+
static void vfstraceDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
+
static void (*vfstraceDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
+
static void vfstraceDlClose(sqlite3_vfs*, void*);
+
static int vfstraceRandomness(sqlite3_vfs*, int nByte, char *zOut);
+
static int vfstraceSleep(sqlite3_vfs*, int microseconds);
+
static int vfstraceCurrentTime(sqlite3_vfs*, double*);
+
static int vfstraceGetLastError(sqlite3_vfs*, int, char*);
+
static int vfstraceCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
+
static int vfstraceSetSystemCall(sqlite3_vfs*,const char*, sqlite3_syscall_ptr);
+
static sqlite3_syscall_ptr vfstraceGetSystemCall(sqlite3_vfs*, const char *);
+
static const char *vfstraceNextSystemCall(sqlite3_vfs*, const char *zName);
+

+
/*
+
** Return a pointer to the tail of the pathname.  Examples:
+
**
+
**     /home/drh/xyzzy.txt -> xyzzy.txt
+
**     xyzzy.txt           -> xyzzy.txt
+
*/
+
static const char *fileTail(const char *z){
+
  size_t i;
+
  if( z==0 ) return 0;
+
  i = strlen(z)-1;
+
  while( i>0 && z[i-1]!='/' ){ i--; }
+
  return &z[i];
+
}
+

+
/*
+
** Send trace output defined by zFormat and subsequent arguments.
+
*/
+
static void vfstrace_printf(
+
  vfstrace_info *pInfo,
+
  const char *zFormat,
+
  ...
+
){
+
  va_list ap;
+
  char *zMsg;
+
  va_start(ap, zFormat);
+
  zMsg = sqlite3_vmprintf(zFormat, ap);
+
  va_end(ap);
+
  pInfo->xOut(zMsg, pInfo->pOutArg);
+
  sqlite3_free(zMsg);
+
}
+

+
/*
+
** Try to convert an error code into a symbolic name for that error code.
+
*/
+
static const char *vfstrace_errcode_name(int rc ){
+
  const char *zVal = 0;
+
  switch( rc ){
+
    case SQLITE_OK:                 zVal = "SQLITE_OK";                 break;
+
    case SQLITE_INTERNAL:           zVal = "SQLITE_INTERNAL";           break;
+
    case SQLITE_ERROR:              zVal = "SQLITE_ERROR";              break;
+
    case SQLITE_PERM:               zVal = "SQLITE_PERM";               break;
+
    case SQLITE_ABORT:              zVal = "SQLITE_ABORT";              break;
+
    case SQLITE_BUSY:               zVal = "SQLITE_BUSY";               break;
+
    case SQLITE_LOCKED:             zVal = "SQLITE_LOCKED";             break;
+
    case SQLITE_NOMEM:              zVal = "SQLITE_NOMEM";              break;
+
    case SQLITE_READONLY:           zVal = "SQLITE_READONLY";           break;
+
    case SQLITE_INTERRUPT:          zVal = "SQLITE_INTERRUPT";          break;
+
    case SQLITE_IOERR:              zVal = "SQLITE_IOERR";              break;
+
    case SQLITE_CORRUPT:            zVal = "SQLITE_CORRUPT";            break;
+
    case SQLITE_NOTFOUND:           zVal = "SQLITE_NOTFOUND";           break;
+
    case SQLITE_FULL:               zVal = "SQLITE_FULL";               break;
+
    case SQLITE_CANTOPEN:           zVal = "SQLITE_CANTOPEN";           break;
+
    case SQLITE_PROTOCOL:           zVal = "SQLITE_PROTOCOL";           break;
+
    case SQLITE_EMPTY:              zVal = "SQLITE_EMPTY";              break;
+
    case SQLITE_SCHEMA:             zVal = "SQLITE_SCHEMA";             break;
+
    case SQLITE_TOOBIG:             zVal = "SQLITE_TOOBIG";             break;
+
    case SQLITE_CONSTRAINT:         zVal = "SQLITE_CONSTRAINT";         break;
+
    case SQLITE_MISMATCH:           zVal = "SQLITE_MISMATCH";           break;
+
    case SQLITE_MISUSE:             zVal = "SQLITE_MISUSE";             break;
+
    case SQLITE_NOLFS:              zVal = "SQLITE_NOLFS";              break;
+
    case SQLITE_IOERR_READ:         zVal = "SQLITE_IOERR_READ";         break;
+
    case SQLITE_IOERR_SHORT_READ:   zVal = "SQLITE_IOERR_SHORT_READ";   break;
+
    case SQLITE_IOERR_WRITE:        zVal = "SQLITE_IOERR_WRITE";        break;
+
    case SQLITE_IOERR_FSYNC:        zVal = "SQLITE_IOERR_FSYNC";        break;
+
    case SQLITE_IOERR_DIR_FSYNC:    zVal = "SQLITE_IOERR_DIR_FSYNC";    break;
+
    case SQLITE_IOERR_TRUNCATE:     zVal = "SQLITE_IOERR_TRUNCATE";     break;
+
    case SQLITE_IOERR_FSTAT:        zVal = "SQLITE_IOERR_FSTAT";        break;
+
    case SQLITE_IOERR_UNLOCK:       zVal = "SQLITE_IOERR_UNLOCK";       break;
+
    case SQLITE_IOERR_RDLOCK:       zVal = "SQLITE_IOERR_RDLOCK";       break;
+
    case SQLITE_IOERR_DELETE:       zVal = "SQLITE_IOERR_DELETE";       break;
+
    case SQLITE_IOERR_BLOCKED:      zVal = "SQLITE_IOERR_BLOCKED";      break;
+
    case SQLITE_IOERR_NOMEM:        zVal = "SQLITE_IOERR_NOMEM";        break;
+
    case SQLITE_IOERR_ACCESS:       zVal = "SQLITE_IOERR_ACCESS";       break;
+
    case SQLITE_IOERR_CHECKRESERVEDLOCK:
+
                               zVal = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
+
    case SQLITE_IOERR_LOCK:         zVal = "SQLITE_IOERR_LOCK";         break;
+
    case SQLITE_IOERR_CLOSE:        zVal = "SQLITE_IOERR_CLOSE";        break;
+
    case SQLITE_IOERR_DIR_CLOSE:    zVal = "SQLITE_IOERR_DIR_CLOSE";    break;
+
    case SQLITE_IOERR_SHMOPEN:      zVal = "SQLITE_IOERR_SHMOPEN";      break;
+
    case SQLITE_IOERR_SHMSIZE:      zVal = "SQLITE_IOERR_SHMSIZE";      break;
+
    case SQLITE_IOERR_SHMLOCK:      zVal = "SQLITE_IOERR_SHMLOCK";      break;
+
    case SQLITE_IOERR_SHMMAP:       zVal = "SQLITE_IOERR_SHMMAP";       break;
+
    case SQLITE_IOERR_SEEK:         zVal = "SQLITE_IOERR_SEEK";         break;
+
    case SQLITE_IOERR_GETTEMPPATH:  zVal = "SQLITE_IOERR_GETTEMPPATH";  break;
+
    case SQLITE_IOERR_CONVPATH:     zVal = "SQLITE_IOERR_CONVPATH";     break;
+
    case SQLITE_READONLY_DBMOVED:   zVal = "SQLITE_READONLY_DBMOVED";   break;
+
    case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break;
+
    case SQLITE_BUSY_RECOVERY:      zVal = "SQLITE_BUSY_RECOVERY";      break;
+
    case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break;
+
  }
+
  return zVal;
+
}
+

+
/*
+
** Convert value rc into a string and print it using zFormat.  zFormat
+
** should have exactly one %s
+
*/
+
static void vfstrace_print_errcode(
+
  vfstrace_info *pInfo,
+
  const char *zFormat,
+
  int rc
+
){
+
  const char *zVal;
+
  char zBuf[50];
+
  zVal = vfstrace_errcode_name(rc);
+
  if( zVal==0 ){
+
    zVal = vfstrace_errcode_name(rc&0xff);
+
    if( zVal ){
+
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%s | 0x%x", zVal, rc&0xffff00);
+
    }else{
+
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%d (0x%x)", rc, rc);
+
    }
+
    zVal = zBuf;
+
  }
+
  vfstrace_printf(pInfo, zFormat, zVal);
+
}
+

+
/*
+
** Append to a buffer.
+
*/
+
static void strappend(char *z, int *pI, const char *zAppend){
+
  int i = *pI;
+
  while( zAppend[0] ){ z[i++] = *(zAppend++); }
+
  z[i] = 0;
+
  *pI = i;
+
}
+

+
/*
+
** Close an vfstrace-file.
+
*/
+
static int vfstraceClose(sqlite3_file *pFile){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
+
  rc = p->pReal->pMethods->xClose(p->pReal);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  if( rc==SQLITE_OK ){
+
    sqlite3_free((void*)p->base.pMethods);
+
    p->base.pMethods = 0;
+
  }
+
  return rc;
+
}
+

+
/*
+
** Read data from an vfstrace-file.
+
*/
+
static int vfstraceRead(
+
  sqlite3_file *pFile, 
+
  void *zBuf, 
+
  int iAmt, 
+
  sqlite_int64 iOfst
+
){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
+
                  pInfo->zVfsName, p->zFName, iAmt, iOfst);
+
  rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Write data to an vfstrace-file.
+
*/
+
static int vfstraceWrite(
+
  sqlite3_file *pFile, 
+
  const void *zBuf, 
+
  int iAmt, 
+
  sqlite_int64 iOfst
+
){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
+
                  pInfo->zVfsName, p->zFName, iAmt, iOfst);
+
  rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Truncate an vfstrace-file.
+
*/
+
static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
+
                  size);
+
  rc = p->pReal->pMethods->xTruncate(p->pReal, size);
+
  vfstrace_printf(pInfo, " -> %d\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Sync an vfstrace-file.
+
*/
+
static int vfstraceSync(sqlite3_file *pFile, int flags){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  int i;
+
  char zBuf[100];
+
  memcpy(zBuf, "|0", 3);
+
  i = 0;
+
  if( flags & SQLITE_SYNC_FULL )        strappend(zBuf, &i, "|FULL");
+
  else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL");
+
  if( flags & SQLITE_SYNC_DATAONLY )    strappend(zBuf, &i, "|DATAONLY");
+
  if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
+
    sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
+
  }
+
  vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
+
                  &zBuf[1]);
+
  rc = p->pReal->pMethods->xSync(p->pReal, flags);
+
  vfstrace_printf(pInfo, " -> %d\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Return the current file-size of an vfstrace-file.
+
*/
+
static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
+
  rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
+
  vfstrace_print_errcode(pInfo, " -> %s,", rc);
+
  vfstrace_printf(pInfo, " size=%lld\n", *pSize);
+
  return rc;
+
}
+

+
/*
+
** Return the name of a lock.
+
*/
+
static const char *lockName(int eLock){
+
  const char *azLockNames[] = {
+
     "NONE", "SHARED", "RESERVED", "PENDING", "EXCLUSIVE"
+
  };
+
  if( eLock<0 || eLock>=(int)(sizeof(azLockNames)/sizeof(azLockNames[0])) ){
+
    return "???";
+
  }else{
+
    return azLockNames[eLock];
+
  }
+
}
+

+
/*
+
** Lock an vfstrace-file.
+
*/
+
static int vfstraceLock(sqlite3_file *pFile, int eLock){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
+
                  lockName(eLock));
+
  rc = p->pReal->pMethods->xLock(p->pReal, eLock);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Unlock an vfstrace-file.
+
*/
+
static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
+
                  lockName(eLock));
+
  rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Check if another file-handle holds a RESERVED lock on an vfstrace-file.
+
*/
+
static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)", 
+
                  pInfo->zVfsName, p->zFName);
+
  rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
+
  vfstrace_print_errcode(pInfo, " -> %s", rc);
+
  vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
+
  return rc;
+
}
+

+
/*
+
** File control method. For custom operations on an vfstrace-file.
+
*/
+
static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  char zBuf[100];
+
  char zBuf2[100];
+
  char *zOp;
+
  char *zRVal = 0;
+
  switch( op ){
+
    case SQLITE_FCNTL_LOCKSTATE:           zOp = "LOCKSTATE";           break;
+
    case SQLITE_GET_LOCKPROXYFILE:         zOp = "GET_LOCKPROXYFILE";   break;
+
    case SQLITE_SET_LOCKPROXYFILE:         zOp = "SET_LOCKPROXYFILE";   break;
+
    case SQLITE_LAST_ERRNO:                zOp = "LAST_ERRNO";          break;
+
    case SQLITE_FCNTL_SIZE_HINT: {
+
      sqlite3_snprintf(sizeof(zBuf), zBuf, "SIZE_HINT,%lld",
+
                       *(sqlite3_int64*)pArg);
+
      zOp = zBuf;
+
      break;
+
    }
+
    case SQLITE_FCNTL_CHUNK_SIZE: {
+
      sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg);
+
      zOp = zBuf;
+
      break;
+
    }
+
    case SQLITE_FCNTL_FILE_POINTER:        zOp = "FILE_POINTER";        break;
+
    case SQLITE_FCNTL_WIN32_AV_RETRY:      zOp = "WIN32_AV_RETRY";      break;
+
    case SQLITE_FCNTL_PERSIST_WAL: {
+
       sqlite3_snprintf(sizeof(zBuf), zBuf, "PERSIST_WAL,%d", *(int*)pArg);
+
       zOp = zBuf;
+
       break;
+
    }
+
    case SQLITE_FCNTL_OVERWRITE:           zOp = "OVERWRITE";           break;
+
    case SQLITE_FCNTL_VFSNAME:             zOp = "VFSNAME";             break;
+
    case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
+
    case SQLITE_FCNTL_PRAGMA: {
+
      const char *const* a = (const char*const*)pArg;
+
      sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
+
      zOp = zBuf;
+
      break;
+
    }
+
    case SQLITE_FCNTL_BUSYHANDLER:         zOp = "BUSYHANDLER";         break;
+
    case SQLITE_FCNTL_TEMPFILENAME:        zOp = "TEMPFILENAME";        break;
+
    case SQLITE_FCNTL_MMAP_SIZE: {
+
      sqlite3_int64 iMMap = *(sqlite3_int64*)pArg;
+
      sqlite3_snprintf(sizeof(zBuf), zBuf, "MMAP_SIZE,%lld",iMMap);
+
      zOp = zBuf;
+
      break;
+
    }
+
    case SQLITE_FCNTL_TRACE:               zOp = "TRACE";               break;
+
    case SQLITE_FCNTL_HAS_MOVED:           zOp = "HAS_MOVED";           break;
+
    case SQLITE_FCNTL_SYNC:                zOp = "SYNC";                break;
+
    case SQLITE_FCNTL_COMMIT_PHASETWO:     zOp = "COMMIT_PHASETWO";     break;
+
    case SQLITE_FCNTL_WIN32_SET_HANDLE:    zOp = "WIN32_SET_HANDLE";    break;
+
    case SQLITE_FCNTL_WAL_BLOCK:           zOp = "WAL_BLOCK";           break;
+
    case SQLITE_FCNTL_ZIPVFS:              zOp = "ZIPVFS";              break; 
+
    case SQLITE_FCNTL_RBU:                 zOp = "RBU";                 break;
+
    case SQLITE_FCNTL_VFS_POINTER:         zOp = "VFS_POINTER";         break;
+
    case SQLITE_FCNTL_JOURNAL_POINTER:     zOp = "JOURNAL_POINTER";     break;
+
    case SQLITE_FCNTL_WIN32_GET_HANDLE:    zOp = "WIN32_GET_HANDLE";    break;
+
    case SQLITE_FCNTL_PDB:                 zOp = "PDB";                 break;
+
    case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE:  zOp = "BEGIN_ATOMIC_WRITE";  break;
+
    case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: zOp = "COMMIT_ATOMIC_WRITE"; break;
+
    case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
+
       zOp = "ROLLBACK_ATOMIC_WRITE";
+
       break;
+
    }
+
    case SQLITE_FCNTL_LOCK_TIMEOUT: {
+
       sqlite3_snprintf(sizeof(zBuf), zBuf, "LOCK_TIMEOUT,%d", *(int*)pArg);
+
       zOp = zBuf;
+
       break;
+
    }
+
    case SQLITE_FCNTL_DATA_VERSION:        zOp = "DATA_VERSION";        break;
+
    case SQLITE_FCNTL_SIZE_LIMIT:          zOp = "SIZE_LIMIT";          break;
+
    case SQLITE_FCNTL_CKPT_DONE:           zOp = "CKPT_DONE";           break;
+
    case SQLITE_FCNTL_RESERVE_BYTES:       zOp = "RESERVED_BYTES";      break;
+
    case SQLITE_FCNTL_CKPT_START:          zOp = "CKPT_START";          break;
+
    case SQLITE_FCNTL_EXTERNAL_READER:     zOp = "EXTERNAL_READER";     break;
+
    case SQLITE_FCNTL_CKSM_FILE:           zOp = "CKSM_FILE";           break;
+
    case SQLITE_FCNTL_RESET_CACHE:         zOp = "RESET_CACHE";         break;
+
    case 0xca093fa0:                       zOp = "DB_UNCHANGED";        break;
+
    default: {
+
      sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
+
      zOp = zBuf;
+
      break;
+
    }
+
  }
+
  vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)",
+
                  pInfo->zVfsName, p->zFName, zOp);
+
  rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
+
  if( rc==SQLITE_OK ){
+
    switch( op ){
+
      case SQLITE_FCNTL_VFSNAME: {
+
        *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
+
                                    pInfo->zVfsName, *(char**)pArg);
+
        zRVal = *(char**)pArg;
+
        break;
+
      }
+
      case SQLITE_FCNTL_MMAP_SIZE: {
+
        sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%lld", *(sqlite3_int64*)pArg);
+
        zRVal = zBuf2;
+
        break;
+
      }
+
      case SQLITE_FCNTL_HAS_MOVED:
+
      case SQLITE_FCNTL_PERSIST_WAL: {
+
        sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%d", *(int*)pArg);
+
        zRVal = zBuf2;
+
        break;
+
      }
+
      case SQLITE_FCNTL_PRAGMA:
+
      case SQLITE_FCNTL_TEMPFILENAME: {
+
        zRVal = *(char**)pArg;
+
        break;
+
      }
+
    }
+
  }
+
  if( zRVal ){
+
    vfstrace_print_errcode(pInfo, " -> %s", rc);
+
    vfstrace_printf(pInfo, ", %s\n", zRVal);
+
  }else{
+
    vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  }
+
  return rc;
+
}
+

+
/*
+
** Return the sector-size in bytes for an vfstrace-file.
+
*/
+
static int vfstraceSectorSize(sqlite3_file *pFile){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
+
  rc = p->pReal->pMethods->xSectorSize(p->pReal);
+
  vfstrace_printf(pInfo, " -> %d\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Return the device characteristic flags supported by an vfstrace-file.
+
*/
+
static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
+
                  pInfo->zVfsName, p->zFName);
+
  rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
+
  vfstrace_printf(pInfo, " -> 0x%08x\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Shared-memory operations.
+
*/
+
static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  char zLck[100];
+
  int i = 0;
+
  memcpy(zLck, "|0", 3);
+
  if( flags & SQLITE_SHM_UNLOCK )    strappend(zLck, &i, "|UNLOCK");
+
  if( flags & SQLITE_SHM_LOCK )      strappend(zLck, &i, "|LOCK");
+
  if( flags & SQLITE_SHM_SHARED )    strappend(zLck, &i, "|SHARED");
+
  if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE");
+
  if( flags & ~(0xf) ){
+
     sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
+
  }
+
  vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)",
+
                  pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]);
+
  rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+
static int vfstraceShmMap(
+
  sqlite3_file *pFile, 
+
  int iRegion, 
+
  int szRegion, 
+
  int isWrite, 
+
  void volatile **pp
+
){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
+
                  pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
+
  rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+
static void vfstraceShmBarrier(sqlite3_file *pFile){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
+
  p->pReal->pMethods->xShmBarrier(p->pReal);
+
}
+
static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = p->pInfo;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
+
                  pInfo->zVfsName, p->zFName, delFlag);
+
  rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+

+

+

+
/*
+
** Open an vfstrace file handle.
+
*/
+
static int vfstraceOpen(
+
  sqlite3_vfs *pVfs,
+
  const char *zName,
+
  sqlite3_file *pFile,
+
  int flags,
+
  int *pOutFlags
+
){
+
  int rc;
+
  vfstrace_file *p = (vfstrace_file *)pFile;
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  p->pInfo = pInfo;
+
  p->zFName = zName ? fileTail(zName) : "<temp>";
+
  p->pReal = (sqlite3_file *)&p[1];
+
  rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
+
  vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
+
                  pInfo->zVfsName, p->zFName, flags);
+
  if( p->pReal->pMethods ){
+
    sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) );
+
    const sqlite3_io_methods *pSub = p->pReal->pMethods;
+
    memset(pNew, 0, sizeof(*pNew));
+
    pNew->iVersion = pSub->iVersion;
+
    pNew->xClose = vfstraceClose;
+
    pNew->xRead = vfstraceRead;
+
    pNew->xWrite = vfstraceWrite;
+
    pNew->xTruncate = vfstraceTruncate;
+
    pNew->xSync = vfstraceSync;
+
    pNew->xFileSize = vfstraceFileSize;
+
    pNew->xLock = vfstraceLock;
+
    pNew->xUnlock = vfstraceUnlock;
+
    pNew->xCheckReservedLock = vfstraceCheckReservedLock;
+
    pNew->xFileControl = vfstraceFileControl;
+
    pNew->xSectorSize = vfstraceSectorSize;
+
    pNew->xDeviceCharacteristics = vfstraceDeviceCharacteristics;
+
    if( pNew->iVersion>=2 ){
+
      pNew->xShmMap = pSub->xShmMap ? vfstraceShmMap : 0;
+
      pNew->xShmLock = pSub->xShmLock ? vfstraceShmLock : 0;
+
      pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0;
+
      pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0;
+
    }
+
    pFile->pMethods = pNew;
+
  }
+
  vfstrace_print_errcode(pInfo, " -> %s", rc);
+
  if( pOutFlags ){
+
    vfstrace_printf(pInfo, ", outFlags=0x%x\n", *pOutFlags);
+
  }else{
+
    vfstrace_printf(pInfo, "\n");
+
  }
+
  return rc;
+
}
+

+
/*
+
** Delete the file located at zPath. If the dirSync argument is true,
+
** ensure the file-system modifications are synced to disk before
+
** returning.
+
*/
+
static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
+
                  pInfo->zVfsName, zPath, dirSync);
+
  rc = pRoot->xDelete(pRoot, zPath, dirSync);
+
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
+
  return rc;
+
}
+

+
/*
+
** Test for access permissions. Return true if the requested permission
+
** is available, or false otherwise.
+
*/
+
static int vfstraceAccess(
+
  sqlite3_vfs *pVfs, 
+
  const char *zPath, 
+
  int flags, 
+
  int *pResOut
+
){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
+
                  pInfo->zVfsName, zPath, flags);
+
  rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
+
  vfstrace_print_errcode(pInfo, " -> %s", rc);
+
  vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
+
  return rc;
+
}
+

+
/*
+
** Populate buffer zOut with the full canonical pathname corresponding
+
** to the pathname in zPath. zOut is guaranteed to point to a buffer
+
** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
+
*/
+
static int vfstraceFullPathname(
+
  sqlite3_vfs *pVfs, 
+
  const char *zPath, 
+
  int nOut, 
+
  char *zOut
+
){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  int rc;
+
  vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
+
                  pInfo->zVfsName, zPath);
+
  rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
+
  vfstrace_print_errcode(pInfo, " -> %s", rc);
+
  vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut);
+
  return rc;
+
}
+

+
/*
+
** Open the dynamic library located at zPath and return a handle.
+
*/
+
static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
+
  return pRoot->xDlOpen(pRoot, zPath);
+
}
+

+
/*
+
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
+
** utf-8 string describing the most recent error encountered associated 
+
** with dynamic libraries.
+
*/
+
static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
+
  pRoot->xDlError(pRoot, nByte, zErrMsg);
+
  vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
+
}
+

+
/*
+
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
+
*/
+
static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  vfstrace_printf(pInfo, "%s.xDlSym(\"%s\")\n", pInfo->zVfsName, zSym);
+
  return pRoot->xDlSym(pRoot, p, zSym);
+
}
+

+
/*
+
** Close the dynamic library handle pHandle.
+
*/
+
static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
+
  pRoot->xDlClose(pRoot, pHandle);
+
}
+

+
/*
+
** Populate the buffer pointed to by zBufOut with nByte bytes of 
+
** random data.
*/
-
int sqlite3_intck_step(sqlite3_intck *p){
-
  if( p->rc==SQLITE_OK ){
-

-
    if( p->zMessage ){
-
      sqlite3_free(p->zMessage);
-
      p->zMessage = 0;
-
    }
-

-
    if( p->bCorruptSchema ){
-
      p->rc = SQLITE_DONE;
-
    }else
-
    if( p->pCheck==0 ){
-
      intckFindObject(p);
-
      if( p->rc==SQLITE_OK ){
-
        if( p->zObj ){
-
          char *zSql = 0;
-
          zSql = intckCheckObjectSql(p, p->zObj, p->zKey, &p->nKeyVal);
-
          p->pCheck = intckPrepare(p, zSql);
-
          sqlite3_free(zSql);
-
          sqlite3_free(p->zKey);
-
          p->zKey = 0;
-
        }else{
-
          p->rc = SQLITE_DONE;
-
        }
-
      }else if( p->rc==SQLITE_CORRUPT ){
-
        p->rc = SQLITE_OK;
-
        p->zMessage = intckMprintf(p, "%s",
-
            "corruption found while reading database schema"
-
        );
-
        p->bCorruptSchema = 1;
-
      }
-
    }
-

-
    if( p->pCheck ){
-
      assert( p->rc==SQLITE_OK );
-
      if( sqlite3_step(p->pCheck)==SQLITE_ROW ){
-
        /* Normal case, do nothing. */
-
      }else{
-
        intckFinalize(p, p->pCheck);
-
        p->pCheck = 0;
-
        p->nKeyVal = 0;
-
        if( p->rc==SQLITE_CORRUPT ){
-
          p->rc = SQLITE_OK;
-
          p->zMessage = intckMprintf(p, 
-
              "corruption found while scanning database object %s", p->zObj
-
          );
-
        }
-
      }
-
    }
-
  }
-

-
  return p->rc;
+
static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
+
  return pRoot->xRandomness(pRoot, nByte, zBufOut);
}

/*
-
** Return a message describing the corruption encountered by the most recent
-
** call to sqlite3_intck_step(), or NULL if no corruption was encountered.
+
** Sleep for nMicro microseconds. Return the number of microseconds 
+
** actually slept.
*/
-
const char *sqlite3_intck_message(sqlite3_intck *p){
-
  assert( p->pCheck==0 || p->zMessage==0 );
-
  if( p->zMessage ){
-
    return p->zMessage;
-
  }
-
  if( p->pCheck ){
-
    return (const char*)sqlite3_column_text(p->pCheck, 0);
-
  }
-
  return 0;
+
static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  return pRoot->xSleep(pRoot, nMicro);
}

/*
-
** Return the error code and message.
+
** Return the current time as a Julian Day number in *pTimeOut.
*/
-
int sqlite3_intck_error(sqlite3_intck *p, const char **pzErr){
-
  if( pzErr ) *pzErr = p->zErr;
-
  return (p->rc==SQLITE_DONE ? SQLITE_OK : p->rc);
+
static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  return pRoot->xCurrentTime(pRoot, pTimeOut);
+
}
+
static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
}

/*
-
** Close any read transaction the integrity-check object is holding open
-
** on the database.
+
** Return th3 most recent error code and message
*/
-
int sqlite3_intck_unlock(sqlite3_intck *p){
-
  if( p->rc==SQLITE_OK && p->pCheck ){
-
    assert( p->zKey==0 && p->nKeyVal>0 );
-
    intckSaveKey(p);
-
    intckFinalize(p, p->pCheck);
-
    p->pCheck = 0;
-
  }
-
  return p->rc;
+
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  return pRoot->xGetLastError(pRoot, iErr, zErr);
}

/*
-
** Return the SQL statement used to check object zObj. Or, if zObj is 
-
** NULL, the current SQL statement.
+
** Override system calls.
*/
-
const char *sqlite3_intck_test_sql(sqlite3_intck *p, const char *zObj){
-
  sqlite3_free(p->zTestSql);
-
  if( zObj ){
-
    p->zTestSql = intckCheckObjectSql(p, zObj, 0, 0);
-
  }else{
-
    if( p->zObj ){
-
      p->zTestSql = intckCheckObjectSql(p, p->zObj, p->zKey, 0);
-
    }else{
-
      sqlite3_free(p->zTestSql);
-
      p->zTestSql = 0;
-
    }
-
  }
-
  return p->zTestSql;
+
static int vfstraceSetSystemCall(
+
  sqlite3_vfs *pVfs,
+
  const char *zName,
+
  sqlite3_syscall_ptr pFunc
+
){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  return pRoot->xSetSystemCall(pRoot, zName, pFunc);
+
}
+
static sqlite3_syscall_ptr vfstraceGetSystemCall(
+
  sqlite3_vfs *pVfs,
+
  const char *zName
+
){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  return pRoot->xGetSystemCall(pRoot, zName);
+
}
+
static const char *vfstraceNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
+
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
+
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
+
  return pRoot->xNextSystemCall(pRoot, zName);
}

-
/************************* End ../ext/intck/sqlite3intck.c ********************/
+

+
/*
+
** Clients invoke this routine to construct a new trace-vfs shim.
+
**
+
** Return SQLITE_OK on success.  
+
**
+
** SQLITE_NOMEM is returned in the case of a memory allocation error.
+
** SQLITE_NOTFOUND is returned if zOldVfsName does not exist.
+
*/
+
int vfstrace_register(
+
   const char *zTraceName,           /* Name of the newly constructed VFS */
+
   const char *zOldVfsName,          /* Name of the underlying VFS */
+
   int (*xOut)(const char*,void*),   /* Output routine.  ex: fputs */
+
   void *pOutArg,                    /* 2nd argument to xOut.  ex: stderr */
+
   int makeDefault                   /* True to make the new VFS the default */
+
){
+
  sqlite3_vfs *pNew;
+
  sqlite3_vfs *pRoot;
+
  vfstrace_info *pInfo;
+
  size_t nName;
+
  size_t nByte;
+

+
  pRoot = sqlite3_vfs_find(zOldVfsName);
+
  if( pRoot==0 ) return SQLITE_NOTFOUND;
+
  nName = strlen(zTraceName);
+
  nByte = sizeof(*pNew) + sizeof(*pInfo) + nName + 1;
+
  pNew = sqlite3_malloc64( nByte );
+
  if( pNew==0 ) return SQLITE_NOMEM;
+
  memset(pNew, 0, nByte);
+
  pInfo = (vfstrace_info*)&pNew[1];
+
  pNew->iVersion = pRoot->iVersion;
+
  pNew->szOsFile = pRoot->szOsFile + sizeof(vfstrace_file);
+
  pNew->mxPathname = pRoot->mxPathname;
+
  pNew->zName = (char*)&pInfo[1];
+
  memcpy((char*)&pInfo[1], zTraceName, nName+1);
+
  pNew->pAppData = pInfo;
+
  pNew->xOpen = vfstraceOpen;
+
  pNew->xDelete = vfstraceDelete;
+
  pNew->xAccess = vfstraceAccess;
+
  pNew->xFullPathname = vfstraceFullPathname;
+
  pNew->xDlOpen = pRoot->xDlOpen==0 ? 0 : vfstraceDlOpen;
+
  pNew->xDlError = pRoot->xDlError==0 ? 0 : vfstraceDlError;
+
  pNew->xDlSym = pRoot->xDlSym==0 ? 0 : vfstraceDlSym;
+
  pNew->xDlClose = pRoot->xDlClose==0 ? 0 : vfstraceDlClose;
+
  pNew->xRandomness = vfstraceRandomness;
+
  pNew->xSleep = vfstraceSleep;
+
  pNew->xCurrentTime = vfstraceCurrentTime;
+
  pNew->xGetLastError = pRoot->xGetLastError==0 ? 0 : vfstraceGetLastError;
+
  if( pNew->iVersion>=2 ){
+
    pNew->xCurrentTimeInt64 = pRoot->xCurrentTimeInt64==0 ? 0 :
+
                                   vfstraceCurrentTimeInt64;
+
    if( pNew->iVersion>=3 ){
+
      pNew->xSetSystemCall = pRoot->xSetSystemCall==0 ? 0 : 
+
                                   vfstraceSetSystemCall;
+
      pNew->xGetSystemCall = pRoot->xGetSystemCall==0 ? 0 : 
+
                                   vfstraceGetSystemCall;
+
      pNew->xNextSystemCall = pRoot->xNextSystemCall==0 ? 0 : 
+
                                   vfstraceNextSystemCall;
+
    }
+
  }
+
  pInfo->pRootVfs = pRoot;
+
  pInfo->xOut = xOut;
+
  pInfo->pOutArg = pOutArg;
+
  pInfo->zVfsName = pNew->zName;
+
  pInfo->pTraceVfs = pNew;
+
  vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
+
       pInfo->zVfsName, pRoot->zName);
+
  return sqlite3_vfs_register(pNew, makeDefault);
+
}
+

+
/*
+
** Look for the named VFS.  If it is a TRACEVFS, then unregister it
+
** and delete it.
+
*/
+
void vfstrace_unregister(const char *zTraceName){
+
  sqlite3_vfs *pVfs = sqlite3_vfs_find(zTraceName);
+
  if( pVfs==0 ) return;
+
  if( pVfs->xOpen!=vfstraceOpen ) return;
+
  sqlite3_vfs_unregister(pVfs);
+
  sqlite3_free(pVfs);
+
}
+

+
/************************* End ../ext/misc/vfstrace.c ********************/

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
@@ -16129,6 +18061,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
            ** near the end of a corrupt record.  */
            rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
            if( rc!=SQLITE_OK ) return rc;
+
            assert( pCsr->rec.aBuf!=0 );
            assert( nPayload!=0 );

            /* Load the nLocal bytes of payload */
@@ -17216,7 +19149,7 @@ static const char *recoverUnusedString(
}

/*
-
** Implementation of scalar SQL function "escape_crnl".  The argument passed to
+
** Implementation of scalar SQL function "escape_crlf".  The argument passed to
** this function is the output of built-in function quote(). If the first
** character of the input is "'", indicating that the value passed to quote()
** was a text value, then this function searches the input for "\n" and "\r"
@@ -17227,7 +19160,7 @@ static const char *recoverUnusedString(
** Or, if the first character of the input is not "'", then a copy of the input
** is returned.
*/
-
static void recoverEscapeCrnl(
+
static void recoverEscapeCrlf(
  sqlite3_context *context, 
  int argc, 
  sqlite3_value **argv
@@ -17442,7 +19375,7 @@ static int recoverOpenOutput(sqlite3_recover *p){
    { "getpage", 1, recoverGetPage },
    { "page_is_used", 1, recoverPageIsUsed },
    { "read_i32", 2, recoverReadI32 },
-
    { "escape_crnl", 1, recoverEscapeCrnl },
+
    { "escape_crlf", 1, recoverEscapeCrlf },
  };

  const int flags = SQLITE_OPEN_URI|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
@@ -17795,7 +19728,7 @@ static sqlite3_stmt *recoverInsertStmt(

      if( bSql ){
        zBind = recoverMPrintf(p, 
-
            "%z%sescape_crnl(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
+
            "%z%sescape_crlf(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
        );
        zSqlSep = "||', '||";
      }else{
@@ -19412,6 +21345,7 @@ struct ShellState {
  u8 bSafeMode;          /* True to prohibit unsafe operations */
  u8 bSafeModePersist;   /* The long-term value of bSafeMode */
  u8 eRestoreState;      /* See comments above doAutoDetectRestore() */
+
  u8 crlfMode;           /* Do NL-to-CRLF translations when enabled (maybe) */
  ColModeOpts cmOpts;    /* Option values affecting columnar mode output */
  unsigned statsOn;      /* True to display memory stats before each finalize */
  unsigned mEqpLines;    /* Mask of vertical lines in the EQP output graph */
@@ -19557,6 +21491,7 @@ static ShellState shellState;
#define MODE_Count   17  /* Output only a count of the rows of output */
#define MODE_Off     18  /* No query output shown */
#define MODE_ScanExp 19  /* Like MODE_Explain, but for ".scanstats vm" */
+
#define MODE_Www     20  /* Full web-page output */

static const char *modeDescr[] = {
  "line",
@@ -19577,7 +21512,9 @@ static const char *modeDescr[] = {
  "table",
  "box",
  "count",
-
  "off"
+
  "off",
+
  "scanexp",
+
  "www",
};

/*
@@ -19605,7 +21542,7 @@ static const char *modeDescr[] = {
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
  ShellState *p = (ShellState*)pArg;
  if( p->pLog==0 ) return;
-
  sputf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
+
  sqlite3_fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
  fflush(p->pLog);
}

@@ -19620,9 +21557,9 @@ static void shellPutsFunc(
  int nVal,
  sqlite3_value **apVal
){
-
  /* Unused: (ShellState*)sqlite3_user_data(pCtx); */
+
  ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
  (void)nVal;
-
  oputf("%s\n", sqlite3_value_text(apVal[0]));
+
  sqlite3_fprintf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
  sqlite3_result_value(pCtx, apVal[0]);
}

@@ -19641,7 +21578,7 @@ static void failIfSafeMode(
    va_start(ap, zErrMsg);
    zMsg = sqlite3_vmprintf(zErrMsg, ap);
    va_end(ap);
-
    eputf("line %d: %s\n", p->lineno, zMsg);
+
    sqlite3_fprintf(stderr, "line %d: %s\n", p->lineno, zMsg);
    exit(1);
  }
}
@@ -19674,7 +21611,7 @@ static void editFunc(
  char *zCmd = 0;
  int bBin;
  int rc;
-
  int hasCRNL = 0;
+
  int hasCRLF = 0;
  FILE *f = 0;
  sqlite3_int64 sz;
  sqlite3_int64 x;
@@ -19708,7 +21645,7 @@ static void editFunc(
  bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
  /* When writing the file to be edited, do \n to \r\n conversions on systems
  ** that want \r\n line endings */
-
  f = fopen(zTempFile, bBin ? "wb" : "w");
+
  f = sqlite3_fopen(zTempFile, bBin ? "wb" : "w");
  if( f==0 ){
    sqlite3_result_error(context, "edit() cannot open temp file", -1);
    goto edit_func_end;
@@ -19719,7 +21656,7 @@ static void editFunc(
  }else{
    const char *z = (const char*)sqlite3_value_text(argv[0]);
    /* Remember whether or not the value originally contained \r\n */
-
    if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
+
    if( z && strstr(z,"\r\n")!=0 ) hasCRLF = 1;
    x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
  }
  fclose(f);
@@ -19739,7 +21676,7 @@ static void editFunc(
    sqlite3_result_error(context, "EDITOR returned non-zero", -1);
    goto edit_func_end;
  }
-
  f = fopen(zTempFile, "rb");
+
  f = sqlite3_fopen(zTempFile, "rb");
  if( f==0 ){
    sqlite3_result_error(context,
      "edit() cannot reopen temp file after edit", -1);
@@ -19764,7 +21701,7 @@ static void editFunc(
    sqlite3_result_blob64(context, p, sz, sqlite3_free);
  }else{
    sqlite3_int64 i, j;
-
    if( hasCRNL ){
+
    if( hasCRLF ){
      /* If the original contains \r\n then do no conversions back to \n */
    }else{
      /* If the file did not originally contain \r\n then convert any new
@@ -19807,9 +21744,24 @@ static void outputModePop(ShellState *p){
}

/*
+
** Set output mode to text or binary for Windows.
+
*/
+
static void setCrlfMode(ShellState *p){
+
#ifdef _WIN32
+
  if( p->crlfMode ){
+
    sqlite3_fsetmode(p->out, _O_TEXT);
+
  }else{
+
    sqlite3_fsetmode(p->out, _O_BINARY);
+
  }
+
#else
+
  UNUSED_PARAMETER(p);
+
#endif    
+
}
+

+
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
-
static void output_hex_blob(const void *pBlob, int nBlob){
+
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
  int i;
  unsigned char *aBlob = (unsigned char*)pBlob;

@@ -19826,7 +21778,7 @@ static void output_hex_blob(const void *pBlob, int nBlob){
  }
  zStr[i*2] = '\0';

-
  oputf("X'%s'", zStr);
+
  sqlite3_fprintf(out, "X'%s'", zStr);
  sqlite3_free(zStr);
}

@@ -19856,28 +21808,26 @@ static const char *unused_string(
**
** See also: output_quoted_escaped_string()
*/
-
static void output_quoted_string(const char *z){
+
static void output_quoted_string(ShellState *p, const char *z){
  int i;
  char c;
-
#ifndef SQLITE_SHELL_FIDDLE
-
  FILE *pfO = setOutputStream(invalidFileStream);
-
  setBinaryMode(pfO, 1);
-
#endif
+
  FILE *out = p->out;
+
  sqlite3_fsetmode(out, _O_BINARY);
  if( z==0 ) return;
  for(i=0; (c = z[i])!=0 && c!='\''; i++){}
  if( c==0 ){
-
    oputf("'%s'",z);
+
    sqlite3_fprintf(out, "'%s'",z);
  }else{
-
    oputz("'");
+
    sqlite3_fputs("'", out);
    while( *z ){
      for(i=0; (c = z[i])!=0 && c!='\''; i++){}
      if( c=='\'' ) i++;
      if( i ){
-
        oputf("%.*s", i, z);
+
        sqlite3_fprintf(out, "%.*s", i, z);
        z += i;
      }
      if( c=='\'' ){
-
        oputz("'");
+
        sqlite3_fputs("'", out);
        continue;
      }
      if( c==0 ){
@@ -19885,13 +21835,9 @@ static void output_quoted_string(const char *z){
      }
      z++;
    }
-
    oputz("'");
+
    sqlite3_fputs("'", out);
  }
-
#ifndef SQLITE_SHELL_FIDDLE
-
  setTextMode(pfO, 1);
-
#else
-
  setTextMode(stdout, 1);
-
#endif
+
  setCrlfMode(p);
}

/*
@@ -19903,16 +21849,14 @@ static void output_quoted_string(const char *z){
** This is like output_quoted_string() but with the addition of the \r\n
** escape mechanism.
*/
-
static void output_quoted_escaped_string(const char *z){
+
static void output_quoted_escaped_string(ShellState *p, const char *z){
  int i;
  char c;
-
#ifndef SQLITE_SHELL_FIDDLE
-
  FILE *pfO = setOutputStream(invalidFileStream);
-
  setBinaryMode(pfO, 1);
-
#endif
+
  FILE *out = p->out;
+
  sqlite3_fsetmode(out, _O_BINARY);
  for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
  if( c==0 ){
-
    oputf("'%s'",z);
+
    sqlite3_fprintf(out, "'%s'",z);
  }else{
    const char *zNL = 0;
    const char *zCR = 0;
@@ -19924,23 +21868,23 @@ static void output_quoted_escaped_string(const char *z){
      if( z[i]=='\r' ) nCR++;
    }
    if( nNL ){
-
      oputz("replace(");
+
      sqlite3_fputs("replace(", out);
      zNL = unused_string(z, "\\n", "\\012", zBuf1);
    }
    if( nCR ){
-
      oputz("replace(");
+
      sqlite3_fputs("replace(", out);
      zCR = unused_string(z, "\\r", "\\015", zBuf2);
    }
-
    oputz("'");
+
    sqlite3_fputs("'", out);
    while( *z ){
      for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
      if( c=='\'' ) i++;
      if( i ){
-
        oputf("%.*s", i, z);
+
        sqlite3_fprintf(out, "%.*s", i, z);
        z += i;
      }
      if( c=='\'' ){
-
        oputz("'");
+
        sqlite3_fputs("'", out);
        continue;
      }
      if( c==0 ){
@@ -19948,24 +21892,20 @@ static void output_quoted_escaped_string(const char *z){
      }
      z++;
      if( c=='\n' ){
-
        oputz(zNL);
+
        sqlite3_fputs(zNL, out);
        continue;
      }
-
      oputz(zCR);
+
      sqlite3_fputs(zCR, out);
    }
-
    oputz("'");
+
    sqlite3_fputs("'", out);
    if( nCR ){
-
      oputf(",'%s',char(13))", zCR);
+
      sqlite3_fprintf(out, ",'%s',char(13))", zCR);
    }
    if( nNL ){
-
      oputf(",'%s',char(10))", zNL);
+
      sqlite3_fprintf(out, ",'%s',char(10))", zNL);
    }
  }
-
#ifndef SQLITE_SHELL_FIDDLE
-
  setTextMode(pfO, 1);
-
#else
-
  setTextMode(stdout, 1);
-
#endif
+
  setCrlfMode(p);
}

/*
@@ -19985,22 +21925,60 @@ static const char *anyOfInStr(const char *s, const char *zAny, size_t ns){
  }
  return pcFirst;
}
+

+
/* Skip over as much z[] input char sequence as is valid UTF-8,
+
** limited per nAccept char's or whole characters and containing
+
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
+
** sequence z:return (inclusive:exclusive) is validated UTF-8.
+
** Limit: nAccept>=0 => char count, nAccept<0 => character
+
 */
+
const char *zSkipValidUtf8(const char *z, int nAccept, long ccm){
+
  int ng = (nAccept<0)? -nAccept : 0;
+
  const char *pcLimit = (nAccept>=0)? z+nAccept : 0;
+
  assert(z!=0);
+
  while( (pcLimit)? (z<pcLimit) : (ng-- != 0) ){
+
    char c = *z;
+
    if( (c & 0x80) == 0 ){
+
      if( ccm != 0L && c < 0x20 && ((1L<<c) & ccm) != 0 ) return z;
+
      ++z; /* ASCII */
+
    }else if( (c & 0xC0) != 0xC0 ) return z; /* not a lead byte */
+
    else{
+
      const char *zt = z+1; /* Got lead byte, look at trail bytes.*/
+
      do{
+
        if( pcLimit && zt >= pcLimit ) return z;
+
        else{
+
          char ct = *zt++;
+
          if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){
+
            /* Trailing bytes are too few, too many, or invalid. */
+
            return z;
+
          }
+
        }
+
      } while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
+
      z = zt;
+
    }
+
  }
+
  return z;
+
}
+

+

/*
** Output the given string as a quoted according to C or TCL quoting rules.
*/
-
static void output_c_string(const char *z){
+
static void output_c_string(FILE *out, const char *z){
  char c;
  static const char *zq = "\"";
  static long ctrlMask = ~0L;
  static const char *zDQBSRO = "\"\\\x7f"; /* double-quote, backslash, rubout */
  char ace[3] = "\\?";
  char cbsSay;
-
  oputz(zq);
+
  sqlite3_fputs(zq, out);
  while( *z!=0 ){
    const char *pcDQBSRO = anyOfInStr(z, zDQBSRO, ~(size_t)0);
    const char *pcPast = zSkipValidUtf8(z, INT_MAX, ctrlMask);
    const char *pcEnd = (pcDQBSRO && pcDQBSRO < pcPast)? pcDQBSRO : pcPast;
-
    if( pcEnd > z ) oputb(z, (int)(pcEnd-z));
+
    if( pcEnd > z ){
+
      sqlite3_fprintf(out, "%.*s", (int)(pcEnd-z), z);
+
    }
    if( (c = *pcEnd)==0 ) break;
    ++pcEnd;
    switch( c ){
@@ -20015,22 +21993,22 @@ static void output_c_string(const char *z){
    }
    if( cbsSay ){
      ace[1] = cbsSay;
-
      oputz(ace);
+
      sqlite3_fputs(ace, out);
    }else if( !isprint(c&0xff) ){
-
      oputf("\\%03o", c&0xff);
+
      sqlite3_fprintf(out, "\\%03o", c&0xff);
    }else{
      ace[1] = (char)c;
-
      oputz(ace+1);
+
      sqlite3_fputs(ace+1, out);
    }
    z = pcEnd;
  }
-
  oputz(zq);
+
  sqlite3_fputs(zq, out);
}

/*
** Output the given string as a quoted according to JSON quoting rules.
*/
-
static void output_json_string(const char *z, i64 n){
+
static void output_json_string(FILE *out, const char *z, i64 n){
  char c;
  static const char *zq = "\"";
  static long ctrlMask = ~0L;
@@ -20041,13 +22019,13 @@ static void output_json_string(const char *z, i64 n){

  if( z==0 ) z = "";
  pcLimit = z + ((n<0)? strlen(z) : (size_t)n);
-
  oputz(zq);
+
  sqlite3_fputs(zq, out);
  while( z < pcLimit ){
    const char *pcDQBS = anyOfInStr(z, zDQBS, pcLimit-z);
    const char *pcPast = zSkipValidUtf8(z, (int)(pcLimit-z), ctrlMask);
    const char *pcEnd = (pcDQBS && pcDQBS < pcPast)? pcDQBS : pcPast;
    if( pcEnd > z ){
-
      oputb(z, (int)(pcEnd-z));
+
      sqlite3_fprintf(out, "%.*s", (int)(pcEnd-z), z);
      z = pcEnd;
    }
    if( z >= pcLimit ) break;
@@ -20065,22 +22043,22 @@ static void output_json_string(const char *z, i64 n){
    }
    if( cbsSay ){
      ace[1] = cbsSay;
-
      oputz(ace);
+
      sqlite3_fputs(ace, out);
    }else if( c<=0x1f ){
-
      oputf("u%04x", c);
+
      sqlite3_fprintf(out, "u%04x", c);
    }else{
      ace[1] = (char)c;
-
      oputz(ace+1);
+
      sqlite3_fputs(ace+1, out);
    }
  }
-
  oputz(zq);
+
  sqlite3_fputs(zq, out);
}

/*
** Output the given string with characters that are special to
** HTML escaped.
*/
-
static void output_html_string(const char *z){
+
static void output_html_string(FILE *out, const char *z){
  int i;
  if( z==0 ) z = "";
  while( *z ){
@@ -20092,18 +22070,18 @@ static void output_html_string(const char *z){
            && z[i]!='\'';
        i++){}
    if( i>0 ){
-
      oputf("%.*s",i,z);
+
      sqlite3_fprintf(out, "%.*s",i,z);
    }
    if( z[i]=='<' ){
-
      oputz("&lt;");
+
      sqlite3_fputs("&lt;", out);
    }else if( z[i]=='&' ){
-
      oputz("&amp;");
+
      sqlite3_fputs("&amp;", out);
    }else if( z[i]=='>' ){
-
      oputz("&gt;");
+
      sqlite3_fputs("&gt;", out);
    }else if( z[i]=='\"' ){
-
      oputz("&quot;");
+
      sqlite3_fputs("&quot;", out);
    }else if( z[i]=='\'' ){
-
      oputz("&#39;");
+
      sqlite3_fputs("&#39;", out);
    }else{
      break;
    }
@@ -20142,7 +22120,7 @@ static const char needCsvQuote[] = {
*/
static void output_csv(ShellState *p, const char *z, int bSep){
  if( z==0 ){
-
    oputf("%s",p->nullValue);
+
    sqlite3_fprintf(p->out, "%s",p->nullValue);
  }else{
    unsigned i;
    for(i=0; z[i]; i++){
@@ -20154,14 +22132,14 @@ static void output_csv(ShellState *p, const char *z, int bSep){
    if( i==0 || strstr(z, p->colSeparator)!=0 ){
      char *zQuoted = sqlite3_mprintf("\"%w\"", z);
      shell_check_oom(zQuoted);
-
      oputz(zQuoted);
+
      sqlite3_fputs(zQuoted, p->out);
      sqlite3_free(zQuoted);
    }else{
-
      oputz(z);
+
      sqlite3_fputs(z, p->out);
    }
  }
  if( bSep ){
-
    oputz(p->colSeparator);
+
    sqlite3_fputs(p->colSeparator, p->out);
  }
}

@@ -20269,16 +22247,16 @@ static int shellAuth(
  az[1] = zA2;
  az[2] = zA3;
  az[3] = zA4;
-
  oputf("authorizer: %s", azAction[op]);
+
  sqlite3_fprintf(p->out, "authorizer: %s", azAction[op]);
  for(i=0; i<4; i++){
-
    oputz(" ");
+
    sqlite3_fputs(" ", p->out);
    if( az[i] ){
-
      output_c_string(az[i]);
+
      output_c_string(p->out, az[i]);
    }else{
-
      oputz("NULL");
+
      sqlite3_fputs("NULL", p->out);
    }
  }
-
  oputz("\n");
+
  sqlite3_fputs("\n", p->out);
  if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
  return SQLITE_OK;
}
@@ -20294,7 +22272,7 @@ static int shellAuth(
** sqlite3_complete() returns false, try to terminate the comment before
** printing the result.  https://sqlite.org/forum/forumpost/d7be961c5c
*/
-
static void printSchemaLine(const char *z, const char *zTail){
+
static void printSchemaLine(FILE *out, const char *z, const char *zTail){
  char *zToFree = 0;
  if( z==0 ) return;
  if( zTail==0 ) return;
@@ -20316,16 +22294,16 @@ static void printSchemaLine(const char *z, const char *zTail){
    }
  }
  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
-
    oputf("CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
+
    sqlite3_fprintf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
  }else{
-
    oputf("%s%s", z, zTail);
+
    sqlite3_fprintf(out, "%s%s", z, zTail);
  }
  sqlite3_free(zToFree);
}
-
static void printSchemaLineN(char *z, int n, const char *zTail){
+
static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
  char c = z[n];
  z[n] = 0;
-
  printSchemaLine(z, zTail);
+
  printSchemaLine(out, z, zTail);
  z[n] = c;
}

@@ -20353,7 +22331,7 @@ static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
  if( zText==0 ) return;
  nText = strlen(zText);
  if( p->autoEQPtest ){
-
    oputf("%d,%d,%s\n", iEqpId, p2, zText);
+
    sqlite3_fprintf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
  }
  pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
  shell_check_oom(pNew);
@@ -20401,7 +22379,8 @@ static void eqp_render_level(ShellState *p, int iEqpId){
  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = eqp_next_row(p, iEqpId, pRow);
    z = pRow->zText;
-
    oputf("%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
+
    sqlite3_fprintf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
+
                            pNext ? "|--" : "`--", z);
    if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
      eqp_render_level(p, pRow->iEqpId);
@@ -20421,13 +22400,13 @@ static void eqp_render(ShellState *p, i64 nCycle){
        eqp_reset(p);
        return;
      }
-
      oputf("%s\n", pRow->zText+3);
+
      sqlite3_fprintf(p->out, "%s\n", pRow->zText+3);
      p->sGraph.pRow = pRow->pNext;
      sqlite3_free(pRow);
    }else if( nCycle>0 ){
-
      oputf("QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
+
      sqlite3_fprintf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
    }else{
-
      oputz("QUERY PLAN\n");
+
      sqlite3_fputs("QUERY PLAN\n", p->out);
    }
    p->sGraph.zPrefix[0] = 0;
    eqp_render_level(p, 0);
@@ -20443,13 +22422,13 @@ static int progress_handler(void *pClientData) {
  ShellState *p = (ShellState*)pClientData;
  p->nProgress++;
  if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
-
    oputf("Progress limit reached (%u)\n", p->nProgress);
+
    sqlite3_fprintf(p->out, "Progress limit reached (%u)\n", p->nProgress);
    if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
    if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
    return 1;
  }
  if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
-
    oputf("Progress %u\n", p->nProgress);
+
    sqlite3_fprintf(p->out, "Progress %u\n", p->nProgress);
  }
  return 0;
}
@@ -20458,14 +22437,14 @@ static int progress_handler(void *pClientData) {
/*
** Print N dashes
*/
-
static void print_dashes(int N){
+
static void print_dashes(FILE *out, int N){
  const char zDash[] = "--------------------------------------------------";
  const int nDash = sizeof(zDash) - 1;
  while( N>nDash ){
-
    oputz(zDash);
+
    sqlite3_fputs(zDash, out);
    N -= nDash;
  }
-
  oputf("%.*s", N, zDash);
+
  sqlite3_fprintf(out, "%.*s", N, zDash);
}

/*
@@ -20478,15 +22457,15 @@ static void print_row_separator(
){
  int i;
  if( nArg>0 ){
-
    oputz(zSep);
-
    print_dashes(p->actualWidth[0]+2);
+
    sqlite3_fputs(zSep, p->out);
+
    print_dashes(p->out, p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
-
      oputz(zSep);
-
      print_dashes(p->actualWidth[i]+2);
+
      sqlite3_fputs(zSep, p->out);
+
      print_dashes(p->out, p->actualWidth[i]+2);
    }
-
    oputz(zSep);
+
    sqlite3_fputs(zSep, p->out);
  }
-
  oputz("\n");
+
  sqlite3_fputs("\n", p->out);
}

/*
@@ -20516,9 +22495,9 @@ static int shell_callback(
        int len = strlen30(azCol[i] ? azCol[i] : "");
        if( len>w ) w = len;
      }
-
      if( p->cnt++>0 ) oputz(p->rowSeparator);
+
      if( p->cnt++>0 ) sqlite3_fputs(p->rowSeparator, p->out);
      for(i=0; i<nArg; i++){
-
        oputf("%*s = %s%s", w, azCol[i],
+
        sqlite3_fprintf(p->out, "%*s = %s%s", w, azCol[i],
              azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
      }
      break;
@@ -20527,7 +22506,7 @@ static int shell_callback(
    case MODE_Explain: {
      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, 6, 6, 13, 4, 4, 4, 13, 2, 13};
+
      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;
@@ -20546,12 +22525,12 @@ static int shell_callback(
      /* If this is the first row seen, print out the headers */
      if( p->cnt++==0 ){
        for(i=0; i<nArg; i++){
-
          utf8_width_print(aWidth[i], azCol[ aMap[i] ]);
-
          oputz(i==nArg-1 ? "\n" : "  ");
+
          utf8_width_print(p->out, aWidth[i], azCol[ aMap[i] ]);
+
          sqlite3_fputs(i==nArg-1 ? "\n" : "  ", p->out);
        }
        for(i=0; i<nArg; i++){
-
          print_dashes(aWidth[i]);
-
          oputz(i==nArg-1 ? "\n" : "  ");
+
          print_dashes(p->out, aWidth[i]);
+
          sqlite3_fputs(i==nArg-1 ? "\n" : "  ", p->out);
        }
      }

@@ -20569,17 +22548,17 @@ static int shell_callback(
        }
        if( i==iIndent && p->aiIndent && p->pStmt ){
          if( p->iIndent<p->nIndent ){
-
            oputf("%*.s", p->aiIndent[p->iIndent], "");
+
            sqlite3_fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
          }
          p->iIndent++;
        }
-
        utf8_width_print(w, zVal ? zVal : p->nullValue);
-
        oputz(i==nArg-1 ? "\n" : zSep);
+
        utf8_width_print(p->out, w, zVal ? zVal : p->nullValue);
+
        sqlite3_fputs(i==nArg-1 ? "\n" : zSep, p->out);
      }
      break;
    }
    case MODE_Semi: {   /* .schema and .fullschema output */
-
      printSchemaLine(azArg[0], ";\n");
+
      printSchemaLine(p->out, azArg[0], ";\n");
      break;
    }
    case MODE_Pretty: {  /* .schema and .fullschema with --indent */
@@ -20594,7 +22573,7 @@ static int shell_callback(
      if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
       || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
      ){
-
        oputf("%s;\n", azArg[0]);
+
        sqlite3_fprintf(p->out, "%s;\n", azArg[0]);
        break;
      }
      z = sqlite3_mprintf("%s", azArg[0]);
@@ -20627,7 +22606,7 @@ static int shell_callback(
          }else if( c==')' ){
            nParen--;
            if( nLine>0 && nParen==0 && j>0 ){
-
              printSchemaLineN(z, j, "\n");
+
              printSchemaLineN(p->out, z, j, "\n");
              j = 0;
            }
          }
@@ -20636,7 +22615,7 @@ static int shell_callback(
           && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
          ){
            if( c=='\n' ) j--;
-
            printSchemaLineN(z, j, "\n  ");
+
            printSchemaLineN(p->out, z, j, "\n  ");
            j = 0;
            nLine++;
            while( IsSpace(z[i+1]) ){ i++; }
@@ -20644,118 +22623,128 @@ static int shell_callback(
        }
        z[j] = 0;
      }
-
      printSchemaLine(z, ";\n");
+
      printSchemaLine(p->out, z, ";\n");
      sqlite3_free(z);
      break;
    }
    case MODE_List: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
-
          oputf("%s%s",azCol[i], i==nArg-1 ? p->rowSeparator : p->colSeparator);
+
          sqlite3_fprintf(p->out, "%s%s", azCol[i],
+
                          i==nArg-1 ? p->rowSeparator : p->colSeparator);
        }
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        char *z = azArg[i];
        if( z==0 ) z = p->nullValue;
-
        oputz(z);
-
        oputz((i<nArg-1)? p->colSeparator : p->rowSeparator);
+
        sqlite3_fputs(z, p->out);
+
        sqlite3_fputs((i<nArg-1)? p->colSeparator : p->rowSeparator, p->out);
      }
      break;
    }
+
    case MODE_Www:
    case MODE_Html: {
-
      if( p->cnt++==0 && p->showHeader ){
-
        oputz("<TR>");
+
      if( p->cnt==0 && p->cMode==MODE_Www ){
+
        sqlite3_fputs(
+
          "</PRE>\n"
+
          "<TABLE border='1' cellspacing='0' cellpadding='2'>\n"
+
          ,p->out
+
        );
+
      }
+
      if( p->cnt==0 && (p->showHeader || p->cMode==MODE_Www) ){
+
        sqlite3_fputs("<TR>", p->out);
        for(i=0; i<nArg; i++){
-
          oputz("<TH>");
-
          output_html_string(azCol[i]);
-
          oputz("</TH>\n");
+
          sqlite3_fputs("<TH>", p->out);
+
          output_html_string(p->out, azCol[i]);
+
          sqlite3_fputs("</TH>\n", p->out);
        }
-
        oputz("</TR>\n");
+
        sqlite3_fputs("</TR>\n", p->out);
      }
+
      p->cnt++;
      if( azArg==0 ) break;
-
      oputz("<TR>");
+
      sqlite3_fputs("<TR>", p->out);
      for(i=0; i<nArg; i++){
-
        oputz("<TD>");
-
        output_html_string(azArg[i] ? azArg[i] : p->nullValue);
-
        oputz("</TD>\n");
+
        sqlite3_fputs("<TD>", p->out);
+
        output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
+
        sqlite3_fputs("</TD>\n", p->out);
      }
-
      oputz("</TR>\n");
+
      sqlite3_fputs("</TR>\n", p->out);
      break;
    }
    case MODE_Tcl: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
-
          output_c_string(azCol[i] ? azCol[i] : "");
-
          if(i<nArg-1) oputz(p->colSeparator);
+
          output_c_string(p->out, azCol[i] ? azCol[i] : "");
+
          if(i<nArg-1) sqlite3_fputs(p->colSeparator, p->out);
        }
-
        oputz(p->rowSeparator);
+
        sqlite3_fputs(p->rowSeparator, p->out);
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
-
        output_c_string(azArg[i] ? azArg[i] : p->nullValue);
-
        if(i<nArg-1) oputz(p->colSeparator);
+
        output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
+
        if(i<nArg-1) sqlite3_fputs(p->colSeparator, p->out);
      }
-
      oputz(p->rowSeparator);
+
      sqlite3_fputs(p->rowSeparator, p->out);
      break;
    }
    case MODE_Csv: {
-
      setBinaryMode(p->out, 1);
+
      sqlite3_fsetmode(p->out, _O_BINARY);
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
        }
-
        oputz(p->rowSeparator);
+
        sqlite3_fputs(p->rowSeparator, p->out);
      }
      if( nArg>0 ){
        for(i=0; i<nArg; i++){
          output_csv(p, azArg[i], i<nArg-1);
        }
-
        oputz(p->rowSeparator);
+
        sqlite3_fputs(p->rowSeparator, p->out);
      }
-
      setTextMode(p->out, 1);
+
      setCrlfMode(p);
      break;
    }
    case MODE_Insert: {
      if( azArg==0 ) break;
-
      oputf("INSERT INTO %s",p->zDestTable);
+
      sqlite3_fprintf(p->out, "INSERT INTO %s",p->zDestTable);
      if( p->showHeader ){
-
        oputz("(");
+
        sqlite3_fputs("(", p->out);
        for(i=0; i<nArg; i++){
-
          if( i>0 ) oputz(",");
+
          if( i>0 ) sqlite3_fputs(",", p->out);
          if( quoteChar(azCol[i]) ){
            char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
            shell_check_oom(z);
-
            oputz(z);
+
            sqlite3_fputs(z, p->out);
            sqlite3_free(z);
          }else{
-
            oputf("%s", azCol[i]);
+
            sqlite3_fprintf(p->out, "%s", azCol[i]);
          }
        }
-
        oputz(")");
+
        sqlite3_fputs(")", p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
-
        oputz(i>0 ? "," : " VALUES(");
+
        sqlite3_fputs(i>0 ? "," : " VALUES(", p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
-
          oputz("NULL");
+
          sqlite3_fputs("NULL", p->out);
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          if( ShellHasFlag(p, SHFLG_Newlines) ){
-
            output_quoted_string(azArg[i]);
+
            output_quoted_string(p, azArg[i]);
          }else{
-
            output_quoted_escaped_string(azArg[i]);
+
            output_quoted_escaped_string(p, azArg[i]);
          }
        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
-
          oputz(azArg[i]);
+
          sqlite3_fputs(azArg[i], p->out);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
-
            oputz("9.0e+999");
+
            sqlite3_fputs("9.0e+999", p->out);
          }else if( ur==0xfff0000000000000LL ){
-
            oputz("-9.0e+999");
+
            sqlite3_fputs("-9.0e+999", p->out);
          }else{
            sqlite3_int64 ir = (sqlite3_int64)r;
            if( r==(double)ir ){
@@ -20763,115 +22752,115 @@ static int shell_callback(
            }else{
              sqlite3_snprintf(50,z,"%!.20g", r);
            }
-
            oputz(z);
+
            sqlite3_fputs(z, p->out);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
-
          output_hex_blob(pBlob, nBlob);
+
          output_hex_blob(p->out, pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
-
          oputz(azArg[i]);
+
          sqlite3_fputs(azArg[i], p->out);
        }else if( ShellHasFlag(p, SHFLG_Newlines) ){
-
          output_quoted_string(azArg[i]);
+
          output_quoted_string(p, azArg[i]);
        }else{
-
          output_quoted_escaped_string(azArg[i]);
+
          output_quoted_escaped_string(p, azArg[i]);
        }
      }
-
      oputz(");\n");
+
      sqlite3_fputs(");\n", p->out);
      break;
    }
    case MODE_Json: {
      if( azArg==0 ) break;
      if( p->cnt==0 ){
-
        fputs("[{", p->out);
+
        sqlite3_fputs("[{", p->out);
      }else{
-
        fputs(",\n{", p->out);
+
        sqlite3_fputs(",\n{", p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
-
        output_json_string(azCol[i], -1);
-
        oputz(":");
+
        output_json_string(p->out, azCol[i], -1);
+
        sqlite3_fputs(":", p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
-
          oputz("null");
+
          sqlite3_fputs("null", p->out);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
-
            oputz("9.0e+999");
+
            sqlite3_fputs("9.0e+999", p->out);
          }else if( ur==0xfff0000000000000LL ){
-
            oputz("-9.0e+999");
+
            sqlite3_fputs("-9.0e+999", p->out);
          }else{
            sqlite3_snprintf(50,z,"%!.20g", r);
-
            oputz(z);
+
            sqlite3_fputs(z, p->out);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
-
          output_json_string(pBlob, nBlob);
+
          output_json_string(p->out, pBlob, nBlob);
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
-
          output_json_string(azArg[i], -1);
+
          output_json_string(p->out, azArg[i], -1);
        }else{
-
          oputz(azArg[i]);
+
          sqlite3_fputs(azArg[i], p->out);
        }
        if( i<nArg-1 ){
-
          oputz(",");
+
          sqlite3_fputs(",", p->out);
        }
      }
-
      oputz("}");
+
      sqlite3_fputs("}", p->out);
      break;
    }
    case MODE_Quote: {
      if( azArg==0 ) break;
      if( p->cnt==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
-
          if( i>0 ) fputs(p->colSeparator, p->out);
-
          output_quoted_string(azCol[i]);
+
          if( i>0 ) sqlite3_fputs(p->colSeparator, p->out);
+
          output_quoted_string(p, azCol[i]);
        }
-
        fputs(p->rowSeparator, p->out);
+
        sqlite3_fputs(p->rowSeparator, p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
-
        if( i>0 ) fputs(p->colSeparator, p->out);
+
        if( i>0 ) sqlite3_fputs(p->colSeparator, p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
-
          oputz("NULL");
+
          sqlite3_fputs("NULL", p->out);
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
-
          output_quoted_string(azArg[i]);
+
          output_quoted_string(p, azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
-
          oputz(azArg[i]);
+
          sqlite3_fputs(azArg[i], p->out);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_snprintf(50,z,"%!.20g", r);
-
          oputz(z);
+
          sqlite3_fputs(z, p->out);
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
-
          output_hex_blob(pBlob, nBlob);
+
          output_hex_blob(p->out, pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
-
          oputz(azArg[i]);
+
          sqlite3_fputs(azArg[i], p->out);
        }else{
-
          output_quoted_string(azArg[i]);
+
          output_quoted_string(p, azArg[i]);
        }
      }
-
      fputs(p->rowSeparator, p->out);
+
      sqlite3_fputs(p->rowSeparator, p->out);
      break;
    }
    case MODE_Ascii: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
-
          if( i>0 ) oputz(p->colSeparator);
-
          oputz(azCol[i] ? azCol[i] : "");
+
          if( i>0 ) sqlite3_fputs(p->colSeparator, p->out);
+
          sqlite3_fputs(azCol[i] ? azCol[i] : "", p->out);
        }
-
        oputz(p->rowSeparator);
+
        sqlite3_fputs(p->rowSeparator, p->out);
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
-
        if( i>0 ) oputz(p->colSeparator);
-
        oputz(azArg[i] ? azArg[i] : p->nullValue);
+
        if( i>0 ) sqlite3_fputs(p->colSeparator, p->out);
+
        sqlite3_fputs(azArg[i] ? azArg[i] : p->nullValue, p->out);
      }
-
      oputz(p->rowSeparator);
+
      sqlite3_fputs(p->rowSeparator, p->out);
      break;
    }
    case MODE_EQP: {
@@ -20950,7 +22939,7 @@ static void createSelftestTable(ShellState *p){
    "DROP TABLE [_shell$self];"
    ,0,0,&zErrMsg);
  if( zErrMsg ){
-
    eputf("SELFTEST initialization failure: %s\n", zErrMsg);
+
    sqlite3_fprintf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
@@ -21053,7 +23042,7 @@ static int run_table_dump_query(
  rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
  if( rc!=SQLITE_OK || !pSelect ){
    char *zContext = shell_error_context(zSelect, p->db);
-
    oputf("/**** ERROR: (%d) %s *****/\n%s",
+
    sqlite3_fprintf(p->out, "/**** ERROR: (%d) %s *****/\n%s",
          rc, sqlite3_errmsg(p->db), zContext);
    sqlite3_free(zContext);
    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
@@ -21063,22 +23052,23 @@ static int run_table_dump_query(
  nResult = sqlite3_column_count(pSelect);
  while( rc==SQLITE_ROW ){
    z = (const char*)sqlite3_column_text(pSelect, 0);
-
    oputf("%s", z);
+
    sqlite3_fprintf(p->out, "%s", z);
    for(i=1; i<nResult; i++){
-
      oputf(",%s", sqlite3_column_text(pSelect, i));
+
      sqlite3_fprintf(p->out, ",%s", sqlite3_column_text(pSelect, i));
    }
    if( z==0 ) z = "";
    while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
    if( z[0] ){
-
      oputz("\n;\n");
+
      sqlite3_fputs("\n;\n", p->out);
    }else{
-
      oputz(";\n");
+
      sqlite3_fputs(";\n", p->out);
    }
    rc = sqlite3_step(pSelect);
  }
  rc = sqlite3_finalize(pSelect);
  if( rc!=SQLITE_OK ){
-
    oputf("/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
+
    sqlite3_fprintf(p->out, "/**** ERROR: (%d) %s *****/\n",
+
                    rc, sqlite3_errmsg(p->db));
    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
  }
  return rc;
@@ -21114,13 +23104,13 @@ static char *save_err_msg(
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
-
static void displayLinuxIoStats(void){
+
static void displayLinuxIoStats(FILE *out){
  FILE *in;
  char z[200];
  sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
-
  in = fopen(z, "rb");
+
  in = sqlite3_fopen(z, "rb");
  if( in==0 ) return;
-
  while( fgets(z, sizeof(z), in)!=0 ){
+
  while( sqlite3_fgets(z, sizeof(z), in)!=0 ){
    static const struct {
      const char *zPattern;
      const char *zDesc;
@@ -21137,7 +23127,7 @@ static void displayLinuxIoStats(void){
    for(i=0; i<ArraySize(aTrans); i++){
      int n = strlen30(aTrans[i].zPattern);
      if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
-
        oputf("%-36s %s", aTrans[i].zDesc, &z[n]);
+
        sqlite3_fprintf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
        break;
      }
    }
@@ -21150,6 +23140,7 @@ static void displayLinuxIoStats(void){
** Display a single line of status using 64-bit values.
*/
static void displayStatLine(
+
  FILE *out,                /* Write to this channel */
  char *zLabel,             /* Label for this one line */
  char *zFormat,            /* Format for the result */
  int iStatusCtrl,          /* Which status to display */
@@ -21168,7 +23159,7 @@ static void displayStatLine(
  }else{
    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
  }
-
  oputf("%-36s %s\n", zLabel, zLine);
+
  sqlite3_fprintf(out, "%-36s %s\n", zLabel, zLine);
}

/*
@@ -21181,28 +23172,31 @@ static int display_stats(
){
  int iCur;
  int iHiwtr;
+
  FILE *out;
  if( pArg==0 || pArg->out==0 ) return 0;
+
  out = pArg->out;

  if( pArg->pStmt && pArg->statsOn==2 ){
    int nCol, i, x;
    sqlite3_stmt *pStmt = pArg->pStmt;
    char z[100];
    nCol = sqlite3_column_count(pStmt);
-
    oputf("%-36s %d\n", "Number of output columns:", nCol);
+
    sqlite3_fprintf(out, "%-36s %d\n", "Number of output columns:", nCol);
    for(i=0; i<nCol; i++){
      sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
-
      oputf("%-36s %s\n", z, sqlite3_column_name(pStmt,i));
+
      sqlite3_fprintf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
#ifndef SQLITE_OMIT_DECLTYPE
      sqlite3_snprintf(30, z+x, "declared type:");
-
      oputf("%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
+
      sqlite3_fprintf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
#endif
#ifdef SQLITE_ENABLE_COLUMN_METADATA
      sqlite3_snprintf(30, z+x, "database name:");
-
      oputf("%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
+
      sqlite3_fprintf(out, "%-36s %s\n", z,
+
                           sqlite3_column_database_name(pStmt,i));
      sqlite3_snprintf(30, z+x, "table name:");
-
      oputf("%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
+
      sqlite3_fprintf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
      sqlite3_snprintf(30, z+x, "origin name:");
-
      oputf("%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
+
      sqlite3_fprintf(out, "%-36s %s\n", z,sqlite3_column_origin_name(pStmt,i));
#endif
    }
  }
@@ -21210,27 +23204,27 @@ static int display_stats(
  if( pArg->statsOn==3 ){
    if( pArg->pStmt ){
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset);
-
      oputf("VM-steps: %d\n", iCur);
+
      sqlite3_fprintf(out, "VM-steps: %d\n", iCur);
    }
    return 0;
  }

-
  displayStatLine("Memory Used:",
+
  displayStatLine(out, "Memory Used:",
     "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
-
  displayStatLine("Number of Outstanding Allocations:",
+
  displayStatLine(out, "Number of Outstanding Allocations:",
     "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
  if( pArg->shellFlgs & SHFLG_Pagecache ){
-
    displayStatLine("Number of Pcache Pages Used:",
+
    displayStatLine(out, "Number of Pcache Pages Used:",
       "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
  }
-
  displayStatLine("Number of Pcache Overflow Bytes:",
+
  displayStatLine(out, "Number of Pcache Overflow Bytes:",
     "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
-
  displayStatLine("Largest Allocation:",
+
  displayStatLine(out, "Largest Allocation:",
     "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
-
  displayStatLine("Largest Pcache Allocation:",
+
  displayStatLine(out, "Largest Pcache Allocation:",
     "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
#ifdef YYTRACKMAXSTACKDEPTH
-
  displayStatLine("Deepest Parser Stack:",
+
  displayStatLine(out, "Deepest Parser Stack:",
     "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
#endif

@@ -21239,68 +23233,87 @@ static int display_stats(
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
                        &iCur, &iHiwtr, bReset);
-
      oputf("Lookaside Slots Used:                %d (max %d)\n", iCur, iHiwtr);
+
      sqlite3_fprintf(out, 
+
           "Lookaside Slots Used:                %d (max %d)\n", iCur, iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
                        &iCur, &iHiwtr, bReset);
-
      oputf("Successful lookaside attempts:       %d\n", iHiwtr);
+
      sqlite3_fprintf(out,
+
           "Successful lookaside attempts:       %d\n", iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
                        &iCur, &iHiwtr, bReset);
-
      oputf("Lookaside failures due to size:      %d\n", iHiwtr);
+
      sqlite3_fprintf(out,
+
           "Lookaside failures due to size:      %d\n", iHiwtr);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
                        &iCur, &iHiwtr, bReset);
-
      oputf("Lookaside failures due to OOM:       %d\n", iHiwtr);
+
      sqlite3_fprintf(out,
+
           "Lookaside failures due to OOM:       %d\n", iHiwtr);
    }
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
-
    oputf("Pager Heap Usage:                    %d bytes\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Pager Heap Usage:                    %d bytes\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
-
    oputf("Page cache hits:                     %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Page cache hits:                     %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
-
    oputf("Page cache misses:                   %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Page cache misses:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
-
    oputf("Page cache writes:                   %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Page cache writes:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
-
    oputf("Page cache spills:                   %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Page cache spills:                   %d\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
-
    oputf("Schema Heap Usage:                   %d bytes\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Schema Heap Usage:                   %d bytes\n", iCur);
    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
-
    oputf("Statement Heap/Lookaside Usage:      %d bytes\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Statement Heap/Lookaside Usage:      %d bytes\n", iCur);
  }

  if( pArg->pStmt ){
    int iHit, iMiss;
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                               bReset);
-
    oputf("Fullscan Steps:                      %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
-
    oputf("Sort Operations:                     %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
-
    oputf("Autoindex Inserts:                   %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Autoindex Inserts:                   %d\n", iCur);
    iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT,
                               bReset);
    iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS,
                                bReset);
    if( iHit || iMiss ){
-
      oputf("Bloom filter bypass taken:           %d/%d\n", iHit, iHit+iMiss);
+
      sqlite3_fprintf(out,
+
           "Bloom filter bypass taken:           %d/%d\n", iHit, iHit+iMiss);
    }
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
-
    oputf("Virtual Machine Steps:               %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Virtual Machine Steps:               %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
-
    oputf("Reprepare operations:                %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Reprepare operations:                %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
-
    oputf("Number of times run:                 %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Number of times run:                 %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
-
    oputf("Memory used by prepared stmt:        %d\n", iCur);
+
    sqlite3_fprintf(out,
+
           "Memory used by prepared stmt:        %d\n", iCur);
  }

#ifdef __linux__
-
  displayLinuxIoStats();
+
  displayLinuxIoStats(pArg->out);
#endif

  /* Do not remove this machine readable comment: extra-stats-output-here */
@@ -21537,7 +23550,13 @@ static void display_scanstats(
  if( pArg->scanstatsOn==3 ){
    const char *zSql =
      "  SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
-
      "   round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
+
      "   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(?)";

    int rc = SQLITE_OK;
@@ -21645,6 +23664,15 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
    }else if( sqlite3_strlike("_INF", zVar, 0)==0 ){
      sqlite3_bind_double(pStmt, i, INFINITY);
#endif
+
    }else if( strncmp(zVar, "$int_", 5)==0 ){
+
      sqlite3_bind_int(pStmt, i, atoi(&zVar[5]));
+
    }else if( strncmp(zVar, "$text_", 6)==0 ){
+
      size_t szVar = strlen(zVar);
+
      char *zBuf = sqlite3_malloc64( szVar-5 );
+
      if( zBuf ){
+
        memcpy(zBuf, &zVar[6], szVar-5);
+
        sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
+
      }
    }else{
      sqlite3_bind_null(pStmt, i);
    }
@@ -21681,17 +23709,17 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
/* Draw horizontal line N characters long using unicode box
** characters
*/
-
static void print_box_line(int N){
+
static void print_box_line(FILE *out, int N){
  const char zDash[] =
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
  const int nDash = sizeof(zDash) - 1;
  N *= 3;
  while( N>nDash ){
-
    oputz(zDash);
+
    sqlite3_fputs(zDash, out);
    N -= nDash;
  }
-
  oputf("%.*s", N, zDash);
+
  sqlite3_fprintf(out, "%.*s", N, zDash);
}

/*
@@ -21706,15 +23734,15 @@ static void print_box_row_separator(
){
  int i;
  if( nArg>0 ){
-
    oputz(zSep1);
-
    print_box_line(p->actualWidth[0]+2);
+
    sqlite3_fputs(zSep1, p->out);
+
    print_box_line(p->out, p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
-
      oputz(zSep2);
-
      print_box_line(p->actualWidth[i]+2);
+
      sqlite3_fputs(zSep2, p->out);
+
      print_box_line(p->out, p->actualWidth[i]+2);
    }
-
    oputz(zSep3);
+
    sqlite3_fputs(zSep3, p->out);
  }
-
  oputz("\n");
+
  sqlite3_fputs("\n", p->out);
}

/*
@@ -21748,12 +23776,22 @@ static char *translateForDisplayAndDup(
  if( mxWidth==0 ) mxWidth = 1000000;
  i = j = n = 0;
  while( n<mxWidth ){
-
    if( z[i]>=' ' ){
+
    unsigned char c = z[i];
+
    if( c>=0xc0 ){
+
      int u;
+
      int len = decodeUtf8(&z[i], &u);
+
      i += len;
+
      j += len;
+
      n += cli_wcwidth(u);
+
      continue;
+
    }
+
    if( c>=' ' ){
      n++;
-
      do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
+
      i++;
+
      j++;
      continue;
    }
-
    if( z[i]=='\t' ){
+
    if( c=='\t' ){
      do{
        n++;
        j++;
@@ -21795,9 +23833,17 @@ static char *translateForDisplayAndDup(
  shell_check_oom(zOut);
  i = j = n = 0;
  while( i<k ){
-
    if( z[i]>=' ' ){
+
    unsigned char c = z[i];
+
    if( c>=0xc0 ){
+
      int u;
+
      int len = decodeUtf8(&z[i], &u);
+
      do{ zOut[j++] = z[i++]; }while( (--len)>0 );
+
      n += cli_wcwidth(u);
+
      continue;
+
    }
+
    if( c>=' ' ){
      n++;
-
      do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
+
      zOut[j++] = z[i++];
      continue;
    }
    if( z[i]=='\t' ){
@@ -21977,12 +24023,12 @@ static void exec_prepared_stmt_columnar(
        for(i=0; i<nColumn; i++){
          w = p->actualWidth[i];
          if( p->colWidth[i]<0 ) w = -w;
-
          utf8_width_print(w, azData[i]);
-
          fputs(i==nColumn-1?"\n":"  ", p->out);
+
          utf8_width_print(p->out, w, azData[i]);
+
          sqlite3_fputs(i==nColumn-1?"\n":"  ", p->out);
        }
        for(i=0; i<nColumn; i++){
-
          print_dashes(p->actualWidth[i]);
-
          fputs(i==nColumn-1?"\n":"  ", p->out);
+
          print_dashes(p->out, p->actualWidth[i]);
+
          sqlite3_fputs(i==nColumn-1?"\n":"  ", p->out);
        }
      }
      break;
@@ -21991,12 +24037,13 @@ static void exec_prepared_stmt_columnar(
      colSep = " | ";
      rowSep = " |\n";
      print_row_separator(p, nColumn, "+");
-
      fputs("| ", p->out);
+
      sqlite3_fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
-
        oputf("%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
-
        oputz(i==nColumn-1?" |\n":" | ");
+
        sqlite3_fprintf(p->out, "%*s%s%*s", (w-n)/2, "",
+
                        azData[i], (w-n+1)/2, "");
+
        sqlite3_fputs(i==nColumn-1?" |\n":" | ", p->out);
      }
      print_row_separator(p, nColumn, "+");
      break;
@@ -22004,12 +24051,13 @@ static void exec_prepared_stmt_columnar(
    case MODE_Markdown: {
      colSep = " | ";
      rowSep = " |\n";
-
      fputs("| ", p->out);
+
      sqlite3_fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
-
        oputf("%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
-
        oputz(i==nColumn-1?" |\n":" | ");
+
        sqlite3_fprintf(p->out, "%*s%s%*s", (w-n)/2, "",
+
                        azData[i], (w-n+1)/2, "");
+
        sqlite3_fputs(i==nColumn-1?" |\n":" | ", p->out);
      }
      print_row_separator(p, nColumn, "|");
      break;
@@ -22018,11 +24066,11 @@ static void exec_prepared_stmt_columnar(
      colSep = " " BOX_13 " ";
      rowSep = " " BOX_13 "\n";
      print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
-
      oputz(BOX_13 " ");
+
      sqlite3_fputs(BOX_13 " ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
-
        oputf("%*s%s%*s%s",
+
        sqlite3_fprintf(p->out, "%*s%s%*s%s",
              (w-n)/2, "", azData[i], (w-n+1)/2, "",
              i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
      }
@@ -22032,28 +24080,28 @@ static void exec_prepared_stmt_columnar(
  }
  for(i=nColumn, j=0; i<nTotal; i++, j++){
    if( j==0 && p->cMode!=MODE_Column ){
-
      oputz(p->cMode==MODE_Box?BOX_13" ":"| ");
+
      sqlite3_fputs(p->cMode==MODE_Box?BOX_13" ":"| ", p->out);
    }
    z = azData[i];
    if( z==0 ) z = p->nullValue;
    w = p->actualWidth[j];
    if( p->colWidth[j]<0 ) w = -w;
-
    utf8_width_print(w, z);
+
    utf8_width_print(p->out, w, z);
    if( j==nColumn-1 ){
-
      oputz(rowSep);
+
      sqlite3_fputs(rowSep, p->out);
      if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
        if( p->cMode==MODE_Table ){
          print_row_separator(p, nColumn, "+");
        }else if( p->cMode==MODE_Box ){
          print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
        }else if( p->cMode==MODE_Column ){
-
          oputz("\n");
+
          sqlite3_fputs("\n", p->out);
        }
      }
      j = -1;
      if( seenInterrupt ) goto columnar_end;
    }else{
-
      oputz(colSep);
+
      sqlite3_fputs(colSep, p->out);
    }
  }
  if( p->cMode==MODE_Table ){
@@ -22063,7 +24111,7 @@ static void exec_prepared_stmt_columnar(
  }
columnar_end:
  if( seenInterrupt ){
-
    oputz("Interrupt\n");
+
    sqlite3_fputs("Interrupt\n", p->out);
  }
  nData = (nRow+1)*nColumn;
  for(i=0; i<nData; i++){
@@ -22150,7 +24198,9 @@ static void exec_prepared_stmt(
      } while( SQLITE_ROW == rc );
      sqlite3_free(pData);
      if( pArg->cMode==MODE_Json ){
-
        fputs("]\n", pArg->out);
+
        sqlite3_fputs("]\n", pArg->out);
+
      }else if( pArg->cMode==MODE_Www ){
+
        sqlite3_fputs("</TABLE>\n<PRE>\n", pArg->out);
      }else if( pArg->cMode==MODE_Count ){
        char zBuf[200];
        sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
@@ -22199,6 +24249,7 @@ static int expertFinish(
){
  int rc = SQLITE_OK;
  sqlite3expert *p = pState->expert.pExpert;
+
  FILE *out = pState->out;
  assert( p );
  assert( bCancel || pzErr==0 || *pzErr==0 );
  if( bCancel==0 ){
@@ -22211,8 +24262,8 @@ static int expertFinish(

      if( bVerbose ){
        const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
-
        oputz("-- Candidates -----------------------------\n");
-
        oputf("%s\n", zCand);
+
        sqlite3_fputs("-- Candidates -----------------------------\n", out);
+
        sqlite3_fprintf(out, "%s\n", zCand);
      }
      for(i=0; i<nQuery; i++){
        const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
@@ -22220,11 +24271,12 @@ static int expertFinish(
        const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
        if( zIdx==0 ) zIdx = "(no new indexes)\n";
        if( bVerbose ){
-
          oputf("-- Query %d --------------------------------\n",i+1);
-
          oputf("%s\n\n", zSql);
+
          sqlite3_fprintf(out,
+
              "-- Query %d --------------------------------\n"
+
              "%s\n\n"
+
              ,i+1, zSql);
        }
-
        oputf("%s\n", zIdx);
-
        oputf("%s\n", zEQP);
+
        sqlite3_fprintf(out, "%s\n%s\n", zIdx, zEQP);
      }
    }
  }
@@ -22259,18 +24311,18 @@ static int expertDotCommand(
    }
    else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
      if( i==(nArg-1) ){
-
        eputf("option requires an argument: %s\n", z);
+
        sqlite3_fprintf(stderr, "option requires an argument: %s\n", z);
        rc = SQLITE_ERROR;
      }else{
        iSample = (int)integerValue(azArg[++i]);
        if( iSample<0 || iSample>100 ){
-
          eputf("value out of range: %s\n", azArg[i]);
+
          sqlite3_fprintf(stderr,"value out of range: %s\n", azArg[i]);
          rc = SQLITE_ERROR;
        }
      }
    }
    else{
-
      eputf("unknown option: %s\n", z);
+
      sqlite3_fprintf(stderr,"unknown option: %s\n", z);
      rc = SQLITE_ERROR;
    }
  }
@@ -22278,7 +24330,8 @@ static int expertDotCommand(
  if( rc==SQLITE_OK ){
    pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
    if( pState->expert.pExpert==0 ){
-
      eputf("sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
+
      sqlite3_fprintf(stderr,
+
          "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
      rc = SQLITE_ERROR;
    }else{
      sqlite3_expert_config(
@@ -22360,6 +24413,7 @@ static int shell_exec(
        sqlite3_reset(pExplain);
        rc = sqlite3_stmt_explain(pExplain, 2);
        if( rc==SQLITE_OK ){
+
          bind_prepared_stmt(pArg, pExplain);
          while( sqlite3_step(pExplain)==SQLITE_ROW ){
            const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
            int iEqpId = sqlite3_column_int(pExplain, 0);
@@ -22377,6 +24431,7 @@ static int shell_exec(
          if( rc==SQLITE_OK ){
            pArg->cMode = MODE_Explain;
            assert( sqlite3_stmt_isexplain(pExplain)==1 );
+
            bind_prepared_stmt(pArg, pExplain);
            explain_data_prepare(pArg, pExplain);
            exec_prepared_stmt(pArg, pExplain);
            explain_data_delete(pArg);
@@ -22605,9 +24660,9 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
  noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;

  if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
-
    if( !dataOnly ) oputz("DELETE FROM sqlite_sequence;\n");
+
    /* no-op */
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
-
    if( !dataOnly ) oputz("ANALYZE sqlite_schema;\n");
+
    if( !dataOnly ) sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
  }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;
  }else if( dataOnly ){
@@ -22615,7 +24670,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
  }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    char *zIns;
    if( !p->writableSchema ){
-
      oputz("PRAGMA writable_schema=ON;\n");
+
      sqlite3_fputs("PRAGMA writable_schema=ON;\n", p->out);
      p->writableSchema = 1;
    }
    zIns = sqlite3_mprintf(
@@ -22623,11 +24678,11 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
       "VALUES('table','%q','%q',0,'%q');",
       zTable, zTable, zSql);
    shell_check_oom(zIns);
-
    oputf("%s\n", zIns);
+
    sqlite3_fprintf(p->out, "%s\n", zIns);
    sqlite3_free(zIns);
    return 0;
  }else{
-
    printSchemaLine(zSql, ";\n");
+
    printSchemaLine(p->out, zSql, ";\n");
  }

  if( cli_strcmp(zType, "table")==0 ){
@@ -22685,7 +24740,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
    p->mode = p->cMode = MODE_Insert;
    rc = shell_exec(p, sSelect.z, 0);
    if( (rc&0xff)==SQLITE_CORRUPT ){
-
      oputz("/****** CORRUPTION ERROR *******/\n");
+
      sqlite3_fputs("/****** CORRUPTION ERROR *******/\n", p->out);
      toggleSelectOrder(p->db);
      shell_exec(p, sSelect.z, 0);
      toggleSelectOrder(p->db);
@@ -22716,9 +24771,9 @@ static int run_schema_dump_query(
  if( rc==SQLITE_CORRUPT ){
    char *zQ2;
    int len = strlen30(zQuery);
-
    oputz("/****** CORRUPTION ERROR *******/\n");
+
    sqlite3_fputs("/****** CORRUPTION ERROR *******/\n", p->out);
    if( zErr ){
-
      oputf("/****** %s ******/\n", zErr);
+
      sqlite3_fprintf(p->out, "/****** %s ******/\n", zErr);
      sqlite3_free(zErr);
      zErr = 0;
    }
@@ -22727,7 +24782,7 @@ static int run_schema_dump_query(
    sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
    if( rc ){
-
      oputf("/****** ERROR: %s ******/\n", zErr);
+
      sqlite3_fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
    }else{
      rc = SQLITE_CORRUPT;
    }
@@ -22790,9 +24845,7 @@ static const char *(azHelp[]) = {
  ".clone NEWDB             Clone data into NEWDB from the existing database",
#endif
  ".connection [close] [#]  Open or close an auxiliary database connection",
-
#if defined(_WIN32) || defined(WIN32)
-
  ".crnl on|off             Translate \\n to \\r\\n.  Default ON",
-
#endif
+
  ".crlf ?on|off?           Whether or not to use \\r\\n line endings",
  ".databases               List names and files of attached databases",
  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
#if SQLITE_SHELL_HAVE_RECOVER
@@ -22898,9 +24951,11 @@ static const char *(azHelp[]) = {
#ifndef SQLITE_SHELL_FIDDLE
  ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
  "     If FILE begins with '|' then open as a pipe",
-
  "       --bom  Put a UTF8 byte-order mark at the beginning",
-
  "       -e     Send output to the system text editor",
-
  "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
+
  "       --bom    Put a UTF8 byte-order mark at the beginning",
+
  "       -e       Send output to the system text editor",
+
  "       --plain  Use text/plain output instead of HTML for -w option",
+
  "       -w       Send output as HTML to a web browser (same as \".www\")",
+
  "       -x       Send output as CSV to a spreadsheet (same as \".excel\")",
  /* Note that .open is (partially) available in WASM builds but is
  ** currently only intended to be used by the fiddle tool, not
  ** end users, so is "undocumented." */
@@ -22923,6 +24978,8 @@ static const char *(azHelp[]) = {
  "   Options:",
  "     --bom                 Prefix output with a UTF8 byte-order mark",
  "     -e                    Send output to the system text editor",
+
  "     --plain               Use text/plain for -w option",
+
  "     -w                    Send output to a web browser",
  "     -x                    Send output as CSV to a spreadsheet",
#endif
  ".parameter CMD ...       Manage SQL parameter bindings",
@@ -23036,6 +25093,10 @@ static const char *(azHelp[]) = {
  ".vfsname ?AUX?           Print the name of the VFS stack",
  ".width NUM1 NUM2 ...     Set minimum column widths for columnar output",
  "     Negative values right-justify",
+
#ifndef SQLITE_SHELL_FIDDLE
+
  ".www                     Display output of the next command in web browser",
+
  "    --plain                 Show results as text/plain, not as HTML",
+
#endif
};

/*
@@ -23084,10 +25145,10 @@ static int showHelp(FILE *out, const char *zPattern){
      }
      if( ((hw^hh)&HH_Undoc)==0 ){
        if( (hh&HH_Summary)!=0 ){
-
          sputf(out, ".%s\n", azHelp[i]+1);
+
          sqlite3_fprintf(out, ".%s\n", azHelp[i]+1);
          ++n;
        }else if( (hw&HW_SummaryOnly)==0 ){
-
          sputf(out, "%s\n", azHelp[i]);
+
          sqlite3_fprintf(out, "%s\n", azHelp[i]);
        }
      }
    }
@@ -23097,7 +25158,7 @@ static int showHelp(FILE *out, const char *zPattern){
    shell_check_oom(zPat);
    for(i=0; i<ArraySize(azHelp); i++){
      if( sqlite3_strglob(zPat, azHelp[i])==0 ){
-
        sputf(out, "%s\n", azHelp[i]);
+
        sqlite3_fprintf(out, "%s\n", azHelp[i]);
        j = i+1;
        n++;
      }
@@ -23108,7 +25169,7 @@ static int showHelp(FILE *out, const char *zPattern){
        /* when zPattern is a prefix of exactly one command, then include
        ** the details of that command, which should begin at offset j */
        while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
-
          sputf(out, "%s\n", azHelp[j]);
+
          sqlite3_fprintf(out, "%s\n", azHelp[j]);
          j++;
        }
      }
@@ -23125,10 +25186,10 @@ static int showHelp(FILE *out, const char *zPattern){
      }
      if( azHelp[i][0]=='.' ) j = i;
      if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
-
        sputf(out, "%s\n", azHelp[j]);
+
        sqlite3_fprintf(out, "%s\n", azHelp[j]);
        while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
          j++;
-
          sputf(out, "%s\n", azHelp[j]);
+
          sqlite3_fprintf(out, "%s\n", azHelp[j]);
        }
        i = j;
        n++;
@@ -23158,7 +25219,7 @@ static int process_input(ShellState *p);
** is undefined in this case.
*/
static char *readFile(const char *zName, int *pnByte){
-
  FILE *in = fopen(zName, "rb");
+
  FILE *in = sqlite3_fopen(zName, "rb");
  long nIn;
  size_t nRead;
  char *pBuf;
@@ -23166,7 +25227,7 @@ static char *readFile(const char *zName, int *pnByte){
  if( in==0 ) return 0;
  rc = fseek(in, 0, SEEK_END);
  if( rc!=0 ){
-
    eputf("Error: '%s' not seekable\n", zName);
+
    sqlite3_fprintf(stderr,"Error: '%s' not seekable\n", zName);
    fclose(in);
    return 0;
  }
@@ -23174,7 +25235,7 @@ static char *readFile(const char *zName, int *pnByte){
  rewind(in);
  pBuf = sqlite3_malloc64( nIn+1 );
  if( pBuf==0 ){
-
    eputz("Error: out of memory\n");
+
    sqlite3_fputs("Error: out of memory\n", stderr);
    fclose(in);
    return 0;
  }
@@ -23182,7 +25243,7 @@ static char *readFile(const char *zName, int *pnByte){
  fclose(in);
  if( nRead!=1 ){
    sqlite3_free(pBuf);
-
    eputf("Error: cannot read '%s'\n", zName);
+
    sqlite3_fprintf(stderr,"Error: cannot read '%s'\n", zName);
    return 0;
  }
  pBuf[nIn] = 0;
@@ -23248,7 +25309,7 @@ static int session_filter(void *pCtx, const char *zTab){
** the type cannot be determined from content.
*/
int deduceDatabaseType(const char *zName, int dfltZip){
-
  FILE *f = fopen(zName, "rb");
+
  FILE *f = sqlite3_fopen(zName, "rb");
  size_t n;
  int rc = SHELL_OPEN_UNSPEC;
  char zBuf[100];
@@ -23301,9 +25362,9 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
  unsigned int x[16];
  char zLine[1000];
  if( zDbFilename ){
-
    in = fopen(zDbFilename, "r");
+
    in = sqlite3_fopen(zDbFilename, "r");
    if( in==0 ){
-
      eputf("cannot open \"%s\" for reading\n", zDbFilename);
+
      sqlite3_fprintf(stderr,"cannot open \"%s\" for reading\n", zDbFilename);
      return 0;
    }
    nLine = 0;
@@ -23314,7 +25375,7 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
  }
  *pnData = 0;
  nLine++;
-
  if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
+
  if( sqlite3_fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
  rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
  if( rc!=2 ) goto readHexDb_error;
  if( n<0 ) goto readHexDb_error;
@@ -23324,10 +25385,10 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
  shell_check_oom(a);
  memset(a, 0, n);
  if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
-
    eputz("invalid pagesize\n");
+
    sqlite3_fputs("invalid pagesize\n", stderr);
    goto readHexDb_error;
  }
-
  for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
+
  for(nLine++; sqlite3_fgets(zLine, sizeof(zLine), in)!=0; nLine++){
    rc = sscanf(zLine, "| page %d offset %d", &j, &k);
    if( rc==2 ){
      iOffset = k;
@@ -23359,14 +25420,14 @@ readHexDb_error:
  if( in!=p->in ){
    fclose(in);
  }else{
-
    while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
+
    while( sqlite3_fgets(zLine, sizeof(zLine), p->in)!=0 ){
      nLine++;
      if(cli_strncmp(zLine, "| end ", 6)==0 ) break;
    }
    p->lineno = nLine;
  }
  sqlite3_free(a);
-
  eputf("Error on line %d of --hexdb input\n", nLine);
+
  sqlite3_fprintf(stderr,"Error on line %d of --hexdb input\n", nLine);
  return 0;
}
#endif /* SQLITE_OMIT_DESERIALIZE */
@@ -23441,7 +25502,7 @@ static void open_db(ShellState *p, int openFlags){
      }
    }
    if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
-
      eputf("Error: unable to open database \"%s\": %s\n",
+
      sqlite3_fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
            zDbFilename, sqlite3_errmsg(p->db));
      if( (openFlags & OPEN_DB_KEEPALIVE)==0 ){
        exit(1);
@@ -23449,10 +25510,12 @@ static void open_db(ShellState *p, int openFlags){
      sqlite3_close(p->db);
      sqlite3_open(":memory:", &p->db);
      if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
-
        eputz("Also: unable to open substitute in-memory database.\n");
+
        sqlite3_fputs("Also: unable to open substitute in-memory database.\n",
+
                      stderr);
        exit(1);
      }else{
-
        eputf("Notice: using substitute in-memory database instead of \"%s\"\n",
+
        sqlite3_fprintf(stderr,
+
              "Notice: using substitute in-memory database instead of \"%s\"\n",
              zDbFilename);
      }
    }
@@ -23469,9 +25532,12 @@ static void open_db(ShellState *p, int openFlags){
#ifndef SQLITE_OMIT_LOAD_EXTENSION
    sqlite3_enable_load_extension(p->db, 1);
#endif
+
    sqlite3_sha_init(p->db, 0, 0);
    sqlite3_shathree_init(p->db, 0, 0);
    sqlite3_uint_init(p->db, 0, 0);
+
    sqlite3_stmtrand_init(p->db, 0, 0);
    sqlite3_decimal_init(p->db, 0, 0);
+
    sqlite3_percentile_init(p->db, 0, 0);
    sqlite3_base64_init(p->db, 0, 0);
    sqlite3_base85_init(p->db, 0, 0);
    sqlite3_regexp_init(p->db, 0, 0);
@@ -23561,7 +25627,7 @@ static void open_db(ShellState *p, int openFlags){
                   SQLITE_DESERIALIZE_RESIZEABLE |
                   SQLITE_DESERIALIZE_FREEONCLOSE);
      if( rc ){
-
        eputf("Error: sqlite3_deserialize() returns %d\n", rc);
+
        sqlite3_fprintf(stderr,"Error: sqlite3_deserialize() returns %d\n", rc);
      }
      if( p->szMax>0 ){
        sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
@@ -23585,7 +25651,8 @@ static void open_db(ShellState *p, int openFlags){
void close_db(sqlite3 *db){
  int rc = sqlite3_close(db);
  if( rc ){
-
    eputf("Error: sqlite3_close() returns %d: %s\n", rc, sqlite3_errmsg(db));
+
    sqlite3_fprintf(stderr,
+
        "Error: sqlite3_close() returns %d: %s\n", rc, sqlite3_errmsg(db));
  }
}

@@ -23624,15 +25691,18 @@ static char **readline_completion(const char *zText, int iStart, int iEnd){

#elif HAVE_LINENOISE
/*
-
** Linenoise completion callback
+
** Linenoise completion callback. Note that the 3rd argument is from
+
** the "msteveb" version of linenoise, not the "antirez" version.
*/
-
static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
+
static void linenoise_completion(const char *zLine, linenoiseCompletions *lc,
+
                                 void *pUserData){
  i64 nLine = strlen(zLine);
  i64 i, iStart;
  sqlite3_stmt *pStmt = 0;
  char *zSql;
  char zBuf[1000];

+
  UNUSED_PARAMETER(pUserData);
  if( nLine>(i64)sizeof(zBuf)-30 ) return;
  if( zLine[0]=='.' || zLine[0]=='#') return;
  for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
@@ -23746,7 +25816,8 @@ static int booleanValue(const char *zArg){
  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
    return 0;
  }
-
  eputf("ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg);
+
  sqlite3_fprintf(stderr,
+
       "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg);
  return 0;
}

@@ -23773,7 +25844,7 @@ static void output_file_close(FILE *f){
** recognized and do the right thing.  NULL is returned if the output
** filename is "off".
*/
-
static FILE *output_file_open(const char *zFile, int bTextMode){
+
static FILE *output_file_open(const char *zFile){
  FILE *f;
  if( cli_strcmp(zFile,"stdout")==0 ){
    f = stdout;
@@ -23782,9 +25853,9 @@ static FILE *output_file_open(const char *zFile, int bTextMode){
  }else if( cli_strcmp(zFile, "off")==0 ){
    f = 0;
  }else{
-
    f = fopen(zFile, bTextMode ? "w" : "wb");
+
    f = sqlite3_fopen(zFile, "w");
    if( f==0 ){
-
      eputf("Error: cannot open \"%s\"\n", zFile);
+
      sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zFile);
    }
  }
  return f;
@@ -23837,12 +25908,13 @@ static int sql_trace_callback(
  switch( mType ){
    case SQLITE_TRACE_ROW:
    case SQLITE_TRACE_STMT: {
-
      sputf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
+
      sqlite3_fprintf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
      break;
    }
    case SQLITE_TRACE_PROFILE: {
      sqlite3_int64 nNanosec = pX ? *(sqlite3_int64*)pX : 0;
-
      sputf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
+
      sqlite3_fprintf(p->traceOut,
+
                      "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
      break;
    }
  }
@@ -23949,10 +26021,11 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
        break;
      }
      if( pc==cQuote && c!='\r' ){
-
        eputf("%s:%d: unescaped %c character\n", p->zFile, p->nLine, cQuote);
+
        sqlite3_fprintf(stderr,"%s:%d: unescaped %c character\n", 
+
                        p->zFile, p->nLine, cQuote);
      }
      if( c==EOF ){
-
        eputf("%s:%d: unterminated %c-quoted field\n",
+
        sqlite3_fprintf(stderr,"%s:%d: unterminated %c-quoted field\n",
              p->zFile, startLine, cQuote);
        p->cTerm = c;
        break;
@@ -24051,7 +26124,7 @@ static void tryToCloneData(
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
-
    eputf("Error %d: %s on [%s]\n",
+
    sqlite3_fprintf(stderr,"Error %d: %s on [%s]\n",
          sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery);
    goto end_data_xfer;
  }
@@ -24068,7 +26141,7 @@ static void tryToCloneData(
  memcpy(zInsert+i, ");", 3);
  rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
  if( rc ){
-
    eputf("Error %d: %s on [%s]\n",
+
    sqlite3_fprintf(stderr,"Error %d: %s on [%s]\n",
          sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb), zInsert);
    goto end_data_xfer;
  }
@@ -24104,7 +26177,7 @@ static void tryToCloneData(
      } /* End for */
      rc = sqlite3_step(pInsert);
      if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
-
        eputf("Error %d: %s\n",
+
        sqlite3_fprintf(stderr,"Error %d: %s\n",
              sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb));
      }
      sqlite3_reset(pInsert);
@@ -24122,7 +26195,7 @@ static void tryToCloneData(
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
-
      eputf("Warning: cannot step \"%s\" backwards", zTable);
+
      sqlite3_fprintf(stderr,"Warning: cannot step \"%s\" backwards", zTable);
      break;
    }
  } /* End for(k=0...) */
@@ -24159,7 +26232,8 @@ static void tryToCloneSchema(
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
-
    eputf("Error: (%d) %s on [%s]\n", sqlite3_extended_errcode(p->db),
+
    sqlite3_fprintf(stderr,
+
          "Error: (%d) %s on [%s]\n", sqlite3_extended_errcode(p->db),
          sqlite3_errmsg(p->db), zQuery);
    goto end_schema_xfer;
  }
@@ -24168,10 +26242,10 @@ static void tryToCloneSchema(
    zSql = sqlite3_column_text(pQuery, 1);
    if( zName==0 || zSql==0 ) continue;
    if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){
-
      sputf(stdout, "%s... ", zName); fflush(stdout);
+
      sqlite3_fprintf(stdout, "%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
-
        eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
+
        sqlite3_fprintf(stderr,"Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
@@ -24189,7 +26263,7 @@ static void tryToCloneSchema(
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
-
      eputf("Error: (%d) %s on [%s]\n",
+
      sqlite3_fprintf(stderr,"Error: (%d) %s on [%s]\n",
            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery);
      goto end_schema_xfer;
    }
@@ -24198,10 +26272,10 @@ static void tryToCloneSchema(
      zSql = sqlite3_column_text(pQuery, 1);
      if( zName==0 || zSql==0 ) continue;
      if( sqlite3_stricmp((char*)zName, "sqlite_sequence")==0 ) continue;
-
      sputf(stdout, "%s... ", zName); fflush(stdout);
+
      sqlite3_fprintf(stdout, "%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
-
        eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
+
        sqlite3_fprintf(stderr,"Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
@@ -24225,12 +26299,13 @@ static void tryToClone(ShellState *p, const char *zNewDb){
  int rc;
  sqlite3 *newDb = 0;
  if( access(zNewDb,0)==0 ){
-
    eputf("File \"%s\" already exists.\n", zNewDb);
+
    sqlite3_fprintf(stderr,"File \"%s\" already exists.\n", zNewDb);
    return;
  }
  rc = sqlite3_open(zNewDb, &newDb);
  if( rc ){
-
    eputf("Cannot create output database: %s\n", sqlite3_errmsg(newDb));
+
    sqlite3_fprintf(stderr,
+
        "Cannot create output database: %s\n", sqlite3_errmsg(newDb));
  }else{
    sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
    sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
@@ -24247,10 +26322,18 @@ static void tryToClone(ShellState *p, const char *zNewDb){
** Change the output stream (file or pipe or console) to something else.
*/
static void output_redir(ShellState *p, FILE *pfNew){
-
  if( p->out != stdout ) eputz("Output already redirected.\n");
-
  else{
+
  if( p->out != stdout ){
+
    sqlite3_fputs("Output already redirected.\n", stderr);
+
  }else{
    p->out = pfNew;
-
    setOutputStream(pfNew);
+
    setCrlfMode(p);
+
    if( p->mode==MODE_Www ){
+
      sqlite3_fputs(
+
        "<!DOCTYPE html>\n"
+
        "<HTML><BODY><PRE>\n",
+
        p->out
+
      );
+
    }
  }
}

@@ -24267,6 +26350,9 @@ static void output_reset(ShellState *p){
    pclose(p->out);
#endif
  }else{
+
    if( p->mode==MODE_Www ){
+
      sqlite3_fputs("</PRE></BODY></HTML>\n", p->out);
+
    }
    output_file_close(p->out);
#ifndef SQLITE_NOHAVE_SYSTEM
    if( p->doXdgOpen ){
@@ -24281,7 +26367,7 @@ static void output_reset(ShellState *p){
      char *zCmd;
      zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
      if( system(zCmd) ){
-
        eputf("Failed: [%s]\n", zCmd);
+
        sqlite3_fprintf(stderr,"Failed: [%s]\n", zCmd);
      }else{
        /* Give the start/open/xdg-open command some time to get
        ** going before we continue, and potential delete the
@@ -24296,7 +26382,7 @@ static void output_reset(ShellState *p){
  }
  p->outfile[0] = 0;
  p->out = stdout;
-
  setOutputStream(stdout);
+
  setCrlfMode(p);
}
#else
# define output_redir(SS,pfO)
@@ -24372,7 +26458,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
             "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
             -1, &pStmt, 0);
  if( rc ){
-
    eputf("error: %s\n", sqlite3_errmsg(p->db));
+
    sqlite3_fprintf(stderr,"error: %s\n", sqlite3_errmsg(p->db));
    sqlite3_finalize(pStmt);
    return 1;
  }
@@ -24385,28 +26471,28 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
    memcpy(aHdr, pb, 100);
    sqlite3_finalize(pStmt);
  }else{
-
    eputz("unable to read database header\n");
+
    sqlite3_fputs("unable to read database header\n", stderr);
    sqlite3_finalize(pStmt);
    return 1;
  }
  i = get2byteInt(aHdr+16);
  if( i==1 ) i = 65536;
-
  oputf("%-20s %d\n", "database page size:", i);
-
  oputf("%-20s %d\n", "write format:", aHdr[18]);
-
  oputf("%-20s %d\n", "read format:", aHdr[19]);
-
  oputf("%-20s %d\n", "reserved bytes:", aHdr[20]);
+
  sqlite3_fprintf(p->out, "%-20s %d\n", "database page size:", i);
+
  sqlite3_fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
+
  sqlite3_fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
+
  sqlite3_fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
  for(i=0; i<ArraySize(aField); i++){
    int ofst = aField[i].ofst;
    unsigned int val = get4byteInt(aHdr + ofst);
-
    oputf("%-20s %u", aField[i].zName, val);
+
    sqlite3_fprintf(p->out, "%-20s %u", aField[i].zName, val);
    switch( ofst ){
      case 56: {
-
        if( val==1 ) oputz(" (utf8)");
-
        if( val==2 ) oputz(" (utf16le)");
-
        if( val==3 ) oputz(" (utf16be)");
+
        if( val==1 ) sqlite3_fputs(" (utf8)", p->out);
+
        if( val==2 ) sqlite3_fputs(" (utf16le)", p->out);
+
        if( val==3 ) sqlite3_fputs(" (utf16be)", p->out);
      }
    }
-
    oputz("\n");
+
    sqlite3_fputs("\n", p->out);
  }
  if( zDb==0 ){
    zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
@@ -24419,21 +26505,26 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
    char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
    int val = db_int(p->db, zSql);
    sqlite3_free(zSql);
-
    oputf("%-20s %d\n", aQuery[i].zName, val);
+
    sqlite3_fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
  }
  sqlite3_free(zSchemaTab);
  sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
-
  oputf("%-20s %u\n", "data version", iDataVersion);
+
  sqlite3_fprintf(p->out, "%-20s %u\n", "data version", iDataVersion);
  return 0;
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */

/*
+
** Print the given string as an error message.
+
*/
+
static void shellEmitError(const char *zErr){
+
  sqlite3_fprintf(stderr,"Error: %s\n", zErr);
+
}
+
/*
** Print the current sqlite3_errmsg() value to stderr and return 1.
*/
static int shellDatabaseError(sqlite3 *db){
-
  const char *zErr = sqlite3_errmsg(db);
-
  eputf("Error: %s\n", zErr);
+
  shellEmitError(sqlite3_errmsg(db));
  return 1;
}

@@ -24674,6 +26765,7 @@ static int lintFkeyIndexes(
  const char *zIndent = "";       /* How much to indent CREATE INDEX by */
  int rc;                         /* Return code */
  sqlite3_stmt *pSql = 0;         /* Compiled version of SQL statement below */
+
  FILE *out = pState->out;        /* Send output here */

  /*
  ** This SELECT statement returns one row for each foreign key constraint
@@ -24749,7 +26841,8 @@ static int lintFkeyIndexes(
      zIndent = "    ";
    }
    else{
-
      eputf("Usage: %s %s ?-verbose? ?-groupbyparent?\n", azArg[0], azArg[1]);
+
      sqlite3_fprintf(stderr,
+
           "Usage: %s %s ?-verbose? ?-groupbyparent?\n", azArg[0], azArg[1]);
      return SQLITE_ERROR;
    }
  }
@@ -24793,22 +26886,23 @@ static int lintFkeyIndexes(
      if( rc!=SQLITE_OK ) break;

      if( res<0 ){
-
        eputz("Error: internal error");
+
        sqlite3_fputs("Error: internal error", stderr);
        break;
      }else{
        if( bGroupByParent
        && (bVerbose || res==0)
        && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
        ){
-
          oputf("-- Parent table %s\n", zParent);
+
          sqlite3_fprintf(out, "-- Parent table %s\n", zParent);
          sqlite3_free(zPrev);
          zPrev = sqlite3_mprintf("%s", zParent);
        }

        if( res==0 ){
-
          oputf("%s%s --> %s\n", zIndent, zCI, zTarget);
+
          sqlite3_fprintf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
        }else if( bVerbose ){
-
          oputf("%s/* no extra indexes required for %s -> %s */\n",
+
          sqlite3_fprintf(out,
+
                "%s/* no extra indexes required for %s -> %s */\n",
                zIndent, zFrom, zTarget
          );
        }
@@ -24817,16 +26911,16 @@ static int lintFkeyIndexes(
    sqlite3_free(zPrev);

    if( rc!=SQLITE_OK ){
-
      eputf("%s\n", sqlite3_errmsg(db));
+
      sqlite3_fprintf(stderr,"%s\n", sqlite3_errmsg(db));
    }

    rc2 = sqlite3_finalize(pSql);
    if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
      rc = rc2;
-
      eputf("%s\n", sqlite3_errmsg(db));
+
      sqlite3_fprintf(stderr,"%s\n", sqlite3_errmsg(db));
    }
  }else{
-
    eputf("%s\n", sqlite3_errmsg(db));
+
    sqlite3_fprintf(stderr,"%s\n", sqlite3_errmsg(db));
  }

  return rc;
@@ -24846,9 +26940,9 @@ static int lintDotCommand(
  return lintFkeyIndexes(pState, azArg, nArg);

 usage:
-
  eputf("Usage %s sub-command ?switches...?\n", azArg[0]);
-
  eputz("Where sub-commands are:\n");
-
  eputz("    fkey-indexes\n");
+
  sqlite3_fprintf(stderr,"Usage %s sub-command ?switches...?\n", azArg[0]);
+
  sqlite3_fprintf(stderr, "Where sub-commands are:\n");
+
  sqlite3_fprintf(stderr, "    fkey-indexes\n");
  return SQLITE_ERROR;
}

@@ -24862,7 +26956,8 @@ static void shellPrepare(
  if( *pRc==SQLITE_OK ){
    int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
    if( rc!=SQLITE_OK ){
-
      eputf("sql error: %s (%d)\n", sqlite3_errmsg(db), sqlite3_errcode(db));
+
      sqlite3_fprintf(stderr,
+
         "sql error: %s (%d)\n", sqlite3_errmsg(db), sqlite3_errcode(db));
      *pRc = rc;
    }
  }
@@ -24906,7 +27001,7 @@ static void shellFinalize(
    int rc = sqlite3_finalize(pStmt);
    if( *pRc==SQLITE_OK ){
      if( rc!=SQLITE_OK ){
-
        eputf("SQL error: %s\n", sqlite3_errmsg(db));
+
        sqlite3_fprintf(stderr,"SQL error: %s\n", sqlite3_errmsg(db));
      }
      *pRc = rc;
    }
@@ -24928,7 +27023,7 @@ void shellReset(
  if( *pRc==SQLITE_OK ){
    if( rc!=SQLITE_OK ){
      sqlite3 *db = sqlite3_db_handle(pStmt);
-
      eputf("SQL error: %s\n", sqlite3_errmsg(db));
+
      sqlite3_fprintf(stderr,"SQL error: %s\n", sqlite3_errmsg(db));
    }
    *pRc = rc;
  }
@@ -24957,6 +27052,7 @@ struct ArCommand {
  const char *zDir;               /* --directory argument, or NULL */
  char **azArg;                   /* Array of command arguments */
  ShellState *p;                  /* Shell state */
+
  FILE *out;                      /* Output to this stream */
  sqlite3 *db;                    /* Database containing the archive */
};

@@ -24978,11 +27074,11 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
  va_start(ap, zFmt);
  z = sqlite3_vmprintf(zFmt, ap);
  va_end(ap);
-
  eputf("Error: %s\n", z);
+
  shellEmitError(z);
  if( pAr->fromCmdLine ){
-
    eputz("Use \"-A\" for more help\n");
+
    sqlite3_fputs("Use \"-A\" for more help\n", stderr);
  }else{
-
    eputz("Use \".archive --help\" for more help\n");
+
    sqlite3_fputs("Use \".archive --help\" for more help\n", stderr);
  }
  sqlite3_free(z);
  return SQLITE_ERROR;
@@ -25082,7 +27178,7 @@ static int arParseCommand(
  struct ArSwitch *pEnd = &aSwitch[nSwitch];

  if( nArg<=1 ){
-
    eputz("Wrong number of arguments.  Usage:\n");
+
    sqlite3_fprintf(stderr, "Wrong number of arguments.  Usage:\n");
    return arUsage(stderr);
  }else{
    char *z = azArg[1];
@@ -25188,7 +27284,7 @@ static int arParseCommand(
    }
  }
  if( pAr->eCmd==0 ){
-
    eputz("Required argument missing.  Usage:\n");
+
    sqlite3_fprintf(stderr, "Required argument missing.  Usage:\n");
    return arUsage(stderr);
  }
  return SQLITE_OK;
@@ -25231,7 +27327,7 @@ static int arCheckEntries(ArCommand *pAr){
      }
      shellReset(&rc, pTest);
      if( rc==SQLITE_OK && bOk==0 ){
-
        eputf("not found in archive: %s\n", z);
+
        sqlite3_fprintf(stderr,"not found in archive: %s\n", z);
        rc = SQLITE_ERROR;
      }
    }
@@ -25298,15 +27394,15 @@ static int arListCommand(ArCommand *pAr){
  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                     pAr->zSrcTable, zWhere);
  if( pAr->bDryRun ){
-
    oputf("%s\n", sqlite3_sql(pSql));
+
    sqlite3_fprintf(pAr->out, "%s\n", sqlite3_sql(pSql));
  }else{
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      if( pAr->bVerbose ){
-
        oputf("%s % 10d  %s  %s\n",
+
        sqlite3_fprintf(pAr->out, "%s % 10d  %s  %s\n",
              sqlite3_column_text(pSql, 0), sqlite3_column_int(pSql, 1),
              sqlite3_column_text(pSql, 2),sqlite3_column_text(pSql, 3));
      }else{
-
        oputf("%s\n", sqlite3_column_text(pSql, 0));
+
        sqlite3_fprintf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
      }
    }
  }
@@ -25333,7 +27429,7 @@ static int arRemoveCommand(ArCommand *pAr){
    zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
                           pAr->zSrcTable, zWhere);
    if( pAr->bDryRun ){
-
      oputf("%s\n", zSql);
+
      sqlite3_fprintf(pAr->out, "%s\n", zSql);
    }else{
      char *zErr = 0;
      rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
@@ -25346,7 +27442,7 @@ static int arRemoveCommand(ArCommand *pAr){
        }
      }
      if( zErr ){
-
        sputf(stdout, "ERROR: %s\n", zErr); /* stdout? */
+
        sqlite3_fprintf(stdout, "ERROR: %s\n", zErr); /* stdout? */
        sqlite3_free(zErr);
      }
    }
@@ -25410,11 +27506,11 @@ static int arExtractCommand(ArCommand *pAr){
      j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
      sqlite3_bind_int(pSql, j, i);
      if( pAr->bDryRun ){
-
        oputf("%s\n", sqlite3_sql(pSql));
+
        sqlite3_fprintf(pAr->out, "%s\n", sqlite3_sql(pSql));
      }else{
        while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
          if( i==0 && pAr->bVerbose ){
-
            oputf("%s\n", sqlite3_column_text(pSql, 0));
+
            sqlite3_fprintf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
          }
        }
      }
@@ -25434,13 +27530,13 @@ static int arExtractCommand(ArCommand *pAr){
static int arExecSql(ArCommand *pAr, const char *zSql){
  int rc;
  if( pAr->bDryRun ){
-
    oputf("%s\n", zSql);
+
    sqlite3_fprintf(pAr->out, "%s\n", zSql);
    rc = SQLITE_OK;
  }else{
    char *zErr = 0;
    rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
    if( zErr ){
-
      sputf(stdout, "ERROR: %s\n", zErr);
+
      sqlite3_fprintf(stdout, "ERROR: %s\n", zErr);
      sqlite3_free(zErr);
    }
  }
@@ -25589,6 +27685,7 @@ static int arDotCommand(
  if( rc==SQLITE_OK ){
    int eDbType = SHELL_OPEN_UNSPEC;
    cmd.p = pState;
+
    cmd.out = pState->out;
    cmd.db = pState->db;
    if( cmd.zFile ){
      eDbType = deduceDatabaseType(cmd.zFile, 1);
@@ -25615,13 +27712,14 @@ static int arDotCommand(
      }
      cmd.db = 0;
      if( cmd.bDryRun ){
-
        oputf("-- open database '%s'%s\n", cmd.zFile,
+
        sqlite3_fprintf(cmd.out, "-- open database '%s'%s\n", cmd.zFile,
              eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
      }
      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
      if( rc!=SQLITE_OK ){
-
        eputf("cannot open file: %s (%s)\n", cmd.zFile, sqlite3_errmsg(cmd.db));
+
        sqlite3_fprintf(stderr, "cannot open file: %s (%s)\n",
+
                        cmd.zFile, sqlite3_errmsg(cmd.db));
        goto end_ar_command;
      }
      sqlite3_fileio_init(cmd.db, 0, 0);
@@ -25634,7 +27732,7 @@ static int arDotCommand(
      if( cmd.eCmd!=AR_CMD_CREATE
       && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
      ){
-
        eputz("database does not contain an 'sqlar' table\n");
+
        sqlite3_fprintf(stderr, "database does not contain an 'sqlar' table\n");
        rc = SQLITE_ERROR;
        goto end_ar_command;
      }
@@ -25692,7 +27790,7 @@ end_ar_command:
*/
static int recoverSqlCb(void *pCtx, const char *zSql){
  ShellState *pState = (ShellState*)pCtx;
-
  sputf(pState->out, "%s;\n", zSql);
+
  sqlite3_fprintf(pState->out, "%s;\n", zSql);
  return SQLITE_OK;
}

@@ -25735,7 +27833,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
      bRowids = 0;
    }
    else{
-
      eputf("unexpected option: %s\n", azArg[i]);
+
      sqlite3_fprintf(stderr,"unexpected option: %s\n", azArg[i]);
      showHelp(pState->out, azArg[0]);
      return 1;
    }
@@ -25754,7 +27852,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
  if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
    const char *zErr = sqlite3_recover_errmsg(p);
    int errCode = sqlite3_recover_errcode(p);
-
    eputf("sql error: %s (%d)\n", zErr, errCode);
+
    sqlite3_fprintf(stderr,"sql error: %s (%d)\n", zErr, errCode);
  }
  rc = sqlite3_recover_finish(p);
  return rc;
@@ -25776,7 +27874,7 @@ static int intckDatabaseCmd(ShellState *pState, i64 nStepPerUnlock){
    while( SQLITE_OK==sqlite3_intck_step(p) ){
      const char *zMsg = sqlite3_intck_message(p);
      if( zMsg ){
-
        oputf("%s\n", zMsg);
+
        sqlite3_fprintf(pState->out, "%s\n", zMsg);
        nError++;
      }
      nStep++;
@@ -25786,11 +27884,11 @@ static int intckDatabaseCmd(ShellState *pState, i64 nStepPerUnlock){
    }
    rc = sqlite3_intck_error(p, &zErr);
    if( zErr ){
-
      eputf("%s\n", zErr);
+
      sqlite3_fprintf(stderr,"%s\n", zErr);
    }
    sqlite3_intck_close(p);

-
    oputf("%lld steps, %lld errors\n", nStep, nError);
+
    sqlite3_fprintf(pState->out, "%lld steps, %lld errors\n", nStep, nError);
  }

  return rc;
@@ -25813,7 +27911,7 @@ static int intckDatabaseCmd(ShellState *pState, i64 nStepPerUnlock){
#define rc_err_oom_die(rc) \
  if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
  else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
-
    eputf("E:%d\n",rc), assert(0)
+
    sqlite3_fprintf(stderr,"E:%d\n",rc), assert(0)
#else
static void rc_err_oom_die(int rc){
  if( rc==SQLITE_NOMEM ) shell_check_oom(0);
@@ -26030,8 +28128,9 @@ static int outputDumpWarning(ShellState *p, const char *zLike){
    "sql LIKE 'CREATE VIRTUAL TABLE%%' AND %s", zLike ? zLike : "true"
  );
  if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
-
    oputz("/* WARNING: "
-
          "Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */\n"
+
    sqlite3_fputs("/* WARNING: "
+
          "Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */\n",
+
          p->out
    );
  }
  shellFinalize(&rc, pStmt);
@@ -26062,12 +28161,14 @@ static int faultsim_callback(int iArg){
  if( faultsim_state.iCnt ){
    if( faultsim_state.iCnt>0 ) faultsim_state.iCnt--;
    if( faultsim_state.eVerbose>=2 ){
-
      oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
+
      sqlite3_fprintf(stdout, 
+
         "FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt);
    }
    return SQLITE_OK;
  }
  if( faultsim_state.eVerbose>=1 ){
-
    oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
+
    sqlite3_fprintf(stdout, 
+
         "FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr);
  }
  faultsim_state.iCnt = faultsim_state.iInterval;
  faultsim_state.nHit++;
@@ -26130,7 +28231,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifndef SQLITE_OMIT_AUTHORIZATION
  if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
    if( nArg!=2 ){
-
      eputz("Usage: .auth ON|OFF\n");
+
      sqlite3_fprintf(stderr, "Usage: .auth ON|OFF\n");
      rc = 1;
      goto meta_command_exit;
    }
@@ -26177,7 +28278,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          bAsync = 1;
        }else
        {
-
          eputf("unknown option: %s\n", azArg[j]);
+
          sqlite3_fprintf(stderr,"unknown option: %s\n", azArg[j]);
          return 1;
        }
      }else if( zDestFile==0 ){
@@ -26186,19 +28287,19 @@ static int do_meta_command(char *zLine, ShellState *p){
        zDb = zDestFile;
        zDestFile = azArg[j];
      }else{
-
        eputz("Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
+
        sqlite3_fprintf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
        return 1;
      }
    }
    if( zDestFile==0 ){
-
      eputz("missing FILENAME argument on .backup\n");
+
      sqlite3_fprintf(stderr, "missing FILENAME argument on .backup\n");
      return 1;
    }
    if( zDb==0 ) zDb = "main";
    rc = sqlite3_open_v2(zDestFile, &pDest,
                  SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
    if( rc!=SQLITE_OK ){
-
      eputf("Error: cannot open \"%s\"\n", zDestFile);
+
      sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zDestFile);
      close_db(pDest);
      return 1;
    }
@@ -26209,7 +28310,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    open_db(p, 0);
    pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
    if( pBackup==0 ){
-
      eputf("Error: %s\n", sqlite3_errmsg(pDest));
+
      shellDatabaseError(pDest);
      close_db(pDest);
      return 1;
    }
@@ -26218,7 +28319,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    if( rc==SQLITE_DONE ){
      rc = 0;
    }else{
-
      eputf("Error: %s\n", sqlite3_errmsg(pDest));
+
      shellDatabaseError(pDest);
      rc = 1;
    }
    close_db(pDest);
@@ -26234,19 +28335,10 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  /* Undocumented.  Legacy only.  See "crnl" below */
+
  /* Undocumented.  Legacy only.  See "crlf" below */
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
-
    if( nArg==2 ){
-
      if( booleanValue(azArg[1]) ){
-
        setBinaryMode(p->out, 1);
-
      }else{
-
        setTextMode(p->out, 1);
-
      }
-
    }else{
-
      eputz("The \".binary\" command is deprecated. Use \".crnl\" instead.\n"
-
            "Usage: .binary on|off\n");
-
      rc = 1;
-
    }
+
    eputz("The \".binary\" command is deprecated.\n");
+
    rc = 1;
  }else

  /* The undocumented ".breakpoint" command causes a call to the no-op
@@ -26268,7 +28360,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = chdir(azArg[1]);
#endif
      if( rc ){
-
        eputf("Cannot change to directory \"%s\"\n", azArg[1]);
+
        sqlite3_fprintf(stderr,"Cannot change to directory \"%s\"\n", azArg[1]);
        rc = 1;
      }
    }else{
@@ -26301,11 +28393,12 @@ static int do_meta_command(char *zLine, ShellState *p){
    }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
      rc = 2;
    }else if( testcase_glob(azArg[1],zRes)==0 ){
-
      eputf("testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
+
      sqlite3_fprintf(stderr,
+
            "testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
            p->zTestcase, azArg[1], zRes);
      rc = 1;
    }else{
-
      oputf("testcase-%s ok\n", p->zTestcase);
+
      sqlite3_fprintf(p->out, "testcase-%s ok\n", p->zTestcase);
      p->nCheck++;
    }
    sqlite3_free(zRes);
@@ -26338,9 +28431,9 @@ static int do_meta_command(char *zLine, ShellState *p){
          zFile = "(temporary-file)";
        }
        if( p->pAuxDb == &p->aAuxDb[i] ){
-
          sputf(stdout, "ACTIVE %d: %s\n", i, zFile);
+
          sqlite3_fprintf(stdout, "ACTIVE %d: %s\n", i, zFile);
        }else if( p->aAuxDb[i].db!=0 ){
-
          sputf(stdout, "       %d: %s\n", i, zFile);
+
          sqlite3_fprintf(stdout, "       %d: %s\n", i, zFile);
        }
      }
    }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
@@ -26370,20 +28463,18 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){
+
  if( c=='c' && n==4
+
   && (cli_strncmp(azArg[0], "crlf", n)==0
+
       || cli_strncmp(azArg[0], "crnl",n)==0)
+
  ){
    if( nArg==2 ){
-
      if( booleanValue(azArg[1]) ){
-
        setTextMode(p->out, 1);
-
      }else{
-
        setBinaryMode(p->out, 1);
-
      }
-
    }else{
-
#if !defined(_WIN32) && !defined(WIN32)
-
      eputz("The \".crnl\" is a no-op on non-Windows machines.\n");
+
#ifdef _WIN32
+
      p->crlfMode = booleanValue(azArg[1]);
+
#else
+
      p->crlfMode = 0;
#endif
-
      eputz("Usage: .crnl on|off\n");
-
      rc = 1;
    }
+
    sqlite3_fprintf(stderr, "crlf is %s\n", p->crlfMode ? "ON" : "OFF");
  }else

  if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
@@ -26394,7 +28485,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    open_db(p, 0);
    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    if( rc ){
-
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
+
      shellDatabaseError(p->db);
      rc = 1;
    }else{
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
@@ -26413,7 +28504,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
      int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
      const char *z = azName[i*2+1];
-
      oputf("%s: %s %s%s\n",
+
      sqlite3_fprintf(p->out, "%s: %s %s%s\n",
            azName[i*2], z && z[0] ? z : "\"\"", bRdonly ? "r/o" : "r/w",
            eTxn==SQLITE_TXN_NONE ? "" :
            eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
@@ -26455,11 +28546,12 @@ static int do_meta_command(char *zLine, ShellState *p){
        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
      }
      sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
-
      oputf("%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
+
      sqlite3_fprintf(p->out, "%19s %s\n",
+
                      aDbConfig[ii].zName, v ? "on" : "off");
      if( nArg>1 ) break;
    }
    if( nArg>1 && ii==ArraySize(aDbConfig) ){
-
      eputf("Error: unknown dbconfig \"%s\"\n", azArg[1]);
+
      sqlite3_fprintf(stderr,"Error: unknown dbconfig \"%s\"\n", azArg[1]);
      eputz("Enter \".dbconfig\" with no arguments for a list\n");
    }
  }else
@@ -26509,7 +28601,8 @@ static int do_meta_command(char *zLine, ShellState *p){
          ShellSetFlag(p, SHFLG_DumpNoSys);
        }else
        {
-
          eputf("Unknown option \"%s\" on \".dump\"\n", azArg[i]);
+
          sqlite3_fprintf(stderr,
+
               "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
@@ -26544,8 +28637,8 @@ static int do_meta_command(char *zLine, ShellState *p){
      /* When playing back a "dump", the content might appear in an order
      ** which causes immediate foreign key constraints to be violated.
      ** So disable foreign-key constraint enforcement to prevent problems. */
-
      oputz("PRAGMA foreign_keys=OFF;\n");
-
      oputz("BEGIN TRANSACTION;\n");
+
      sqlite3_fputs("PRAGMA foreign_keys=OFF;\n", p->out);
+
      sqlite3_fputs("BEGIN TRANSACTION;\n", p->out);
    }
    p->writableSchema = 0;
    p->showHeader = 0;
@@ -26577,13 +28670,13 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    sqlite3_free(zLike);
    if( p->writableSchema ){
-
      oputz("PRAGMA writable_schema=OFF;\n");
+
      sqlite3_fputs("PRAGMA writable_schema=OFF;\n", p->out);
      p->writableSchema = 0;
    }
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
-
      oputz(p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
+
      sqlite3_fputs(p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n", p->out);
    }
    p->showHeader = savedShowHeader;
    p->shellFlgs = savedShellFlags;
@@ -26663,7 +28756,8 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
    if( p->bSafeMode ){
-
      eputf("Cannot run experimental commands such as \"%s\" in safe mode\n",
+
      sqlite3_fprintf(stderr,
+
            "Cannot run experimental commands such as \"%s\" in safe mode\n",
            azArg[0]);
      rc = 1;
    }else{
@@ -26720,9 +28814,10 @@ static int do_meta_command(char *zLine, ShellState *p){

    /* --help lists all file-controls */
    if( cli_strcmp(zCmd,"help")==0 ){
-
      oputz("Available file-controls:\n");
+
      sqlite3_fputs("Available file-controls:\n", p->out);
      for(i=0; i<ArraySize(aCtrl); i++){
-
        oputf("  .filectrl %s %s\n", aCtrl[i].zCtrlName, aCtrl[i].zUsage);
+
        sqlite3_fprintf(p->out,
+
               "  .filectrl %s %s\n", aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
      goto meta_command_exit;
@@ -26737,7 +28832,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          filectrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
-
          eputf("Error: ambiguous file-control: \"%s\"\n"
+
          sqlite3_fprintf(stderr,"Error: ambiguous file-control: \"%s\"\n"
                "Use \".filectrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
@@ -26745,7 +28840,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
    }
    if( filectrl<0 ){
-
      eputf("Error: unknown file-control: %s\n"
+
      sqlite3_fprintf(stderr,"Error: unknown file-control: %s\n"
            "Use \".filectrl --help\" for help\n", zCmd);
    }else{
      switch(filectrl){
@@ -26789,7 +28884,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          if( nArg!=2 ) break;
          sqlite3_file_control(p->db, zSchema, filectrl, &z);
          if( z ){
-
            oputf("%s\n", z);
+
            sqlite3_fprintf(p->out, "%s\n", z);
            sqlite3_free(z);
          }
          isOk = 2;
@@ -26803,19 +28898,20 @@ static int do_meta_command(char *zLine, ShellState *p){
          }
          x = -1;
          sqlite3_file_control(p->db, zSchema, filectrl, &x);
-
          oputf("%d\n", x);
+
          sqlite3_fprintf(p->out, "%d\n", x);
          isOk = 2;
          break;
        }
      }
    }
    if( isOk==0 && iCtrl>=0 ){
-
      oputf("Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
+
      sqlite3_fprintf(p->out, "Usage: .filectrl %s %s\n",
+
                      zCmd, aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      char zBuf[100];
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
-
      oputf("%s\n", zBuf);
+
      sqlite3_fprintf(p->out, "%s\n", zBuf);
    }
  }else

@@ -26856,15 +28952,15 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
    }
    if( doStats==0 ){
-
      oputz("/* No STAT tables available */\n");
+
      sqlite3_fputs("/* No STAT tables available */\n", p->out);
    }else{
-
      oputz("ANALYZE sqlite_schema;\n");
+
      sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
      data.cMode = data.mode = MODE_Insert;
      data.zDestTable = "sqlite_stat1";
      shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
      data.zDestTable = "sqlite_stat4";
      shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
-
      oputz("ANALYZE sqlite_schema;\n");
+
      sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
    }
  }else

@@ -26882,7 +28978,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    if( nArg>=2 ){
      n = showHelp(p->out, azArg[1]);
      if( n==0 ){
-
        oputf("Nothing matches '%s'\n", azArg[1]);
+
        sqlite3_fprintf(p->out, "Nothing matches '%s'\n", azArg[1]);
      }
    }else{
      showHelp(p->out, 0);
@@ -26925,7 +29021,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        }else if( zTable==0 ){
          zTable = z;
        }else{
-
          oputf("ERROR: extra argument: \"%s\".  Usage:\n", z);
+
          sqlite3_fprintf(p->out, "ERROR: extra argument: \"%s\". Usage:\n",z);
          showHelp(p->out, "import");
          goto meta_command_exit;
        }
@@ -26946,13 +29042,13 @@ static int do_meta_command(char *zLine, ShellState *p){
        xRead = csv_read_one_field;
        useOutputMode = 0;
      }else{
-
        oputf("ERROR: unknown option: \"%s\".  Usage:\n", z);
+
        sqlite3_fprintf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
        showHelp(p->out, "import");
        goto meta_command_exit;
      }
    }
    if( zTable==0 ){
-
      oputf("ERROR: missing %s argument. Usage:\n",
+
      sqlite3_fprintf(p->out, "ERROR: missing %s argument. Usage:\n",
            zFile==0 ? "FILE" : "TABLE");
      showHelp(p->out, "import");
      goto meta_command_exit;
@@ -27002,28 +29098,28 @@ static int do_meta_command(char *zLine, ShellState *p){
      eputz("Error: pipes are not supported in this OS\n");
      goto meta_command_exit;
#else
-
      sCtx.in = popen(sCtx.zFile+1, "r");
+
      sCtx.in = sqlite3_popen(sCtx.zFile+1, "r");
      sCtx.zFile = "<pipe>";
      sCtx.xCloser = pclose;
#endif
    }else{
-
      sCtx.in = fopen(sCtx.zFile, "rb");
+
      sCtx.in = sqlite3_fopen(sCtx.zFile, "rb");
      sCtx.xCloser = fclose;
    }
    if( sCtx.in==0 ){
-
      eputf("Error: cannot open \"%s\"\n", zFile);
+
      sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zFile);
      goto meta_command_exit;
    }
    if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
      char zSep[2];
      zSep[1] = 0;
      zSep[0] = sCtx.cColSep;
-
      oputz("Column separator ");
-
      output_c_string(zSep);
-
      oputz(", row separator ");
+
      sqlite3_fputs("Column separator ", p->out);
+
      output_c_string(p->out, zSep);
+
      sqlite3_fputs(", row separator ", p->out);
      zSep[0] = sCtx.cRowSep;
-
      output_c_string(zSep);
-
      oputz("\n");
+
      output_c_string(p->out, zSep);
+
      sqlite3_fputs("\n", p->out);
    }
    sCtx.z = sqlite3_malloc64(120);
    if( sCtx.z==0 ){
@@ -27048,16 +29144,17 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
      zColDefs = zAutoColumn(0, &dbCols, &zRenames);
      if( zRenames!=0 ){
-
        sputf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
+
        sqlite3_fprintf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
              "Columns renamed during .import %s due to duplicates:\n"
              "%s\n", sCtx.zFile, zRenames);
        sqlite3_free(zRenames);
      }
      assert(dbCols==0);
      if( zColDefs==0 ){
-
        eputf("%s: empty file\n", sCtx.zFile);
+
        sqlite3_fprintf(stderr,"%s: empty file\n", sCtx.zFile);
        import_cleanup(&sCtx);
        rc = 1;
+
        sqlite3_free(zCreate);
        goto meta_command_exit;
      }
      zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
@@ -27066,13 +29163,16 @@ static int do_meta_command(char *zLine, ShellState *p){
        shell_out_of_memory();
      }
      if( eVerbose>=1 ){
-
        oputf("%s\n", zCreate);
+
        sqlite3_fprintf(p->out, "%s\n", zCreate);
      }
      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
+
      if( rc ){
+
        sqlite3_fprintf(stderr,
+
             "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
+
      }
      sqlite3_free(zCreate);
      zCreate = 0;
      if( rc ){
-
        eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
        import_cleanup(&sCtx);
        rc = 1;
        goto meta_command_exit;
@@ -27089,7 +29189,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    zSql = 0;
    if( rc ){
      if (pStmt) sqlite3_finalize(pStmt);
-
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
+
      shellDatabaseError(p->db);
      import_cleanup(&sCtx);
      rc = 1;
      goto meta_command_exit;
@@ -27127,13 +29227,13 @@ static int do_meta_command(char *zLine, ShellState *p){
    zSql[j] = 0;
    assert( j<nByte );
    if( eVerbose>=2 ){
-
      oputf("Insert using: %s\n", zSql);
+
      sqlite3_fprintf(p->out, "Insert using: %s\n", zSql);
    }
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    zSql = 0;
    if( rc ){
-
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
+
      shellDatabaseError(p->db);
      if (pStmt) sqlite3_finalize(pStmt);
      import_cleanup(&sCtx);
      rc = 1;
@@ -27166,7 +29266,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        }
        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
        if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
-
          eputf("%s:%d: expected %d columns but found %d"
+
          sqlite3_fprintf(stderr,"%s:%d: expected %d columns but found %d"
                " - filling the rest with NULL\n",
                sCtx.zFile, startLine, nCol, i+1);
          i += 2;
@@ -27178,14 +29278,15 @@ static int do_meta_command(char *zLine, ShellState *p){
          xRead(&sCtx);
          i++;
        }while( sCtx.cTerm==sCtx.cColSep );
-
        eputf("%s:%d: expected %d columns but found %d - extras ignored\n",
+
        sqlite3_fprintf(stderr,
+
              "%s:%d: expected %d columns but found %d - extras ignored\n",
              sCtx.zFile, startLine, nCol, i);
      }
      if( i>=nCol ){
        sqlite3_step(pStmt);
        rc = sqlite3_reset(pStmt);
        if( rc!=SQLITE_OK ){
-
          eputf("%s:%d: INSERT failed: %s\n",
+
          sqlite3_fprintf(stderr,"%s:%d: INSERT failed: %s\n",
                sCtx.zFile, startLine, sqlite3_errmsg(p->db));
          sCtx.nErr++;
        }else{
@@ -27198,7 +29299,8 @@ static int do_meta_command(char *zLine, ShellState *p){
    sqlite3_finalize(pStmt);
    if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
    if( eVerbose>0 ){
-
      oputf("Added %d rows with %d errors using %d lines of input\n",
+
      sqlite3_fprintf(p->out,
+
            "Added %d rows with %d errors using %d lines of input\n",
            sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
    }
  }else
@@ -27214,7 +29316,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
    int i;
    if( !ShellHasFlag(p,SHFLG_TestingMode) ){
-
      eputf(".%s unavailable without --unsafe-testing\n",
+
      sqlite3_fprintf(stderr,".%s unavailable without --unsafe-testing\n",
            "imposter");
      rc = 1;
      goto meta_command_exit;
@@ -27280,7 +29382,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    sqlite3_finalize(pStmt);
    if( i==0 || tnum==0 ){
-
      eputf("no such index: \"%s\"\n", azArg[1]);
+
      sqlite3_fprintf(stderr,"no such index: \"%s\"\n", azArg[1]);
      rc = 1;
      sqlite3_free(zCollist);
      goto meta_command_exit;
@@ -27295,14 +29397,16 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
      if( rc ){
-
        eputf("Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
+
        sqlite3_fprintf(stderr,
+
              "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
      }else{
-
        sputf(stdout, "%s;\n", zSql);
-
        sputf(stdout, "WARNING: writing to an imposter table will corrupt"
+
        sqlite3_fprintf(stdout, "%s;\n", zSql);
+
        sqlite3_fprintf(stdout,
+
              "WARNING: writing to an imposter table will corrupt"
              " the \"%s\" %s!\n", azArg[1], isWO ? "table" : "index");
      }
    }else{
-
      eputf("SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
+
      sqlite3_fprintf(stderr,"SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
      rc = 1;
    }
    sqlite3_free(zSql);
@@ -27316,7 +29420,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      if( iArg==0 ) iArg = -1;
    }
    if( (nArg!=1 && nArg!=2) || iArg<0 ){
-
      eputf("%s","Usage: .intck STEPS_PER_UNLOCK\n");
+
      sqlite3_fprintf(stderr,"%s","Usage: .intck STEPS_PER_UNLOCK\n");
      rc = 1;
      goto meta_command_exit;
    }
@@ -27335,9 +29439,9 @@ static int do_meta_command(char *zLine, ShellState *p){
      sqlite3IoTrace = iotracePrintf;
      iotrace = stdout;
    }else{
-
      iotrace = fopen(azArg[1], "w");
+
      iotrace = sqlite3_fopen(azArg[1], "w");
      if( iotrace==0 ){
-
        eputf("Error: cannot open \"%s\"\n", azArg[1]);
+
        sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
        sqlite3IoTrace = 0;
        rc = 1;
      }else{
@@ -27369,7 +29473,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    open_db(p, 0);
    if( nArg==1 ){
      for(i=0; i<ArraySize(aLimit); i++){
-
        sputf(stdout, "%20s %d\n", aLimit[i].zLimitName,
+
        sqlite3_fprintf(stdout, "%20s %d\n", aLimit[i].zLimitName,
              sqlite3_limit(p->db, aLimit[i].limitCode, -1));
      }
    }else if( nArg>3 ){
@@ -27384,14 +29488,14 @@ static int do_meta_command(char *zLine, ShellState *p){
          if( iLimit<0 ){
            iLimit = i;
          }else{
-
            eputf("ambiguous limit: \"%s\"\n", azArg[1]);
+
            sqlite3_fprintf(stderr,"ambiguous limit: \"%s\"\n", azArg[1]);
            rc = 1;
            goto meta_command_exit;
          }
        }
      }
      if( iLimit<0 ){
-
        eputf("unknown limit: \"%s\"\n"
+
        sqlite3_fprintf(stderr,"unknown limit: \"%s\"\n"
              "enter \".limits\" with no arguments for a list.\n",
              azArg[1]);
        rc = 1;
@@ -27401,7 +29505,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        sqlite3_limit(p->db, aLimit[iLimit].limitCode,
                      (int)integerValue(azArg[2]));
      }
-
      sputf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
+
      sqlite3_fprintf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
            sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
    }
  }else
@@ -27427,7 +29531,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    open_db(p, 0);
    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
    if( rc!=SQLITE_OK ){
-
      eputf("Error: %s\n", zErrMsg);
+
      shellEmitError(zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }
@@ -27450,7 +29554,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
      output_file_close(p->pLog);
      if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout";
-
      p->pLog = output_file_open(zFile, 0);
+
      p->pLog = output_file_open(zFile);
    }
  }else

@@ -27484,7 +29588,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      }else if( zTabname==0 ){
        zTabname = z;
      }else if( z[0]=='-' ){
-
        eputf("unknown option: %s\n", z);
+
        sqlite3_fprintf(stderr,"unknown option: %s\n", z);
        eputz("options:\n"
              "  --noquote\n"
              "  --quote\n"
@@ -27494,7 +29598,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        rc = 1;
        goto meta_command_exit;
      }else{
-
        eputf("extra argument: \"%s\"\n", z);
+
        sqlite3_fprintf(stderr,"extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }
@@ -27503,12 +29607,14 @@ static int do_meta_command(char *zLine, ShellState *p){
      if( p->mode==MODE_Column
       || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
      ){
-
        oputf("current output mode: %s --wrap %d --wordwrap %s --%squote\n",
+
        sqlite3_fprintf(p->out,
+
              "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
              modeDescr[p->mode], p->cmOpts.iWrap,
              p->cmOpts.bWordWrap ? "on" : "off",
              p->cmOpts.bQuote ? "" : "no");
      }else{
-
        oputf("current output mode: %s\n", modeDescr[p->mode]);
+
        sqlite3_fprintf(p->out,
+
              "current output mode: %s\n", modeDescr[p->mode]);
      }
      zMode = modeDescr[p->mode];
    }
@@ -27581,7 +29687,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      eputz("Usage: .nonce NONCE\n");
      rc = 1;
    }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
-
      eputf("line %d: incorrect nonce: \"%s\"\n",
+
      sqlite3_fprintf(stderr,"line %d: incorrect nonce: \"%s\"\n",
            p->lineno, azArg[1]);
      exit(1);
    }else{
@@ -27636,11 +29742,11 @@ static int do_meta_command(char *zLine, ShellState *p){
      }else
#endif /* !SQLITE_SHELL_FIDDLE */
      if( z[0]=='-' ){
-
        eputf("unknown option: %s\n", z);
+
        sqlite3_fprintf(stderr,"unknown option: %s\n", z);
        rc = 1;
        goto meta_command_exit;
      }else if( zFN ){
-
        eputf("extra argument: \"%s\"\n", z);
+
        sqlite3_fprintf(stderr,"extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }else{
@@ -27682,7 +29788,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      p->pAuxDb->zDbFilename = zNewFilename;
      open_db(p, OPEN_DB_KEEPALIVE);
      if( p->db==0 ){
-
        eputf("Error: cannot open '%s'\n", zNewFilename);
+
        sqlite3_fprintf(stderr,"Error: cannot open '%s'\n", zNewFilename);
        sqlite3_free(zNewFilename);
      }else{
        p->pAuxDb->zFreeOnClose = zNewFilename;
@@ -27700,19 +29806,23 @@ static int do_meta_command(char *zLine, ShellState *p){
        && (cli_strncmp(azArg[0], "output", n)==0
            || cli_strncmp(azArg[0], "once", n)==0))
   || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0)
+
   || (c=='w' && n==3 && cli_strcmp(azArg[0],"www")==0)
  ){
    char *zFile = 0;
-
    int bTxtMode = 0;
    int i;
    int eMode = 0;
-
    int bOnce = 0;            /* 0: .output, 1: .once, 2: .excel */
-
    static const char *zBomUtf8 = "\xef\xbb\xbf";
+
    int bOnce = 0;            /* 0: .output, 1: .once, 2: .excel/.www */
+
    int bPlain = 0;           /* --plain option */
+
    static const char *zBomUtf8 = "\357\273\277";
    const char *zBom = 0;

    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    if( c=='e' ){
      eMode = 'x';
      bOnce = 2;
+
    }else if( c=='w' ){
+
      eMode = 'w';
+
      bOnce = 2;
    }else if( cli_strncmp(azArg[0],"once",n)==0 ){
      bOnce = 1;
    }
@@ -27722,24 +29832,30 @@ static int do_meta_command(char *zLine, ShellState *p){
        if( z[1]=='-' ) z++;
        if( cli_strcmp(z,"-bom")==0 ){
          zBom = zBomUtf8;
-
        }else if( c!='e' && cli_strcmp(z,"-x")==0 ){
+
        }else if( cli_strcmp(z,"-plain")==0 ){
+
          bPlain = 1;
+
        }else if( c=='o' && cli_strcmp(z,"-x")==0 ){
          eMode = 'x';  /* spreadsheet */
-
        }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
+
        }else if( c=='o' && cli_strcmp(z,"-e")==0 ){
          eMode = 'e';  /* text editor */
+
        }else if( c=='o' && cli_strcmp(z,"-w")==0 ){
+
          eMode = 'w';  /* Web browser */
        }else{
-
          oputf("ERROR: unknown option: \"%s\".  Usage:\n", azArg[i]);
+
          sqlite3_fprintf(p->out, 
+
                          "ERROR: unknown option: \"%s\". Usage:\n", azArg[i]);
          showHelp(p->out, azArg[0]);
          rc = 1;
          goto meta_command_exit;
        }
-
      }else if( zFile==0 && eMode!='e' && eMode!='x' ){
+
      }else if( zFile==0 && eMode==0 ){
        zFile = sqlite3_mprintf("%s", z);
        if( zFile && zFile[0]=='|' ){
          while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
          break;
        }
      }else{
-
        oputf("ERROR: extra parameter: \"%s\".  Usage:\n", azArg[i]);
+
        sqlite3_fprintf(p->out,
+
            "ERROR: extra parameter: \"%s\".  Usage:\n", azArg[i]);
        showHelp(p->out, azArg[0]);
        rc = 1;
        sqlite3_free(zFile);
@@ -27756,7 +29872,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    output_reset(p);
#ifndef SQLITE_NOHAVE_SYSTEM
-
    if( eMode=='e' || eMode=='x' ){
+
    if( eMode=='e' || eMode=='x' || eMode=='w' ){
      p->doXdgOpen = 1;
      outputModePush(p);
      if( eMode=='x' ){
@@ -27766,10 +29882,17 @@ static int do_meta_command(char *zLine, ShellState *p){
        p->mode = MODE_Csv;
        sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
+
#ifdef _WIN32
+
        zBom = zBomUtf8;  /* Always include the BOM on Windows, as Excel does
+
                          ** not work without it. */
+
#endif
+
      }else if( eMode=='w' ){
+
        /* web-browser mode. */
+
        newTempFile(p, "html");
+
        if( !bPlain ) p->mode = MODE_Www;
      }else{
        /* text editor mode */
        newTempFile(p, "txt");
-
        bTxtMode = 1;
      }
      sqlite3_free(zFile);
      zFile = sqlite3_mprintf("%s", p->zTempFile);
@@ -27782,26 +29905,32 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = 1;
      output_redir(p, stdout);
#else
-
      FILE *pfPipe = popen(zFile + 1, "w");
+
      FILE *pfPipe = sqlite3_popen(zFile + 1, "w");
      if( pfPipe==0 ){
-
        eputf("Error: cannot open pipe \"%s\"\n", zFile + 1);
+
        sqlite3_fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
        rc = 1;
      }else{
        output_redir(p, pfPipe);
-
        if( zBom ) oputz(zBom);
+
        if( zBom ) sqlite3_fputs(zBom, pfPipe);
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
#endif
    }else{
-
      FILE *pfFile = output_file_open(zFile, bTxtMode);
+
      FILE *pfFile = output_file_open(zFile);
      if( pfFile==0 ){
        if( cli_strcmp(zFile,"off")!=0 ){
-
          eputf("Error: cannot write to \"%s\"\n", zFile);
+
          sqlite3_fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
        }
        rc = 1;
      } else {
        output_redir(p, pfFile);
-
        if( zBom ) oputz(zBom);
+
        if( zBom ) sqlite3_fputs(zBom, pfFile);
+
        if( bPlain && eMode=='w' ){
+
          sqlite3_fputs(
+
            "<!DOCTYPE html>\n<BODY>\n<PLAINTEXT>\n",
+
            pfFile
+
          );
+
        }
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
    }
@@ -27842,7 +29971,8 @@ static int do_meta_command(char *zLine, ShellState *p){
             "SELECT key, quote(value) "
             "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
        while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
-
          oputf("%-*s %s\n", len, sqlite3_column_text(pStmt,0),
+
          sqlite3_fprintf(p->out,
+
                "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
                sqlite3_column_text(pStmt,1));
        }
        sqlite3_finalize(pStmt);
@@ -27887,7 +30017,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
        sqlite3_free(zSql);
        if( rx!=SQLITE_OK ){
-
          oputf("Error: %s\n", sqlite3_errmsg(p->db));
+
          sqlite3_fprintf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
          sqlite3_finalize(pStmt);
          pStmt = 0;
          rc = 1;
@@ -27916,10 +30046,10 @@ static int do_meta_command(char *zLine, ShellState *p){
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
    int i;
    for(i=1; i<nArg; i++){
-
      if( i>1 ) oputz(" ");
-
      oputz(azArg[i]);
+
      if( i>1 ) sqlite3_fputs(" ", p->out);
+
      sqlite3_fputs(azArg[i], p->out);
    }
-
    oputz("\n");
+
    sqlite3_fputs("\n", p->out);
  }else

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
@@ -27956,7 +30086,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          }
          continue;
        }
-
        eputf("Error: unknown option: \"%s\"\n", azArg[i]);
+
        sqlite3_fprintf(stderr,"Error: unknown option: \"%s\"\n", azArg[i]);
        rc = 1;
        goto meta_command_exit;
      }else{
@@ -27997,11 +30127,10 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_OMIT_POPEN
      eputz("Error: pipes are not supported in this OS\n");
      rc = 1;
-
      p->out = stdout;
#else
-
      p->in = popen(azArg[1]+1, "r");
+
      p->in = sqlite3_popen(azArg[1]+1, "r");
      if( p->in==0 ){
-
        eputf("Error: cannot open \"%s\"\n", azArg[1]);
+
        sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
        rc = 1;
      }else{
        rc = process_input(p);
@@ -28009,7 +30138,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
#endif
    }else if( (p->in = openChrSource(azArg[1]))==0 ){
-
      eputf("Error: cannot open \"%s\"\n", azArg[1]);
+
      sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
      rc = 1;
    }else{
      rc = process_input(p);
@@ -28042,14 +30171,14 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    rc = sqlite3_open(zSrcFile, &pSrc);
    if( rc!=SQLITE_OK ){
-
      eputf("Error: cannot open \"%s\"\n", zSrcFile);
+
      sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zSrcFile);
      close_db(pSrc);
      return 1;
    }
    open_db(p, 0);
    pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
    if( pBackup==0 ){
-
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
+
      shellDatabaseError(p->db);
      close_db(pSrc);
      return 1;
    }
@@ -28067,7 +30196,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      eputz("Error: source database is busy\n");
      rc = 1;
    }else{
-
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
+
      shellDatabaseError(p->db);
      rc = 1;
    }
    close_db(pSrc);
@@ -28125,7 +30254,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      }else if( optionMatch(azArg[ii],"nosys") ){
        bNoSystemTabs = 1;
      }else if( azArg[ii][0]=='-' ){
-
        eputf("Unknown option: \"%s\"\n", azArg[ii]);
+
        sqlite3_fprintf(stderr,"Unknown option: \"%s\"\n", azArg[ii]);
        rc = 1;
        goto meta_command_exit;
      }else if( zName==0 ){
@@ -28164,7 +30293,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
                              -1, &pStmt, 0);
      if( rc ){
-
        eputf("Error: %s\n", sqlite3_errmsg(p->db));
+
        shellDatabaseError(p->db);
        sqlite3_finalize(pStmt);
        rc = 1;
        goto meta_command_exit;
@@ -28226,14 +30355,14 @@ static int do_meta_command(char *zLine, ShellState *p){
      appendText(&sSelect, "sql IS NOT NULL"
                           " ORDER BY snum, rowid", 0);
      if( bDebug ){
-
        oputf("SQL: %s;\n", sSelect.z);
+
        sqlite3_fprintf(p->out, "SQL: %s;\n", sSelect.z);
      }else{
        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
      }
      freeText(&sSelect);
    }
    if( zErrMsg ){
-
      eputf("Error: %s\n", zErrMsg);
+
      shellEmitError(zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
@@ -28287,7 +30416,8 @@ static int do_meta_command(char *zLine, ShellState *p){
      }else{
        rc = sqlite3session_attach(pSession->p, azCmd[1]);
        if( rc ){
-
          eputf("ERROR: sqlite3session_attach() returns %d\n",rc);
+
          sqlite3_fprintf(stderr,
+
               "ERROR: sqlite3session_attach() returns %d\n",rc);
          rc = 0;
        }
      }
@@ -28304,9 +30434,9 @@ static int do_meta_command(char *zLine, ShellState *p){
      failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ) goto session_not_open;
-
      out = fopen(azCmd[1], "wb");
+
      out = sqlite3_fopen(azCmd[1], "wb");
      if( out==0 ){
-
        eputf("ERROR: cannot open \"%s\" for writing\n",
+
        sqlite3_fprintf(stderr,"ERROR: cannot open \"%s\" for writing\n",
              azCmd[1]);
      }else{
        int szChng;
@@ -28317,12 +30447,13 @@ static int do_meta_command(char *zLine, ShellState *p){
          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
        }
        if( rc ){
-
          sputf(stdout, "Error: error code %d\n", rc);
+
          sqlite3_fprintf(stdout, "Error: error code %d\n", rc);
          rc = 0;
        }
        if( pChng
          && fwrite(pChng, szChng, 1, out)!=1 ){
-
          eputf("ERROR: Failed to write entire %d-byte output\n", szChng);
+
          sqlite3_fprintf(stderr,
+
              "ERROR: Failed to write entire %d-byte output\n", szChng);
        }
        sqlite3_free(pChng);
        fclose(out);
@@ -28349,7 +30480,8 @@ static int do_meta_command(char *zLine, ShellState *p){
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( pAuxDb->nSession ){
        ii = sqlite3session_enable(pSession->p, ii);
-
        oputf("session %s enable flag = %d\n", pSession->zName, ii);
+
        sqlite3_fprintf(p->out,
+
            "session %s enable flag = %d\n", pSession->zName, ii);
      }
    }else

@@ -28384,7 +30516,8 @@ static int do_meta_command(char *zLine, ShellState *p){
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( pAuxDb->nSession ){
        ii = sqlite3session_indirect(pSession->p, ii);
-
        oputf("session %s indirect flag = %d\n", pSession->zName, ii);
+
        sqlite3_fprintf(p->out,
+
            "session %s indirect flag = %d\n", pSession->zName, ii);
      }
    }else

@@ -28396,7 +30529,8 @@ static int do_meta_command(char *zLine, ShellState *p){
      if( nCmd!=1 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
        ii = sqlite3session_isempty(pSession->p);
-
        oputf("session %s isempty flag = %d\n", pSession->zName, ii);
+
        sqlite3_fprintf(p->out,
+
             "session %s isempty flag = %d\n", pSession->zName, ii);
      }
    }else

@@ -28405,7 +30539,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    */
    if( cli_strcmp(azCmd[0],"list")==0 ){
      for(i=0; i<pAuxDb->nSession; i++){
-
        oputf("%d %s\n", i, pAuxDb->aSession[i].zName);
+
        sqlite3_fprintf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
      }
    }else

@@ -28420,18 +30554,19 @@ static int do_meta_command(char *zLine, ShellState *p){
      if( zName[0]==0 ) goto session_syntax_error;
      for(i=0; i<pAuxDb->nSession; i++){
        if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
-
          eputf("Session \"%s\" already exists\n", zName);
+
          sqlite3_fprintf(stderr,"Session \"%s\" already exists\n", zName);
          goto meta_command_exit;
        }
      }
      if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
-
        eputf("Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
+
        sqlite3_fprintf(stderr,
+
           "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
        goto meta_command_exit;
      }
      pSession = &pAuxDb->aSession[pAuxDb->nSession];
      rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
      if( rc ){
-
        eputf("Cannot open session: error code=%d\n", rc);
+
        sqlite3_fprintf(stderr,"Cannot open session: error code=%d\n", rc);
        rc = 0;
        goto meta_command_exit;
      }
@@ -28455,7 +30590,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      int i, v;
      for(i=1; i<nArg; i++){
        v = booleanValue(azArg[i]);
-
        oputf("%s: %d 0x%x\n", azArg[i], v, v);
+
        sqlite3_fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
      }
    }
    if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
@@ -28464,7 +30599,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        char zBuf[200];
        v = integerValue(azArg[i]);
        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
-
        oputz(zBuf);
+
        sqlite3_fputs(zBuf, p->out);
      }
    }
  }else
@@ -28491,8 +30626,9 @@ static int do_meta_command(char *zLine, ShellState *p){
        bVerbose++;
      }else
      {
-
        eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);
-
        eputz("Should be one of: --init -v\n");
+
        sqlite3_fprintf(stderr,
+
              "Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);
+
        sqlite3_fputs("Should be one of: --init -v\n", stderr);
        rc = 1;
        goto meta_command_exit;
      }
@@ -28537,10 +30673,10 @@ static int do_meta_command(char *zLine, ShellState *p){
        if( zAns==0 ) continue;
        k = 0;
        if( bVerbose>0 ){
-
          sputf(stdout, "%d: %s %s\n", tno, zOp, zSql);
+
          sqlite3_fprintf(stdout, "%d: %s %s\n", tno, zOp, zSql);
        }
        if( cli_strcmp(zOp,"memo")==0 ){
-
          oputf("%s\n", zSql);
+
          sqlite3_fprintf(p->out, "%s\n", zSql);
        }else
        if( cli_strcmp(zOp,"run")==0 ){
          char *zErrMsg = 0;
@@ -28549,22 +30685,23 @@ static int do_meta_command(char *zLine, ShellState *p){
          rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
          nTest++;
          if( bVerbose ){
-
            oputf("Result: %s\n", str.z);
+
            sqlite3_fprintf(p->out, "Result: %s\n", str.z);
          }
          if( rc || zErrMsg ){
            nErr++;
            rc = 1;
-
            oputf("%d: error-code-%d: %s\n", tno, rc, zErrMsg);
+
            sqlite3_fprintf(p->out, "%d: error-code-%d: %s\n", tno, rc,zErrMsg);
            sqlite3_free(zErrMsg);
          }else if( cli_strcmp(zAns,str.z)!=0 ){
            nErr++;
            rc = 1;
-
            oputf("%d: Expected: [%s]\n", tno, zAns);
-
            oputf("%d:      Got: [%s]\n", tno, str.z);
+
            sqlite3_fprintf(p->out, "%d: Expected: [%s]\n", tno, zAns);
+
            sqlite3_fprintf(p->out, "%d:      Got: [%s]\n", tno, str.z);
          }
        }
        else{
-
          eputf("Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
+
          sqlite3_fprintf(stderr,
+
                "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
          rc = 1;
          break;
        }
@@ -28572,7 +30709,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      sqlite3_finalize(pStmt);
    } /* End loop over k */
    freeText(&str);
-
    oputf("%d errors out of %d tests\n", nErr, nTest);
+
    sqlite3_fprintf(p->out, "%d errors out of %d tests\n", nErr, nTest);
  }else

  if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
@@ -28620,7 +30757,8 @@ static int do_meta_command(char *zLine, ShellState *p){
          bDebug = 1;
        }else
        {
-
          eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);
+
          sqlite3_fprintf(stderr,
+
                  "Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);
          showHelp(p->out, azArg[0]);
          rc = 1;
          goto meta_command_exit;
@@ -28698,7 +30836,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    freeText(&sQuery);
    freeText(&sSql);
    if( bDebug ){
-
      oputf("%s\n", zSql);
+
      sqlite3_fprintf(p->out, "%s\n", zSql);
    }else{
      shell_exec(p, zSql, 0);
    }
@@ -28728,7 +30866,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          "' OR ') as query, tname from tabcols group by tname)"
          , zRevText);
      shell_check_oom(zRevText);
-
      if( bDebug ) oputf("%s\n", zRevText);
+
      if( bDebug ) sqlite3_fprintf(p->out, "%s\n", zRevText);
      lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
      if( lrc!=SQLITE_OK ){
        /* assert(lrc==SQLITE_NOMEM); // might also be SQLITE_ERROR if the
@@ -28741,7 +30879,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0);
          sqlite3_stmt *pCheckStmt;
          lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0);
-
          if( bDebug ) oputf("%s\n", zGenQuery);
+
          if( bDebug ) sqlite3_fprintf(p->out, "%s\n", zGenQuery);
          if( lrc!=SQLITE_OK ){
            rc = 1;
          }else{
@@ -28749,7 +30887,8 @@ static int do_meta_command(char *zLine, ShellState *p){
              double countIrreversible = sqlite3_column_double(pCheckStmt, 0);
              if( countIrreversible>0 ){
                int sz = (int)(countIrreversible + 0.5);
-
                eputf("Digest includes %d invalidly encoded text field%s.\n",
+
                sqlite3_fprintf(stderr,
+
                      "Digest includes %d invalidly encoded text field%s.\n",
                      sz, (sz>1)? "s": "");
              }
            }
@@ -28783,11 +30922,11 @@ static int do_meta_command(char *zLine, ShellState *p){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }
-
    consoleRestore();
+
    /*consoleRestore();*/
    x = zCmd!=0 ? system(zCmd) : 1;
-
    consoleRenewSetup();
+
    /*consoleRenewSetup();*/
    sqlite3_free(zCmd);
-
    if( x ) eputf("System command returns %d\n", x);
+
    if( x ) sqlite3_fprintf(stderr,"System command returns %d\n", x);
  }else
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */

@@ -28800,46 +30939,48 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = 1;
      goto meta_command_exit;
    }
-
    oputf("%12.12s: %s\n","echo",
+
    sqlite3_fprintf(p->out, "%12.12s: %s\n","echo",
          azBool[ShellHasFlag(p, SHFLG_Echo)]);
-
    oputf("%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
-
    oputf("%12.12s: %s\n","explain",
+
    sqlite3_fprintf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
+
    sqlite3_fprintf(p->out, "%12.12s: %s\n","explain",
          p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
-
    oputf("%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
+
    sqlite3_fprintf(p->out, "%12.12s: %s\n","headers",
+
          azBool[p->showHeader!=0]);
    if( p->mode==MODE_Column
     || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
    ){
-
      oputf("%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
+
      sqlite3_fprintf(p->out,
+
            "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
            modeDescr[p->mode], p->cmOpts.iWrap,
            p->cmOpts.bWordWrap ? "on" : "off",
            p->cmOpts.bQuote ? "" : "no");
    }else{
-
      oputf("%12.12s: %s\n","mode", modeDescr[p->mode]);
+
      sqlite3_fprintf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
    }
-
    oputf("%12.12s: ", "nullvalue");
-
    output_c_string(p->nullValue);
-
    oputz("\n");
-
    oputf("%12.12s: %s\n","output",
+
    sqlite3_fprintf(p->out, "%12.12s: ", "nullvalue");
+
    output_c_string(p->out, p->nullValue);
+
    sqlite3_fputs("\n", p->out);
+
    sqlite3_fprintf(p->out, "%12.12s: %s\n","output",
          strlen30(p->outfile) ? p->outfile : "stdout");
-
    oputf("%12.12s: ", "colseparator");
-
     output_c_string(p->colSeparator);
-
     oputz("\n");
-
    oputf("%12.12s: ", "rowseparator");
-
     output_c_string(p->rowSeparator);
-
     oputz("\n");
+
    sqlite3_fprintf(p->out, "%12.12s: ", "colseparator");
+
    output_c_string(p->out, p->colSeparator);
+
    sqlite3_fputs("\n", p->out);
+
    sqlite3_fprintf(p->out, "%12.12s: ", "rowseparator");
+
    output_c_string(p->out, p->rowSeparator);
+
    sqlite3_fputs("\n", p->out);
    switch( p->statsOn ){
      case 0:  zOut = "off";     break;
      default: zOut = "on";      break;
      case 2:  zOut = "stmt";    break;
      case 3:  zOut = "vmstep";  break;
    }
-
    oputf("%12.12s: %s\n","stats", zOut);
-
    oputf("%12.12s: ", "width");
+
    sqlite3_fprintf(p->out, "%12.12s: %s\n","stats", zOut);
+
    sqlite3_fprintf(p->out, "%12.12s: ", "width");
    for (i=0;i<p->nWidth;i++) {
-
      oputf("%d ", p->colWidth[i]);
+
      sqlite3_fprintf(p->out, "%d ", p->colWidth[i]);
    }
-
    oputz("\n");
-
    oputf("%12.12s: %s\n", "filename",
+
    sqlite3_fputs("\n", p->out);
+
    sqlite3_fprintf(p->out, "%12.12s: %s\n", "filename",
          p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
  }else

@@ -28957,9 +31098,10 @@ static int do_meta_command(char *zLine, ShellState *p){
      for(i=0; i<nPrintRow; i++){
        for(j=i; j<nRow; j+=nPrintRow){
          char *zSp = j<nPrintRow ? "" : "  ";
-
          oputf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
+
          sqlite3_fprintf(p->out,
+
               "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
        }
-
        oputz("\n");
+
        sqlite3_fputs("\n", p->out);
      }
    }

@@ -28971,7 +31113,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  /* Begin redirecting output to the file "testcase-out.txt" */
  if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
    output_reset(p);
-
    p->out = output_file_open("testcase-out.txt", 0);
+
    p->out = output_file_open("testcase-out.txt");
    if( p->out==0 ){
      eputz("Error: cannot open 'testcase-out.txt'\n");
    }
@@ -29004,18 +31146,17 @@ static int do_meta_command(char *zLine, ShellState *p){
    {"json_selfcheck",     SQLITE_TESTCTRL_JSON_SELFCHECK ,0,"BOOLEAN"      },
    {"localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN"      },
    {"never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN"       },
-
    {"optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK"   },
+
    {"optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK ..."},
#ifdef YYCOVERAGE
    {"parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE,0,""             },
#endif
-
    {"pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET  "       },
+
    {"pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,1, "OFFSET  "       },
    {"prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,0, ""               },
    {"prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,   0, ""               },
    {"prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,   0, "SEED ?db?"      },
    {"seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,  0, ""               },
    {"sorter_mmap",        SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX"           },
    {"tune",               SQLITE_TESTCTRL_TUNE,        1, "ID VALUE"       },
-
    {"uselongdouble",  SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"},
    };
    int testctrl = -1;
    int iCtrl = -1;
@@ -29035,10 +31176,10 @@ static int do_meta_command(char *zLine, ShellState *p){

    /* --help lists all test-controls */
    if( cli_strcmp(zCmd,"help")==0 ){
-
      oputz("Available test-controls:\n");
+
      sqlite3_fputs("Available test-controls:\n", p->out);
      for(i=0; i<ArraySize(aCtrl); i++){
        if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
-
        oputf("  .testctrl %s %s\n",
+
        sqlite3_fprintf(p->out, "  .testctrl %s %s\n",
              aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
@@ -29055,7 +31196,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          testctrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
-
          eputf("Error: ambiguous test-control: \"%s\"\n"
+
          sqlite3_fprintf(stderr,"Error: ambiguous test-control: \"%s\"\n"
                "Use \".testctrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
@@ -29063,13 +31204,124 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
    }
    if( testctrl<0 ){
-
      eputf("Error: unknown test-control: %s\n"
+
      sqlite3_fprintf(stderr,"Error: unknown test-control: %s\n"
            "Use \".testctrl --help\" for help\n", zCmd);
    }else{
      switch(testctrl){

+
        /* Special processing for .testctrl opt MASK ...
+
        ** Each MASK argument can be one of:
+
        **
+
        **      +LABEL       Enable the named optimization 
+
        **
+
        **      -LABEL       Disable the named optimization
+
        **
+
        **      INTEGER      Mask of optimizations to disable
+
        */
+
        case SQLITE_TESTCTRL_OPTIMIZATIONS: {
+
          static const struct {
+
             unsigned int mask;    /* Mask for this optimization */
+
             unsigned int bDsply;  /* Display this on output */
+
             const char *zLabel;   /* Name of optimization */
+
          } aLabel[] = {
+
            { 0x00000001, 1, "QueryFlattener" },
+
            { 0x00000001, 0, "Flatten" },
+
            { 0x00000002, 1, "WindowFunc" },
+
            { 0x00000004, 1, "GroupByOrder" },
+
            { 0x00000008, 1, "FactorOutConst" },
+
            { 0x00000010, 1, "DistinctOpt" },
+
            { 0x00000020, 1, "CoverIdxScan" },
+
            { 0x00000040, 1, "OrderByIdxJoin" },
+
            { 0x00000080, 1, "Transitive" },
+
            { 0x00000100, 1, "OmitNoopJoin" },
+
            { 0x00000200, 1, "CountOfView" },
+
            { 0x00000400, 1, "CurosrHints" },
+
            { 0x00000800, 1, "Stat4" },
+
            { 0x00001000, 1, "PushDown" },
+
            { 0x00002000, 1, "SimplifyJoin" },
+
            { 0x00004000, 1, "SkipScan" },
+
            { 0x00008000, 1, "PropagateConst" },
+
            { 0x00010000, 1, "MinMaxOpt" },
+
            { 0x00020000, 1, "SeekScan" },
+
            { 0x00040000, 1, "OmitOrderBy" },
+
            { 0x00080000, 1, "BloomFilter" },
+
            { 0x00100000, 1, "BloomPulldown" },
+
            { 0x00200000, 1, "BalancedMerge" },
+
            { 0x00400000, 1, "ReleaseReg" },
+
            { 0x00800000, 1, "FlttnUnionAll" },
+
            { 0x01000000, 1, "IndexedEXpr" },
+
            { 0x02000000, 1, "Coroutines" },
+
            { 0x04000000, 1, "NullUnusedCols" },
+
            { 0x08000000, 1, "OnePass" },
+
            { 0x10000000, 1, "OrderBySubq" },
+
            { 0xffffffff, 0, "All" },
+
          };
+
          unsigned int curOpt;
+
          unsigned int newOpt;
+
          int ii;
+
          sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, p->db, &curOpt);
+
          newOpt = curOpt;
+
          for(ii=2; ii<nArg; ii++){
+
            const char *z = azArg[ii];
+
            int useLabel = 0;
+
            const char *zLabel = 0;
+
            if( (z[0]=='+'|| z[0]=='-') && !IsDigit(z[1]) ){
+
              useLabel = z[0];
+
              zLabel = &z[1];
+
            }else if( !IsDigit(z[0]) && z[0]!=0 && !IsDigit(z[1]) ){
+
              useLabel = '+';
+
              zLabel = z;
+
            }else{
+
              newOpt = (unsigned int)strtol(z,0,0);
+
            }
+
            if( useLabel ){
+
              int jj;
+
              for(jj=0; jj<ArraySize(aLabel); jj++){
+
                if( sqlite3_stricmp(zLabel, aLabel[jj].zLabel)==0 ) break;
+
              }
+
              if( jj>=ArraySize(aLabel) ){
+
                sqlite3_fprintf(stderr,
+
                    "Error: no such optimization: \"%s\"\n", zLabel);
+
                sqlite3_fputs("Should be one of:", stderr);
+
                for(jj=0; jj<ArraySize(aLabel); jj++){
+
                  sqlite3_fprintf(stderr," %s", aLabel[jj].zLabel);
+
                }
+
                sqlite3_fputs("\n", stderr);
+
                rc = 1;
+
                goto meta_command_exit;
+
              }
+
              if( useLabel=='+' ){
+
                newOpt &= ~aLabel[jj].mask;
+
              }else{
+
                newOpt |= aLabel[jj].mask;
+
              }
+
            }
+
          }
+
          if( curOpt!=newOpt ){
+
            sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,p->db,newOpt);
+
          }else if( nArg<3 ){
+
            curOpt = ~newOpt;
+
          }
+
          if( newOpt==0 ){
+
            sqlite3_fputs("+All\n", p->out);
+
          }else if( newOpt==0xffffffff ){
+
            sqlite3_fputs("-All\n", p->out);
+
          }else{
+
            int jj;
+
            for(jj=0; jj<ArraySize(aLabel); jj++){
+
              unsigned int m = aLabel[jj].mask;
+
              if( !aLabel[jj].bDsply  ) continue;
+
              if( (curOpt&m)!=(newOpt&m) ){
+
                sqlite3_fprintf(p->out, "%c%s\n", (newOpt & m)==0 ? '+' : '-',
+
                      aLabel[jj].zLabel);
+
              }
+
            }
+
          }
+
          rc2 = isOk = 3;
+
          break;
+
        }
+

        /* sqlite3_test_control(int, db, int) */
-
        case SQLITE_TESTCTRL_OPTIMIZATIONS:
        case SQLITE_TESTCTRL_FK_NO_ACTION:
          if( nArg==3 ){
            unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
@@ -29104,7 +31356,7 @@ static int do_meta_command(char *zLine, ShellState *p){
            sqlite3 *db;
            if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
              sqlite3_randomness(sizeof(ii),&ii);
-
              sputf(stdout, "-- random seed: %d\n", ii);
+
              sqlite3_fprintf(stdout, "-- random seed: %d\n", ii);
            }
            if( nArg==3 ){
              db = 0;
@@ -29138,21 +31390,6 @@ static int do_meta_command(char *zLine, ShellState *p){
          }
          break;

-
        /* sqlite3_test_control(int, int) */
-
        case SQLITE_TESTCTRL_USELONGDOUBLE: {
-
          int opt = -1;
-
          if( nArg==3 ){
-
            if( cli_strcmp(azArg[2],"default")==0 ){
-
              opt = 2;
-
            }else{
-
              opt = booleanValue(azArg[2]);
-
            }
-
          }
-
          rc2 = sqlite3_test_control(testctrl, opt);
-
          isOk = 1;
-
          break;
-
        }
-

        /* sqlite3_test_control(sqlite3*) */
        case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
          rc2 = sqlite3_test_control(testctrl, p->db);
@@ -29172,7 +31409,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        case SQLITE_TESTCTRL_SEEK_COUNT: {
          u64 x = 0;
          rc2 = sqlite3_test_control(testctrl, p->db, &x);
-
          oputf("%llu\n", x);
+
          sqlite3_fprintf(p->out, "%llu\n", x);
          isOk = 3;
          break;
        }
@@ -29203,11 +31440,11 @@ static int do_meta_command(char *zLine, ShellState *p){
              int val = 0;
              rc2 = sqlite3_test_control(testctrl, -id, &val);
              if( rc2!=SQLITE_OK ) break;
-
              if( id>1 ) oputz("  ");
-
              oputf("%d: %d", id, val);
+
              if( id>1 ) sqlite3_fputs("  ", p->out);
+
              sqlite3_fprintf(p->out, "%d: %d", id, val);
              id++;
            }
-
            if( id>1 ) oputz("\n");
+
            if( id>1 ) sqlite3_fputs("\n", p->out);
            isOk = 3;
          }
          break;
@@ -29249,14 +31486,22 @@ static int do_meta_command(char *zLine, ShellState *p){
              faultsim_state.nHit = 0;
              sqlite3_test_control(testctrl, faultsim_callback);
            }else if( cli_strcmp(z,"status")==0 ){
-
              oputf("faultsim.iId:       %d\n", faultsim_state.iId);
-
              oputf("faultsim.iErr:      %d\n", faultsim_state.iErr);
-
              oputf("faultsim.iCnt:      %d\n", faultsim_state.iCnt);
-
              oputf("faultsim.nHit:      %d\n", faultsim_state.nHit);
-
              oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval);
-
              oputf("faultsim.eVerbose:  %d\n", faultsim_state.eVerbose);
-
              oputf("faultsim.nRepeat:   %d\n", faultsim_state.nRepeat);
-
              oputf("faultsim.nSkip:     %d\n", faultsim_state.nSkip);
+
              sqlite3_fprintf(p->out, "faultsim.iId:       %d\n",
+
                              faultsim_state.iId);
+
              sqlite3_fprintf(p->out, "faultsim.iErr:      %d\n",
+
                              faultsim_state.iErr);
+
              sqlite3_fprintf(p->out, "faultsim.iCnt:      %d\n",
+
                              faultsim_state.iCnt);
+
              sqlite3_fprintf(p->out, "faultsim.nHit:      %d\n",
+
                              faultsim_state.nHit);
+
              sqlite3_fprintf(p->out, "faultsim.iInterval: %d\n",
+
                              faultsim_state.iInterval);
+
              sqlite3_fprintf(p->out, "faultsim.eVerbose:  %d\n",
+
                              faultsim_state.eVerbose);
+
              sqlite3_fprintf(p->out, "faultsim.nRepeat:   %d\n",
+
                              faultsim_state.nRepeat);
+
              sqlite3_fprintf(p->out, "faultsim.nSkip:     %d\n",
+
                              faultsim_state.nSkip);
            }else if( cli_strcmp(z,"-v")==0 ){
              if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++;
            }else if( cli_strcmp(z,"-q")==0 ){
@@ -29274,7 +31519,8 @@ static int do_meta_command(char *zLine, ShellState *p){
            }else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){
              bShowHelp = 1;
            }else{
-
              eputf("Unrecognized fault_install argument: \"%s\"\n",
+
              sqlite3_fprintf(stderr,
+
                  "Unrecognized fault_install argument: \"%s\"\n",
                  azArg[kk]);
              rc = 1;
              bShowHelp = 1;
@@ -29282,7 +31528,7 @@ static int do_meta_command(char *zLine, ShellState *p){
            }
          }
          if( bShowHelp ){
-
            oputz(
+
            sqlite3_fputs(
               "Usage: .testctrl fault_install ARGS\n"
               "Possible arguments:\n"
               "   off               Disable faultsim\n"
@@ -29296,6 +31542,7 @@ static int do_meta_command(char *zLine, ShellState *p){
               "   --interval N      Trigger only after every N-th call\n"
               "   --repeat N        Turn off after N hits.  0 means never\n"
               "   --skip N          Skip the first N encounters\n"
+
               ,p->out
            );
          }
          break;
@@ -29303,12 +31550,13 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
    }
    if( isOk==0 && iCtrl>=0 ){
-
      oputf("Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
+
      sqlite3_fprintf(p->out,
+
          "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
-
      oputf("%d\n", rc2);
+
      sqlite3_fprintf(p->out, "%d\n", rc2);
    }else if( isOk==2 ){
-
      oputf("0x%08x\n", rc2);
+
      sqlite3_fprintf(p->out, "0x%08x\n", rc2);
    }
  }else
#endif /* !defined(SQLITE_UNTESTABLE) */
@@ -29363,13 +31611,13 @@ static int do_meta_command(char *zLine, ShellState *p){
          mType |= SQLITE_TRACE_CLOSE;
        }
        else {
-
          eputf("Unknown option \"%s\" on \".trace\"\n", z);
+
          sqlite3_fprintf(stderr,"Unknown option \"%s\" on \".trace\"\n", z);
          rc = 1;
          goto meta_command_exit;
        }
      }else{
        output_file_close(p->traceOut);
-
        p->traceOut = output_file_open(z, 0);
+
        p->traceOut = output_file_open(z);
      }
    }
    if( p->traceOut==0 ){
@@ -29423,7 +31671,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                     strlen30(azArg[3]));
      if( rc ){
-
        eputf("Authentication failed for user %s\n", azArg[2]);
+
        sqlite3_fprintf(stderr,"Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"add")==0 ){
@@ -29435,7 +31683,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                            booleanValue(azArg[4]));
      if( rc ){
-
        eputf("User-Add failed: %d\n", rc);
+
        sqlite3_fprintf(stderr,"User-Add failed: %d\n", rc);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"edit")==0 ){
@@ -29447,7 +31695,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                              booleanValue(azArg[4]));
      if( rc ){
-
        eputf("User-Edit failed: %d\n", rc);
+
        sqlite3_fprintf(stderr,"User-Edit failed: %d\n", rc);
        rc = 1;
      }
    }else if( cli_strcmp(azArg[1],"delete")==0 ){
@@ -29458,7 +31706,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      }
      rc = sqlite3_user_delete(p->db, azArg[2]);
      if( rc ){
-
        eputf("User-Delete failed: %d\n", rc);
+
        sqlite3_fprintf(stderr,"User-Delete failed: %d\n", rc);
        rc = 1;
      }
    }else{
@@ -29471,21 +31719,21 @@ static int do_meta_command(char *zLine, ShellState *p){

  if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
    char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit";
-
    oputf("SQLite %s %s\n" /*extra-version-info*/,
+
    sqlite3_fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
          sqlite3_libversion(), sqlite3_sourceid());
#if SQLITE_HAVE_ZLIB
-
    oputf("zlib version %s\n", zlibVersion());
+
    sqlite3_fprintf(p->out, "zlib version %s\n", zlibVersion());
#endif
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
#if defined(__clang__) && defined(__clang_major__)
-
    oputf("clang-" CTIMEOPT_VAL(__clang_major__) "."
+
    sqlite3_fprintf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
          CTIMEOPT_VAL(__clang_minor__) "."
          CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz);
#elif defined(_MSC_VER)
-
    oputf("msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
+
    sqlite3_fprintf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
#elif defined(__GNUC__) && defined(__VERSION__)
-
    oputf("gcc-" __VERSION__ " (%s)\n", zPtrSz);
+
    sqlite3_fprintf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz);
#endif
  }else

@@ -29495,10 +31743,10 @@ static int do_meta_command(char *zLine, ShellState *p){
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
      if( pVfs ){
-
        oputf("vfs.zName      = \"%s\"\n", pVfs->zName);
-
        oputf("vfs.iVersion   = %d\n", pVfs->iVersion);
-
        oputf("vfs.szOsFile   = %d\n", pVfs->szOsFile);
-
        oputf("vfs.mxPathname = %d\n", pVfs->mxPathname);
+
        sqlite3_fprintf(p->out, "vfs.zName      = \"%s\"\n", pVfs->zName);
+
        sqlite3_fprintf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
+
        sqlite3_fprintf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
+
        sqlite3_fprintf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
      }
    }
  }else
@@ -29510,13 +31758,13 @@ static int do_meta_command(char *zLine, ShellState *p){
      sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
    }
    for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
-
      oputf("vfs.zName      = \"%s\"%s\n", pVfs->zName,
+
      sqlite3_fprintf(p->out, "vfs.zName      = \"%s\"%s\n", pVfs->zName,
            pVfs==pCurrent ? "  <--- CURRENT" : "");
-
      oputf("vfs.iVersion   = %d\n", pVfs->iVersion);
-
      oputf("vfs.szOsFile   = %d\n", pVfs->szOsFile);
-
      oputf("vfs.mxPathname = %d\n", pVfs->mxPathname);
+
      sqlite3_fprintf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
+
      sqlite3_fprintf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
+
      sqlite3_fprintf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
      if( pVfs->pNext ){
-
        oputz("-----------------------------------\n");
+
        sqlite3_fputs("-----------------------------------\n", p->out);
      }
    }
  }else
@@ -29527,7 +31775,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
      if( zVfsName ){
-
        oputf("%s\n", zVfsName);
+
        sqlite3_fprintf(p->out, "%s\n", zVfsName);
        sqlite3_free(zVfsName);
      }
    }
@@ -29551,7 +31799,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else

  {
-
    eputf("Error: unknown command or invalid arguments: "
+
    sqlite3_fprintf(stderr,"Error: unknown command or invalid arguments: "
          " \"%s\". Enter \".help\" for help\n", azArg[0]);
    rc = 1;
  }
@@ -29732,7 +31980,10 @@ static int doAutoDetectRestore(ShellState *p, const char *zSql){
      case 0: {
        const char *zExpect = "PRAGMA foreign_keys=OFF;";
        assert( strlen(zExpect)==24 );
-
        if( p->bSafeMode==0 && memcmp(zSql, zExpect, 25)==0 ){
+
        if( p->bSafeMode==0
+
         && strlen(zSql)>=24
+
         && memcmp(zSql, zExpect, 25)==0
+
        ){
          p->eRestoreState = 1;
        }else{
          p->eRestoreState = 7;
@@ -29800,7 +32051,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
  if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
  BEGIN_TIMER;
  rc = shell_exec(p, zSql, &zErrMsg);
-
  END_TIMER;
+
  END_TIMER(p->out);
  if( rc || zErrMsg ){
    char zPrefix[100];
    const char *zErrorTail;
@@ -29824,7 +32075,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
    }else{
      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
    }
-
    eputf("%s %s\n", zPrefix, zErrorTail);
+
    sqlite3_fprintf(stderr,"%s %s\n", zPrefix, zErrorTail);
    sqlite3_free(zErrMsg);
    zErrMsg = 0;
    return 1;
@@ -29833,7 +32084,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
    sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
            "changes: %lld   total_changes: %lld",
            sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
-
    oputf("%s\n", zLineBuf);
+
    sqlite3_fprintf(p->out, "%s\n", zLineBuf);
  }

  if( doAutoDetectRestore(p, zSql) ) return 1;
@@ -29841,7 +32092,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
}

static void echo_group_input(ShellState *p, const char *zDo){
-
  if( ShellHasFlag(p, SHFLG_Echo) ) oputf("%s\n", zDo);
+
  if( ShellHasFlag(p, SHFLG_Echo) ) sqlite3_fprintf(p->out, "%s\n", zDo);
}

#ifdef SQLITE_SHELL_FIDDLE
@@ -29899,7 +32150,7 @@ static int process_input(ShellState *p){

  if( p->inputNesting==MAX_INPUT_NESTING ){
    /* This will be more informative in a later version. */
-
    eputf("Input nesting limit (%d) reached at line %d."
+
    sqlite3_fprintf(stderr,"Input nesting limit (%d) reached at line %d."
          " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
    return 1;
  }
@@ -29911,7 +32162,7 @@ static int process_input(ShellState *p){
    zLine = one_input_line(p->in, zLine, nSql>0);
    if( zLine==0 ){
      /* End of input */
-
      if( p->in==0 && stdin_is_interactive ) oputz("\n");
+
      if( p->in==0 && stdin_is_interactive ) sqlite3_fputs("\n", p->out);
      break;
    }
    if( seenInterrupt ){
@@ -30068,27 +32319,29 @@ static char *find_home_dir(int clearFlag){
/*
** On non-Windows platforms, look for $XDG_CONFIG_HOME.
** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
-
** the path to it, else return 0. The result is cached for
-
** subsequent calls.
+
** the path to it.  If there is no $(XDG_CONFIG_HOME) then
+
** look for $(HOME)/.config/sqlite3/sqliterc and if found
+
** return that.  If none of these are found, return 0.
+
**
+
** The string returned is obtained from sqlite3_malloc() and
+
** should be freed by the caller.
*/
-
static const char *find_xdg_config(void){
+
static char *find_xdg_config(void){
#if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
     || defined(__RTP__) || defined(_WRS_KERNEL)
  return 0;
#else
-
  static int alreadyTried = 0;
-
  static char *zConfig = 0;
+
  char *zConfig = 0;
  const char *zXdgHome;

-
  if( alreadyTried!=0 ){
-
    return zConfig;
-
  }
-
  alreadyTried = 1;
  zXdgHome = getenv("XDG_CONFIG_HOME");
  if( zXdgHome==0 ){
-
    return 0;
+
    const char *zHome = getenv("HOME");
+
    if( zHome==0 ) return 0;
+
    zConfig = sqlite3_mprintf("%s/.config/sqlite3/sqliterc", zHome);
+
  }else{
+
    zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
  }
-
  zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
  shell_check_oom(zConfig);
  if( access(zConfig,0)!=0 ){
    sqlite3_free(zConfig);
@@ -30116,7 +32369,7 @@ static void process_sqliterc(
  int savedLineno = p->lineno;

  if( sqliterc == NULL ){
-
    sqliterc = find_xdg_config();
+
    sqliterc = zBuf = find_xdg_config();
  }
  if( sqliterc == NULL ){
    home_dir = find_home_dir(0);
@@ -30129,15 +32382,15 @@ static void process_sqliterc(
    shell_check_oom(zBuf);
    sqliterc = zBuf;
  }
-
  p->in = fopen(sqliterc,"rb");
+
  p->in = sqlite3_fopen(sqliterc,"rb");
  if( p->in ){
    if( stdin_is_interactive ){
-
      eputf("-- Loading resources from %s\n", sqliterc);
+
      sqlite3_fprintf(stderr,"-- Loading resources from %s\n", sqliterc);
    }
    if( process_input(p) && bail_on_error ) exit(1);
    fclose(p->in);
  }else if( sqliterc_override!=0 ){
-
    eputf("cannot open: \"%s\"\n", sqliterc);
+
    sqlite3_fprintf(stderr,"cannot open: \"%s\"\n", sqliterc);
    if( bail_on_error ) exit(1);
  }
  p->in = inSaved;
@@ -30206,19 +32459,17 @@ static const char zOptions[] =
  "   -unsafe-testing      allow unsafe commands and modes for testing\n"
  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"
-
#ifdef SQLITE_ENABLE_VFSTRACE
  "   -vfstrace            enable tracing of all VFS calls\n"
-
#endif
#ifdef SQLITE_HAVE_ZLIB
  "   -zip                 open the file as a ZIP Archive\n"
#endif
;
static void usage(int showDetail){
-
  eputf("Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
+
  sqlite3_fprintf(stderr,"Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
       "FILENAME is the name of an SQLite database. A new database is created\n"
       "if the file does not previously exist. Defaults to :memory:.\n", Argv0);
  if( showDetail ){
-
    eputf("OPTIONS include:\n%s", zOptions);
+
    sqlite3_fprintf(stderr,"OPTIONS include:\n%s", zOptions);
  }else{
    eputz("Use the -help option for additional information\n");
  }
@@ -30243,6 +32494,9 @@ static void main_init(ShellState *data) {
  memset(data, 0, sizeof(*data));
  data->normalMode = data->cMode = data->mode = MODE_List;
  data->autoExplain = 1;
+
#ifdef _WIN32
+
  data->crlfMode = 1;
+
#endif
  data->pAuxDb = &data->aAuxDb[0];
  memcpy(data->colSeparator,SEP_Column, 2);
  memcpy(data->rowSeparator,SEP_Row, 2);
@@ -30278,7 +32532,7 @@ static void printBold(const char *zText){
}
#else
static void printBold(const char *zText){
-
  sputf(stdout, "\033[1m%s\033[0m", zText);
+
  sqlite3_fprintf(stdout, "\033[1m%s\033[0m", zText);
}
#endif

@@ -30288,7 +32542,8 @@ static void printBold(const char *zText){
*/
static char *cmdline_option_value(int argc, char **argv, int i){
  if( i==argc ){
-
    eputf("%s: Error: missing argument to %s\n", argv[0], argv[argc-1]);
+
    sqlite3_fprintf(stderr,
+
            "%s: Error: missing argument to %s\n", argv[0], argv[argc-1]);
    exit(1);
  }
  return argv[i];
@@ -30325,7 +32580,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#  define data shellState
#else
  ShellState data;
-
  StreamsAreConsole consStreams = SAC_NoConsole;
#endif
  const char *zInitFile = 0;
  int i;
@@ -30334,6 +32588,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
  int readStdin = 1;
  int nCmd = 0;
  int nOptsEnd = argc;
+
  int bEnableVfstrace = 0;
  char **azCmd = 0;
  const char *zVfs = 0;           /* Value of -vfs command-line option */
#if !SQLITE_SHELL_IS_UTF8
@@ -30347,10 +32602,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
  stdout_is_console = 1;
  data.wasm.zDefaultDbName = "/fiddle.sqlite3";
#else
-
  consStreams = consoleClassifySetup(stdin, stdout, stderr);
-
  stdin_is_interactive = (consStreams & SAC_InConsole)!=0;
-
  stdout_is_console = (consStreams & SAC_OutConsole)!=0;
-
  atexit(consoleRestore);
+
  stdin_is_interactive = isatty(0);
+
  stdout_is_console = isatty(1);
#endif
  atexit(sayAbnormalExit);
#ifdef SQLITE_DEBUG
@@ -30359,9 +32612,15 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#if !defined(_WIN32_WCE)
  if( getenv("SQLITE_DEBUG_BREAK") ){
    if( isatty(0) && isatty(2) ){
-
      eputf("attach debugger to process %d and press any key to continue.\n",
+
      char zLine[100];
+
      sqlite3_fprintf(stderr,
+
            "attach debugger to process %d and press ENTER to continue...",
            GETPID());
-
      fgetc(stdin);
+
      if( sqlite3_fgets(zLine, sizeof(zLine), stdin)!=0
+
       && cli_strcmp(zLine,"stop")==0
+
      ){
+
        exit(1);
+
      }
    }else{
#if defined(_WIN32) || defined(WIN32)
#if SQLITE_OS_WINRT
@@ -30386,7 +32645,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){

#if USE_SYSTEM_SQLITE+0!=1
  if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
-
    eputf("SQLite header and source version mismatch\n%s\n%s\n",
+
    sqlite3_fprintf(stderr,
+
          "SQLite header and source version mismatch\n%s\n%s\n",
          sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
  }
@@ -30528,17 +32788,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
         case 2:  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);   break;
         default: sqlite3_config(SQLITE_CONFIG_SERIALIZED);    break;
      }
-
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
-
      extern int vfstrace_register(
-
         const char *zTraceName,
-
         const char *zOldVfsName,
-
         int (*xOut)(const char*,void*),
-
         void *pOutArg,
-
         int makeDefault
-
      );
-
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
-
#endif
+
      vfstrace_register("trace",0,(int(*)(const char*,void*))sqlite3_fputs,
+
                        stderr,1);
+
      bEnableVfstrace = 1;
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiplex_initialize(const char*,int);
@@ -30594,7 +32847,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
    }
  }
#ifndef SQLITE_SHELL_FIDDLE
-
  verify_uninitialized();
+
  if( !bEnableVfstrace ) verify_uninitialized();
#endif


@@ -30618,7 +32871,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
    if( pVfs ){
      sqlite3_vfs_register(pVfs, 1);
    }else{
-
      eputf("no such VFS: \"%s\"\n", zVfs);
+
      sqlite3_fprintf(stderr,"no such VFS: \"%s\"\n", zVfs);
      exit(1);
    }
  }
@@ -30628,7 +32881,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
    data.pAuxDb->zDbFilename = ":memory:";
    warnInmemoryDb = argc==1;
#else
-
    eputf("%s: Error: no database filename specified\n", Argv0);
+
    sqlite3_fprintf(stderr,
+
                    "%s: Error: no database filename specified\n", Argv0);
    return 1;
#endif
  }
@@ -30745,7 +32999,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
    }else if( cli_strcmp(z,"-bail")==0 ){
      /* No-op.  The bail_on_error flag should already be set. */
    }else if( cli_strcmp(z,"-version")==0 ){
-
      sputf(stdout, "%s %s (%d-bit)\n",
+
      sqlite3_fprintf(stdout, "%s %s (%d-bit)\n",
            sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
      return 0;
    }else if( cli_strcmp(z,"-interactive")==0 ){
@@ -30783,10 +33037,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
    }else if( cli_strcmp(z,"-vfs")==0 ){
      i++;
-
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      i++;
-
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      i++;
@@ -30807,17 +33059,17 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
        open_db(&data, 0);
        rc = shell_exec(&data, z, &zErrMsg);
        if( zErrMsg!=0 ){
-
          eputf("Error: %s\n", zErrMsg);
+
          shellEmitError(zErrMsg);
          if( bail_on_error ) return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
-
          eputf("Error: unable to process SQL \"%s\"\n", z);
+
          sqlite3_fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
          if( bail_on_error ) return rc;
        }
      }
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
    }else if( cli_strncmp(z, "-A", 2)==0 ){
      if( nCmd>0 ){
-
        eputf("Error: cannot mix regular SQL or dot-commands"
+
        sqlite3_fprintf(stderr,"Error: cannot mix regular SQL or dot-commands"
              " with \"%s\"\n", z);
        return 1;
      }
@@ -30836,7 +33088,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
    }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
      /* Acted upon in first pass. */
    }else{
-
      eputf("%s: Error: unknown option: %s\n", Argv0, z);
+
      sqlite3_fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
      eputz("Use -help for a list of options.\n");
      return 1;
    }
@@ -30852,8 +33104,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
      if( azCmd[i][0]=='.' ){
        rc = do_meta_command(azCmd[i], &data);
        if( rc ){
-
          free(azCmd);
-
          return rc==2 ? 0 : rc;
+
          if( rc==2 ) rc = 0;
+
          goto shell_main_exit;
        }
      }else{
        open_db(&data, 0);
@@ -30861,13 +33113,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
        rc = shell_exec(&data, azCmd[i], &zErrMsg);
        if( zErrMsg || rc ){
          if( zErrMsg!=0 ){
-
            eputf("Error: %s\n", zErrMsg);
+
            shellEmitError(zErrMsg);
          }else{
-
            eputf("Error: unable to process SQL: %s\n", azCmd[i]);
+
            sqlite3_fprintf(stderr,
+
                            "Error: unable to process SQL: %s\n", azCmd[i]);
          }
          sqlite3_free(zErrMsg);
-
          free(azCmd);
-
          return rc!=0 ? rc : 1;
+
          if( rc==0 ) rc = 1;
+
          goto shell_main_exit;
        }
      }
    }
@@ -30883,7 +33136,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#else
# define SHELL_CIO_CHAR_SET ""
#endif
-
      sputf(stdout, "SQLite version %s %.19s%s\n" /*extra-version-info*/
+
      sqlite3_fprintf(stdout,
+
            "SQLite version %s %.19s%s\n" /*extra-version-info*/
            "Enter \".help\" for usage hints.\n",
            sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);
      if( warnInmemoryDb ){
@@ -30905,7 +33159,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#if HAVE_READLINE || HAVE_EDITLINE
      rl_attempted_completion_function = readline_completion;
#elif HAVE_LINENOISE
-
      linenoiseSetCompletionCallback(linenoise_completion);
+
      linenoiseSetCompletionCallback(linenoise_completion, NULL);
#endif
      data.in = 0;
      rc = process_input(&data);
@@ -30927,6 +33181,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
    expertFinish(&data, 1, 0);
  }
#endif
+
 shell_main_exit:
  free(azCmd);
  set_table_name(&data, 0);
  if( data.db ){
@@ -30953,13 +33208,18 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
  /* Clear the global data structure so that valgrind will detect memory
  ** leaks */
  memset(&data, 0, sizeof(data));
+
  if( bEnableVfstrace ){
+
    vfstrace_unregister("trace");
+
  }
#ifdef SQLITE_DEBUG
  if( sqlite3_memory_used()>mem_main_enter ){
-
    eputf("Memory leaked: %u bytes\n",
+
    sqlite3_fprintf(stderr,"Memory leaked: %u bytes\n",
          (unsigned int)(sqlite3_memory_used()-mem_main_enter));
  }
#endif
-
#endif /* !SQLITE_SHELL_FIDDLE */
+
#else /* SQLITE_SHELL_FIDDLE... */
+
  shell_main_exit:
+
#endif
  return rc;
}

@@ -30993,7 +33253,7 @@ sqlite3_vfs * fiddle_db_vfs(const char *zDbName){

/* Only for emcc experimentation purposes. */
sqlite3 * fiddle_db_arg(sqlite3 *arg){
-
    oputf("fiddle_db_arg(%p)\n", (const void*)arg);
+
    sqlite3_fprintf(stdout, "fiddle_db_arg(%p)\n", (const void*)arg);
    return arg;
}

@@ -31030,7 +33290,7 @@ void fiddle_reset_db(void){
      ** Resolve problem reported in
      ** https://sqlite.org/forum/forumpost/0b41a25d65
      */
-
      oputz("Rolling back in-progress transaction.\n");
+
      sqlite3_fputs("Rolling back in-progress transaction.\n", stdout);
      sqlite3_exec(globalDb,"ROLLBACK", 0, 0, 0);
    }
    rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
modified external/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-
** version 3.46.1.  By combining all the individual C code files into this
+
** version 3.47.0.  By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
@@ -18,7 +18,7 @@
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
-
** c9c2ab54ba1f5f46360f1b4f35d849cd3f08.
+
** 03a9703e27c44437c39363d0baf82db4ebc9.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ -256,10 +256,13 @@
/*
** Macro to disable warnings about missing "break" at the end of a "case".
*/
-
#if GCC_VERSION>=7000000
-
# define deliberate_fall_through __attribute__((fallthrough));
-
#else
-
# define deliberate_fall_through
+
#if defined(__has_attribute)
+
#  if __has_attribute(fallthrough)
+
#    define deliberate_fall_through __attribute__((fallthrough));
+
#  endif
+
#endif
+
#if !defined(deliberate_fall_through)
+
#  define deliberate_fall_through
#endif

/*
@@ -459,9 +462,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.46.1"
-
#define SQLITE_VERSION_NUMBER 3046001
-
#define SQLITE_SOURCE_ID      "2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33"
+
#define SQLITE_VERSION        "3.47.0"
+
#define SQLITE_VERSION_NUMBER 3047000
+
#define SQLITE_SOURCE_ID      "2024-10-21 16:30:22 03a9703e27c44437c39363d0baf82db4ebc94538a0f28411c85dda156f82636e"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1085,8 +1088,8 @@ struct sqlite3_file {
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
-
** PENDING, or EXCLUSIVE lock on the file.  It returns true
-
** if such a lock exists and false otherwise.
+
** PENDING, or EXCLUSIVE lock on the file.  It returns, via its output
+
** pointer parameter, true if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom
** VFS implementations to directly control an open file using the
@@ -3883,8 +3886,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
**
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
** <dd>The database connection comes up in "extended result code mode".
-
** In other words, the database behaves has if
-
** [sqlite3_extended_result_codes(db,1)] where called on the database
+
** In other words, the database behaves as if
+
** [sqlite3_extended_result_codes(db,1)] were called on the database
** connection as soon as the connection is created. In addition to setting
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
** to return an extended result code.</dd>
@@ -4535,13 +4538,17 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** and sqlite3_prepare16_v3() use UTF-16.
**
** ^If the nByte argument is negative, then zSql is read up to the
-
** first zero terminator. ^If nByte is positive, then it is the
-
** number of bytes read from zSql.  ^If nByte is zero, then no prepared
+
** first zero terminator. ^If nByte is positive, then it is the maximum
+
** number of bytes read from zSql.  When nByte is positive, zSql is read
+
** up to the first zero terminator or until the nByte bytes have been read,
+
** whichever comes first.  ^If nByte is zero, then no prepared
** statement is generated.
** If the caller knows that the supplied string is nul-terminated, then
** there is a small performance advantage to passing an nByte parameter that
** is the number of bytes in the input string <i>including</i>
** the nul-terminator.
+
** Note that nByte measure the length of the input in bytes, not
+
** characters, even for the UTF-16 interfaces.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql.  These routines only
@@ -5912,7 +5919,7 @@ SQLITE_API int sqlite3_create_window_function(
** This flag instructs SQLite to omit some corner-case optimizations that
** might disrupt the operation of the [sqlite3_value_subtype()] function,
** causing it to return zero rather than the correct subtype().
-
** SQL functions that invokes [sqlite3_value_subtype()] should have this
+
** All SQL functions that invoke [sqlite3_value_subtype()] should have this
** property.  If the SQLITE_SUBTYPE property is omitted, then the return
** value from [sqlite3_value_subtype()] might sometimes be zero even though
** a non-zero subtype was specified by the function argument expression.
@@ -5928,6 +5935,15 @@ SQLITE_API int sqlite3_create_window_function(
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes.
+
**
+
** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd>
+
** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
+
** that internally orders the values provided to the first argument.  The
+
** ordered-set aggregate SQL notation with a single ORDER BY term can be
+
** used to invoke this function.  If the ordered-set aggregate notation is
+
** used on a function that lacks this flag, then an error is raised. Note
+
** that the ordered-set aggregate syntax is only available if SQLite is
+
** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
** </dd>
** </dl>
*/
@@ -5936,6 +5952,7 @@ SQLITE_API int sqlite3_create_window_function(
#define SQLITE_SUBTYPE          0x000100000
#define SQLITE_INNOCUOUS        0x000200000
#define SQLITE_RESULT_SUBTYPE   0x001000000
+
#define SQLITE_SELFORDER1       0x002000000

/*
** CAPI3REF: Deprecated Functions
@@ -6133,7 +6150,7 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
** one SQL function to another.  Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
-
** Every [application-defined SQL function] that invoke this interface
+
** Every [application-defined SQL function] that invokes this interface
** should include the [SQLITE_SUBTYPE] property in the text
** encoding argument when the function is [sqlite3_create_function|registered].
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
@@ -7740,9 +7757,11 @@ struct sqlite3_module {
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
-
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
-
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
-
** assumes that the strategy may visit at most one row.
+
** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
+
** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
+
** output to show the idxNum has hex instead of as decimal.  Another flag is
+
** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
+
** return at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
@@ -7806,7 +7825,9 @@ struct sqlite3_index_info {
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
-
#define SQLITE_INDEX_SCAN_UNIQUE      1     /* Scan visits at most 1 row */
+
#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
+
#define SQLITE_INDEX_SCAN_HEX    0x00000002 /* Display idxNum as hex */
+
                                            /* in EXPLAIN QUERY PLAN */

/*
** CAPI3REF: Virtual Table Constraint Operator Codes
@@ -8643,6 +8664,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_JSON_SELFCHECK          14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16  /* NOT USED */
+
#define SQLITE_TESTCTRL_GETOPT                  16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17  /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS      17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
@@ -8662,7 +8684,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_TRACEFLAGS              31
#define SQLITE_TESTCTRL_TUNE                    32
#define SQLITE_TESTCTRL_LOGEST                  33
-
#define SQLITE_TESTCTRL_USELONGDOUBLE           34
+
#define SQLITE_TESTCTRL_USELONGDOUBLE           34  /* NOT USED */
#define SQLITE_TESTCTRL_LAST                    34  /* Largest TESTCTRL */

/*
@@ -9638,6 +9660,16 @@ typedef struct sqlite3_backup sqlite3_backup;
** APIs are not strictly speaking threadsafe. If they are invoked at the
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
+
**
+
** <b>Alternatives To Using The Backup API</b>
+
**
+
** Other techniques for safely creating a consistent backup of an SQLite
+
** database include:
+
**
+
** <ul>
+
** <li> The [VACUUM INTO] command.
+
** <li> The [sqlite3_rsync] utility program.
+
** </ul>
*/
SQLITE_API sqlite3_backup *sqlite3_backup_init(
  sqlite3 *pDest,                        /* Destination database handle */
@@ -10837,6 +10869,14 @@ typedef struct sqlite3_snapshot {
** If there is not already a read-transaction open on schema S when
** this function is called, one is opened automatically.
**
+
** If a read-transaction is opened by this function, then it is guaranteed
+
** that the returned snapshot object may not be invalidated by a database
+
** writer or checkpointer until after the read-transaction is closed. This
+
** is not guaranteed if a read-transaction is already open when this
+
** function is called. In that case, any subsequent write or checkpoint
+
** operation on the database may invalidate the returned snapshot handle,
+
** even while the read-transaction remains open.
+
**
** The following must be true for this function to succeed. If any of
** the following statements are false when sqlite3_snapshot_get() is
** called, SQLITE_ERROR is returned. The final value of *P is undefined
@@ -11145,8 +11185,6 @@ SQLITE_API int sqlite3_deserialize(
#if defined(__wasi__)
# undef SQLITE_WASI
# define SQLITE_WASI 1
-
# undef SQLITE_OMIT_WAL
-
# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
# ifndef SQLITE_OMIT_LOAD_EXTENSION
#  define SQLITE_OMIT_LOAD_EXTENSION
# endif
@@ -13349,6 +13387,10 @@ struct Fts5PhraseIter {
**   (i.e. if it is a contentless table), then this API always iterates
**   through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
+
**   In all cases, matches are visited in (column ASC, offset ASC) order.
+
**   i.e. all those in column 0, sorted by offset, followed by those in
+
**   column 1, etc.
+
**
** xPhraseNext()
**   See xPhraseFirst above.
**
@@ -13415,9 +13457,32 @@ struct Fts5PhraseIter {
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option.
+
**
+
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+
**   If parameter iCol is less than zero, or greater than or equal to the
+
**   number of columns in the table, SQLITE_RANGE is returned.
+
**
+
**   Otherwise, this function attempts to retrieve the locale associated
+
**   with column iCol of the current row. Usually, there is no associated
+
**   locale, and output parameters (*pzLocale) and (*pnLocale) are set
+
**   to NULL and 0, respectively. However, if the fts5_locale() function
+
**   was used to associate a locale with the value when it was inserted
+
**   into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+
**   buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+
**   is set to the size in bytes of the buffer, not including the
+
**   nul-terminator.
+
**
+
**   If successful, SQLITE_OK is returned. Or, if an error occurs, an
+
**   SQLite error code is returned. The final value of the output parameters
+
**   is undefined in this case.
+
**
+
** xTokenize_v2:
+
**   Tokenize text using the tokenizer belonging to the FTS5 table. This
+
**   API is the same as the xTokenize() API, except that it allows a tokenizer
+
**   locale to be specified.
*/
struct Fts5ExtensionApi {
-
  int iVersion;                   /* Currently always set to 3 */
+
  int iVersion;                   /* Currently always set to 4 */

  void *(*xUserData)(Fts5Context*);

@@ -13459,6 +13524,15 @@ struct Fts5ExtensionApi {
      const char **ppToken, int *pnToken
  );
  int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+

+
  /* Below this point are iVersion>=4 only */
+
  int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+
  int (*xTokenize_v2)(Fts5Context*,
+
    const char *pText, int nText,      /* Text to tokenize */
+
    const char *pLocale, int nLocale,  /* Locale to pass to tokenizer */
+
    void *pCtx,                        /* Context passed to xToken() */
+
    int (*xToken)(void*, int, const char*, int, int, int)       /* Callback */
+
  );
};

/*
@@ -13479,7 +13553,7 @@ struct Fts5ExtensionApi {
**   A tokenizer instance is required to actually tokenize text.
**
**   The first argument passed to this function is a copy of the (void*)
-
**   pointer provided by the application when the fts5_tokenizer object
+
**   pointer provided by the application when the fts5_tokenizer_v2 object
**   was registered with FTS5 (the third argument to xCreateTokenizer()).
**   The second and third arguments are an array of nul-terminated strings
**   containing the tokenizer arguments, if any, specified following the
@@ -13503,7 +13577,7 @@ struct Fts5ExtensionApi {
**   argument passed to this function is a pointer to an Fts5Tokenizer object
**   returned by an earlier call to xCreate().
**
-
**   The second argument indicates the reason that FTS5 is requesting
+
**   The third argument indicates the reason that FTS5 is requesting
**   tokenization of the supplied text. This is always one of the following
**   four values:
**
@@ -13527,6 +13601,13 @@ struct Fts5ExtensionApi {
**            on a columnsize=0 database.
**   </ul>
**
+
**   The sixth and seventh arguments passed to xTokenize() - pLocale and
+
**   nLocale - are a pointer to a buffer containing the locale to use for
+
**   tokenization (e.g. "en_US") and its size in bytes, respectively. The
+
**   pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+
**   which case nLocale is always 0) to indicate that the tokenizer should
+
**   use its default locale.
+
**
**   For each token in the input string, the supplied callback xToken() must
**   be invoked. The first argument to it should be a copy of the pointer
**   passed as the second argument to xTokenize(). The third and fourth
@@ -13550,6 +13631,30 @@ struct Fts5ExtensionApi {
**   may abandon the tokenization and return any error code other than
**   SQLITE_OK or SQLITE_DONE.
**
+
**   If the tokenizer is registered using an fts5_tokenizer_v2 object,
+
**   then the xTokenize() method has two additional arguments - pLocale
+
**   and nLocale. These specify the locale that the tokenizer should use
+
**   for the current request. If pLocale and nLocale are both 0, then the
+
**   tokenizer should use its default locale. Otherwise, pLocale points to
+
**   an nLocale byte buffer containing the name of the locale to use as utf-8
+
**   text. pLocale is not nul-terminated.
+
**
+
** FTS5_TOKENIZER
+
**
+
** There is also an fts5_tokenizer object. This is an older, deprecated,
+
** version of fts5_tokenizer_v2. It is similar except that:
+
**
+
**  <ul>
+
**    <li> There is no "iVersion" field, and
+
**    <li> The xTokenize() method does not take a locale argument.
+
**  </ul>
+
**
+
** Legacy fts5_tokenizer tokenizers must be registered using the
+
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+
**
+
** Tokenizer implementations registered using either API may be retrieved
+
** using both xFindTokenizer() and xFindTokenizer_v2().
+
**
** SYNONYM SUPPORT
**
**   Custom tokenizers may also support synonyms. Consider a case in which a
@@ -13658,6 +13763,33 @@ struct Fts5ExtensionApi {
**   inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
+
typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+
struct fts5_tokenizer_v2 {
+
  int iVersion;             /* Currently always 2 */
+

+
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+
  void (*xDelete)(Fts5Tokenizer*);
+
  int (*xTokenize)(Fts5Tokenizer*,
+
      void *pCtx,
+
      int flags,            /* Mask of FTS5_TOKENIZE_* flags */
+
      const char *pText, int nText,
+
      const char *pLocale, int nLocale,
+
      int (*xToken)(
+
        void *pCtx,         /* Copy of 2nd argument to xTokenize() */
+
        int tflags,         /* Mask of FTS5_TOKEN_* flags */
+
        const char *pToken, /* Pointer to buffer containing token */
+
        int nToken,         /* Size of token in bytes */
+
        int iStart,         /* Byte offset of token within input text */
+
        int iEnd            /* Byte offset of end of token within input text */
+
      )
+
  );
+
};
+

+
/*
+
** New code should use the fts5_tokenizer_v2 type to define tokenizer
+
** implementations. The following type is included for legacy applications
+
** that still use it.
+
*/
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
@@ -13677,6 +13809,7 @@ struct fts5_tokenizer {
  );
};

+

/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY     0x0001
#define FTS5_TOKENIZE_PREFIX    0x0002
@@ -13696,7 +13829,7 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
-
  int iVersion;                   /* Currently always set to 2 */
+
  int iVersion;                   /* Currently always set to 3 */

  /* Create a new tokenizer */
  int (*xCreateTokenizer)(
@@ -13723,6 +13856,25 @@ struct fts5_api {
    fts5_extension_function xFunction,
    void (*xDestroy)(void*)
  );
+

+
  /* APIs below this point are only available if iVersion>=3 */
+

+
  /* Create a new tokenizer */
+
  int (*xCreateTokenizer_v2)(
+
    fts5_api *pApi,
+
    const char *zName,
+
    void *pUserData,
+
    fts5_tokenizer_v2 *pTokenizer,
+
    void (*xDestroy)(void*)
+
  );
+

+
  /* Find an existing tokenizer */
+
  int (*xFindTokenizer_v2)(
+
    fts5_api *pApi,
+
    const char *zName,
+
    void **ppUserData,
+
    fts5_tokenizer_v2 **ppTokenizer
+
  );
};

/*
@@ -14532,132 +14684,132 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_OR                              43
#define TK_AND                             44
#define TK_IS                              45
-
#define TK_MATCH                           46
-
#define TK_LIKE_KW                         47
-
#define TK_BETWEEN                         48
-
#define TK_IN                              49
-
#define TK_ISNULL                          50
-
#define TK_NOTNULL                         51
-
#define TK_NE                              52
-
#define TK_EQ                              53
-
#define TK_GT                              54
-
#define TK_LE                              55
-
#define TK_LT                              56
-
#define TK_GE                              57
-
#define TK_ESCAPE                          58
-
#define TK_ID                              59
-
#define TK_COLUMNKW                        60
-
#define TK_DO                              61
-
#define TK_FOR                             62
-
#define TK_IGNORE                          63
-
#define TK_INITIALLY                       64
-
#define TK_INSTEAD                         65
-
#define TK_NO                              66
-
#define TK_KEY                             67
-
#define TK_OF                              68
-
#define TK_OFFSET                          69
-
#define TK_PRAGMA                          70
-
#define TK_RAISE                           71
-
#define TK_RECURSIVE                       72
-
#define TK_REPLACE                         73
-
#define TK_RESTRICT                        74
-
#define TK_ROW                             75
-
#define TK_ROWS                            76
-
#define TK_TRIGGER                         77
-
#define TK_VACUUM                          78
-
#define TK_VIEW                            79
-
#define TK_VIRTUAL                         80
-
#define TK_WITH                            81
-
#define TK_NULLS                           82
-
#define TK_FIRST                           83
-
#define TK_LAST                            84
-
#define TK_CURRENT                         85
-
#define TK_FOLLOWING                       86
-
#define TK_PARTITION                       87
-
#define TK_PRECEDING                       88
-
#define TK_RANGE                           89
-
#define TK_UNBOUNDED                       90
-
#define TK_EXCLUDE                         91
-
#define TK_GROUPS                          92
-
#define TK_OTHERS                          93
-
#define TK_TIES                            94
-
#define TK_GENERATED                       95
-
#define TK_ALWAYS                          96
-
#define TK_MATERIALIZED                    97
-
#define TK_REINDEX                         98
-
#define TK_RENAME                          99
-
#define TK_CTIME_KW                       100
-
#define TK_ANY                            101
-
#define TK_BITAND                         102
-
#define TK_BITOR                          103
-
#define TK_LSHIFT                         104
-
#define TK_RSHIFT                         105
-
#define TK_PLUS                           106
-
#define TK_MINUS                          107
-
#define TK_STAR                           108
-
#define TK_SLASH                          109
-
#define TK_REM                            110
-
#define TK_CONCAT                         111
-
#define TK_PTR                            112
-
#define TK_COLLATE                        113
-
#define TK_BITNOT                         114
-
#define TK_ON                             115
-
#define TK_INDEXED                        116
-
#define TK_STRING                         117
-
#define TK_JOIN_KW                        118
-
#define TK_CONSTRAINT                     119
-
#define TK_DEFAULT                        120
-
#define TK_NULL                           121
-
#define TK_PRIMARY                        122
-
#define TK_UNIQUE                         123
-
#define TK_CHECK                          124
-
#define TK_REFERENCES                     125
-
#define TK_AUTOINCR                       126
-
#define TK_INSERT                         127
-
#define TK_DELETE                         128
-
#define TK_UPDATE                         129
-
#define TK_SET                            130
-
#define TK_DEFERRABLE                     131
-
#define TK_FOREIGN                        132
-
#define TK_DROP                           133
-
#define TK_UNION                          134
-
#define TK_ALL                            135
-
#define TK_EXCEPT                         136
-
#define TK_INTERSECT                      137
-
#define TK_SELECT                         138
-
#define TK_VALUES                         139
-
#define TK_DISTINCT                       140
-
#define TK_DOT                            141
-
#define TK_FROM                           142
-
#define TK_JOIN                           143
-
#define TK_USING                          144
-
#define TK_ORDER                          145
-
#define TK_GROUP                          146
-
#define TK_HAVING                         147
-
#define TK_LIMIT                          148
-
#define TK_WHERE                          149
-
#define TK_RETURNING                      150
-
#define TK_INTO                           151
-
#define TK_NOTHING                        152
-
#define TK_FLOAT                          153
-
#define TK_BLOB                           154
-
#define TK_INTEGER                        155
-
#define TK_VARIABLE                       156
-
#define TK_CASE                           157
-
#define TK_WHEN                           158
-
#define TK_THEN                           159
-
#define TK_ELSE                           160
-
#define TK_INDEX                          161
-
#define TK_ALTER                          162
-
#define TK_ADD                            163
-
#define TK_WINDOW                         164
-
#define TK_OVER                           165
-
#define TK_FILTER                         166
-
#define TK_COLUMN                         167
-
#define TK_AGG_FUNCTION                   168
-
#define TK_AGG_COLUMN                     169
-
#define TK_TRUEFALSE                      170
-
#define TK_ISNOT                          171
+
#define TK_ISNOT                           46
+
#define TK_MATCH                           47
+
#define TK_LIKE_KW                         48
+
#define TK_BETWEEN                         49
+
#define TK_IN                              50
+
#define TK_ISNULL                          51
+
#define TK_NOTNULL                         52
+
#define TK_NE                              53
+
#define TK_EQ                              54
+
#define TK_GT                              55
+
#define TK_LE                              56
+
#define TK_LT                              57
+
#define TK_GE                              58
+
#define TK_ESCAPE                          59
+
#define TK_ID                              60
+
#define TK_COLUMNKW                        61
+
#define TK_DO                              62
+
#define TK_FOR                             63
+
#define TK_IGNORE                          64
+
#define TK_INITIALLY                       65
+
#define TK_INSTEAD                         66
+
#define TK_NO                              67
+
#define TK_KEY                             68
+
#define TK_OF                              69
+
#define TK_OFFSET                          70
+
#define TK_PRAGMA                          71
+
#define TK_RAISE                           72
+
#define TK_RECURSIVE                       73
+
#define TK_REPLACE                         74
+
#define TK_RESTRICT                        75
+
#define TK_ROW                             76
+
#define TK_ROWS                            77
+
#define TK_TRIGGER                         78
+
#define TK_VACUUM                          79
+
#define TK_VIEW                            80
+
#define TK_VIRTUAL                         81
+
#define TK_WITH                            82
+
#define TK_NULLS                           83
+
#define TK_FIRST                           84
+
#define TK_LAST                            85
+
#define TK_CURRENT                         86
+
#define TK_FOLLOWING                       87
+
#define TK_PARTITION                       88
+
#define TK_PRECEDING                       89
+
#define TK_RANGE                           90
+
#define TK_UNBOUNDED                       91
+
#define TK_EXCLUDE                         92
+
#define TK_GROUPS                          93
+
#define TK_OTHERS                          94
+
#define TK_TIES                            95
+
#define TK_GENERATED                       96
+
#define TK_ALWAYS                          97
+
#define TK_MATERIALIZED                    98
+
#define TK_REINDEX                         99
+
#define TK_RENAME                         100
+
#define TK_CTIME_KW                       101
+
#define TK_ANY                            102
+
#define TK_BITAND                         103
+
#define TK_BITOR                          104
+
#define TK_LSHIFT                         105
+
#define TK_RSHIFT                         106
+
#define TK_PLUS                           107
+
#define TK_MINUS                          108
+
#define TK_STAR                           109
+
#define TK_SLASH                          110
+
#define TK_REM                            111
+
#define TK_CONCAT                         112
+
#define TK_PTR                            113
+
#define TK_COLLATE                        114
+
#define TK_BITNOT                         115
+
#define TK_ON                             116
+
#define TK_INDEXED                        117
+
#define TK_STRING                         118
+
#define TK_JOIN_KW                        119
+
#define TK_CONSTRAINT                     120
+
#define TK_DEFAULT                        121
+
#define TK_NULL                           122
+
#define TK_PRIMARY                        123
+
#define TK_UNIQUE                         124
+
#define TK_CHECK                          125
+
#define TK_REFERENCES                     126
+
#define TK_AUTOINCR                       127
+
#define TK_INSERT                         128
+
#define TK_DELETE                         129
+
#define TK_UPDATE                         130
+
#define TK_SET                            131
+
#define TK_DEFERRABLE                     132
+
#define TK_FOREIGN                        133
+
#define TK_DROP                           134
+
#define TK_UNION                          135
+
#define TK_ALL                            136
+
#define TK_EXCEPT                         137
+
#define TK_INTERSECT                      138
+
#define TK_SELECT                         139
+
#define TK_VALUES                         140
+
#define TK_DISTINCT                       141
+
#define TK_DOT                            142
+
#define TK_FROM                           143
+
#define TK_JOIN                           144
+
#define TK_USING                          145
+
#define TK_ORDER                          146
+
#define TK_GROUP                          147
+
#define TK_HAVING                         148
+
#define TK_LIMIT                          149
+
#define TK_WHERE                          150
+
#define TK_RETURNING                      151
+
#define TK_INTO                           152
+
#define TK_NOTHING                        153
+
#define TK_FLOAT                          154
+
#define TK_BLOB                           155
+
#define TK_INTEGER                        156
+
#define TK_VARIABLE                       157
+
#define TK_CASE                           158
+
#define TK_WHEN                           159
+
#define TK_THEN                           160
+
#define TK_ELSE                           161
+
#define TK_INDEX                          162
+
#define TK_ALTER                          163
+
#define TK_ADD                            164
+
#define TK_WINDOW                         165
+
#define TK_OVER                           166
+
#define TK_FILTER                         167
+
#define TK_COLUMN                         168
+
#define TK_AGG_FUNCTION                   169
+
#define TK_AGG_COLUMN                     170
+
#define TK_TRUEFALSE                      171
#define TK_FUNCTION                       172
#define TK_UPLUS                          173
#define TK_UMINUS                         174
@@ -14680,6 +14832,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#include <string.h>
#include <assert.h>
#include <stddef.h>
+
#include <ctype.h>

/*
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
@@ -14700,7 +14853,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
# define float sqlite_int64
-
# define LONGDOUBLE_TYPE sqlite_int64
+
# define fabs(X) ((X)<0?-(X):(X))
+
# define sqlite3IsOverflow(X) 0
# ifndef SQLITE_BIG_DBL
#   define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
# endif
@@ -14875,9 +15029,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#  define INT8_TYPE signed char
# endif
#endif
-
#ifndef LONGDOUBLE_TYPE
-
# define LONGDOUBLE_TYPE long double
-
#endif
typedef sqlite_int64 i64;          /* 8-byte signed integer */
typedef sqlite_uint64 u64;         /* 8-byte unsigned integer */
typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
@@ -15377,6 +15528,7 @@ typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+
typedef struct Subquery Subquery;
typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
@@ -16259,6 +16411,9 @@ SQLITE_PRIVATE int sqlite3BtreeCursor(
);
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
+
#ifdef SQLITE_DEBUG
+
SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*);
+
#endif
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -16477,6 +16632,19 @@ typedef struct Vdbe Vdbe;
*/
typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
+
typedef struct SubrtnSig SubrtnSig;
+

+
/*
+
** A signature for a reusable subroutine that materializes the RHS of
+
** an IN operator.
+
*/
+
struct SubrtnSig {
+
  int selId;          /* SELECT-id for the SELECT statement on the RHS */
+
  char *zAff;         /* Affinity of the overall IN expression */
+
  int iTable;         /* Ephemeral table generated by the subroutine */
+
  int iAddr;          /* Subroutine entry address */
+
  int regReturn;      /* Register used to hold return address */
+
};

/*
** A single instruction of the virtual machine has an opcode
@@ -16505,6 +16673,7 @@ struct VdbeOp {
    u32 *ai;               /* Used when p4type is P4_INTARRAY */
    SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
    Table *pTab;           /* Used when p4type is P4_TABLE */
+
    SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
    Expr *pExpr;           /* Used when p4type is P4_EXPR */
#endif
@@ -16572,6 +16741,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INTARRAY   (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX    (-15) /* P4 is a pointer to an sqlite3_context object */
#define P4_TABLEREF   (-16) /* Like P4_TABLE, but reference counted */
+
#define P4_SUBRTNSIG  (-17) /* P4 is a SubrtnSig pointer */

/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -16663,16 +16833,16 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_RowSetTest     47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
#define OP_Program        48 /* jump0                                      */
#define OP_FkIfZero       49 /* jump, synopsis: if fkctr[P1]==0 goto P2    */
-
#define OP_IsNull         50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-
#define OP_NotNull        51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-
#define OP_Ne             52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
-
#define OP_Eq             53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
-
#define OP_Gt             54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
-
#define OP_Le             55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
-
#define OP_Lt             56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
-
#define OP_Ge             57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
-
#define OP_ElseEq         58 /* jump, same as TK_ESCAPE                    */
-
#define OP_IfPos          59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+
#define OP_IfPos          50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+
#define OP_IsNull         51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+
#define OP_NotNull        52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+
#define OP_Ne             53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
+
#define OP_Eq             54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
+
#define OP_Gt             55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
+
#define OP_Le             56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
+
#define OP_Lt             57 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
+
#define OP_Ge             58 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
+
#define OP_ElseEq         59 /* jump, same as TK_ESCAPE                    */
#define OP_IfNotZero      60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
#define OP_DecrJumpZero   61 /* jump, synopsis: if (--r[P1])==0 goto P2    */
#define OP_IncrVacuum     62 /* jump                                       */
@@ -16715,23 +16885,23 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_ReadCookie     99
#define OP_SetCookie     100
#define OP_ReopenIdx     101 /* synopsis: root=P2 iDb=P3                   */
-
#define OP_BitAnd        102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-
#define OP_BitOr         103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-
#define OP_ShiftLeft     104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-
#define OP_ShiftRight    105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-
#define OP_Add           106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-
#define OP_Subtract      107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-
#define OP_Multiply      108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-
#define OP_Divide        109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-
#define OP_Remainder     110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-
#define OP_Concat        111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-
#define OP_OpenRead      112 /* synopsis: root=P2 iDb=P3                   */
+
#define OP_OpenRead      102 /* synopsis: root=P2 iDb=P3                   */
+
#define OP_BitAnd        103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+
#define OP_BitOr         104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+
#define OP_ShiftLeft     105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+
#define OP_ShiftRight    106 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+
#define OP_Add           107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+
#define OP_Subtract      108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+
#define OP_Multiply      109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+
#define OP_Divide        110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+
#define OP_Remainder     111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+
#define OP_Concat        112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
#define OP_OpenWrite     113 /* synopsis: root=P2 iDb=P3                   */
-
#define OP_BitNot        114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-
#define OP_OpenDup       115
+
#define OP_OpenDup       114
+
#define OP_BitNot        115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2                       */
-
#define OP_String8       117 /* same as TK_STRING, synopsis: r[P2]='P4'    */
-
#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2                       */
+
#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2                       */
+
#define OP_String8       118 /* same as TK_STRING, synopsis: r[P2]='P4'    */
#define OP_SorterOpen    119
#define OP_SequenceTest  120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2   */
#define OP_OpenPseudo    121 /* synopsis: P3 columns in r[P2]              */
@@ -16766,8 +16936,8 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_LoadAnalysis  150
#define OP_DropTable     151
#define OP_DropIndex     152
-
#define OP_Real          153 /* same as TK_FLOAT, synopsis: r[P2]=P4       */
-
#define OP_DropTrigger   154
+
#define OP_DropTrigger   153
+
#define OP_Real          154 /* same as TK_FLOAT, synopsis: r[P2]=P4       */
#define OP_IntegrityCk   155
#define OP_RowSetAdd     156 /* synopsis: rowset(P1)=r[P2]                 */
#define OP_Param         157
@@ -16823,20 +16993,20 @@ typedef struct VdbeOpList VdbeOpList;
/*  24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
/*  32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\
/*  40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
-
/*  48 */ 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-
/*  56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
+
/*  48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
+
/*  56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\
/*  64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
/*  72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
/*  80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
/*  88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
-
/*  96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\
+
/*  96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
-
/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
+
/* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\
/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-
/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
+
/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\
/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
@@ -17897,6 +18067,7 @@ struct sqlite3 {
#define SQLITE_Coroutines     0x02000000 /* Co-routines for subqueries */
#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
#define SQLITE_OnePass        0x08000000 /* Single-pass DELETE and UPDATE */
+
#define SQLITE_OrderBySubq    0x10000000 /* ORDER BY in subquery helps outer */
#define SQLITE_AllOpts        0xffffffff /* All optimizations */

/*
@@ -18884,9 +19055,15 @@ struct AggInfo {
** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
** The assert()s that are part of this macro verify that constraint.
*/
+
#ifndef NDEBUG
#define AggInfoColumnReg(A,I)  (assert((A)->iFirstReg),(A)->iFirstReg+(I))
#define AggInfoFuncReg(A,I)    \
                      (assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))
+
#else
+
#define AggInfoColumnReg(A,I)  ((A)->iFirstReg+(I))
+
#define AggInfoFuncReg(A,I)    \
+
                      ((A)->iFirstReg+(A)->nColumn+(I))
+
#endif

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
@@ -19067,7 +19244,7 @@ struct Expr {
#define EP_IsTrue   0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse  0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL  0x40000000 /* Originates from sqlite_schema */
-
               /*   0x80000000 // Available */
+
#define EP_SubtArg  0x80000000 /* Is argument to SQLITE_SUBTYPE function */

/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
@@ -19239,6 +19416,16 @@ struct IdList {
#define EU4_EXPR   2   /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */

/*
+
** Details of the implementation of a subquery.
+
*/
+
struct Subquery {
+
  Select *pSelect;  /* A SELECT statement used in place of a table name */
+
  int addrFillSub;  /* Address of subroutine to initialize a subquery */
+
  int regReturn;    /* Register holding return address of addrFillSub */
+
  int regResult;    /* Registers holding results of a co-routine */
+
};
+

+
/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
**
@@ -19250,29 +19437,40 @@ struct IdList {
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
**
-
** Union member validity:
+
** Aggressive use of "union" helps keep the size of the object small.  This
+
** has been shown to boost performance, in addition to saving memory.
+
** Access to union elements is gated by the following rules which should
+
** always be checked, either by an if-statement or by an assert().
**
-
**    u1.zIndexedBy      fg.isIndexedBy && !fg.isTabFunc
-
**    u1.pFuncArg        fg.isTabFunc   && !fg.isIndexedBy
+
**    Field              Only access if this is true
+
**    ---------------    -----------------------------------
+
**    u1.zIndexedBy      fg.isIndexedBy
+
**    u1.pFuncArg        fg.isTabFunc
**    u1.nRow            !fg.isTabFunc  && !fg.isIndexedBy
**
-
**    u2.pIBIndex        fg.isIndexedBy && !fg.isCte
-
**    u2.pCteUse         fg.isCte       && !fg.isIndexedBy
+
**    u2.pIBIndex        fg.isIndexedBy
+
**    u2.pCteUse         fg.isCte
+
**
+
**    u3.pOn             !fg.isUsing
+
**    u3.pUsing          fg.isUsing
+
**
+
**    u4.zDatabase       !fg.fixedSchema && !fg.isSubquery
+
**    u4.pSchema         fg.fixedSchema
+
**    u4.pSubq           fg.isSubquery
+
**
+
** See also the sqlite3SrcListDelete() routine for assert() statements that
+
** check invariants on the fields of this object, especially the flags
+
** inside the fg struct.
*/
struct SrcItem {
-
  Schema *pSchema;  /* Schema to which this item is fixed */
-
  char *zDatabase;  /* Name of database holding this table */
  char *zName;      /* Name of the table */
  char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
-
  Table *pTab;      /* An SQL table corresponding to zName */
-
  Select *pSelect;  /* A SELECT statement used in place of a table name */
-
  int addrFillSub;  /* Address of subroutine to manifest a subquery */
-
  int regReturn;    /* Register holding return address of addrFillSub */
-
  int regResult;    /* Registers holding results of a co-routine */
+
  Table *pSTab;     /* Table object for zName. Mnemonic: Srcitem-TABle */
  struct {
    u8 jointype;      /* Type of join between this table and the previous */
    unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
    unsigned isIndexedBy :1;   /* True if there is an INDEXED BY clause */
+
    unsigned isSubquery :1;    /* True if this term is a subquery */
    unsigned isTabFunc :1;     /* True if table-valued-function syntax */
    unsigned isCorrelated :1;  /* True if sub-query is correlated */
    unsigned isMaterialized:1; /* This is a materialized view */
@@ -19286,12 +19484,10 @@ struct SrcItem {
    unsigned isSynthUsing :1;  /* u3.pUsing is synthesized from NATURAL */
    unsigned isNestedFrom :1;  /* pSelect is a SF_NestedFrom subquery */
    unsigned rowidUsed :1;     /* The ROWID of this table is referenced */
+
    unsigned fixedSchema :1;   /* Uses u4.pSchema, not u4.zDatabase */
+
    unsigned hadSchema :1;     /* Had u4.zDatabase before u4.pSchema */
  } fg;
  int iCursor;      /* The VDBE cursor number used to access this table */
-
  union {
-
    Expr *pOn;        /* fg.isUsing==0 =>  The ON clause of a join */
-
    IdList *pUsing;   /* fg.isUsing==1 =>  The USING clause of a join */
-
  } u3;
  Bitmask colUsed;  /* Bit N set if column N used. Details above for N>62 */
  union {
    char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */
@@ -19302,6 +19498,15 @@ struct SrcItem {
    Index *pIBIndex;  /* Index structure corresponding to u1.zIndexedBy */
    CteUse *pCteUse;  /* CTE Usage info when fg.isCte is true */
  } u2;
+
  union {
+
    Expr *pOn;        /* fg.isUsing==0 =>  The ON clause of a join */
+
    IdList *pUsing;   /* fg.isUsing==1 =>  The USING clause of a join */
+
  } u3;
+
  union {
+
    Schema *pSchema;  /* Schema to which this item is fixed */
+
    char *zDatabase;  /* Name of database holding this table */
+
    Subquery *pSubq;  /* Description of a subquery */
+
  } u4;
};

/*
@@ -19433,7 +19638,7 @@ struct NameContext {
#define NC_UUpsert   0x000200 /* True if uNC.pUpsert is used */
#define NC_UBaseReg  0x000400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen.  See note above */
-
#define NC_Complex   0x002000 /* True if a function or subquery seen */
+
/*                   0x002000 // available for reuse */
#define NC_AllowWin  0x004000 /* Window functions are allowed here */
#define NC_HasWin    0x008000 /* One or more window functions seen */
#define NC_IsDDL     0x010000 /* Resolving names in a CREATE statement */
@@ -19561,8 +19766,10 @@ struct Select {
#define SF_UpdateFrom   0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated   0x20000000 /* True if references the outer context */

-
/* True if S exists and has SF_NestedFrom */
-
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
+
/* True if SrcItem X is a subquery that has SF_NestedFrom */
+
#define IsNestedFrom(X) \
+
   ((X)->fg.isSubquery && \
+
    ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)

/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -19592,7 +19799,11 @@ struct Select {
**     SRT_Set         The result must be a single column.  Store each
**                     row of result as the key in table pDest->iSDParm.
**                     Apply the affinity pDest->affSdst before storing
-
**                     results.  Used to implement "IN (SELECT ...)".
+
**                     results.  if pDest->iSDParm2 is positive, then it is
+
**                     a register holding a Bloom filter for the IN operator
+
**                     that should be populated in addition to the
+
**                     pDest->iSDParm table.  This SRT is used to
+
**                     implement "IN (SELECT ...)".
**
**     SRT_EphemTab    Create an temporary table pDest->iSDParm and store
**                     the result there. The cursor is left open after
@@ -19800,6 +20011,7 @@ struct Parse {
  u8 prepFlags;        /* SQLITE_PREPARE_* flags */
  u8 withinRJSubrtn;   /* Nesting level for RIGHT JOIN body subroutines */
  u8 bHasWith;         /* True if statement contains WITH */
+
  u8 mSubrtnSig;       /* mini Bloom filter on available SubrtnSig.selId */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
  u8 earlyCleanup;     /* OOM inside sqlite3ParserAddCleanup() */
#endif
@@ -20095,7 +20307,7 @@ struct Returning {
};

/*
-
** An objected used to accumulate the text of a string where we
+
** An object used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct sqlite3_str {
@@ -20109,7 +20321,7 @@ struct sqlite3_str {
};
#define SQLITE_PRINTF_INTERNAL 0x01  /* Internal-use-only converters allowed */
#define SQLITE_PRINTF_SQLFUNC  0x02  /* SQL function arguments to VXPrintf */
-
#define SQLITE_PRINTF_MALLOCED 0x04  /* True if xText is allocated space */
+
#define SQLITE_PRINTF_MALLOCED 0x04  /* True if zText is allocated space */

#define isMalloced(X)  (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)

@@ -20187,7 +20399,6 @@ struct Sqlite3Config {
  u8 bUseCis;                       /* Use covering indices for full-scans */
  u8 bSmallMalloc;                  /* Avoid large memory allocations if true */
  u8 bExtraSchemaChecks;            /* Verify type,name,tbl_name in schema */
-
  u8 bUseLongDouble;                /* Make use of long double */
#ifdef SQLITE_DEBUG
  u8 bJsonSelfcheck;                /* Double-check JSON parsing */
#endif
@@ -20563,15 +20774,6 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
#endif

/*
-
** The ctype.h header is needed for non-ASCII systems.  It is also
-
** needed by FTS3 when FTS3 is included in the amalgamation.
-
*/
-
#if !defined(SQLITE_ASCII) || \
-
    (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
-
# include <ctype.h>
-
#endif
-

-
/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
** sqlite versions only work for ASCII characters, regardless of locale.
@@ -20949,6 +21151,9 @@ SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
+
SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3*,Subquery*);
+
SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3*,SrcItem*);
+
SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(Parse*, SrcItem*, Select*, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
@@ -20998,6 +21203,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
+
SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
@@ -21060,7 +21266,7 @@ SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,i
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
#endif
-
SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*);
+
SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
@@ -21188,7 +21394,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
#ifndef SQLITE_OMIT_UTF16
-
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
+
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar);
#endif
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
@@ -22174,6 +22380,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
  "ENABLE_OFFSET_SQL_FUNC",
#endif
+
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
+
  "ENABLE_ORDERED_SET_AGGREGATES",
+
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
@@ -22921,7 +23130,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
   0,                         /* bSmallMalloc */
   1,                         /* bExtraSchemaChecks */
-
   sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
#ifdef SQLITE_DEBUG
   0,                         /* bJsonSelfcheck */
#endif
@@ -23644,6 +23852,7 @@ struct PreUpdate {
  Mem *aNew;                      /* Array of new.* values */
  Table *pTab;                    /* Schema object being updated */
  Index *pPk;                     /* PK index if pTab is WITHOUT ROWID */
+
  sqlite3_value **apDflt;         /* Array of default values, if required */
};

/*
@@ -24490,8 +24699,8 @@ static void computeJD(DateTime *p){
    Y--;
    M += 12;
  }
-
  A = Y/100;
-
  B = 2 - A + (A/4);
+
  A = (Y+4800)/100;
+
  B = 38 - A + (A/4);
  X1 = 36525*(Y+4716)/100;
  X2 = 306001*(M+1)/10000;
  p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
@@ -24675,7 +24884,7 @@ static int validJulianDay(sqlite3_int64 iJD){
** Compute the Year, Month, and Day from the julian day number.
*/
static void computeYMD(DateTime *p){
-
  int Z, A, B, C, D, E, X1;
+
  int Z, alpha, A, B, C, D, E, X1;
  if( p->validYMD ) return;
  if( !p->validJD ){
    p->Y = 2000;
@@ -24686,8 +24895,8 @@ static void computeYMD(DateTime *p){
    return;
  }else{
    Z = (int)((p->iJD + 43200000)/86400000);
-
    A = (int)((Z - 1867216.25)/36524.25);
-
    A = Z + 1 + A - (A/4);
+
    alpha = (int)((Z + 32044.75)/36524.25) - 52;
+
    A = Z + 1 + alpha - ((alpha+100)/4) + 25;
    B = A + 1524;
    C = (int)((B - 122.1)/365.25);
    D = (36525*(C&32767))/100;
@@ -24886,8 +25095,8 @@ static const struct {
  /* 1 */ { 6, "minute",   7.7379e+12,        60.0  },
  /* 2 */ { 4, "hour",     1.2897e+11,      3600.0  },
  /* 3 */ { 3, "day",      5373485.0,      86400.0  },
-
  /* 4 */ { 5, "month",    176546.0,  30.0*86400.0  },
-
  /* 5 */ { 4, "year",     14713.0,  365.0*86400.0  },
+
  /* 4 */ { 5, "month",    176546.0,     2592000.0  },
+
  /* 5 */ { 4, "year",     14713.0,     31536000.0  },
};

/*
@@ -29089,16 +29298,29 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
+
**
+
** Because these routines raise false-positive alerts in TSAN, disable
+
** them (make them always return 1) when compiling with TSAN.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+
# if defined(__has_feature)
+
#   if __has_feature(thread_sanitizer)
+
      p = 0;
+
#   endif
+
# endif
  assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
  return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+
# if defined(__has_feature)
+
#   if __has_feature(thread_sanitizer)
+
      p = 0;
+
#   endif
+
# endif
  assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
  return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
-
#endif
+
#endif /* NDEBUG */

#endif /* !defined(SQLITE_MUTEX_OMIT) */

@@ -31986,16 +32208,19 @@ SQLITE_API void sqlite3_str_vappendf(
        if( pItem->zAlias && !flag_altform2 ){
          sqlite3_str_appendall(pAccum, pItem->zAlias);
        }else if( pItem->zName ){
-
          if( pItem->zDatabase ){
-
            sqlite3_str_appendall(pAccum, pItem->zDatabase);
+
          if( pItem->fg.fixedSchema==0
+
           && pItem->fg.isSubquery==0
+
           && pItem->u4.zDatabase!=0
+
          ){
+
            sqlite3_str_appendall(pAccum, pItem->u4.zDatabase);
            sqlite3_str_append(pAccum, ".", 1);
          }
          sqlite3_str_appendall(pAccum, pItem->zName);
        }else if( pItem->zAlias ){
          sqlite3_str_appendall(pAccum, pItem->zAlias);
-
        }else{
-
          Select *pSel = pItem->pSelect;
-
          assert( pSel!=0 ); /* Because of tag-20240424-1 */
+
        }else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */
+
          Select *pSel = pItem->u4.pSubq->pSelect;
+
          assert( pSel!=0 );
          if( pSel->selFlags & SF_NestedFrom ){
            sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
          }else if( pSel->selFlags & SF_MultiValue ){
@@ -32777,9 +33002,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
    sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
    x.printfFlags |= SQLITE_PRINTF_INTERNAL;
    sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
-
    if( pItem->pTab ){
+
    if( pItem->pSTab ){
      sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
-
           pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab,
+
           pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab,
           pItem->colUsed,
           pItem->fg.rowidUsed ? "+rowid" : "");
    }
@@ -32810,25 +33035,30 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
    if( pItem->fg.viaCoroutine )   sqlite3_str_appendf(&x, " viaCoroutine");
    if( pItem->fg.notCte )         sqlite3_str_appendf(&x, " notCte");
    if( pItem->fg.isNestedFrom )   sqlite3_str_appendf(&x, " isNestedFrom");
+
    if( pItem->fg.fixedSchema )    sqlite3_str_appendf(&x, " fixedSchema");
+
    if( pItem->fg.hadSchema )      sqlite3_str_appendf(&x, " hadSchema");
+
    if( pItem->fg.isSubquery )     sqlite3_str_appendf(&x, " isSubquery");

    sqlite3StrAccumFinish(&x);
    sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
    n = 0;
-
    if( pItem->pSelect ) n++;
+
    if( pItem->fg.isSubquery ) n++;
    if( pItem->fg.isTabFunc ) n++;
    if( pItem->fg.isUsing ) n++;
    if( pItem->fg.isUsing ){
      sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
    }
-
    if( pItem->pSelect ){
-
      sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
-
      if( pItem->pTab ){
-
        Table *pTab = pItem->pTab;
+
    if( pItem->fg.isSubquery ){
+
      assert( n==1 );
+
      if( pItem->pSTab ){
+
        Table *pTab = pItem->pSTab;
        sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
      }
-
      assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
-
      sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
+
      assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
+
      sqlite3TreeViewPush(&pView, 0);
+
      sqlite3TreeViewLine(pView, "SUBQUERY");
      sqlite3TreeViewPop(&pView);
+
      sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);
    }
    if( pItem->fg.isTabFunc ){
      sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
@@ -32870,7 +33100,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
      n = 1000;
    }else{
      n = 0;
-
      if( p->pSrc && p->pSrc->nSrc ) n++;
+
      if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++;
      if( p->pWhere ) n++;
      if( p->pGroupBy ) n++;
      if( p->pHaving ) n++;
@@ -32896,7 +33126,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
      sqlite3TreeViewPop(&pView);
    }
#endif
-
    if( p->pSrc && p->pSrc->nSrc ){
+
    if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){
      sqlite3TreeViewPush(&pView, (n--)>0);
      sqlite3TreeViewLine(pView, "FROM");
      sqlite3TreeViewSrcList(pView, p->pSrc);
@@ -33404,7 +33634,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
        case OE_Ignore:     zType = "ignore";    break;
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
-
      sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
+
      sqlite3TreeViewLine(pView, "RAISE %s", zType);
+
      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
      break;
    }
#endif
@@ -33484,9 +33715,10 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
    sqlite3TreeViewLine(pView, "%s", zLabel);
    for(i=0; i<pList->nExpr; i++){
      int j = pList->a[i].u.x.iOrderByCol;
+
      u8 sortFlags = pList->a[i].fg.sortFlags;
      char *zName = pList->a[i].zEName;
      int moreToFollow = i<pList->nExpr - 1;
-
      if( j || zName ){
+
      if( j || zName || sortFlags ){
        sqlite3TreeViewPush(&pView, moreToFollow);
        moreToFollow = 0;
        sqlite3TreeViewLine(pView, 0);
@@ -33507,13 +33739,18 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
          }
        }
        if( j ){
-
          fprintf(stdout, "iOrderByCol=%d", j);
+
          fprintf(stdout, "iOrderByCol=%d ", j);
+
        }
+
        if( sortFlags & KEYINFO_ORDER_DESC ){
+
          fprintf(stdout, "DESC ");
+
        }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){
+
          fprintf(stdout, "NULLS-LAST");
        }
        fprintf(stdout, "\n");
        fflush(stdout);
      }
      sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
-
      if( j || zName ){
+
      if( j || zName || sortFlags ){
        sqlite3TreeViewPop(&pView);
      }
    }
@@ -34476,7 +34713,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
  c = *(zIn++);                                            \
  if( c>=0xc0 ){                                           \
    c = sqlite3Utf8Trans1[c-0xc0];                         \
-
    while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){            \
+
    while( zIn<zTerm && (*zIn & 0xc0)==0x80 ){             \
      c = (c<<6) + (0x3f & *(zIn++));                      \
    }                                                      \
    if( c<0x80                                             \
@@ -34854,20 +35091,22 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
}

/*
-
** zIn is a UTF-16 encoded unicode string at least nChar characters long.
+
** zIn is a UTF-16 encoded unicode string at least nByte bytes long.
** Return the number of bytes in the first nChar unicode characters
-
** in pZ.  nChar must be non-negative.
+
** in pZ.  nChar must be non-negative.  Surrogate pairs count as a single
+
** character.
*/
-
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
+
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nByte, int nChar){
  int c;
  unsigned char const *z = zIn;
+
  unsigned char const *zEnd = &z[nByte-1];
  int n = 0;

  if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++;
-
  while( n<nChar ){
+
  while( n<nChar && ALWAYS(z<=zEnd) ){
    c = z[0];
    z += 2;
-
    if( c>=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
+
    if( c>=0xd8 && c<0xdc && z<=zEnd && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
    n++;
  }
  return (int)(z-(unsigned char const *)zIn)
@@ -35448,6 +35687,8 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
  int eValid = 1;  /* True exponent is either not used or is well-formed */
  int nDigit = 0;  /* Number of digits processed */
  int eType = 1;   /* 1: pure integer,  2+: fractional  -1 or less: bad UTF16 */
+
  double rr[2];
+
  u64 s2;

  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
  *pResult = 0.0;   /* Default return value, in case of an error */
@@ -35559,68 +35800,41 @@ do_atof_calc:
    e++;
  }

-
  if( e==0 ){
-
    *pResult = s;
-
  }else if( sqlite3Config.bUseLongDouble ){
-
    LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
-
    if( e>0 ){
-
      while( e>=100  ){ e-=100; r *= 1.0e+100L; }
-
      while( e>=10   ){ e-=10;  r *= 1.0e+10L;  }
-
      while( e>=1    ){ e-=1;   r *= 1.0e+01L;  }
-
    }else{
-
      while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
-
      while( e<=-10  ){ e+=10;  r *= 1.0e-10L;  }
-
      while( e<=-1   ){ e+=1;   r *= 1.0e-01L;  }
-
    }
-
    assert( r>=0.0 );
-
    if( r>+1.7976931348623157081452742373e+308L ){
-
#ifdef INFINITY
-
      *pResult = +INFINITY;
-
#else
-
      *pResult = 1.0e308*10.0;
+
  rr[0] = (double)s;
+
  s2 = (u64)rr[0];
+
#if defined(_MSC_VER) && _MSC_VER<1700
+
  if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
#endif
-
    }else{
-
      *pResult = (double)r;
+
  rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
+
  if( e>0 ){
+
    while( e>=100  ){
+
      e -= 100;
+
      dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+
    }
+
    while( e>=10   ){
+
      e -= 10;
+
      dekkerMul2(rr, 1.0e+10, 0.0);
+
    }
+
    while( e>=1    ){
+
      e -= 1;
+
      dekkerMul2(rr, 1.0e+01, 0.0);
    }
  }else{
-
    double rr[2];
-
    u64 s2;
-
    rr[0] = (double)s;
-
    s2 = (u64)rr[0];
-
#if defined(_MSC_VER) && _MSC_VER<1700
-
    if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
-
#endif
-
    rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
-
    if( e>0 ){
-
      while( e>=100  ){
-
        e -= 100;
-
        dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
-
      }
-
      while( e>=10   ){
-
        e -= 10;
-
        dekkerMul2(rr, 1.0e+10, 0.0);
-
      }
-
      while( e>=1    ){
-
        e -= 1;
-
        dekkerMul2(rr, 1.0e+01, 0.0);
-
      }
-
    }else{
-
      while( e<=-100 ){
-
        e += 100;
-
        dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
-
      }
-
      while( e<=-10  ){
-
        e += 10;
-
        dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
-
      }
-
      while( e<=-1   ){
-
        e += 1;
-
        dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
-
      }
+
    while( e<=-100 ){
+
      e += 100;
+
      dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+
    }
+
    while( e<=-10  ){
+
      e += 10;
+
      dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+
    }
+
    while( e<=-1   ){
+
      e += 1;
+
      dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
    }
-
    *pResult = rr[0]+rr[1];
-
    if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
  }
+
  *pResult = rr[0]+rr[1];
+
  if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
  if( sign<0 ) *pResult = -*pResult;
  assert( !sqlite3IsNaN(*pResult) );

@@ -35924,10 +36138,13 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){
** Decode a floating-point value into an approximate decimal
** representation.
**
-
** Round the decimal representation to n significant digits if
-
** n is positive.  Or round to -n signficant digits after the
-
** decimal point if n is negative.  No rounding is performed if
-
** n is zero.
+
** If iRound<=0 then round to -iRound significant digits to the
+
** the left of the decimal point, or to a maximum of mxRound total
+
** significant digits.
+
**
+
** If iRound>0 round to min(iRound,mxRound) significant digits total.
+
**
+
** mxRound must be positive.
**
** The significant digits of the decimal representation are
** stored in p->z[] which is a often (but not always) a pointer
@@ -35938,8 +36155,11 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
  int i;
  u64 v;
  int e, exp = 0;
+
  double rr[2];
+

  p->isSpecial = 0;
  p->z = p->zBuf;
+
  assert( mxRound>0 );

  /* Convert negative numbers to positive.  Deal with Infinity, 0.0, and
  ** NaN. */
@@ -35966,62 +36186,45 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou

  /* Multiply r by powers of ten until it lands somewhere in between
  ** 1.0e+19 and 1.0e+17.
+
  **
+
  ** Use Dekker-style double-double computation to increase the
+
  ** precision.
+
  **
+
  ** The error terms on constants like 1.0e+100 computed using the
+
  ** decimal extension, for example as follows:
+
  **
+
  **   SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
  */
-
  if( sqlite3Config.bUseLongDouble ){
-
    LONGDOUBLE_TYPE rr = r;
-
    if( rr>=1.0e+19 ){
-
      while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
-
      while( rr>=1.0e+29L  ){ exp+=10;  rr *= 1.0e-10L;  }
-
      while( rr>=1.0e+19L  ){ exp++;    rr *= 1.0e-1L;   }
-
    }else{
-
      while( rr<1.0e-97L   ){ exp-=100; rr *= 1.0e+100L; }
-
      while( rr<1.0e+07L   ){ exp-=10;  rr *= 1.0e+10L;  }
-
      while( rr<1.0e+17L   ){ exp--;    rr *= 1.0e+1L;   }
+
  rr[0] = r;
+
  rr[1] = 0.0;
+
  if( rr[0]>9.223372036854774784e+18 ){
+
    while( rr[0]>9.223372036854774784e+118 ){
+
      exp += 100;
+
      dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+
    }
+
    while( rr[0]>9.223372036854774784e+28 ){
+
      exp += 10;
+
      dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+
    }
+
    while( rr[0]>9.223372036854774784e+18 ){
+
      exp += 1;
+
      dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
    }
-
    v = (u64)rr;
  }else{
-
    /* If high-precision floating point is not available using "long double",
-
    ** then use Dekker-style double-double computation to increase the
-
    ** precision.
-
    **
-
    ** The error terms on constants like 1.0e+100 computed using the
-
    ** decimal extension, for example as follows:
-
    **
-
    **   SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
-
    */
-
    double rr[2];
-
    rr[0] = r;
-
    rr[1] = 0.0;
-
    if( rr[0]>9.223372036854774784e+18 ){
-
      while( rr[0]>9.223372036854774784e+118 ){
-
        exp += 100;
-
        dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
-
      }
-
      while( rr[0]>9.223372036854774784e+28 ){
-
        exp += 10;
-
        dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
-
      }
-
      while( rr[0]>9.223372036854774784e+18 ){
-
        exp += 1;
-
        dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
-
      }
-
    }else{
-
      while( rr[0]<9.223372036854774784e-83  ){
-
        exp -= 100;
-
        dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
-
      }
-
      while( rr[0]<9.223372036854774784e+07  ){
-
        exp -= 10;
-
        dekkerMul2(rr, 1.0e+10, 0.0);
-
      }
-
      while( rr[0]<9.22337203685477478e+17  ){
-
        exp -= 1;
-
        dekkerMul2(rr, 1.0e+01, 0.0);
-
      }
+
    while( rr[0]<9.223372036854774784e-83  ){
+
      exp -= 100;
+
      dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+
    }
+
    while( rr[0]<9.223372036854774784e+07  ){
+
      exp -= 10;
+
      dekkerMul2(rr, 1.0e+10, 0.0);
+
    }
+
    while( rr[0]<9.22337203685477478e+17  ){
+
      exp -= 1;
+
      dekkerMul2(rr, 1.0e+01, 0.0);
    }
-
    v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
  }
-

+
  v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];

  /* Extract significant digits. */
  i = sizeof(p->zBuf)-1;
@@ -36792,104 +36995,6 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam
  return 0;
}

-
/*
-
** High-resolution hardware timer used for debugging and testing only.
-
*/
-
#if defined(VDBE_PROFILE)  \
-
 || defined(SQLITE_PERFORMANCE_TRACE) \
-
 || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-
/************** Include hwtime.h in the middle of util.c *********************/
-
/************** Begin file hwtime.h ******************************************/
-
/*
-
** 2008 May 27
-
**
-
** The author disclaims copyright to this source code.  In place of
-
** a legal notice, here is a blessing:
-
**
-
**    May you do good and not evil.
-
**    May you find forgiveness for yourself and forgive others.
-
**    May you share freely, never taking more than you give.
-
**
-
******************************************************************************
-
**
-
** This file contains inline asm code for retrieving "high-performance"
-
** counters for x86 and x86_64 class CPUs.
-
*/
-
#ifndef SQLITE_HWTIME_H
-
#define SQLITE_HWTIME_H
-

-
/*
-
** The following routine only works on Pentium-class (or newer) processors.
-
** It uses the RDTSC opcode to read the cycle count value out of the
-
** processor and returns that value.  This can be used for high-res
-
** profiling.
-
*/
-
#if !defined(__STRICT_ANSI__) && \
-
    (defined(__GNUC__) || defined(_MSC_VER)) && \
-
    (defined(i386) || defined(__i386__) || defined(_M_IX86))
-

-
  #if defined(__GNUC__)
-

-
  __inline__ sqlite_uint64 sqlite3Hwtime(void){
-
     unsigned int lo, hi;
-
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
-
     return (sqlite_uint64)hi << 32 | lo;
-
  }
-

-
  #elif defined(_MSC_VER)
-

-
  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
-
     __asm {
-
        rdtsc
-
        ret       ; return value at EDX:EAX
-
     }
-
  }
-

-
  #endif
-

-
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-

-
  __inline__ sqlite_uint64 sqlite3Hwtime(void){
-
     unsigned int lo, hi;
-
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
-
     return (sqlite_uint64)hi << 32 | lo;
-
  }
-

-
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-

-
  __inline__ sqlite_uint64 sqlite3Hwtime(void){
-
      unsigned long long retval;
-
      unsigned long junk;
-
      __asm__ __volatile__ ("\n\
-
          1:      mftbu   %1\n\
-
                  mftb    %L0\n\
-
                  mftbu   %0\n\
-
                  cmpw    %0,%1\n\
-
                  bne     1b"
-
                  : "=r" (retval), "=r" (junk));
-
      return retval;
-
  }
-

-
#else
-

-
  /*
-
  ** asm() is needed for hardware timing support.  Without asm(),
-
  ** disable the sqlite3Hwtime() routine.
-
  **
-
  ** sqlite3Hwtime() is only used for some obscure debugging
-
  ** and analysis configurations, not in any deliverable, so this
-
  ** should not be a great loss.
-
  */
-
SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-

-
#endif
-

-
#endif /* !defined(SQLITE_HWTIME_H) */
-

-
/************** End of hwtime.h **********************************************/
-
/************** Continuing where we left off in util.c ***********************/
-
#endif
-

/************** End of util.c ************************************************/
/************** Begin file hash.c ********************************************/
/*
@@ -37227,16 +37332,16 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
    /*  47 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
    /*  48 */ "Program"          OpHelp(""),
    /*  49 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
-
    /*  50 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
-
    /*  51 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
-
    /*  52 */ "Ne"               OpHelp("IF r[P3]!=r[P1]"),
-
    /*  53 */ "Eq"               OpHelp("IF r[P3]==r[P1]"),
-
    /*  54 */ "Gt"               OpHelp("IF r[P3]>r[P1]"),
-
    /*  55 */ "Le"               OpHelp("IF r[P3]<=r[P1]"),
-
    /*  56 */ "Lt"               OpHelp("IF r[P3]<r[P1]"),
-
    /*  57 */ "Ge"               OpHelp("IF r[P3]>=r[P1]"),
-
    /*  58 */ "ElseEq"           OpHelp(""),
-
    /*  59 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+
    /*  50 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+
    /*  51 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
+
    /*  52 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
+
    /*  53 */ "Ne"               OpHelp("IF r[P3]!=r[P1]"),
+
    /*  54 */ "Eq"               OpHelp("IF r[P3]==r[P1]"),
+
    /*  55 */ "Gt"               OpHelp("IF r[P3]>r[P1]"),
+
    /*  56 */ "Le"               OpHelp("IF r[P3]<=r[P1]"),
+
    /*  57 */ "Lt"               OpHelp("IF r[P3]<r[P1]"),
+
    /*  58 */ "Ge"               OpHelp("IF r[P3]>=r[P1]"),
+
    /*  59 */ "ElseEq"           OpHelp(""),
    /*  60 */ "IfNotZero"        OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
    /*  61 */ "DecrJumpZero"     OpHelp("if (--r[P1])==0 goto P2"),
    /*  62 */ "IncrVacuum"       OpHelp(""),
@@ -37279,23 +37384,23 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
    /*  99 */ "ReadCookie"       OpHelp(""),
    /* 100 */ "SetCookie"        OpHelp(""),
    /* 101 */ "ReopenIdx"        OpHelp("root=P2 iDb=P3"),
-
    /* 102 */ "BitAnd"           OpHelp("r[P3]=r[P1]&r[P2]"),
-
    /* 103 */ "BitOr"            OpHelp("r[P3]=r[P1]|r[P2]"),
-
    /* 104 */ "ShiftLeft"        OpHelp("r[P3]=r[P2]<<r[P1]"),
-
    /* 105 */ "ShiftRight"       OpHelp("r[P3]=r[P2]>>r[P1]"),
-
    /* 106 */ "Add"              OpHelp("r[P3]=r[P1]+r[P2]"),
-
    /* 107 */ "Subtract"         OpHelp("r[P3]=r[P2]-r[P1]"),
-
    /* 108 */ "Multiply"         OpHelp("r[P3]=r[P1]*r[P2]"),
-
    /* 109 */ "Divide"           OpHelp("r[P3]=r[P2]/r[P1]"),
-
    /* 110 */ "Remainder"        OpHelp("r[P3]=r[P2]%r[P1]"),
-
    /* 111 */ "Concat"           OpHelp("r[P3]=r[P2]+r[P1]"),
-
    /* 112 */ "OpenRead"         OpHelp("root=P2 iDb=P3"),
+
    /* 102 */ "OpenRead"         OpHelp("root=P2 iDb=P3"),
+
    /* 103 */ "BitAnd"           OpHelp("r[P3]=r[P1]&r[P2]"),
+
    /* 104 */ "BitOr"            OpHelp("r[P3]=r[P1]|r[P2]"),
+
    /* 105 */ "ShiftLeft"        OpHelp("r[P3]=r[P2]<<r[P1]"),
+
    /* 106 */ "ShiftRight"       OpHelp("r[P3]=r[P2]>>r[P1]"),
+
    /* 107 */ "Add"              OpHelp("r[P3]=r[P1]+r[P2]"),
+
    /* 108 */ "Subtract"         OpHelp("r[P3]=r[P2]-r[P1]"),
+
    /* 109 */ "Multiply"         OpHelp("r[P3]=r[P1]*r[P2]"),
+
    /* 110 */ "Divide"           OpHelp("r[P3]=r[P2]/r[P1]"),
+
    /* 111 */ "Remainder"        OpHelp("r[P3]=r[P2]%r[P1]"),
+
    /* 112 */ "Concat"           OpHelp("r[P3]=r[P2]+r[P1]"),
    /* 113 */ "OpenWrite"        OpHelp("root=P2 iDb=P3"),
-
    /* 114 */ "BitNot"           OpHelp("r[P2]= ~r[P1]"),
-
    /* 115 */ "OpenDup"          OpHelp(""),
+
    /* 114 */ "OpenDup"          OpHelp(""),
+
    /* 115 */ "BitNot"           OpHelp("r[P2]= ~r[P1]"),
    /* 116 */ "OpenAutoindex"    OpHelp("nColumn=P2"),
-
    /* 117 */ "String8"          OpHelp("r[P2]='P4'"),
-
    /* 118 */ "OpenEphemeral"    OpHelp("nColumn=P2"),
+
    /* 117 */ "OpenEphemeral"    OpHelp("nColumn=P2"),
+
    /* 118 */ "String8"          OpHelp("r[P2]='P4'"),
    /* 119 */ "SorterOpen"       OpHelp(""),
    /* 120 */ "SequenceTest"     OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
    /* 121 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
@@ -37330,8 +37435,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
    /* 150 */ "LoadAnalysis"     OpHelp(""),
    /* 151 */ "DropTable"        OpHelp(""),
    /* 152 */ "DropIndex"        OpHelp(""),
-
    /* 153 */ "Real"             OpHelp("r[P2]=P4"),
-
    /* 154 */ "DropTrigger"      OpHelp(""),
+
    /* 153 */ "DropTrigger"      OpHelp(""),
+
    /* 154 */ "Real"             OpHelp("r[P2]=P4"),
    /* 155 */ "IntegrityCk"      OpHelp(""),
    /* 156 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
    /* 157 */ "Param"            OpHelp(""),
@@ -38680,7 +38785,7 @@ static pid_t randomnessPid = 0;
#define UNIXFILE_EXCL        0x01     /* Connections from one process only */
#define UNIXFILE_RDONLY      0x02     /* Connection is read only */
#define UNIXFILE_PERSIST_WAL 0x04     /* Persistent WAL mode */
-
#ifndef SQLITE_DISABLE_DIRSYNC
+
#if !defined(SQLITE_DISABLE_DIRSYNC) && !defined(_AIX)
# define UNIXFILE_DIRSYNC    0x08     /* Directory sync needed */
#else
# define UNIXFILE_DIRSYNC    0x00
@@ -40637,26 +40742,22 @@ static int nolockClose(sqlite3_file *id) {

/*
** This routine checks if there is a RESERVED lock held on the specified
-
** file by this or any other process. If such a lock is held, set *pResOut
-
** to a non-zero value otherwise *pResOut is set to zero.  The return value
-
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-
**
-
** In dotfile locking, either a lock exists or it does not.  So in this
-
** variation of CheckReservedLock(), *pResOut is set to true if any lock
-
** is held on the file and false if the file is unlocked.
+
** file by this or any other process. If the caller holds a SHARED
+
** or greater lock when it is called, then it is assumed that no other
+
** client may hold RESERVED. Or, if the caller holds no lock, then it
+
** is assumed another client holds RESERVED if the lock-file exists.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
-
  int rc = SQLITE_OK;
-
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;
-

  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

-
  assert( pFile );
-
  reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
-
  OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
-
  *pResOut = reserved;
-
  return rc;
+
  if( pFile->eFileLock>=SHARED_LOCK ){
+
    *pResOut = 0;
+
  }else{
+
    *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
+
  }
+
  OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
+
  return SQLITE_OK;
}

/*
@@ -40826,54 +40927,33 @@ static int robust_flock(int fd, int op){
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
-
  int rc = SQLITE_OK;
-
  int reserved = 0;
+
#ifdef SQLITE_DEBUG
  unixFile *pFile = (unixFile*)id;
+
#else
+
  UNUSED_PARAMETER(id);
+
#endif

  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

  assert( pFile );
+
  assert( pFile->eFileLock<=SHARED_LOCK );

-
  /* Check if a thread in this process holds such a lock */
-
  if( pFile->eFileLock>SHARED_LOCK ){
-
    reserved = 1;
-
  }
-

-
  /* Otherwise see if some other process holds it. */
-
  if( !reserved ){
-
    /* attempt to get the lock */
-
    int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
-
    if( !lrc ){
-
      /* got the lock, unlock it */
-
      lrc = robust_flock(pFile->h, LOCK_UN);
-
      if ( lrc ) {
-
        int tErrno = errno;
-
        /* unlock failed with an error */
-
        lrc = SQLITE_IOERR_UNLOCK;
-
        storeLastErrno(pFile, tErrno);
-
        rc = lrc;
-
      }
-
    } else {
-
      int tErrno = errno;
-
      reserved = 1;
-
      /* someone else might have it reserved */
-
      lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-
      if( IS_LOCK_ERROR(lrc) ){
-
        storeLastErrno(pFile, tErrno);
-
        rc = lrc;
-
      }
-
    }
-
  }
-
  OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
+
  /* The flock VFS only ever takes exclusive locks (see function flockLock).
+
  ** Therefore, if this connection is holding any lock at all, no other
+
  ** connection may be holding a RESERVED lock. So set *pResOut to 0
+
  ** in this case.
+
  **
+
  ** Or, this connection may be holding no lock. In that case, set *pResOut to
+
  ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the
+
  ** db in order to roll the hot journal back. If there is another connection
+
  ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to
+
  ** the user. With other VFS, we try to avoid this, in order to allow a reader
+
  ** to proceed while a writer is preparing its transaction. But that won't
+
  ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is
+
  ** not a problem in this case.  */
+
  *pResOut = 0;

-
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-
  if( (rc & 0xff) == SQLITE_IOERR ){
-
    rc = SQLITE_OK;
-
    reserved=1;
-
  }
-
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-
  *pResOut = reserved;
-
  return rc;
+
  return SQLITE_OK;
}

/*
@@ -42345,7 +42425,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){

/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
-
#ifndef SQLITE_OMIT_WAL
+
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
 static int unixFcntlExternalReader(unixFile*, int*);
#endif

@@ -42472,7 +42552,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */

    case SQLITE_FCNTL_EXTERNAL_READER: {
-
#ifndef SQLITE_OMIT_WAL
+
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
      return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
#else
      *(int*)pArg = 0;
@@ -42561,7 +42641,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
      pFile->sectorSize = fsInfo.f_bsize;
      pFile->deviceCharacteristics =
        /* full bitset of atomics from max sector size and smaller */
-
        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+
        (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
                                      ** so it is ordered */
        0;
@@ -42569,7 +42649,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
      pFile->sectorSize = fsInfo.f_bsize;
      pFile->deviceCharacteristics =
        /* full bitset of atomics from max sector size and smaller */
-
        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+
        (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
                                      ** so it is ordered */
        0;
@@ -42645,7 +42725,7 @@ static int unixGetpagesize(void){

#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */

-
#ifndef SQLITE_OMIT_WAL
+
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)

/*
** Object used to represent an shared memory buffer.
@@ -54730,6 +54810,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
  pPgHdr->pData = pPage->pBuf;
  pPgHdr->pExtra = (void *)&pPgHdr[1];
  memset(pPgHdr->pExtra, 0, 8);
+
  assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) );
  pPgHdr->pCache = pCache;
  pPgHdr->pgno = pgno;
  pPgHdr->flags = PGHDR_CLEAN;
@@ -55476,7 +55557,8 @@ static int pcache1InitBulk(PCache1 *pCache){
    do{
      PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
      pX->page.pBuf = zBulk;
-
      pX->page.pExtra = &pX[1];
+
      pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+
      assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
      pX->isBulkLocal = 1;
      pX->isAnchor = 0;
      pX->pNext = pCache->pFree;
@@ -55613,7 +55695,8 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
    if( pPg==0 ) return 0;
    p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
    p->page.pBuf = pPg;
-
    p->page.pExtra = &p[1];
+
    p->page.pExtra = (u8*)p + ROUND8(sizeof(*p));
+
    assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) );
    p->isBulkLocal = 0;
    p->isAnchor = 0;
    p->pLruPrev = 0;           /* Initializing this saves a valgrind error */
@@ -61172,6 +61255,7 @@ static int pagerAcquireMapPage(
      return SQLITE_NOMEM_BKPT;
    }
    p->pExtra = (void *)&p[1];
+
    assert( EIGHT_BYTE_ALIGNMENT( p->pExtra ) );
    p->flags = PGHDR_MMAP;
    p->nRef = 1;
    p->pPager = pPager;
@@ -64955,7 +65039,7 @@ SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){
**    28: Checksum-2 (second part of checksum for first 24 bytes of header).
**
** Immediately following the wal-header are zero or more frames. Each
-
** frame consists of a 24-byte frame-header followed by a <page-size> bytes
+
** frame consists of a 24-byte frame-header followed by <page-size> bytes
** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
@@ -65452,6 +65536,7 @@ struct Wal {
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
  WalIndexHdr *pSnapshot;    /* Start transaction here if not NULL */
+
  int bGetSnapshot;          /* Transaction opened for sqlite3_get_snapshot() */
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  sqlite3 *db;
@@ -67344,7 +67429,7 @@ static int walHandleException(Wal *pWal){

/*
** Assert that the Wal.lockMask mask, which indicates the locks held
-
** by the connenction, is consistent with the Wal.readLock, Wal.writeLock
+
** by the connection, is consistent with the Wal.readLock, Wal.writeLock
** and Wal.ckptLock variables. To be used as:
**
**   assert( walAssertLockmask(pWal) );
@@ -68008,7 +68093,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
  SEH_INJECT_FAULT;
  if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
-
   && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
+
   && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
#endif
  ){
    /* The WAL has been completely backfilled (or it is empty).
@@ -69408,7 +69493,20 @@ SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
  Wal *pWal,
  sqlite3_snapshot *pSnapshot
){
-
  pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+
  if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){
+
    /* iVersion==0 means that this is a call to sqlite3_snapshot_get().  In
+
    ** this case set the bGetSnapshot flag so that if the call to
+
    ** sqlite3_snapshot_get() is about to read transaction on this wal
+
    ** file, it does not take read-lock 0 if the wal file has been completely
+
    ** checkpointed. Taking read-lock 0 would work, but then it would be
+
    ** possible for a subsequent writer to destroy the snapshot even while
+
    ** this connection is holding its read-transaction open. This is contrary
+
    ** to user expectations, so we avoid it by not taking read-lock 0. */
+
    pWal->bGetSnapshot = 1;
+
  }else{
+
    pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+
    pWal->bGetSnapshot = 0;
+
  }
}

/*
@@ -75289,6 +75387,25 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){
  return ROUND8(sizeof(BtCursor));
}

+
#ifdef SQLITE_DEBUG
+
/*
+
** Return true if and only if the Btree object will be automatically
+
** closed with the BtCursor closes.  This is used within assert() statements
+
** only.
+
*/
+
SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(
+
  Btree *pBtree,       /* the btree object */
+
  BtCursor *pCur       /* Corresponding cursor */
+
){
+
  BtShared *pBt = pBtree->pBt;
+
  if( (pBt->openFlags & BTREE_SINGLE)==0 ) return 0;
+
  if( pBt->pCursor!=pCur ) return 0;
+
  if( pCur->pNext!=0 ) return 0;
+
  if( pCur->pBtree!=pBtree ) return 0;
+
  return 1;
+
}
+
#endif
+

/*
** Initialize memory that will be converted into a BtCursor object.
**
@@ -76532,7 +76649,7 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
     && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
     && pIdxKey->errCode==SQLITE_OK
    ){
-
      pCur->curFlags &= ~BTCF_ValidOvfl;
+
      pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
      if( !pCur->pPage->isInit ){
        return SQLITE_CORRUPT_BKPT;
      }
@@ -78110,7 +78227,8 @@ static int rebuildPage(
  if( j>(u32)usableSize ){ j = 0; }
  memcpy(&pTmp[j], &aData[j], usableSize - j);

-
  for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i; k++){}
+
  assert( pCArray->ixNx[NB*2-1]>i );
+
  for(k=0; pCArray->ixNx[k]<=i; k++){}
  pSrcEnd = pCArray->apEnd[k];

  pData = pEnd;
@@ -78193,7 +78311,8 @@ static int pageInsertArray(
  u8 *pEnd;                       /* Maximum extent of cell data */
  assert( CORRUPT_DB || pPg->hdrOffset==0 );    /* Never called on page 1 */
  if( iEnd<=iFirst ) return 0;
-
  for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i ; k++){}
+
  assert( pCArray->ixNx[NB*2-1]>i );
+
  for(k=0; pCArray->ixNx[k]<=i ; k++){}
  pEnd = pCArray->apEnd[k];
  while( 1 /*Exit by break*/ ){
    int sz, rc;
@@ -78478,6 +78597,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
    b.szCell = &szCell;
    b.apEnd[0] = pPage->aDataEnd;
    b.ixNx[0] = 2;
+
    b.ixNx[NB*2-1] = 0x7fffffff;
    rc = rebuildPage(&b, 0, 1, pNew);
    if( NEVER(rc) ){
      releasePage(pNew);
@@ -78713,7 +78833,9 @@ static int balance_nonroot(
  CellArray b;                 /* Parsed information on cells being balanced */

  memset(abDone, 0, sizeof(abDone));
-
  memset(&b, 0, sizeof(b));
+
  assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) );
+
  memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0]));
+
  b.ixNx[NB*2-1] = 0x7fffffff;
  pBt = pParent->pBt;
  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -79304,7 +79426,8 @@ static int balance_nonroot(
    iOvflSpace += sz;
    assert( sz<=pBt->maxLocal+23 );
    assert( iOvflSpace <= (int)pBt->pageSize );
-
    for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
+
    assert( b.ixNx[NB*2-1]>j );
+
    for(k=0; b.ixNx[k]<=j; k++){}
    pSrcEnd = b.apEnd[k];
    if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
      rc = SQLITE_CORRUPT_BKPT;
@@ -84316,7 +84439,8 @@ static int valueFromFunction(
      goto value_from_function_out;
    }
    for(i=0; i<nVal; i++){
-
      rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
+
      rc = sqlite3Stat4ValueFromExpr(pCtx->pParse, pList->a[i].pExpr, aff,
+
                                     &apVal[i]);
      if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
    }
  }
@@ -86250,6 +86374,12 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
      if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
      break;
    }
+
    case P4_SUBRTNSIG: {
+
      SubrtnSig *pSig = (SubrtnSig*)p4;
+
      sqlite3DbFree(db, pSig->zAff);
+
      sqlite3DbFree(db, pSig);
+
      break;
+
    }
  }
}

@@ -86829,6 +86959,11 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
      zP4 = pOp->p4.pTab->zName;
      break;
    }
+
    case P4_SUBRTNSIG: {
+
      SubrtnSig *pSig = pOp->p4.pSubrtnSig;
+
      sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff);
+
      break;
+
    }
    default: {
      zP4 = pOp->p4.z;
    }
@@ -89338,7 +89473,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem
** We must use separate SQLITE_NOINLINE functions here, since otherwise
** optimizer code movement causes gcov to become very confused.
*/
-
#if  defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
static int SQLITE_NOINLINE doubleLt(double a, double b){ return a<b; }
static int SQLITE_NOINLINE doubleEq(double a, double b){ return a==b; }
#endif
@@ -89353,13 +89488,6 @@ SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){
    /* SQLite considers NaN to be a NULL. And all integer values are greater
    ** than NULL */
    return 1;
-
  }
-
  if( sqlite3Config.bUseLongDouble ){
-
    LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
-
    testcase( x<r );
-
    testcase( x>r );
-
    testcase( x==r );
-
    return (x<r) ? -1 : (x>r);
  }else{
    i64 y;
    if( r<-9223372036854775808.0 ) return +1;
@@ -90369,6 +90497,13 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
    }
    sqlite3DbNNFreeNN(db, preupdate.aNew);
  }
+
  if( preupdate.apDflt ){
+
    int i;
+
    for(i=0; i<pTab->nCol; i++){
+
      sqlite3ValueFree(preupdate.apDflt[i]);
+
    }
+
    sqlite3DbFree(db, preupdate.apDflt);
+
  }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */

@@ -91997,6 +92132,17 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
+
**
+
** (tag-20240917-01) If  vdbeUnbind(p,(u32)(i-1))  returns SQLITE_OK,
+
** that means all of the the following will be true:
+
**
+
**     p!=0
+
**     p->pVar!=0
+
**     i>0
+
**     i<=p->nVar
+
**
+
** An assert() is normally added after vdbeUnbind() to help static analyzers
+
** realize this.
*/
static int vdbeUnbind(Vdbe *p, unsigned int i){
  Mem *pVar;
@@ -92054,6 +92200,7 @@ static int bindText(

  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
+
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    if( zData!=0 ){
      pVar = &p->aVar[i-1];
      rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
@@ -92103,6 +92250,7 @@ SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
+
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
@@ -92116,6 +92264,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
+
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
@@ -92126,6 +92275,7 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
+
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
@@ -92141,6 +92291,7 @@ SQLITE_API int sqlite3_bind_pointer(
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
+
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
    sqlite3_mutex_leave(p->db->mutex);
  }else if( xDestructor ){
@@ -92222,6 +92373,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
+
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
#ifndef SQLITE_OMIT_INCRBLOB
    sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
@@ -92581,7 +92733,30 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
  if( iIdx==p->pTab->iPKey ){
    sqlite3VdbeMemSetInt64(pMem, p->iKey1);
  }else if( iIdx>=p->pUnpacked->nField ){
-
    *ppValue = (sqlite3_value *)columnNullValue();
+
    /* This occurs when the table has been extended using ALTER TABLE
+
    ** ADD COLUMN. The value to return is the default value of the column. */
+
    Column *pCol = &p->pTab->aCol[iIdx];
+
    if( pCol->iDflt>0 ){
+
      if( p->apDflt==0 ){
+
        int nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
+
        p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
+
        if( p->apDflt==0 ) goto preupdate_old_out;
+
      }
+
      if( p->apDflt[iIdx]==0 ){
+
        sqlite3_value *pVal = 0;
+
        Expr *pDflt;
+
        assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
+
        pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
+
        rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
+
        if( rc==SQLITE_OK && pVal==0 ){
+
          rc = SQLITE_CORRUPT_BKPT;
+
        }
+
        p->apDflt[iIdx] = pVal;
+
      }
+
      *ppValue = p->apDflt[iIdx];
+
    }else{
+
      *ppValue = (sqlite3_value *)columnNullValue();
+
    }
  }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
    if( pMem->flags & (MEM_Int|MEM_IntReal) ){
      testcase( pMem->flags & MEM_Int );
@@ -93135,6 +93310,104 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
/* #include "vdbeInt.h" */

/*
+
** High-resolution hardware timer used for debugging and testing only.
+
*/
+
#if defined(VDBE_PROFILE)  \
+
 || defined(SQLITE_PERFORMANCE_TRACE) \
+
 || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+
/************** Include hwtime.h in the middle of vdbe.c *********************/
+
/************** Begin file hwtime.h ******************************************/
+
/*
+
** 2008 May 27
+
**
+
** The author disclaims copyright to this source code.  In place of
+
** a legal notice, here is a blessing:
+
**
+
**    May you do good and not evil.
+
**    May you find forgiveness for yourself and forgive others.
+
**    May you share freely, never taking more than you give.
+
**
+
******************************************************************************
+
**
+
** This file contains inline asm code for retrieving "high-performance"
+
** counters for x86 and x86_64 class CPUs.
+
*/
+
#ifndef SQLITE_HWTIME_H
+
#define SQLITE_HWTIME_H
+

+
/*
+
** The following routine only works on Pentium-class (or newer) processors.
+
** It uses the RDTSC opcode to read the cycle count value out of the
+
** processor and returns that value.  This can be used for high-res
+
** profiling.
+
*/
+
#if !defined(__STRICT_ANSI__) && \
+
    (defined(__GNUC__) || defined(_MSC_VER)) && \
+
    (defined(i386) || defined(__i386__) || defined(_M_IX86))
+

+
  #if defined(__GNUC__)
+

+
  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+
     unsigned int lo, hi;
+
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+
     return (sqlite_uint64)hi << 32 | lo;
+
  }
+

+
  #elif defined(_MSC_VER)
+

+
  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+
     __asm {
+
        rdtsc
+
        ret       ; return value at EDX:EAX
+
     }
+
  }
+

+
  #endif
+

+
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
+

+
  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+
     unsigned int lo, hi;
+
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+
     return (sqlite_uint64)hi << 32 | lo;
+
  }
+

+
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
+

+
  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+
      unsigned long long retval;
+
      unsigned long junk;
+
      __asm__ __volatile__ ("\n\
+
          1:      mftbu   %1\n\
+
                  mftb    %L0\n\
+
                  mftbu   %0\n\
+
                  cmpw    %0,%1\n\
+
                  bne     1b"
+
                  : "=r" (retval), "=r" (junk));
+
      return retval;
+
  }
+

+
#else
+

+
  /*
+
  ** asm() is needed for hardware timing support.  Without asm(),
+
  ** disable the sqlite3Hwtime() routine.
+
  **
+
  ** sqlite3Hwtime() is only used for some obscure debugging
+
  ** and analysis configurations, not in any deliverable, so this
+
  ** should not be a great loss.
+
  */
+
SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+

+
#endif
+

+
#endif /* !defined(SQLITE_HWTIME_H) */
+

+
/************** End of hwtime.h **********************************************/
+
/************** Continuing where we left off in vdbe.c ***********************/
+
#endif
+

+
/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell.  This macro verifies that shallow copies are
** not misused.  A shallow copy of a string or blob just copies a
@@ -94327,7 +94600,7 @@ case OP_HaltIfNull: { /* in3 */
  /* no break */ deliberate_fall_through
}

-
/* Opcode:  Halt P1 P2 * P4 P5
+
/* Opcode:  Halt P1 P2 P3 P4 P5
**
** Exit immediately.  All open cursors, etc are closed
** automatically.
@@ -94340,18 +94613,22 @@ case OP_HaltIfNull: { /* in3 */
** then back out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
-
** If P4 is not null then it is an error message string.
+
** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
+
** text of an error message.
**
-
** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
+
** If P3 is zero and P4 is not null then the error message string is held
+
** in P4.
+
**
+
** P5 is a value between 1 and 4, inclusive, then the P4 error message
+
** string is modified as follows:
**
-
**    0:  (no change)
**    1:  NOT NULL constraint failed: P4
**    2:  UNIQUE constraint failed: P4
**    3:  CHECK constraint failed: P4
**    4:  FOREIGN KEY constraint failed: P4
**
-
** If P5 is not zero and P4 is NULL, then everything after the ":" is
-
** omitted.
+
** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
+
** the ":" is omitted.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program.  So a jump past the last instruction of the program
@@ -94364,6 +94641,9 @@ case OP_Halt: {
#ifdef SQLITE_DEBUG
  if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
+
  assert( pOp->p4type==P4_NOTUSED
+
       || pOp->p4type==P4_STATIC
+
       || pOp->p4type==P4_DYNAMIC );

  /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
  ** something is wrong with the code generator.  Raise an assertion in order
@@ -94394,7 +94674,12 @@ case OP_Halt: {
  p->errorAction = (u8)pOp->p2;
  assert( pOp->p5<=4 );
  if( p->rc ){
-
    if( pOp->p5 ){
+
    if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){
+
      const char *zErr;
+
      assert( pOp->p3<=(p->nMem + 1 - p->nCursor) );
+
      zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8);
+
      sqlite3VdbeError(p, "%s", zErr);
+
    }else if( pOp->p5 ){
      static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
                                             "FOREIGN KEY" };
      testcase( pOp->p5==1 );
@@ -95197,7 +95482,7 @@ case OP_RealAffinity: { /* in1 */
}
#endif

-
#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_ANALYZE)
+
#if !defined(SQLITE_OMIT_CAST) || !defined(SQLITE_OMIT_ANALYZE)
/* Opcode: Cast P1 P2 * * *
** Synopsis: affinity(r[P1])
**
@@ -97437,23 +97722,23 @@ case OP_OpenWrite:
    if( pDb->pSchema->file_format < p->minWriteFileFormat ){
      p->minWriteFileFormat = pDb->pSchema->file_format;
    }
+
    if( pOp->p5 & OPFLAG_P2ISREG ){
+
      assert( p2>0 );
+
      assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
+
      pIn2 = &aMem[p2];
+
      assert( memIsValid(pIn2) );
+
      assert( (pIn2->flags & MEM_Int)!=0 );
+
      sqlite3VdbeMemIntegerify(pIn2);
+
      p2 = (int)pIn2->u.i;
+
      /* The p2 value always comes from a prior OP_CreateBtree opcode and
+
      ** that opcode will always set the p2 value to 2 or more or else fail.
+
      ** If there were a failure, the prepared statement would have halted
+
      ** before reaching this instruction. */
+
      assert( p2>=2 );
+
    }
  }else{
    wrFlag = 0;
-
  }
-
  if( pOp->p5 & OPFLAG_P2ISREG ){
-
    assert( p2>0 );
-
    assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
-
    assert( pOp->opcode==OP_OpenWrite );
-
    pIn2 = &aMem[p2];
-
    assert( memIsValid(pIn2) );
-
    assert( (pIn2->flags & MEM_Int)!=0 );
-
    sqlite3VdbeMemIntegerify(pIn2);
-
    p2 = (int)pIn2->u.i;
-
    /* The p2 value always comes from a prior OP_CreateBtree opcode and
-
    ** that opcode will always set the p2 value to 2 or more or else fail.
-
    ** If there were a failure, the prepared statement would have halted
-
    ** before reaching this instruction. */
-
    assert( p2>=2 );
+
    assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
  }
  if( pOp->p4type==P4_KEYINFO ){
    pKeyInfo = pOp->p4.pKeyInfo;
@@ -97631,7 +97916,10 @@ case OP_OpenEphemeral: { /* ncycle */
      }
      pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
      if( rc ){
+
        assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
        sqlite3BtreeClose(pCx->ub.pBtx);
+
      }else{
+
        assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
      }
    }
  }
@@ -98409,6 +98697,7 @@ case OP_Found: { /* jump, in3, ncycle */
    r.pKeyInfo = pC->pKeyInfo;
    r.default_rc = 0;
#ifdef SQLITE_DEBUG
+
    (void)sqlite3FaultSim(50);  /* For use by --counter in TH3 */
    for(ii=0; ii<r.nField; ii++){
      assert( memIsValid(&r.aMem[ii]) );
      assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
@@ -100771,18 +101060,29 @@ case OP_AggInverse:
case OP_AggStep: {
  int n;
  sqlite3_context *pCtx;
+
  u64 nAlloc;

  assert( pOp->p4type==P4_FUNCDEF );
  n = pOp->p5;
  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
-
  pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
-
               (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
+

+
  /* Allocate space for (a) the context object and (n-1) extra pointers
+
  ** to append to the sqlite3_context.argv[1] array, and (b) a memory
+
  ** cell in which to store the accumulation. Be careful that the memory
+
  ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
+
  **
+
  ** Note: We could avoid this by using a regular memory cell from aMem[] for
+
  ** the accumulator, instead of allocating one here. */
+
  nAlloc = ROUND8P( sizeof(pCtx[0]) + (n-1)*sizeof(sqlite3_value*) );
+
  pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
  if( pCtx==0 ) goto no_mem;
-
  pCtx->pMem = 0;
-
  pCtx->pOut = (Mem*)&(pCtx->argv[n]);
+
  pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
+
  assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
+

  sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
+
  pCtx->pMem = 0;
  pCtx->pFunc = pOp->p4.pFunc;
  pCtx->iOp = (int)(pOp - aOp);
  pCtx->pVdbe = p;
@@ -102116,14 +102416,29 @@ case OP_ReleaseReg: {

/* Opcode: Noop * * * * *
**
-
** Do nothing.  This instruction is often useful as a jump
-
** destination.
+
** Do nothing.  Continue downward to the next opcode.
*/
-
/*
-
** The magic Explain opcode are only inserted when explain==2 (which
-
** is to say when the EXPLAIN QUERY PLAN syntax is used.)
-
** This opcode records information from the optimizer.  It is the
-
** the same as a no-op.  This opcodesnever appears in a real VM program.
+
/* Opcode: Explain P1 P2 P3 P4 *
+
**
+
** This is the same as OP_Noop during normal query execution.  The
+
** purpose of this opcode is to hold information about the query
+
** plan for the purpose of EXPLAIN QUERY PLAN output.
+
**
+
** The P4 value is human-readable text that describes the query plan
+
** element.  Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1".
+
**
+
** The P1 value is the ID of the current element and P2 is the parent
+
** element for the case of nested query plan elements.  If P2 is zero
+
** then this element is a top-level element.
+
**
+
** For loop elements, P3 is the estimated code of each invocation of this
+
** element.
+
**
+
** As with all opcodes, the meanings of the parameters for OP_Explain
+
** are subject to change from one release to the next.  Applications
+
** should not attempt to interpret or use any of the information
+
** contained in the OP_Explain opcode.  The information provided by this
+
** opcode is intended for testing and debugging use only.
*/
default: {          /* This is really OP_Noop, OP_Explain */
  assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
@@ -102450,6 +102765,11 @@ SQLITE_API int sqlite3_blob_open(
      pTab = 0;
      sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
    }
+
    if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){
+
      pTab = 0;
+
      sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s",
+
                      zTable);
+
    }
#ifndef SQLITE_OMIT_VIEW
    if( pTab && IsView(pTab) ){
      pTab = 0;
@@ -103357,13 +103677,14 @@ static int vdbePmaReadBlob(
    while( nRem>0 ){
      int rc;                     /* vdbePmaReadBlob() return code */
      int nCopy;                  /* Number of bytes to copy */
-
      u8 *aNext;                  /* Pointer to buffer to copy data from */
+
      u8 *aNext = 0;              /* Pointer to buffer to copy data from */

      nCopy = nRem;
      if( nRem>p->nBuffer ) nCopy = p->nBuffer;
      rc = vdbePmaReadBlob(p, nCopy, &aNext);
      if( rc!=SQLITE_OK ) return rc;
      assert( aNext!=p->aAlloc );
+
      assert( aNext!=0 );
      memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
      nRem -= nCopy;
    }
@@ -106633,7 +106954,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
  pSrc = p->pSrc;
  if( ALWAYS(pSrc) ){
    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
-
      if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+
      if( pItem->fg.isSubquery
+
       && sqlite3WalkSelect(pWalker, pItem->u4.pSubq->pSelect)
+
      ){
        return WRC_Abort;
      }
      if( pItem->fg.isTabFunc
@@ -106939,7 +107262,7 @@ static void extendFJMatch(
  if( pNew ){
    pNew->iTable = pMatch->iCursor;
    pNew->iColumn = iColumn;
-
    pNew->y.pTab = pMatch->pTab;
+
    pNew->y.pTab = pMatch->pSTab;
    assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
    ExprSetProperty(pNew, EP_CanBeNull);
    *ppList = sqlite3ExprListAppend(pParse, *ppList, pNew);
@@ -107070,10 +107393,10 @@ static int lookupName(
    if( pSrcList ){
      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
        u8 hCol;
-
        pTab = pItem->pTab;
+
        pTab = pItem->pSTab;
        assert( pTab!=0 && pTab->zName!=0 );
        assert( pTab->nCol>0 || pParse->nErr );
-
        assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+
        assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem));
        if( pItem->fg.isNestedFrom ){
          /* In this case, pItem is a subquery that has been formed from a
          ** parenthesized subset of the FROM clause terms.  Example:
@@ -107082,8 +107405,12 @@ static int lookupName(
          **             This pItem -------------^
          */
          int hit = 0;
-
          assert( pItem->pSelect!=0 );
-
          pEList = pItem->pSelect->pEList;
+
          Select *pSel;
+
          assert( pItem->fg.isSubquery );
+
          assert( pItem->u4.pSubq!=0 );
+
          pSel = pItem->u4.pSubq->pSelect;
+
          assert( pSel!=0 );
+
          pEList = pSel->pEList;
          assert( pEList!=0 );
          assert( pEList->nExpr==pTab->nCol );
          for(j=0; j<pEList->nExpr; j++){
@@ -107206,9 +107533,9 @@ static int lookupName(
          */
          if( cntTab==0
           || (cntTab==1
-
               && ALWAYS(pMatch!=0)
-
               && ALWAYS(pMatch->pTab!=0)
-
               && (pMatch->pTab->tabFlags & TF_Ephemeral)!=0
+
               && pMatch!=0
+
               && ALWAYS(pMatch->pSTab!=0)
+
               && (pMatch->pSTab->tabFlags & TF_Ephemeral)!=0
               && (pTab->tabFlags & TF_Ephemeral)==0)
          ){
            cntTab = 1;
@@ -107229,7 +107556,7 @@ static int lookupName(
      if( pMatch ){
        pExpr->iTable = pMatch->iCursor;
        assert( ExprUseYTab(pExpr) );
-
        pExpr->y.pTab = pMatch->pTab;
+
        pExpr->y.pTab = pMatch->pSTab;
        if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
          ExprSetProperty(pExpr, EP_CanBeNull);
        }
@@ -107271,7 +107598,7 @@ static int lookupName(
      if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
        Upsert *pUpsert = pNC->uNC.pUpsert;
        if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
-
          pTab = pUpsert->pUpsertSrc->a[0].pTab;
+
          pTab = pUpsert->pUpsertSrc->a[0].pSTab;
          pExpr->iTable = EXCLUDED_TABLE_NUMBER;
        }
      }
@@ -107354,11 +107681,11 @@ static int lookupName(
     && pMatch
     && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
     && sqlite3IsRowid(zCol)
-
     && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
+
     && ALWAYS(VisibleRowid(pMatch->pSTab) || pMatch->fg.isNestedFrom)
    ){
      cnt = cntTab;
#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
-
      if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
+
      if( pMatch->pSTab!=0 && IsView(pMatch->pSTab) ){
        eNewExprOp = TK_NULL;
      }
#endif
@@ -107595,7 +107922,7 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
    SrcItem *pItem = &pSrc->a[iSrc];
    Table *pTab;
    assert( ExprUseYTab(p) );
-
    pTab = p->y.pTab = pItem->pTab;
+
    pTab = p->y.pTab = pItem->pSTab;
    p->iTable = pItem->iCursor;
    if( p->y.pTab->iPKey==iCol ){
      p->iColumn = -1;
@@ -107714,7 +108041,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
      pItem = pSrcList->a;
      pExpr->op = TK_COLUMN;
      assert( ExprUseYTab(pExpr) );
-
      pExpr->y.pTab = pItem->pTab;
+
      pExpr->y.pTab = pItem->pSTab;
      pExpr->iTable = pItem->iCursor;
      pExpr->iColumn--;
      pExpr->affExpr = SQLITE_AFF_INTEGER;
@@ -107839,8 +108166,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
    /* Resolve function names
    */
    case TK_FUNCTION: {
-
      ExprList *pList = pExpr->x.pList;    /* The argument list */
-
      int n = pList ? pList->nExpr : 0;    /* Number of arguments */
+
      ExprList *pList;            /* The argument list */
+
      int n;                      /* Number of arguments */
      int no_such_func = 0;       /* True if no such function exists */
      int wrong_num_args = 0;     /* True if wrong number of arguments */
      int is_agg = 0;             /* True if is an aggregate function */
@@ -107853,6 +108180,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
      assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
      assert( pExpr->pLeft==0 || pExpr->pLeft->op==TK_ORDER );
+
      pList = pExpr->x.pList;
+
      n = pList ? pList->nExpr : 0;
      zId = pExpr->u.zToken;
      pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
      if( pDef==0 ){
@@ -107901,6 +108230,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
          }
        }
#endif
+

+
        /* If the function may call sqlite3_value_subtype(), then set the
+
        ** EP_SubtArg flag on all of its argument expressions. This prevents
+
        ** where.c from replacing the expression with a value read from an
+
        ** index on the same expression, which will not have the correct
+
        ** subtype. Also set the flag if the function expression itself is
+
        ** an EP_SubtArg expression. In this case subtypes are required as
+
        ** the function may return a value with a subtype back to its
+
        ** caller using sqlite3_result_value().  */
+
        if( (pDef->funcFlags & SQLITE_SUBTYPE)
+
         || ExprHasProperty(pExpr, EP_SubtArg)
+
        ){
+
          int ii;
+
          for(ii=0; ii<n; ii++){
+
            ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
+
          }
+
        }
+

        if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
          /* For the purposes of the EP_ConstFunc flag, date and time
          ** functions and other functions that change slowly are considered
@@ -108020,9 +108367,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
          sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList);
        }
#ifndef SQLITE_OMIT_WINDOWFUNC
-
        if( pWin ){
+
        if( pWin && pParse->nErr==0 ){
          Select *pSel = pNC->pWinSelect;
-
          assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
+
          assert( ExprUseYWin(pExpr) && pWin==pExpr->y.pWin );
          if( IN_RENAME_OBJECT==0 ){
            sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
            if( pParse->db->mallocFailed ) break;
@@ -108229,7 +108576,7 @@ static int resolveOrderByTermToExprList(
  int rc;            /* Return code from subprocedures */
  u8 savedSuppErr;   /* Saved value of db->suppressErr */

-
  assert( sqlite3ExprIsInteger(pE, &i)==0 );
+
  assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
  pEList = pSelect->pEList;

  /* Resolve all names in the ORDER BY term expression
@@ -108328,7 +108675,7 @@ static int resolveCompoundOrderBy(
      if( pItem->fg.done ) continue;
      pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
      if( NEVER(pE==0) ) continue;
-
      if( sqlite3ExprIsInteger(pE, &iCol) ){
+
      if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
        if( iCol<=0 || iCol>pEList->nExpr ){
          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
          return 1;
@@ -108513,7 +108860,7 @@ static int resolveOrderGroupBy(
        continue;
      }
    }
-
    if( sqlite3ExprIsInteger(pE2, &iCol) ){
+
    if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
      /* The ORDER BY term is an integer constant.  Again, set the column
      ** number so that sqlite3ResolveOrderGroupBy() will convert the
      ** order-by term to a copy of the result-set expression */
@@ -108604,7 +108951,11 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
    ** moves the pOrderBy down to the sub-query. It will be moved back
    ** after the names have been resolved.  */
    if( p->selFlags & SF_Converted ){
-
      Select *pSub = p->pSrc->a[0].pSelect;
+
      Select *pSub;
+
      assert( p->pSrc->a[0].fg.isSubquery );
+
      assert( p->pSrc->a[0].u4.pSubq!=0 );
+
      pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+
      assert( pSub!=0 );
      assert( p->pSrc->nSrc==1 && p->pOrderBy );
      assert( pSub->pPrior && pSub->pOrderBy==0 );
      pSub->pOrderBy = p->pOrderBy;
@@ -108616,13 +108967,16 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
    if( pOuterNC ) pOuterNC->nNestedSelect++;
    for(i=0; i<p->pSrc->nSrc; i++){
      SrcItem *pItem = &p->pSrc->a[i];
-
      assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
-
      if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
+
      assert( pItem->zName!=0
+
              || pItem->fg.isSubquery );  /* Test of tag-20240424-1*/
+
      if( pItem->fg.isSubquery
+
       && (pItem->u4.pSubq->pSelect->selFlags & SF_Resolved)==0
+
      ){
        int nRef = pOuterNC ? pOuterNC->nRef : 0;
        const char *zSavedContext = pParse->zAuthContext;

        if( pItem->zName ) pParse->zAuthContext = pItem->zName;
-
        sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
+
        sqlite3ResolveSelectNames(pParse, pItem->u4.pSubq->pSelect, pOuterNC);
        pParse->zAuthContext = zSavedContext;
        if( pParse->nErr ) return WRC_Abort;
        assert( db->mallocFailed==0 );
@@ -108724,7 +109078,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
    ** These integers will be replaced by copies of the corresponding result
    ** set expressions by the call to resolveOrderGroupBy() below.  */
    if( p->selFlags & SF_Converted ){
-
      Select *pSub = p->pSrc->a[0].pSelect;
+
      Select *pSub;
+
      assert( p->pSrc->a[0].fg.isSubquery );
+
      pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+
      assert( pSub!=0 );
      p->pOrderBy = pSub->pOrderBy;
      pSub->pOrderBy = 0;
    }
@@ -108991,7 +109348,7 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference(
  if( pTab ){
    sSrc.nSrc = 1;
    sSrc.a[0].zName = pTab->zName;
-
    sSrc.a[0].pTab = pTab;
+
    sSrc.a[0].pSTab = pTab;
    sSrc.a[0].iCursor = -1;
    if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
      /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
@@ -109096,7 +109453,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
      op = pExpr->op;
      continue;
    }
-
    if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
+
    if( op!=TK_REGISTER ) break;
+
    op = pExpr->op2;
+
    if( NEVER( op==TK_REGISTER ) ) break;
  }
  return pExpr->affExpr;
}
@@ -110886,15 +111245,30 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int fla
    SrcItem *pNewItem = &pNew->a[i];
    const SrcItem *pOldItem = &p->a[i];
    Table *pTab;
-
    pNewItem->pSchema = pOldItem->pSchema;
-
    pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
+
    pNewItem->fg = pOldItem->fg;
+
    if( pOldItem->fg.isSubquery ){
+
      Subquery *pNewSubq = sqlite3DbMallocRaw(db, sizeof(Subquery));
+
      if( pNewSubq==0 ){
+
        assert( db->mallocFailed );
+
        pNewItem->fg.isSubquery = 0;
+
      }else{
+
        memcpy(pNewSubq, pOldItem->u4.pSubq, sizeof(*pNewSubq));
+
        pNewSubq->pSelect = sqlite3SelectDup(db, pNewSubq->pSelect, flags);
+
        if( pNewSubq->pSelect==0 ){
+
          sqlite3DbFree(db, pNewSubq);
+
          pNewSubq = 0;
+
          pNewItem->fg.isSubquery = 0;
+
        }
+
      }
+
      pNewItem->u4.pSubq = pNewSubq;
+
    }else if( pOldItem->fg.fixedSchema ){
+
      pNewItem->u4.pSchema = pOldItem->u4.pSchema;
+
    }else{
+
      pNewItem->u4.zDatabase = sqlite3DbStrDup(db, pOldItem->u4.zDatabase);
+
    }
    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
-
    pNewItem->fg = pOldItem->fg;
    pNewItem->iCursor = pOldItem->iCursor;
-
    pNewItem->addrFillSub = pOldItem->addrFillSub;
-
    pNewItem->regReturn = pOldItem->regReturn;
-
    pNewItem->regResult = pOldItem->regResult;
    if( pNewItem->fg.isIndexedBy ){
      pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
    }else if( pNewItem->fg.isTabFunc ){
@@ -110907,11 +111281,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int fla
    if( pNewItem->fg.isCte ){
      pNewItem->u2.pCteUse->nUse++;
    }
-
    pTab = pNewItem->pTab = pOldItem->pTab;
+
    pTab = pNewItem->pSTab = pOldItem->pSTab;
    if( pTab ){
      pTab->nTabRef++;
    }
-
    pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
    if( pOldItem->fg.isUsing ){
      assert( pNewItem->fg.isUsing );
      pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing);
@@ -110985,7 +111358,6 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla
    pp = &pNew->pPrior;
    pNext = pNew;
  }
-

  return pRet;
}
#else
@@ -111800,8 +112172,12 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue.  If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
+
**
+
** If the pParse pointer is provided, then allow the expression p to be
+
** a parameter (TK_VARIABLE) that is bound to an integer.
+
** But if pParse is NULL, then p must be a pure integer literal.
*/
-
SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
+
SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
  int rc = 0;
  if( NEVER(p==0) ) return 0;  /* Used to only happen following on OOM */

@@ -111816,18 +112192,38 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
  }
  switch( p->op ){
    case TK_UPLUS: {
-
      rc = sqlite3ExprIsInteger(p->pLeft, pValue);
+
      rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
      break;
    }
    case TK_UMINUS: {
      int v = 0;
-
      if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+
      if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
        assert( ((unsigned int)v)!=0x80000000 );
        *pValue = -v;
        rc = 1;
      }
      break;
    }
+
    case TK_VARIABLE: {
+
      sqlite3_value *pVal;
+
      if( pParse==0 ) break;
+
      if( NEVER(pParse->pVdbe==0) ) break;
+
      if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
+
      sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
+
      pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
+
                                      SQLITE_AFF_BLOB);
+
      if( pVal ){
+
        if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
+
          sqlite3_int64 vv = sqlite3_value_int64(pVal);
+
          if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
+
            *pValue = (int)vv;
+
            rc = 1;
+
          }
+
        }
+
        sqlite3ValueFree(pVal);
+
      }
+
      break;
+
    }
    default: break;
  }
  return rc;
@@ -111981,8 +112377,8 @@ static Select *isCandidateForInOpt(const Expr *pX){
  pSrc = p->pSrc;
  assert( pSrc!=0 );
  if( pSrc->nSrc!=1 ) return 0;          /* Single term in FROM clause */
-
  if( pSrc->a[0].pSelect ) return 0;     /* FROM is not a subquery or view */
-
  pTab = pSrc->a[0].pTab;
+
  if( pSrc->a[0].fg.isSubquery) return 0;/* FROM is not a subquery or view */
+
  pTab = pSrc->a[0].pSTab;
  assert( pTab!=0 );
  assert( !IsView(pTab)  );              /* FROM clause is not a view */
  if( IsVirtual(pTab) ) return 0;        /* FROM clause not a virtual table */
@@ -112165,7 +112561,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
    assert( p->pEList!=0 );             /* Because of isCandidateForInOpt(p) */
    assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
    assert( p->pSrc!=0 );               /* Because of isCandidateForInOpt(p) */
-
    pTab = p->pSrc->a[0].pTab;
+
    pTab = p->pSrc->a[0].pSTab;

    /* Code an OP_Transaction and OP_TableLock for <table>. */
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -112407,6 +112803,49 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){

#ifndef SQLITE_OMIT_SUBQUERY
/*
+
** Scan all previously generated bytecode looking for an OP_BeginSubrtn
+
** that is compatible with pExpr.  If found, add the y.sub values
+
** to pExpr and return true.  If not found, return false.
+
*/
+
static int findCompatibleInRhsSubrtn(
+
  Parse *pParse,          /* Parsing context */
+
  Expr *pExpr,            /* IN operator with RHS that we want to reuse */
+
  SubrtnSig *pNewSig      /* Signature for the IN operator */
+
){
+
  VdbeOp *pOp, *pEnd;
+
  SubrtnSig *pSig;
+
  Vdbe *v;
+

+
  if( pNewSig==0 ) return 0;
+
  if( (pParse->mSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0;
+
  assert( pExpr->op==TK_IN );
+
  assert( !ExprUseYSub(pExpr) );
+
  assert( ExprUseXSelect(pExpr) );
+
  assert( pExpr->x.pSelect!=0 );
+
  assert( (pExpr->x.pSelect->selFlags & SF_All)==0 );
+
  v = pParse->pVdbe;
+
  assert( v!=0 );
+
  pOp = sqlite3VdbeGetOp(v, 1);
+
  pEnd = sqlite3VdbeGetLastOp(v);
+
  for(; pOp<pEnd; pOp++){
+
    if( pOp->p4type!=P4_SUBRTNSIG ) continue;
+
    assert( pOp->opcode==OP_BeginSubrtn );
+
    pSig = pOp->p4.pSubrtnSig;
+
    assert( pSig!=0 );
+
    if( pNewSig->selId!=pSig->selId ) continue;
+
    if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue;
+
    pExpr->y.sub.iAddr = pSig->iAddr;
+
    pExpr->y.sub.regReturn = pSig->regReturn;
+
    pExpr->iTable = pSig->iTable;
+
    ExprSetProperty(pExpr, EP_Subrtn);
+
    return 1;
+
  }
+
  return 0;
+
}
+
#endif /* SQLITE_OMIT_SUBQUERY */
+

+
#ifndef SQLITE_OMIT_SUBQUERY
+
/*
** Generate code that will construct an ephemeral table containing all terms
** in the RHS of an IN operator.  The IN operator can be in either of two
** forms:
@@ -112454,11 +112893,28 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
  ** and reuse it many names.
  */
  if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
-
    /* Reuse of the RHS is allowed */
-
    /* If this routine has already been coded, but the previous code
-
    ** might not have been invoked yet, so invoke it now as a subroutine.
+
    /* Reuse of the RHS is allowed
+
    **
+
    ** Compute a signature for the RHS of the IN operator to facility
+
    ** finding and reusing prior instances of the same IN operator.
    */
-
    if( ExprHasProperty(pExpr, EP_Subrtn) ){
+
    SubrtnSig *pSig = 0;
+
    assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 );
+
    if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){
+
      pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0]));
+
      if( pSig ){
+
        pSig->selId = pExpr->x.pSelect->selId;
+
        pSig->zAff = exprINAffinity(pParse, pExpr);
+
      }
+
    }
+

+
    /* Check to see if there is a prior materialization of the RHS of
+
    ** this IN operator.  If there is, then make use of that prior
+
    ** materialization rather than recomputing it.
+
    */
+
    if( ExprHasProperty(pExpr, EP_Subrtn)
+
     || findCompatibleInRhsSubrtn(pParse, pExpr, pSig)
+
    ){
      addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
      if( ExprUseXSelect(pExpr) ){
        ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
@@ -112470,6 +112926,10 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
      assert( iTab!=pExpr->iTable );
      sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
      sqlite3VdbeJumpHere(v, addrOnce);
+
      if( pSig ){
+
        sqlite3DbFree(pParse->db, pSig->zAff);
+
        sqlite3DbFree(pParse->db, pSig);
+
      }
      return;
    }

@@ -112480,7 +112940,13 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
    pExpr->y.sub.regReturn = ++pParse->nMem;
    pExpr->y.sub.iAddr =
      sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
-

+
    if( pSig ){
+
      pSig->iAddr = pExpr->y.sub.iAddr;
+
      pSig->regReturn = pExpr->y.sub.regReturn;
+
      pSig->iTable = iTab;
+
      pParse->mSubrtnSig = 1 << (pSig->selId&7);
+
      sqlite3VdbeChangeP4(v, -1, (const char*)pSig, P4_SUBRTNSIG);
+
    }
    addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  }

@@ -112521,15 +112987,30 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
      SelectDest dest;
      int i;
      int rc;
+
      int addrBloom = 0;
      sqlite3SelectDestInit(&dest, SRT_Set, iTab);
      dest.zAffSdst = exprINAffinity(pParse, pExpr);
      pSelect->iLimit = 0;
+
      if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
+
        int regBloom = ++pParse->nMem;
+
        addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
+
        VdbeComment((v, "Bloom filter"));
+
        dest.iSDParm2 = regBloom;
+
      }
      testcase( pSelect->selFlags & SF_Distinct );
      testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
      pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
      rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
      sqlite3SelectDelete(pParse->db, pCopy);
      sqlite3DbFree(pParse->db, dest.zAffSdst);
+
      if( addrBloom ){
+
        sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+
        if( dest.iSDParm2==0 ){
+
          sqlite3VdbeChangeToNoop(v, addrBloom);
+
        }else{
+
          sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+
        }
+
      }
      if( rc ){
        sqlite3KeyInfoUnref(pKeyInfo);
        return;
@@ -112827,9 +113308,7 @@ static void sqlite3ExprCodeIN(
  if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
  zAff = exprINAffinity(pParse, pExpr);
  nVector = sqlite3ExprVectorSize(pExpr->pLeft);
-
  aiMap = (int*)sqlite3DbMallocZero(
-
      pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
-
  );
+
  aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int));
  if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;

  /* Attempt to compute the RHS. After this step, if anything other than
@@ -112972,6 +113451,15 @@ static void sqlite3ExprCodeIN(
    sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
    if( destIfFalse==destIfNull ){
      /* Combine Step 3 and Step 5 into a single opcode */
+
      if( ExprHasProperty(pExpr, EP_Subrtn) ){
+
        const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
+
        assert( pOp->opcode==OP_Once || pParse->nErr );
+
        if( pOp->opcode==OP_Once && pOp->p3>0 ){
+
          assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
+
          sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
+
                               rLhs, nVector); VdbeCoverage(v);
+
        }
+
      }
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
                           rLhs, nVector); VdbeCoverage(v);
      goto sqlite3ExprCodeIN_finished;
@@ -113254,13 +113742,17 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
** register iReg.  The caller must ensure that iReg already contains
** the correct value for the expression.
*/
-
static void exprToRegister(Expr *pExpr, int iReg){
+
SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){
  Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
  if( NEVER(p==0) ) return;
-
  p->op2 = p->op;
-
  p->op = TK_REGISTER;
-
  p->iTable = iReg;
-
  ExprClearProperty(p, EP_Skip);
+
  if( p->op==TK_REGISTER ){
+
    assert( p->iTable==iReg );
+
  }else{
+
    p->op2 = p->op;
+
    p->op = TK_REGISTER;
+
    p->iTable = iReg;
+
    ExprClearProperty(p, EP_Skip);
+
  }
}

/*
@@ -113431,6 +113923,59 @@ static int exprCodeInlineFunction(
}

/*
+
** Expression Node callback for sqlite3ExprCanReturnSubtype().
+
**
+
** Only a function call is able to return a subtype.  So if the node
+
** is not a function call, return WRC_Prune immediately.
+
**
+
** A function call is able to return a subtype if it has the
+
** SQLITE_RESULT_SUBTYPE property.
+
**
+
** Assume that every function is able to pass-through a subtype from
+
** one of its argument (using sqlite3_result_value()).  Most functions
+
** are not this way, but we don't have a mechanism to distinguish those
+
** that are from those that are not, so assume they all work this way.
+
** That means that if one of its arguments is another function and that
+
** other function is able to return a subtype, then this function is
+
** able to return a subtype.
+
*/
+
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
+
  int n;
+
  FuncDef *pDef;
+
  sqlite3 *db;
+
  if( pExpr->op!=TK_FUNCTION ){
+
    return WRC_Prune;
+
  }
+
  assert( ExprUseXList(pExpr) );
+
  db = pWalker->pParse->db;
+
  n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
+
  pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
+
  if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
+
    pWalker->eCode = 1;
+
    return WRC_Prune;
+
  }
+
  return WRC_Continue;
+
}
+

+
/*
+
** Return TRUE if expression pExpr is able to return a subtype.
+
**
+
** A TRUE return does not guarantee that a subtype will be returned.
+
** It only indicates that a subtype return is possible.  False positives
+
** are acceptable as they only disable an optimization.  False negatives,
+
** on the other hand, can lead to incorrect answers.
+
*/
+
static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
+
  Walker w;
+
  memset(&w, 0, sizeof(w));
+
  w.pParse = pParse;
+
  w.xExprCallback = exprNodeCanReturnSubtype;
+
  sqlite3WalkExpr(&w, pExpr);
+
  return w.eCode;
+
}
+

+

+
/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
** return the register into which the value has been read.  If pExpr is
@@ -113462,6 +114007,17 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
      continue;
    }

+

+
    /* Functions that might set a subtype should not be replaced by the
+
    ** value taken from an expression index if they are themselves an
+
    ** argument to another scalar function or aggregate.
+
    ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */
+
    if( ExprHasProperty(pExpr, EP_SubtArg)
+
     && sqlite3ExprCanReturnSubtype(pParse, pExpr)
+
    ){
+
      continue;
+
    }
+

    v = pParse->pVdbe;
    assert( v!=0 );
    if( p->bMaybeNullRow ){
@@ -114263,7 +114819,7 @@ expr_code_doover:
          break;
        }
        testcase( pX->op==TK_COLUMN );
-
        exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
+
        sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
        testcase( regFree1==0 );
        memset(&opCompare, 0, sizeof(opCompare));
        opCompare.op = TK_EQ;
@@ -114317,15 +114873,14 @@ expr_code_doover:
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      if( pExpr->affExpr==OE_Ignore ){
-
        sqlite3VdbeAddOp4(
-
            v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
+
        sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore);
        VdbeCoverage(v);
      }else{
-
        sqlite3HaltConstraint(pParse,
+
        r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+
        sqlite3VdbeAddOp3(v, OP_Halt,
             pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
-
             pExpr->affExpr, pExpr->u.zToken, 0, 0);
+
             pExpr->affExpr, r1);
      }
-

      break;
    }
#endif
@@ -114614,7 +115169,7 @@ static void exprCodeBetween(
    compRight.op = TK_LE;
    compRight.pLeft = pDel;
    compRight.pRight = pExpr->x.pList->a[1].pExpr;
-
    exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
+
    sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
    if( xJump ){
      xJump(pParse, &exprAnd, dest, jumpIfNull);
    }else{
@@ -117508,8 +118063,9 @@ static int renameResolveTrigger(Parse *pParse){
          int i;
          for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){
            SrcItem *p = &pStep->pFrom->a[i];
-
            if( p->pSelect ){
-
              sqlite3SelectPrep(pParse, p->pSelect, 0);
+
            if( p->fg.isSubquery ){
+
              assert( p->u4.pSubq!=0 );
+
              sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0);
            }
          }
        }
@@ -117577,8 +118133,12 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
    }
    if( pStep->pFrom ){
      int i;
-
      for(i=0; i<pStep->pFrom->nSrc; i++){
-
        sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
+
      SrcList *pFrom = pStep->pFrom;
+
      for(i=0; i<pFrom->nSrc; i++){
+
        if( pFrom->a[i].fg.isSubquery ){
+
          assert( pFrom->a[i].u4.pSubq!=0 );
+
          sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect);
+
        }
      }
    }
  }
@@ -117825,7 +118385,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
  }
  for(i=0; i<pSrc->nSrc; i++){
    SrcItem *pItem = &pSrc->a[i];
-
    if( pItem->pTab==p->pTab ){
+
    if( pItem->pSTab==p->pTab ){
      renameTokenFind(pWalker->pParse, p, pItem->zName);
    }
  }
@@ -120253,12 +120813,13 @@ static int loadStatTbl(
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    int nIdxCol = 1;              /* Number of columns in stat4 records */

-
    char *zIndex;   /* Index name */
-
    Index *pIdx;    /* Pointer to the index object */
-
    int nSample;    /* Number of samples */
-
    int nByte;      /* Bytes of space required */
-
    int i;          /* Bytes of space required */
-
    tRowcnt *pSpace;
+
    char *zIndex;    /* Index name */
+
    Index *pIdx;     /* Pointer to the index object */
+
    int nSample;     /* Number of samples */
+
    i64 nByte;       /* Bytes of space required */
+
    i64 i;           /* Bytes of space required */
+
    tRowcnt *pSpace; /* Available allocated memory space */
+
    u8 *pPtr;        /* Available memory as a u8 for easier manipulation */

    zIndex = (char *)sqlite3_column_text(pStmt, 0);
    if( zIndex==0 ) continue;
@@ -120278,7 +120839,7 @@ static int loadStatTbl(
    }
    pIdx->nSampleCol = nIdxCol;
    pIdx->mxSample = nSample;
-
    nByte = sizeof(IndexSample) * nSample;
+
    nByte = ROUND8(sizeof(IndexSample) * nSample);
    nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
    nByte += nIdxCol * sizeof(tRowcnt);     /* Space for Index.aAvgEq[] */

@@ -120287,7 +120848,10 @@ static int loadStatTbl(
      sqlite3_finalize(pStmt);
      return SQLITE_NOMEM_BKPT;
    }
-
    pSpace = (tRowcnt*)&pIdx->aSample[nSample];
+
    pPtr = (u8*)pIdx->aSample;
+
    pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
+
    pSpace = (tRowcnt*)pPtr;
+
    assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
    pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
    pIdx->pTable->tabFlags |= TF_HasStat4;
    for(i=0; i<nSample; i++){
@@ -120955,20 +121519,21 @@ static int fixSelectCb(Walker *p, Select *pSelect){

  if( NEVER(pList==0) ) return WRC_Continue;
  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
-
    if( pFix->bTemp==0 ){
-
      if( pItem->zDatabase ){
-
        if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
+
    if( pFix->bTemp==0 && pItem->fg.isSubquery==0 ){
+
      if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+
        if( iDb!=sqlite3FindDbName(db, pItem->u4.zDatabase) ){
          sqlite3ErrorMsg(pFix->pParse,
              "%s %T cannot reference objects in database %s",
-
              pFix->zType, pFix->pName, pItem->zDatabase);
+
              pFix->zType, pFix->pName, pItem->u4.zDatabase);
          return WRC_Abort;
        }
-
        sqlite3DbFree(db, pItem->zDatabase);
-
        pItem->zDatabase = 0;
+
        sqlite3DbFree(db, pItem->u4.zDatabase);
        pItem->fg.notCte = 1;
+
        pItem->fg.hadSchema = 1;
      }
-
      pItem->pSchema = pFix->pSchema;
+
      pItem->u4.pSchema = pFix->pSchema;
      pItem->fg.fromDDL = 1;
+
      pItem->fg.fixedSchema = 1;
    }
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
    if( pList->a[i].fg.isUsing==0
@@ -121261,7 +121826,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
    assert( pTabList );
    for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
      if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
-
        pTab = pTabList->a[iSrc].pTab;
+
        pTab = pTabList->a[iSrc].pSTab;
        break;
      }
    }
@@ -121864,12 +122429,12 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
  SrcItem *p
){
  const char *zDb;
-
  assert( p->pSchema==0 || p->zDatabase==0 );
-
  if( p->pSchema ){
-
    int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+
  if( p->fg.fixedSchema ){
+
    int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
    zDb = pParse->db->aDb[iDb].zDbSName;
  }else{
-
    zDb = p->zDatabase;
+
    assert( !p->fg.isSubquery );
+
    zDb = p->u4.zDatabase;
  }
  return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}
@@ -124854,6 +125419,8 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
  }
  assert( pParse->nErr==0 );
  assert( pName->nSrc==1 );
+
  assert( pName->a[0].fg.fixedSchema==0 );
+
  assert( pName->a[0].fg.isSubquery==0 );
  if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
  if( noErr ) db->suppressErr++;
  assert( isView==0 || isView==LOCATE_VIEW );
@@ -124862,7 +125429,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,

  if( pTab==0 ){
    if( noErr ){
-
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
      sqlite3ForceNotReadOnly(pParse);
    }
    goto exit_drop_table;
@@ -125953,15 +126520,17 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
  }
  assert( pParse->nErr==0 );   /* Never called with prior non-OOM errors */
  assert( pName->nSrc==1 );
+
  assert( pName->a[0].fg.fixedSchema==0 );
+
  assert( pName->a[0].fg.isSubquery==0 );
  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
    goto exit_drop_index;
  }
-
  pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
+
  pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].u4.zDatabase);
  if( pIndex==0 ){
    if( !ifExists ){
      sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
    }else{
-
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
      sqlite3ForceNotReadOnly(pParse);
    }
    pParse->checkSchema = 1;
@@ -126258,12 +126827,14 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
  if( pDatabase && pDatabase->z==0 ){
    pDatabase = 0;
  }
+
  assert( pItem->fg.fixedSchema==0 );
+
  assert( pItem->fg.isSubquery==0 );
  if( pDatabase ){
    pItem->zName = sqlite3NameFromToken(db, pDatabase);
-
    pItem->zDatabase = sqlite3NameFromToken(db, pTable);
+
    pItem->u4.zDatabase = sqlite3NameFromToken(db, pTable);
  }else{
    pItem->zName = sqlite3NameFromToken(db, pTable);
-
    pItem->zDatabase = 0;
+
    pItem->u4.zDatabase = 0;
  }
  return pList;
}
@@ -126279,14 +126850,41 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
    for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
      if( pItem->iCursor>=0 ) continue;
      pItem->iCursor = pParse->nTab++;
-
      if( pItem->pSelect ){
-
        sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
+
      if( pItem->fg.isSubquery ){
+
        assert( pItem->u4.pSubq!=0 );
+
        assert( pItem->u4.pSubq->pSelect!=0 );
+
        assert( pItem->u4.pSubq->pSelect->pSrc!=0 );
+
        sqlite3SrcListAssignCursors(pParse, pItem->u4.pSubq->pSelect->pSrc);
      }
    }
  }
}

/*
+
** Delete a Subquery object and its substructure.
+
*/
+
SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3 *db, Subquery *pSubq){
+
  assert( pSubq!=0 && pSubq->pSelect!=0 );
+
  sqlite3SelectDelete(db, pSubq->pSelect);
+
  sqlite3DbFree(db, pSubq);
+
}
+

+
/*
+
** Remove a Subquery from a SrcItem.  Return the associated Select object.
+
** The returned Select becomes the responsibility of the caller.
+
*/
+
SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3 *db, SrcItem *pItem){
+
  Select *pSel;
+
  assert( pItem!=0 );
+
  assert( pItem->fg.isSubquery );
+
  pSel = pItem->u4.pSubq->pSelect;
+
  sqlite3DbFree(db, pItem->u4.pSubq);
+
  pItem->u4.pSubq = 0;
+
  pItem->fg.isSubquery = 0;
+
  return pSel;
+
}
+

+
/*
** Delete an entire SrcList including all its substructure.
*/
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
@@ -126295,13 +126893,24 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
  assert( db!=0 );
  if( pList==0 ) return;
  for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
-
    if( pItem->zDatabase ) sqlite3DbNNFreeNN(db, pItem->zDatabase);
+

+
    /* Check invariants on SrcItem */
+
    assert( !pItem->fg.isIndexedBy || !pItem->fg.isTabFunc );
+
    assert( !pItem->fg.isCte || !pItem->fg.isIndexedBy );
+
    assert( !pItem->fg.fixedSchema || !pItem->fg.isSubquery );
+
    assert( !pItem->fg.isSubquery || (pItem->u4.pSubq!=0 &&
+
                                      pItem->u4.pSubq->pSelect!=0) );
+

    if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName);
    if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias);
+
    if( pItem->fg.isSubquery ){
+
      sqlite3SubqueryDelete(db, pItem->u4.pSubq);
+
    }else if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+
      sqlite3DbNNFreeNN(db, pItem->u4.zDatabase);
+
    }
    if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
    if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
-
    sqlite3DeleteTable(db, pItem->pTab);
-
    if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+
    sqlite3DeleteTable(db, pItem->pSTab);
    if( pItem->fg.isUsing ){
      sqlite3IdListDelete(db, pItem->u3.pUsing);
    }else if( pItem->u3.pOn ){
@@ -126312,6 +126921,54 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
}

/*
+
** Attach a Subquery object to pItem->uv.pSubq.  Set the
+
** pSelect value but leave all the other values initialized
+
** to zero.
+
**
+
** A copy of the Select object is made if dupSelect is true, and the
+
** SrcItem takes responsibility for deleting the copy.  If dupSelect is
+
** false, ownership of the Select passes to the SrcItem.  Either way,
+
** the SrcItem will take responsibility for deleting the Select.
+
**
+
** When dupSelect is zero, that means the Select might get deleted right
+
** away if there is an OOM error.  Beware.
+
**
+
** Return non-zero on success.  Return zero on an OOM error.
+
*/
+
SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(
+
  Parse *pParse,     /* Parsing context */
+
  SrcItem *pItem,    /* Item to which the subquery is to be attached */
+
  Select *pSelect,   /* The subquery SELECT.  Must be non-NULL */
+
  int dupSelect      /* If true, attach a copy of pSelect, not pSelect itself.*/
+
){
+
  Subquery *p;
+
  assert( pSelect!=0 );
+
  assert( pItem->fg.isSubquery==0 );
+
  if( pItem->fg.fixedSchema ){
+
    pItem->u4.pSchema = 0;
+
    pItem->fg.fixedSchema = 0;
+
  }else if( pItem->u4.zDatabase!=0 ){
+
    sqlite3DbFree(pParse->db, pItem->u4.zDatabase);
+
    pItem->u4.zDatabase = 0;
+
  }
+
  if( dupSelect ){
+
    pSelect = sqlite3SelectDup(pParse->db, pSelect, 0);
+
    if( pSelect==0 ) return 0;
+
  }
+
  p = pItem->u4.pSubq = sqlite3DbMallocRawNN(pParse->db, sizeof(Subquery));
+
  if( p==0 ){
+
    sqlite3SelectDelete(pParse->db, pSelect);
+
    return 0;
+
  }
+
  pItem->fg.isSubquery = 1;
+
  p->pSelect = pSelect;
+
  assert( offsetof(Subquery, pSelect)==0 );
+
  memset(((char*)p)+sizeof(p->pSelect), 0, sizeof(*p)-sizeof(p->pSelect));
+
  return 1;
+
}
+

+

+
/*
** This routine is called by the parser to add a new term to the
** end of a growing FROM clause.  The "p" parameter is the part of
** the FROM clause that has already been constructed.  "p" is NULL
@@ -126360,10 +127017,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
  if( pAlias->n ){
    pItem->zAlias = sqlite3NameFromToken(db, pAlias);
  }
+
  assert( pSubquery==0 || pDatabase==0 );
  if( pSubquery ){
-
    pItem->pSelect = pSubquery;
-
    if( pSubquery->selFlags & SF_NestedFrom ){
-
      pItem->fg.isNestedFrom = 1;
+
    if( sqlite3SrcItemAttachSubquery(pParse, pItem, pSubquery, 0) ){
+
      if( pSubquery->selFlags & SF_NestedFrom ){
+
        pItem->fg.isNestedFrom = 1;
+
      }
    }
  }
  assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
@@ -127641,8 +128300,8 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
**
** The following fields are initialized appropriate in pSrc:
**
-
**    pSrc->a[0].pTab       Pointer to the Table object
-
**    pSrc->a[0].pIndex     Pointer to the INDEXED BY index, if there is one
+
**    pSrc->a[0].spTab        Pointer to the Table object
+
**    pSrc->a[0].u2.pIBIndex  Pointer to the INDEXED BY index, if there is one
**
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
@@ -127650,8 +128309,8 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
  Table *pTab;
  assert( pItem && pSrc->nSrc>=1 );
  pTab = sqlite3LocateTableItem(pParse, 0, pItem);
-
  if( pItem->pTab ) sqlite3DeleteTable(pParse->db, pItem->pTab);
-
  pItem->pTab = pTab;
+
  if( pItem->pSTab ) sqlite3DeleteTable(pParse->db, pItem->pSTab);
+
  pItem->pSTab = pTab;
  pItem->fg.notCte = 1;
  if( pTab ){
    pTab->nTabRef++;
@@ -127692,6 +128351,7 @@ SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *
**      is for a top-level SQL statement.
*/
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
+
  assert( IsVirtual(pTab) );
  if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
    return 1;
  }
@@ -127773,7 +128433,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
  if( pFrom ){
    assert( pFrom->nSrc==1 );
    pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
-
    pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+
    assert( pFrom->a[0].fg.fixedSchema==0 && pFrom->a[0].fg.isSubquery==0 );
+
    pFrom->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
    assert( pFrom->a[0].fg.isUsing==0 );
    assert( pFrom->a[0].u3.pOn==0 );
  }
@@ -127835,7 +128496,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
  **   );
  */

-
  pTab = pSrc->a[0].pTab;
+
  pTab = pSrc->a[0].pSTab;
  if( HasRowid(pTab) ){
    pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
    pEList = sqlite3ExprListAppend(
@@ -127868,9 +128529,9 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(

  /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
  ** and the SELECT subtree. */
-
  pSrc->a[0].pTab = 0;
+
  pSrc->a[0].pSTab = 0;
  pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
-
  pSrc->a[0].pTab = pTab;
+
  pSrc->a[0].pSTab = pTab;
  if( pSrc->a[0].fg.isIndexedBy ){
    assert( pSrc->a[0].fg.isCte==0 );
    pSrc->a[0].u2.pIBIndex = 0;
@@ -130697,7 +131358,11 @@ static void minMaxFinalize(sqlite3_context *context){
** group_concat(EXPR, ?SEPARATOR?)
** string_agg(EXPR, SEPARATOR)
**
-
** The SEPARATOR goes before the EXPR string.  This is tragic.  The
+
** Content is accumulated in GroupConcatCtx.str with the SEPARATOR
+
** coming before the EXPR value, except for the first entry which
+
** omits the SEPARATOR.
+
**
+
** It is tragic that the SEPARATOR goes before the EXPR string.  The
** groupConcatInverse() implementation would have been easier if the
** SEPARATOR were appended after EXPR.  And the order is undocumented,
** so we could change it, in theory.  But the old behavior has been
@@ -130801,7 +131466,7 @@ static void groupConcatInverse(
  /* pGCC is always non-NULL since groupConcatStep() will have always
  ** run first to initialize it */
  if( ALWAYS(pGCC) ){
-
    int nVS;
+
    int nVS;  /* Number of characters to remove */
    /* Must call sqlite3_value_text() to convert the argument into text prior
    ** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
    (void)sqlite3_value_text(argv[0]);
@@ -131179,7 +131844,13 @@ static void signFunc(
** Implementation of fpdecode(x,y,z) function.
**
** x is a real number that is to be decoded.  y is the precision.
-
** z is the maximum real precision.
+
** z is the maximum real precision.  Return a string that shows the
+
** results of the sqlite3FpDecode() function.
+
**
+
** Used for testing and debugging only, specifically testing and debugging
+
** of the sqlite3FpDecode() function.  This SQL function does not appear
+
** in production builds.  This function is not an API and is subject to
+
** modification or removal in future versions of SQLite.
*/
static void fpdecodeFunc(
  sqlite3_context *context,
@@ -131195,6 +131866,7 @@ static void fpdecodeFunc(
  x = sqlite3_value_double(argv[0]);
  y = sqlite3_value_int(argv[1]);
  z = sqlite3_value_int(argv[2]);
+
  if( z<=0 ) z = 1;
  sqlite3FpDecode(&s, x, y, z);
  if( s.isSpecial==2 ){
    sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
@@ -131205,6 +131877,82 @@ static void fpdecodeFunc(
}
#endif /* SQLITE_DEBUG */

+
#ifdef SQLITE_DEBUG
+
/*
+
** Implementation of parseuri(uri,flags) function.
+
**
+
** Required Arguments:
+
**    "uri"        The URI to parse.
+
**    "flags"      Bitmask of flags, as if to sqlite3_open_v2().
+
**
+
** Additional arguments beyond the first two make calls to
+
** sqlite3_uri_key() for integers and sqlite3_uri_parameter for
+
** anything else.
+
**
+
** The result is a string showing the results of calling sqlite3ParseUri().
+
**
+
** Used for testing and debugging only, specifically testing and debugging
+
** of the sqlite3ParseUri() function.  This SQL function does not appear
+
** in production builds.  This function is not an API and is subject to
+
** modification or removal in future versions of SQLite.
+
*/
+
static void parseuriFunc(
+
  sqlite3_context *ctx,
+
  int argc,
+
  sqlite3_value **argv
+
){
+
  sqlite3_str *pResult;
+
  const char *zVfs;
+
  const char *zUri;
+
  unsigned int flgs;
+
  int rc;
+
  sqlite3_vfs *pVfs = 0;
+
  char *zFile = 0;
+
  char *zErr = 0;
+

+
  if( argc<2 ) return;
+
  pVfs = sqlite3_vfs_find(0);
+
  assert( pVfs );
+
  zVfs = pVfs->zName;
+
  zUri = (const char*)sqlite3_value_text(argv[0]);
+
  if( zUri==0 ) return;
+
  flgs = (unsigned int)sqlite3_value_int(argv[1]);
+
  rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
+
  pResult = sqlite3_str_new(0);
+
  if( pResult ){
+
    int i;
+
    sqlite3_str_appendf(pResult, "rc=%d", rc);
+
    sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
+
    sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
+
    sqlite3_str_appendf(pResult, ", err=%Q", zErr);
+
    sqlite3_str_appendf(pResult, ", file=%Q", zFile);
+
    if( zFile ){
+
      const char *z = zFile;
+
      z += sqlite3Strlen30(z)+1;
+
      while( z[0] ){
+
        sqlite3_str_appendf(pResult, ", %Q", z);
+
        z += sqlite3Strlen30(z)+1;
+
      }
+
      for(i=2; i<argc; i++){
+
        const char *zArg;
+
        if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
+
          int k = sqlite3_value_int(argv[i]);
+
          sqlite3_str_appendf(pResult, ", '%d:%q'",k,sqlite3_uri_key(zFile, k));
+
        }else if( (zArg = (const char*)sqlite3_value_text(argv[i]))!=0 ){
+
          sqlite3_str_appendf(pResult, ", '%q:%q'",
+
                 zArg, sqlite3_uri_parameter(zFile,zArg));
+
        }else{
+
          sqlite3_str_appendf(pResult, ", NULL");
+
        }
+
      }
+
    }
+
    sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free);
+
  }
+
  sqlite3_free_filename(zFile);
+
  sqlite3_free(zErr);
+
}
+
#endif /* SQLITE_DEBUG */
+

/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table.  This occurs at start-time (as
@@ -131267,7 +132015,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
    WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
                                 SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
    FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
-
    FUNCTION2(subtype,           1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
+
    FUNCTION2(subtype,           1, 0, 0, subtypeFunc,
+
                                           SQLITE_FUNC_TYPEOF|SQLITE_SUBTYPE),
    FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
    FUNCTION2(octet_length,      1, 0, 0, bytelengthFunc,SQLITE_FUNC_BYTELEN),
    FUNCTION(instr,              2, 0, 0, instrFunc        ),
@@ -131278,6 +132027,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
    FUNCTION(abs,                1, 0, 0, absFunc          ),
#ifdef SQLITE_DEBUG
    FUNCTION(fpdecode,           3, 0, 0, fpdecodeFunc     ),
+
    FUNCTION(parseuri,          -1, 0, 0, parseuriFunc     ),
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(round,              1, 0, 0, roundFunc        ),
@@ -131372,7 +132122,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
    MFUNCTION(sqrt,              1, sqrt,      math1Func   ),
    MFUNCTION(radians,           1, degToRad,  math1Func   ),
    MFUNCTION(degrees,           1, radToDeg,  math1Func   ),
-
    FUNCTION(pi,                 0, 0, 0,      piFunc      ),
+
    MFUNCTION(pi,                0, 0,         piFunc      ),
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
    FUNCTION(sign,               1, 0, 0,      signFunc    ),
    INLINE_FUNC(coalesce,       -1, INLINEFUNC_coalesce, 0 ),
@@ -132451,9 +133201,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
    pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
    if( pSrc ){
      SrcItem *pItem = pSrc->a;
-
      pItem->pTab = pFKey->pFrom;
+
      pItem->pSTab = pFKey->pFrom;
      pItem->zName = pFKey->pFrom->zName;
-
      pItem->pTab->nTabRef++;
+
      pItem->pSTab->nTabRef++;
      pItem->iCursor = pParse->nTab++;

      if( regNew!=0 ){
@@ -132736,7 +133486,8 @@ static Trigger *fkActionTrigger(
      SrcList *pSrc;
      Expr *pRaise;

-
      pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
+
      pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"),
+
      pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0);
      if( pRaise ){
        pRaise->affExpr = OE_Abort;
      }
@@ -132744,7 +133495,8 @@ static Trigger *fkActionTrigger(
      if( pSrc ){
        assert( pSrc->nSrc==1 );
        pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom);
-
        pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+
        assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 );
+
        pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
      }
      pSelect = sqlite3SelectNew(pParse,
          sqlite3ExprListAppend(pParse, 0, pRaise),
@@ -133478,8 +134230,11 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
  if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){
    SrcItem *pItem = &pVal->pSrc->a[0];
-
    sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn);
-
    sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1);
+
    assert( (pItem->fg.isSubquery && pItem->u4.pSubq!=0) || pParse->nErr );
+
    if( pItem->fg.isSubquery ){
+
      sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->u4.pSubq->regReturn);
+
      sqlite3VdbeJumpHere(pParse->pVdbe, pItem->u4.pSubq->addrFillSub - 1);
+
    }
  }
}

@@ -133607,6 +134362,7 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList

      if( pRet ){
        SelectDest dest;
+
        Subquery *pSubq;
        pRet->pSrc->nSrc = 1;
        pRet->pPrior = pLeft->pPrior;
        pRet->op = pLeft->op;
@@ -133616,28 +134372,32 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
        assert( pLeft->pNext==0 );
        assert( pRet->pNext==0 );
        p = &pRet->pSrc->a[0];
-
        p->pSelect = pLeft;
        p->fg.viaCoroutine = 1;
-
        p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
-
        p->regReturn = ++pParse->nMem;
        p->iCursor = -1;
+
        assert( !p->fg.isIndexedBy && !p->fg.isTabFunc );
        p->u1.nRow = 2;
-
        sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub);
-
        sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn);
-

-
        /* Allocate registers for the output of the co-routine. Do so so
-
        ** that there are two unused registers immediately before those
-
        ** used by the co-routine. This allows the code in sqlite3Insert()
-
        ** to use these registers directly, instead of copying the output
-
        ** of the co-routine to a separate array for processing.  */
-
        dest.iSdst = pParse->nMem + 3;
-
        dest.nSdst = pLeft->pEList->nExpr;
-
        pParse->nMem += 2 + dest.nSdst;
-

-
        pLeft->selFlags |= SF_MultiValue;
-
        sqlite3Select(pParse, pLeft, &dest);
-
        p->regResult = dest.iSdst;
-
        assert( pParse->nErr || dest.iSdst>0 );
+
        if( sqlite3SrcItemAttachSubquery(pParse, p, pLeft, 0) ){
+
          pSubq = p->u4.pSubq;
+
          pSubq->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
+
          pSubq->regReturn = ++pParse->nMem;
+
          sqlite3VdbeAddOp3(v, OP_InitCoroutine,
+
                            pSubq->regReturn, 0, pSubq->addrFillSub);
+
          sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn);
+

+
          /* Allocate registers for the output of the co-routine. Do so so
+
          ** that there are two unused registers immediately before those
+
          ** used by the co-routine. This allows the code in sqlite3Insert()
+
          ** to use these registers directly, instead of copying the output
+
          ** of the co-routine to a separate array for processing.  */
+
          dest.iSdst = pParse->nMem + 3;
+
          dest.nSdst = pLeft->pEList->nExpr;
+
          pParse->nMem += 2 + dest.nSdst;
+

+
          pLeft->selFlags |= SF_MultiValue;
+
          sqlite3Select(pParse, pLeft, &dest);
+
          pSubq->regResult = dest.iSdst;
+
          assert( pParse->nErr || dest.iSdst>0 );
+
        }
        pLeft = pRet;
      }
    }else{
@@ -133647,12 +134407,18 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
    }

    if( pParse->nErr==0 ){
+
      Subquery *pSubq;
      assert( p!=0 );
-
      if( p->pSelect->pEList->nExpr!=pRow->nExpr ){
-
        sqlite3SelectWrongNumTermsError(pParse, p->pSelect);
+
      assert( p->fg.isSubquery );
+
      pSubq = p->u4.pSubq;
+
      assert( pSubq!=0 );
+
      assert( pSubq->pSelect!=0 );
+
      assert( pSubq->pSelect->pEList!=0 );
+
      if( pSubq->pSelect->pEList->nExpr!=pRow->nExpr ){
+
        sqlite3SelectWrongNumTermsError(pParse, pSubq->pSelect);
      }else{
-
        sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0);
-
        sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn);
+
        sqlite3ExprCodeExprList(pParse, pRow, pSubq->regResult, 0, 0);
+
        sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, pSubq->regReturn);
      }
    }
    sqlite3ExprListDelete(pParse->db, pRow);
@@ -134003,9 +134769,14 @@ SQLITE_PRIVATE void sqlite3Insert(
     && pSelect->pPrior==0
    ){
      SrcItem *pItem = &pSelect->pSrc->a[0];
-
      dest.iSDParm = pItem->regReturn;
-
      regFromSelect = pItem->regResult;
-
      nColumn = pItem->pSelect->pEList->nExpr;
+
      Subquery *pSubq;
+
      assert( pItem->fg.isSubquery );
+
      pSubq = pItem->u4.pSubq;
+
      dest.iSDParm = pSubq->regReturn;
+
      regFromSelect = pSubq->regResult;
+
      assert( pSubq->pSelect!=0 );
+
      assert( pSubq->pSelect->pEList!=0 );
+
      nColumn = pSubq->pSelect->pEList->nExpr;
      ExplainQueryPlan((pParse, 0, "SCAN %S", pItem));
      if( bIdListInOrder && nColumn==pTab->nCol ){
        regData = regFromSelect;
@@ -135925,7 +136696,7 @@ static int xferOptimization(
  if( pSelect->pSrc->nSrc!=1 ){
    return 0;   /* FROM clause must have exactly one term */
  }
-
  if( pSelect->pSrc->a[0].pSelect ){
+
  if( pSelect->pSrc->a[0].fg.isSubquery ){
    return 0;   /* FROM clause cannot contain a subquery */
  }
  if( pSelect->pWhere ){
@@ -140485,6 +141256,7 @@ SQLITE_PRIVATE void sqlite3Pragma(

      /* Make sure sufficient number of registers have been allocated */
      sqlite3TouchRegister(pParse, 8+cnt);
+
      sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt);
      sqlite3ClearTempRegCache(pParse);

      /* Do the b-tree integrity checks */
@@ -142810,12 +143582,24 @@ static int sqlite3Prepare16(
  if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
    return SQLITE_MISUSE_BKPT;
  }
+

+
  /* Make sure nBytes is non-negative and correct.  It should be the
+
  ** number of bytes until the end of the input buffer or until the first
+
  ** U+0000 character.  If the input nBytes is odd, convert it into
+
  ** an even number.  If the input nBytes is negative, then the input
+
  ** must be terminated by at least one U+0000 character */
  if( nBytes>=0 ){
    int sz;
    const char *z = (const char*)zSql;
    for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
    nBytes = sz;
+
  }else{
+
    int sz;
+
    const char *z = (const char*)zSql;
+
    for(sz=0; z[sz]!=0 || z[sz+1]!=0; sz += 2){}
+
    nBytes = sz;
  }
+

  sqlite3_mutex_enter(db->mutex);
  zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
  if( zSql8 ){
@@ -142829,7 +143613,7 @@ static int sqlite3Prepare16(
    ** the same number of characters into the UTF-16 string.
    */
    int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
-
    *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
+
    *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, nBytes, chars_parsed);
  }
  sqlite3DbFree(db, zSql8);
  rc = sqlite3ApiExit(db, rc);
@@ -143223,11 +144007,13 @@ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
*/
SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
  assert( pItem!=0 );
-
  assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+
  assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
  if( pItem->fg.isNestedFrom ){
    ExprList *pResults;
-
    assert( pItem->pSelect!=0 );
-
    pResults = pItem->pSelect->pEList;
+
    assert( pItem->fg.isSubquery );
+
    assert( pItem->u4.pSubq!=0 );
+
    assert( pItem->u4.pSubq->pSelect!=0 );
+
    pResults = pItem->u4.pSubq->pSelect->pEList;
    assert( pResults!=0 );
    assert( iCol>=0 && iCol<pResults->nExpr );
    pResults->a[iCol].fg.bUsed = 1;
@@ -143261,9 +144047,9 @@ static int tableAndColumnIndex(
  assert( (piTab==0)==(piCol==0) );  /* Both or neither are NULL */

  for(i=iStart; i<=iEnd; i++){
-
    iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
+
    iCol = sqlite3ColumnIndex(pSrc->a[i].pSTab, zCol);
    if( iCol>=0
-
     && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
+
     && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pSTab->aCol[iCol])==0)
    ){
      if( piTab ){
        sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
@@ -143392,10 +144178,10 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
  pLeft = &pSrc->a[0];
  pRight = &pLeft[1];
  for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
-
    Table *pRightTab = pRight->pTab;
+
    Table *pRightTab = pRight->pSTab;
    u32 joinType;

-
    if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
+
    if( NEVER(pLeft->pSTab==0 || pRightTab==0) ) continue;
    joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON;

    /* If this is a NATURAL join, synthesize an appropriate USING clause
@@ -144268,12 +145054,18 @@ static void selectInnerLoop(
        ** case the order does matter */
        pushOntoSorter(
            pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
+
        pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */
      }else{
        int r1 = sqlite3GetTempReg(pParse);
        assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
            r1, pDest->zAffSdst, nResultCol);
        sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
+
        if( pDest->iSDParm2 ){
+
          sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+
                               regResult, nResultCol);
+
          ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+
        }
        sqlite3ReleaseTempReg(pParse, r1);
      }
      break;
@@ -144815,8 +145607,12 @@ static const char *columnTypeImpl(
        SrcList *pTabList = pNC->pSrcList;
        for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
        if( j<pTabList->nSrc ){
-
          pTab = pTabList->a[j].pTab;
-
          pS = pTabList->a[j].pSelect;
+
          pTab = pTabList->a[j].pSTab;
+
          if( pTabList->a[j].fg.isSubquery ){
+
            pS = pTabList->a[j].u4.pSubq->pSelect;
+
          }else{
+
            pS = 0;
+
          }
        }else{
          pNC = pNC->pNext;
        }
@@ -145383,7 +146179,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
    p->iLimit = iLimit = ++pParse->nMem;
    v = sqlite3GetVdbe(pParse);
    assert( v!=0 );
-
    if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
+
    if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
      sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
      VdbeComment((v, "LIMIT counter"));
      if( n==0 ){
@@ -145863,7 +146659,7 @@ static int multiSelect(
        p->pPrior = pPrior;
        p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
        if( p->pLimit
-
         && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
+
         && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
         && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
        ){
          p->nSelectRow = sqlite3LogEst((u64)nLimit);
@@ -146207,6 +147003,11 @@ static int generateOutputSubroutine(
          r1, pDest->zAffSdst, pIn->nSdst);
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
                           pIn->iSdst, pIn->nSdst);
+
      if( pDest->iSDParm2>0 ){
+
        sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+
                             pIn->iSdst, pIn->nSdst);
+
        ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+
      }
      sqlite3ReleaseTempReg(pParse, r1);
      break;
    }
@@ -146863,7 +147664,9 @@ static void substSelect(
    pSrc = p->pSrc;
    assert( pSrc!=0 );
    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
-
      substSelect(pSubst, pItem->pSelect, 1);
+
      if( pItem->fg.isSubquery ){
+
        substSelect(pSubst, pItem->u4.pSubq->pSelect, 1);
+
      }
      if( pItem->fg.isTabFunc ){
        substExprList(pSubst, pItem->u1.pFuncArg);
      }
@@ -146894,7 +147697,7 @@ static void recomputeColumnsUsed(
  SrcItem *pSrcItem                /* Which FROM clause item to recompute */
){
  Walker w;
-
  if( NEVER(pSrcItem->pTab==0) ) return;
+
  if( NEVER(pSrcItem->pSTab==0) ) return;
  memset(&w, 0, sizeof(w));
  w.xExprCallback = recomputeColumnsUsedExpr;
  w.xSelectCallback = sqlite3SelectWalkNoop;
@@ -146934,8 +147737,10 @@ static void srclistRenumberCursors(
        aCsrMap[pItem->iCursor+1] = pParse->nTab++;
      }
      pItem->iCursor = aCsrMap[pItem->iCursor+1];
-
      for(p=pItem->pSelect; p; p=p->pPrior){
-
        srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+
      if( pItem->fg.isSubquery ){
+
        for(p=pItem->u4.pSubq->pSelect; p; p=p->pPrior){
+
          srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+
        }
      }
    }
  }
@@ -147246,7 +148051,8 @@ static int flattenSubquery(
  assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
  pSubitem = &pSrc->a[iFrom];
  iParent = pSubitem->iCursor;
-
  pSub = pSubitem->pSelect;
+
  assert( pSubitem->fg.isSubquery );
+
  pSub = pSubitem->u4.pSubq->pSelect;
  assert( pSub!=0 );

#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -147299,7 +148105,7 @@ static int flattenSubquery(
  */
  if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
    if( pSubSrc->nSrc>1                        /* (3a) */
-
     || IsVirtual(pSubSrc->a[0].pTab)          /* (3b) */
+
     || IsVirtual(pSubSrc->a[0].pSTab)         /* (3b) */
     || (p->selFlags & SF_Distinct)!=0         /* (3d) */
     || (pSubitem->fg.jointype & JT_RIGHT)!=0  /* (26) */
    ){
@@ -147385,14 +148191,18 @@ static int flattenSubquery(
  pParse->zAuthContext = zSavedAuthContext;

  /* Delete the transient structures associated with the subquery */
-
  pSub1 = pSubitem->pSelect;
-
  sqlite3DbFree(db, pSubitem->zDatabase);
+

+
  if( ALWAYS(pSubitem->fg.isSubquery) ){
+
    pSub1 = sqlite3SubqueryDetach(db, pSubitem);
+
  }else{
+
    pSub1 = 0;
+
  }
+
  assert( pSubitem->fg.isSubquery==0 );
+
  assert( pSubitem->fg.fixedSchema==0 );
  sqlite3DbFree(db, pSubitem->zName);
  sqlite3DbFree(db, pSubitem->zAlias);
-
  pSubitem->zDatabase = 0;
  pSubitem->zName = 0;
  pSubitem->zAlias = 0;
-
  pSubitem->pSelect = 0;
  assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 );

  /* If the sub-query is a compound SELECT statement, then (by restrictions
@@ -147433,8 +148243,8 @@ static int flattenSubquery(
    ExprList *pOrderBy = p->pOrderBy;
    Expr *pLimit = p->pLimit;
    Select *pPrior = p->pPrior;
-
    Table *pItemTab = pSubitem->pTab;
-
    pSubitem->pTab = 0;
+
    Table *pItemTab = pSubitem->pSTab;
+
    pSubitem->pSTab = 0;
    p->pOrderBy = 0;
    p->pPrior = 0;
    p->pLimit = 0;
@@ -147442,7 +148252,7 @@ static int flattenSubquery(
    p->pLimit = pLimit;
    p->pOrderBy = pOrderBy;
    p->op = TK_ALL;
-
    pSubitem->pTab = pItemTab;
+
    pSubitem->pSTab = pItemTab;
    if( pNew==0 ){
      p->pPrior = pPrior;
    }else{
@@ -147457,11 +148267,14 @@ static int flattenSubquery(
      TREETRACE(0x4,pParse,p,("compound-subquery flattener"
                              " creates %u as peer\n",pNew->selId));
    }
-
    assert( pSubitem->pSelect==0 );
+
    assert( pSubitem->fg.isSubquery==0 );
  }
  sqlite3DbFree(db, aCsrMap);
  if( db->mallocFailed ){
-
    pSubitem->pSelect = pSub1;
+
    assert( pSubitem->fg.fixedSchema==0 );
+
    assert( pSubitem->fg.isSubquery==0 );
+
    assert( pSubitem->u4.zDatabase==0 );
+
    sqlite3SrcItemAttachSubquery(pParse, pSubitem, pSub1, 0);
    return 1;
  }

@@ -147472,8 +148285,8 @@ static int flattenSubquery(
  **
  ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
  */
-
  if( ALWAYS(pSubitem->pTab!=0) ){
-
    Table *pTabToDel = pSubitem->pTab;
+
  if( ALWAYS(pSubitem->pSTab!=0) ){
+
    Table *pTabToDel = pSubitem->pSTab;
    if( pTabToDel->nTabRef==1 ){
      Parse *pToplevel = sqlite3ParseToplevel(pParse);
      sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel);
@@ -147481,7 +148294,7 @@ static int flattenSubquery(
    }else{
      pTabToDel->nTabRef--;
    }
-
    pSubitem->pTab = 0;
+
    pSubitem->pSTab = 0;
  }

  /* The following loop runs once for each term in a compound-subquery
@@ -147537,8 +148350,11 @@ static int flattenSubquery(
    */
    for(i=0; i<nSubSrc; i++){
      SrcItem *pItem = &pSrc->a[i+iFrom];
-
      if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
      assert( pItem->fg.isTabFunc==0 );
+
      assert( pItem->fg.isSubquery
+
           || pItem->fg.fixedSchema
+
           || pItem->u4.zDatabase==0 );
+
      if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
      *pItem = pSubSrc->a[i];
      pItem->fg.jointype |= ltorj;
      iNewParent = pSubSrc->a[i].iCursor;
@@ -147957,7 +148773,8 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
**
** NAME AMBIGUITY
**
-
** This optimization is called the "WHERE-clause push-down optimization".
+
** This optimization is called the "WHERE-clause push-down optimization"
+
** or sometimes the "predicate push-down optimization".
**
** Do not confuse this optimization with another unrelated optimization
** with a similar name:  The "MySQL push-down optimization" causes WHERE
@@ -148221,10 +149038,10 @@ static int disableUnusedSubqueryResultColumns(SrcItem *pItem){
  if( pItem->fg.isCorrelated || pItem->fg.isCte ){
    return 0;
  }
-
  assert( pItem->pTab!=0 );
-
  pTab = pItem->pTab;
-
  assert( pItem->pSelect!=0 );
-
  pSub = pItem->pSelect;
+
  assert( pItem->pSTab!=0 );
+
  pTab = pItem->pSTab;
+
  assert( pItem->fg.isSubquery );
+
  pSub = pItem->u4.pSubq->pSelect;
  assert( pSub->pEList->nExpr==pTab->nCol );
  for(pX=pSub; pX; pX=pX->pPrior){
    if( (pX->selFlags & (SF_Distinct|SF_Aggregate))!=0 ){
@@ -148353,13 +149170,13 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
  if( p->pWhere
   || p->pEList->nExpr!=1
   || p->pSrc->nSrc!=1
-
   || p->pSrc->a[0].pSelect
+
   || p->pSrc->a[0].fg.isSubquery
   || pAggInfo->nFunc!=1
   || p->pHaving
  ){
    return 0;
  }
-
  pTab = p->pSrc->a[0].pTab;
+
  pTab = p->pSrc->a[0].pSTab;
  assert( pTab!=0 );
  assert( !IsView(pTab) );
  if( !IsOrdinaryTable(pTab) ) return 0;
@@ -148384,7 +149201,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** pFrom->pIndex and return SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
-
  Table *pTab = pFrom->pTab;
+
  Table *pTab = pFrom->pSTab;
  char *zIndexedBy = pFrom->u1.zIndexedBy;
  Index *pIdx;
  assert( pTab!=0 );
@@ -148461,7 +149278,11 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
  if( pNew==0 ) return WRC_Abort;
  memset(&dummy, 0, sizeof(dummy));
  pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0);
-
  if( pNewSrc==0 ) return WRC_Abort;
+
  assert( pNewSrc!=0 || pParse->nErr );
+
  if( pParse->nErr ){
+
    sqlite3SrcListDelete(db, pNewSrc);
+
    return WRC_Abort;
+
  }
  *pNew = *p;
  p->pSrc = pNewSrc;
  p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0));
@@ -148516,7 +149337,7 @@ static struct Cte *searchWith(
){
  const char *zName = pItem->zName;
  With *p;
-
  assert( pItem->zDatabase==0 );
+
  assert( pItem->fg.fixedSchema || pItem->u4.zDatabase==0 );
  assert( zName!=0 );
  for(p=pWith; p; p=p->pOuter){
    int i;
@@ -148586,7 +149407,7 @@ static int resolveFromTermToCte(
  Cte *pCte;               /* Matched CTE (or NULL if no match) */
  With *pWith;             /* The matching WITH */

-
  assert( pFrom->pTab==0 );
+
  assert( pFrom->pSTab==0 );
  if( pParse->pWith==0 ){
    /* There are no WITH clauses in the stack.  No match is possible */
    return 0;
@@ -148596,7 +149417,8 @@ static int resolveFromTermToCte(
    ** go no further. */
    return 0;
  }
-
  if( pFrom->zDatabase!=0 ){
+
  assert( pFrom->fg.hadSchema==0 || pFrom->fg.notCte!=0 );
+
  if( pFrom->fg.fixedSchema==0 && pFrom->u4.zDatabase!=0 ){
    /* The FROM term contains a schema qualifier (ex: main.t1) and so
    ** it cannot possibly be a CTE reference. */
    return 0;
@@ -148632,7 +149454,7 @@ static int resolveFromTermToCte(
    }
    if( cannotBeFunction(pParse, pFrom) ) return 2;

-
    assert( pFrom->pTab==0 );
+
    assert( pFrom->pSTab==0 );
    pTab = sqlite3DbMallocZero(db, sizeof(Table));
    if( pTab==0 ) return 2;
    pCteUse = pCte->pUse;
@@ -148646,26 +149468,29 @@ static int resolveFromTermToCte(
      }
      pCteUse->eM10d = pCte->eM10d;
    }
-
    pFrom->pTab = pTab;
+
    pFrom->pSTab = pTab;
    pTab->nTabRef = 1;
    pTab->zName = sqlite3DbStrDup(db, pCte->zName);
    pTab->iPKey = -1;
    pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
    pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
-
    pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
+
    sqlite3SrcItemAttachSubquery(pParse, pFrom, pCte->pSelect, 1);
    if( db->mallocFailed ) return 2;
-
    pFrom->pSelect->selFlags |= SF_CopyCte;
-
    assert( pFrom->pSelect );
+
    assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+
    pSel = pFrom->u4.pSubq->pSelect;
+
    assert( pSel!=0 );
+
    pSel->selFlags |= SF_CopyCte;
    if( pFrom->fg.isIndexedBy ){
      sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
      return 2;
    }
+
    assert( !pFrom->fg.isIndexedBy );
    pFrom->fg.isCte = 1;
    pFrom->u2.pCteUse = pCteUse;
    pCteUse->nUse++;

    /* Check if this is a recursive CTE. */
-
    pRecTerm = pSel = pFrom->pSelect;
+
    pRecTerm = pSel;
    bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
    while( bMayRecursive && pRecTerm->op==pSel->op ){
      int i;
@@ -148673,11 +149498,13 @@ static int resolveFromTermToCte(
      assert( pRecTerm->pPrior!=0 );
      for(i=0; i<pSrc->nSrc; i++){
        SrcItem *pItem = &pSrc->a[i];
-
        if( pItem->zDatabase==0
-
         && pItem->zName!=0
+
        if( pItem->zName!=0
+
         && !pItem->fg.hadSchema
+
         && ALWAYS( !pItem->fg.isSubquery )
+
         && (pItem->fg.fixedSchema || pItem->u4.zDatabase==0)
         && 0==sqlite3StrICmp(pItem->zName, pCte->zName)
        ){
-
          pItem->pTab = pTab;
+
          pItem->pSTab = pTab;
          pTab->nTabRef++;
          pItem->fg.isRecursive = 1;
          if( pRecTerm->selFlags & SF_Recursive ){
@@ -148779,11 +149606,14 @@ SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){
** SQLITE_NOMEM.
*/
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
-
  Select *pSel = pFrom->pSelect;
+
  Select *pSel;
  Table *pTab;

+
  assert( pFrom->fg.isSubquery );
+
  assert( pFrom->u4.pSubq!=0 );
+
  pSel = pFrom->u4.pSubq->pSelect;
  assert( pSel );
-
  pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
+
  pFrom->pSTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
  if( pTab==0 ) return SQLITE_NOMEM;
  pTab->nTabRef = 1;
  if( pFrom->zAlias ){
@@ -148903,33 +149733,35 @@ static int selectExpander(Walker *pWalker, Select *p){
  */
  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
    Table *pTab;
-
    assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
-
    if( pFrom->pTab ) continue;
+
    assert( pFrom->fg.isRecursive==0 || pFrom->pSTab!=0 );
+
    if( pFrom->pSTab ) continue;
    assert( pFrom->fg.isRecursive==0 );
    if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
-
      Select *pSel = pFrom->pSelect;
+
      Select *pSel;
+
      assert( pFrom->fg.isSubquery && pFrom->u4.pSubq!=0 );
+
      pSel = pFrom->u4.pSubq->pSelect;
      /* A sub-query in the FROM clause of a SELECT */
      assert( pSel!=0 );
-
      assert( pFrom->pTab==0 );
+
      assert( pFrom->pSTab==0 );
      if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
      if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
#ifndef SQLITE_OMIT_CTE
    }else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
      if( rc>1 ) return WRC_Abort;
-
      pTab = pFrom->pTab;
+
      pTab = pFrom->pSTab;
      assert( pTab!=0 );
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
-
      assert( pFrom->pTab==0 );
-
      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
+
      assert( pFrom->pSTab==0 );
+
      pFrom->pSTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
      if( pTab==0 ) return WRC_Abort;
      if( pTab->nTabRef>=0xffff ){
        sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
           pTab->zName);
-
        pFrom->pTab = 0;
+
        pFrom->pSTab = 0;
        return WRC_Abort;
      }
      pTab->nTabRef++;
@@ -148941,7 +149773,7 @@ static int selectExpander(Walker *pWalker, Select *p){
        i16 nCol;
        u8 eCodeOrig = pWalker->eCode;
        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
-
        assert( pFrom->pSelect==0 );
+
        assert( pFrom->fg.isSubquery==0 );
        if( IsView(pTab) ){
          if( (db->flags & SQLITE_EnableView)==0
           && pTab->pSchema!=db->aDb[1].pSchema
@@ -148949,7 +149781,7 @@ static int selectExpander(Walker *pWalker, Select *p){
            sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
              pTab->zName);
          }
-
          pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
+
          sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
        }
#ifndef SQLITE_OMIT_VIRTUALTABLE
        else if( ALWAYS(IsVirtual(pTab))
@@ -148965,7 +149797,9 @@ static int selectExpander(Walker *pWalker, Select *p){
        nCol = pTab->nCol;
        pTab->nCol = -1;
        pWalker->eCode = 1;  /* Turn on Select.selId renumbering */
-
        sqlite3WalkSelect(pWalker, pFrom->pSelect);
+
        if( pFrom->fg.isSubquery ){
+
          sqlite3WalkSelect(pWalker, pFrom->u4.pSubq->pSelect);
+
        }
        pWalker->eCode = eCodeOrig;
        pTab->nCol = nCol;
      }
@@ -149052,7 +149886,7 @@ static int selectExpander(Walker *pWalker, Select *p){
        }
        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
          int nAdd;                    /* Number of cols including rowid */
-
          Table *pTab = pFrom->pTab;   /* Table for this data source */
+
          Table *pTab = pFrom->pSTab;  /* Table for this data source */
          ExprList *pNestedFrom;       /* Result-set of a nested FROM clause */
          char *zTabName;              /* AS name for this data source */
          const char *zSchemaName = 0; /* Schema name for this data source */
@@ -149063,10 +149897,11 @@ static int selectExpander(Walker *pWalker, Select *p){
            zTabName = pTab->zName;
          }
          if( db->mallocFailed ) break;
-
          assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
+
          assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom) );
          if( pFrom->fg.isNestedFrom ){
-
            assert( pFrom->pSelect!=0 );
-
            pNestedFrom = pFrom->pSelect->pEList;
+
            assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+
            assert( pFrom->u4.pSubq->pSelect!=0 );
+
            pNestedFrom = pFrom->u4.pSubq->pSelect->pEList;
            assert( pNestedFrom!=0 );
            assert( pNestedFrom->nExpr==pTab->nCol );
            assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
@@ -149305,14 +150140,12 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
  assert( (p->selFlags & SF_Resolved) );
  pTabList = p->pSrc;
  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
-
    Table *pTab = pFrom->pTab;
+
    Table *pTab = pFrom->pSTab;
    assert( pTab!=0 );
-
    if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
+
    if( (pTab->tabFlags & TF_Ephemeral)!=0 && pFrom->fg.isSubquery ){
      /* A sub-query in the FROM clause of a SELECT */
-
      Select *pSel = pFrom->pSelect;
-
      if( pSel ){
-
        sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
-
      }
+
      Select *pSel = pFrom->u4.pSubq->pSelect;
+
      sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
    }
  }
}
@@ -149626,6 +150459,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    ExprList *pList;
    assert( ExprUseXList(pF->pFExpr) );
+
    if( pParse->nErr ) return;
    pList = pF->pFExpr->x.pList;
    if( pF->iOBTab>=0 ){
      /* For an ORDER BY aggregate, calls to OP_AggStep were deferred.  Inputs
@@ -149835,6 +150669,7 @@ static void updateAccumulator(
    if( addrNext ){
      sqlite3VdbeResolveLabel(v, addrNext);
    }
+
    if( pParse->nErr ) return;
  }
  if( regHit==0 && pAggInfo->nAccumulator ){
    regHit = regAcc;
@@ -149844,6 +150679,7 @@ static void updateAccumulator(
  }
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite3ExprCode(pParse, pC->pCExpr, AggInfoColumnReg(pAggInfo,i));
+
    if( pParse->nErr ) return;
  }

  pAggInfo->directMode = 0;
@@ -149959,25 +150795,28 @@ static SrcItem *isSelfJoinView(
  int iFirst, int iEnd        /* Range of FROM-clause entries to search. */
){
  SrcItem *pItem;
-
  assert( pThis->pSelect!=0 );
-
  if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
+
  Select *pSel;
+
  assert( pThis->fg.isSubquery );
+
  pSel = pThis->u4.pSubq->pSelect;
+
  assert( pSel!=0 );
+
  if( pSel->selFlags & SF_PushDown ) return 0;
  while( iFirst<iEnd ){
    Select *pS1;
    pItem = &pTabList->a[iFirst++];
-
    if( pItem->pSelect==0 ) continue;
+
    if( !pItem->fg.isSubquery ) continue;
    if( pItem->fg.viaCoroutine ) continue;
    if( pItem->zName==0 ) continue;
-
    assert( pItem->pTab!=0 );
-
    assert( pThis->pTab!=0 );
-
    if( pItem->pTab->pSchema!=pThis->pTab->pSchema ) continue;
+
    assert( pItem->pSTab!=0 );
+
    assert( pThis->pSTab!=0 );
+
    if( pItem->pSTab->pSchema!=pThis->pSTab->pSchema ) continue;
    if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
-
    pS1 = pItem->pSelect;
-
    if( pItem->pTab->pSchema==0 && pThis->pSelect->selId!=pS1->selId ){
+
    pS1 = pItem->u4.pSubq->pSelect;
+
    if( pItem->pSTab->pSchema==0 && pSel->selId!=pS1->selId ){
      /* The query flattener left two different CTE tables with identical
      ** names in the same FROM clause. */
      continue;
    }
-
    if( pItem->pSelect->selFlags & SF_PushDown ){
+
    if( pS1->selFlags & SF_PushDown ){
      /* The view was modified by some other optimization such as
      ** pushDownWhereTerms() */
      continue;
@@ -150021,6 +150860,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
  Expr *pExpr;
  Expr *pCount;
  sqlite3 *db;
+
  SrcItem *pFrom;
  if( (p->selFlags & SF_Aggregate)==0 ) return 0;   /* This is an aggregate */
  if( p->pEList->nExpr!=1 ) return 0;               /* Single result column */
  if( p->pWhere ) return 0;
@@ -150035,8 +150875,9 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
  if( pExpr->x.pList!=0 ) return 0;                 /* Must be count(*) */
  if( p->pSrc->nSrc!=1 ) return 0;                  /* One table in FROM  */
  if( ExprHasProperty(pExpr, EP_WinFunc) ) return 0;/* Not a window function */
-
  pSub = p->pSrc->a[0].pSelect;
-
  if( pSub==0 ) return 0;                           /* The FROM is a subquery */
+
  pFrom = p->pSrc->a;
+
  if( pFrom->fg.isSubquery==0 ) return 0;    /* FROM is a subquery */
+
  pSub = pFrom->u4.pSubq->pSelect;
  if( pSub->pPrior==0 ) return 0;                   /* Must be a compound */
  if( pSub->selFlags & SF_CopyCte ) return 0;       /* Not a CTE */
  do{
@@ -150045,7 +150886,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
    if( pSub->pLimit ) return 0;                      /* No LIMIT clause */
    if( pSub->selFlags & SF_Aggregate ) return 0;     /* Not an aggregate */
    assert( pSub->pHaving==0 );  /* Due to the previous */
-
   pSub = pSub->pPrior;                              /* Repeat over compound */
+
    pSub = pSub->pPrior;                              /* Repeat over compound */
  }while( pSub );

  /* If we reach this point then it is OK to perform the transformation */
@@ -150053,8 +150894,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
  db = pParse->db;
  pCount = pExpr;
  pExpr = 0;
-
  pSub = p->pSrc->a[0].pSelect;
-
  p->pSrc->a[0].pSelect = 0;
+
  pSub = sqlite3SubqueryDetach(db, pFrom);
  sqlite3SrcListDelete(db, p->pSrc);
  p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
  while( pSub ){
@@ -150099,12 +150939,12 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
  for(i=0; i<pSrc->nSrc; i++){
    SrcItem *p1 = &pSrc->a[i];
    if( p1==p0 ) continue;
-
    if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
+
    if( p0->pSTab==p1->pSTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
      return 1;
    }
-
    if( p1->pSelect
-
     && (p1->pSelect->selFlags & SF_NestedFrom)!=0
-
     && sameSrcAlias(p0, p1->pSelect->pSrc)
+
    if( p1->fg.isSubquery
+
     && (p1->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0
+
     && sameSrcAlias(p0, p1->u4.pSubq->pSelect->pSrc)
    ){
      return 1;
    }
@@ -150169,13 +151009,13 @@ static int fromClauseTermCanBeCoroutine(
    if( i==0 ) break;
    i--;
    pItem--;
-
    if( pItem->pSelect!=0 ) return 0;                             /* (1c-i) */
+
    if( pItem->fg.isSubquery ) return 0;                          /* (1c-i) */
  }
  return 1;
}

/*
-
** Generate code for the SELECT statement given in the p argument.
+
** Generate byte-code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
@@ -150186,6 +151026,40 @@ static int fromClauseTermCanBeCoroutine(
**
** This routine does NOT free the Select structure passed in.  The
** calling function needs to do that.
+
**
+
** This is a long function.  The following is an outline of the processing
+
** steps, with tags referencing various milestones:
+
**
+
**  *  Resolve names and similar preparation                tag-select-0100
+
**  *  Scan of the FROM clause                              tag-select-0200
+
**      +  OUTER JOIN strength reduction                      tag-select-0220
+
**      +  Sub-query ORDER BY removal                         tag-select-0230
+
**      +  Query flattening                                   tag-select-0240
+
**  *  Separate subroutine for compound-SELECT              tag-select-0300
+
**  *  WHERE-clause constant propagation                    tag-select-0330
+
**  *  Count()-of-VIEW optimization                         tag-select-0350
+
**  *  Scan of the FROM clause again                        tag-select-0400
+
**      +  Authorize unreferenced tables                      tag-select-0410
+
**      +  Predicate push-down optimization                   tag-select-0420
+
**      +  Omit unused subquery columns optimization          tag-select-0440
+
**      +  Generate code to implement subqueries              tag-select-0480
+
**         -  Co-routines                                       tag-select-0482
+
**         -  Reuse previously computed CTE                     tag-select-0484
+
**         -  REuse previously computed VIEW                    tag-select-0486
+
**         -  Materialize a VIEW or CTE                         tag-select-0488
+
**  *  DISTINCT ORDER BY -> GROUP BY optimization           tag-select-0500
+
**  *  Set up for ORDER BY                                  tag-select-0600
+
**  *  Create output table                                  tag-select-0630
+
**  *  Prepare registers for LIMIT                          tag-select-0650
+
**  *  Setup for DISTINCT                                   tag-select-0680
+
**  *  Generate code for non-aggregate and non-GROUP BY     tag-select-0700
+
**  *  Generate code for aggregate and/or GROUP BY          tag-select-0800
+
**      +  GROUP BY queries                                   tag-select-0810
+
**      +  non-GROUP BY queries                               tag-select-0820
+
**         -  Special case of count() w/o GROUP BY              tag-select-0821
+
**         -  General case of non-GROUP BY aggregates           tag-select-0822
+
**  *  Sort results, as needed                              tag-select-0900
+
**  *  Internal self-checks                                 tag-select-1000
*/
SQLITE_PRIVATE int sqlite3Select(
  Parse *pParse,         /* The parser context */
@@ -150229,6 +151103,7 @@ SQLITE_PRIVATE int sqlite3Select(
  }
#endif

+
  /* tag-select-0100 */
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
@@ -150280,7 +151155,7 @@ SQLITE_PRIVATE int sqlite3Select(
    if( sameSrcAlias(p0, p->pSrc) ){
      sqlite3ErrorMsg(pParse,
          "target object/alias may not appear in FROM clause: %s",
-
          p0->zAlias ? p0->zAlias : p0->pTab->zName
+
          p0->zAlias ? p0->zAlias : p0->pSTab->zName
      );
      goto select_end;
    }
@@ -150315,12 +151190,13 @@ SQLITE_PRIVATE int sqlite3Select(

  /* Try to do various optimizations (flattening subqueries, and strength
  ** reduction of join operators) in the FROM clause up into the main query
+
  ** tag-select-0200
  */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
    SrcItem *pItem = &pTabList->a[i];
-
    Select *pSub = pItem->pSelect;
-
    Table *pTab = pItem->pTab;
+
    Select *pSub = pItem->fg.isSubquery ? pItem->u4.pSubq->pSelect : 0;
+
    Table *pTab = pItem->pSTab;

    /* The expander should have already created transient Table objects
    ** even for FROM clause elements such as subqueries that do not correspond
@@ -150337,6 +151213,7 @@ SQLITE_PRIVATE int sqlite3Select(
    ** way that the i-th table cannot be the NULL row of a join, then
    ** perform the appropriate simplification. This is called
    ** "OUTER JOIN strength reduction" in the SQLite documentation.
+
    ** tag-select-0220
    */
    if( (pItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0
     && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor,
@@ -150407,7 +151284,8 @@ SQLITE_PRIVATE int sqlite3Select(
    if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
    assert( pSub->pGroupBy==0 );

-
    /* If a FROM-clause subquery has an ORDER BY clause that is not
+
    /* tag-select-0230:
+
    ** If a FROM-clause subquery has an ORDER BY clause that is not
    ** really doing anything, then delete it now so that it does not
    ** interfere with query flattening.  See the discussion at
    ** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a
@@ -150426,13 +151304,16 @@ SQLITE_PRIVATE int sqlite3Select(
    **            (a)  The outer query has a different ORDER BY clause
    **            (b)  The subquery is part of a join
    **          See forum post 062d576715d277c8
+
    **    (6)   The subquery is not a recursive CTE.  ORDER BY has a different
+
    **          meaning for recursive CTEs and this optimization does not
+
    **          apply.
    **
    ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled.
    */
    if( pSub->pOrderBy!=0
     && (p->pOrderBy!=0 || pTabList->nSrc>1)      /* Condition (5) */
     && pSub->pLimit==0                           /* Condition (1) */
-
     && (pSub->selFlags & SF_OrderByReqd)==0      /* Condition (2) */
+
     && (pSub->selFlags & (SF_OrderByReqd|SF_Recursive))==0  /* (2) and (6) */
     && (p->selFlags & SF_OrderByReqd)==0         /* Condition (3) and (4) */
     && OptimizationEnabled(db, SQLITE_OmitOrderBy)
    ){
@@ -150470,6 +151351,7 @@ SQLITE_PRIVATE int sqlite3Select(
      continue;
    }

+
    /* tag-select-0240 */
    if( flattenSubquery(pParse, p, i, isAgg) ){
      if( pParse->nErr ) goto select_end;
      /* This subquery can be absorbed into its parent. */
@@ -150485,7 +151367,7 @@ SQLITE_PRIVATE int sqlite3Select(

#ifndef SQLITE_OMIT_COMPOUND_SELECT
  /* Handle compound SELECT statements using the separate multiSelect()
-
  ** procedure.
+
  ** procedure.  tag-select-0300
  */
  if( p->pPrior ){
    rc = multiSelect(pParse, p, pDest);
@@ -150501,9 +151383,9 @@ SQLITE_PRIVATE int sqlite3Select(
#endif

  /* Do the WHERE-clause constant propagation optimization if this is
-
  ** a join.  No need to speed time on this operation for non-join queries
+
  ** a join.  No need to spend time on this operation for non-join queries
  ** as the equivalent optimization will be handled by query planner in
-
  ** sqlite3WhereBegin().
+
  ** sqlite3WhereBegin().  tag-select-0330
  */
  if( p->pWhere!=0
   && p->pWhere->op==TK_AND
@@ -150520,6 +151402,7 @@ SQLITE_PRIVATE int sqlite3Select(
    TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n"));
  }

+
  /* tag-select-0350 */
  if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
   && countOfViewOptimization(pParse, p)
  ){
@@ -150527,20 +151410,26 @@ SQLITE_PRIVATE int sqlite3Select(
    pTabList = p->pSrc;
  }

-
  /* For each term in the FROM clause, do two things:
-
  ** (1) Authorized unreferenced tables
-
  ** (2) Generate code for all sub-queries
+
  /* Loop over all terms in the FROM clause and do two things for each term:
+
  **
+
  **   (1) Authorize unreferenced tables
+
  **   (2) Generate code for all sub-queries
+
  **
+
  ** tag-select-0400
  */
  for(i=0; i<pTabList->nSrc; i++){
    SrcItem *pItem = &pTabList->a[i];
    SrcItem *pPrior;
    SelectDest dest;
+
    Subquery *pSubq;
    Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
    const char *zSavedAuthContext;
#endif

-
    /* Issue SQLITE_READ authorizations with a fake column name for any
+
    /* Authorized unreferenced tables.  tag-select-0410
+
    **
+
    ** Issue SQLITE_READ authorizations with a fake column name for any
    ** tables that are referenced but from which no values are extracted.
    ** Examples of where these kinds of null SQLITE_READ authorizations
    ** would occur:
@@ -150557,17 +151446,28 @@ SQLITE_PRIVATE int sqlite3Select(
    ** string for the fake column name seems safer.
    */
    if( pItem->colUsed==0 && pItem->zName!=0 ){
-
      sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
+
      const char *zDb;
+
      if( pItem->fg.fixedSchema ){
+
        int iDb = sqlite3SchemaToIndex(pParse->db, pItem->u4.pSchema);
+
        zDb = db->aDb[iDb].zDbSName;
+
      }else if( pItem->fg.isSubquery ){
+
        zDb = 0;
+
      }else{
+
        zDb = pItem->u4.zDatabase;
+
      }
+
      sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", zDb);
    }

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
    /* Generate code for all sub-queries in the FROM clause
    */
-
    pSub = pItem->pSelect;
-
    if( pSub==0 || pItem->addrFillSub!=0 ) continue;
+
    if( pItem->fg.isSubquery==0 ) continue;
+
    pSubq = pItem->u4.pSubq;
+
    assert( pSubq!=0 );
+
    pSub = pSubq->pSelect;

    /* The code for a subquery should only be generated once. */
-
    assert( pItem->addrFillSub==0 );
+
    if( pSubq->addrFillSub!=0 ) continue;

    /* Increment Parse.nHeight by the height of the largest expression
    ** tree referred to by this, the parent select. The child select
@@ -150580,6 +151480,7 @@ SQLITE_PRIVATE int sqlite3Select(

    /* Make copies of constant WHERE-clause terms in the outer query down
    ** inside the subquery.  This can help the subquery to run more efficiently.
+
    ** This is the "predicate push-down optimization".  tag-select-0420
    */
    if( OptimizationEnabled(db, SQLITE_PushDown)
     && (pItem->fg.isCte==0
@@ -150593,13 +151494,14 @@ SQLITE_PRIVATE int sqlite3Select(
        sqlite3TreeViewSelect(0, p, 0);
      }
#endif
-
      assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
+
      assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 );
    }else{
      TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
    }

    /* Convert unused result columns of the subquery into simple NULL
    ** expressions, to avoid unneeded searching and computation.
+
    ** tag-select-0440
    */
    if( OptimizationEnabled(db, SQLITE_NullUnusedCols)
     && disableUnusedSubqueryResultColumns(pItem)
@@ -150617,32 +151519,33 @@ SQLITE_PRIVATE int sqlite3Select(
    zSavedAuthContext = pParse->zAuthContext;
    pParse->zAuthContext = pItem->zName;

-
    /* Generate code to implement the subquery
+
    /* Generate byte-code to implement the subquery  tag-select-0480
    */
    if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){
      /* Implement a co-routine that will return a single row of the result
-
      ** set on each invocation.
+
      ** set on each invocation.  tag-select-0482
      */
      int addrTop = sqlite3VdbeCurrentAddr(v)+1;

-
      pItem->regReturn = ++pParse->nMem;
-
      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
+
      pSubq->regReturn = ++pParse->nMem;
+
      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pSubq->regReturn, 0, addrTop);
      VdbeComment((v, "%!S", pItem));
-
      pItem->addrFillSub = addrTop;
-
      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+
      pSubq->addrFillSub = addrTop;
+
      sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn);
      ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
      sqlite3Select(pParse, pSub, &dest);
-
      pItem->pTab->nRowLogEst = pSub->nSelectRow;
+
      pItem->pSTab->nRowLogEst = pSub->nSelectRow;
      pItem->fg.viaCoroutine = 1;
-
      pItem->regResult = dest.iSdst;
-
      sqlite3VdbeEndCoroutine(v, pItem->regReturn);
+
      pSubq->regResult = dest.iSdst;
+
      sqlite3VdbeEndCoroutine(v, pSubq->regReturn);
+
      VdbeComment((v, "end %!S", pItem));
      sqlite3VdbeJumpHere(v, addrTop-1);
      sqlite3ClearTempRegCache(pParse);
    }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
      /* This is a CTE for which materialization code has already been
      ** generated.  Invoke the subroutine to compute the materialization,
-
      ** the make the pItem->iCursor be a copy of the ephemeral table that
-
      ** holds the result of the materialization. */
+
      ** then make the pItem->iCursor be a copy of the ephemeral table that
+
      ** holds the result of the materialization. tag-select-0484 */
      CteUse *pCteUse = pItem->u2.pCteUse;
      sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
      if( pItem->iCursor!=pCteUse->iCur ){
@@ -150652,25 +151555,30 @@ SQLITE_PRIVATE int sqlite3Select(
      pSub->nSelectRow = pCteUse->nRowEst;
    }else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){
      /* This view has already been materialized by a prior entry in
-
      ** this same FROM clause.  Reuse it. */
-
      if( pPrior->addrFillSub ){
-
        sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
+
      ** this same FROM clause.  Reuse it.  tag-select-0486 */
+
      Subquery *pPriorSubq;
+
      assert( pPrior->fg.isSubquery );
+
      pPriorSubq = pPrior->u4.pSubq;
+
      assert( pPriorSubq!=0 );
+
      if( pPriorSubq->addrFillSub ){
+
        sqlite3VdbeAddOp2(v, OP_Gosub, pPriorSubq->regReturn,
+
                                       pPriorSubq->addrFillSub);
      }
      sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
-
      pSub->nSelectRow = pPrior->pSelect->nSelectRow;
+
      pSub->nSelectRow = pPriorSubq->pSelect->nSelectRow;
    }else{
      /* Materialize the view.  If the view is not correlated, generate a
      ** subroutine to do the materialization so that subsequent uses of
-
      ** the same view can reuse the materialization. */
+
      ** the same view can reuse the materialization.  tag-select-0488 */
      int topAddr;
      int onceAddr = 0;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
      int addrExplain;
#endif

-
      pItem->regReturn = ++pParse->nMem;
+
      pSubq->regReturn = ++pParse->nMem;
      topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
-
      pItem->addrFillSub = topAddr+1;
+
      pSubq->addrFillSub = topAddr+1;
      pItem->fg.isMaterialized = 1;
      if( pItem->fg.isCorrelated==0 ){
        /* If the subquery is not correlated and if we are not inside of
@@ -150685,17 +151593,17 @@ SQLITE_PRIVATE int sqlite3Select(

      ExplainQueryPlan2(addrExplain, (pParse, 1, "MATERIALIZE %!S", pItem));
      sqlite3Select(pParse, pSub, &dest);
-
      pItem->pTab->nRowLogEst = pSub->nSelectRow;
+
      pItem->pSTab->nRowLogEst = pSub->nSelectRow;
      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
-
      sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1);
+
      sqlite3VdbeAddOp2(v, OP_Return, pSubq->regReturn, topAddr+1);
      VdbeComment((v, "end %!S", pItem));
      sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1);
      sqlite3VdbeJumpHere(v, topAddr);
      sqlite3ClearTempRegCache(pParse);
      if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
        CteUse *pCteUse = pItem->u2.pCteUse;
-
        pCteUse->addrM9e = pItem->addrFillSub;
-
        pCteUse->regRtn = pItem->regReturn;
+
        pCteUse->addrM9e = pSubq->addrFillSub;
+
        pCteUse->regRtn = pSubq->regReturn;
        pCteUse->iCur = pItem->iCursor;
        pCteUse->nRowEst = pSub->nSelectRow;
      }
@@ -150721,7 +151629,9 @@ SQLITE_PRIVATE int sqlite3Select(
  }
#endif

-
  /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
+
  /* tag-select-0500
+
  **
+
  ** If the query is DISTINCT with an ORDER BY but is not an aggregate, and
  ** if the select-list is the same as the ORDER BY list, then this query
  ** can be rewritten as a GROUP BY. In other words, this:
  **
@@ -150738,12 +151648,18 @@ SQLITE_PRIVATE int sqlite3Select(
  */
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
   && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
+
   && OptimizationEnabled(db, SQLITE_GroupByOrder)
#ifndef SQLITE_OMIT_WINDOWFUNC
   && p->pWin==0
#endif
  ){
    p->selFlags &= ~SF_Distinct;
    pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
+
    if( pGroupBy ){
+
      for(i=0; i<pGroupBy->nExpr; i++){
+
        pGroupBy->a[i].u.x.iOrderByCol = i+1;
+
      }
+
    }
    p->selFlags |= SF_Aggregate;
    /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
    ** the sDistinct.isTnct is still set.  Hence, isTnct represents the
@@ -150765,7 +151681,7 @@ SQLITE_PRIVATE int sqlite3Select(
  ** If that is the case, then the OP_OpenEphemeral instruction will be
  ** changed to an OP_Noop once we figure out that the sorting index is
  ** not needed.  The sSort.addrSortIndex variable is used to facilitate
-
  ** that change.
+
  ** that change.  tag-select-0600
  */
  if( sSort.pOrderBy ){
    KeyInfo *pKeyInfo;
@@ -150782,6 +151698,7 @@ SQLITE_PRIVATE int sqlite3Select(
  }

  /* If the output is destined for a temporary table, open that table.
+
  ** tag-select-0630
  */
  if( pDest->eDest==SRT_EphemTab ){
    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
@@ -150799,7 +151716,7 @@ SQLITE_PRIVATE int sqlite3Select(
    }
  }

-
  /* Set the limiter.
+
  /* Set the limiter.  tag-select-0650
  */
  iEnd = sqlite3VdbeMakeLabel(pParse);
  if( (p->selFlags & SF_FixedLimit)==0 ){
@@ -150811,7 +151728,7 @@ SQLITE_PRIVATE int sqlite3Select(
    sSort.sortFlags |= SORTFLAG_UseSorter;
  }

-
  /* Open an ephemeral index to use for the distinct set.
+
  /* Open an ephemeral index to use for the distinct set. tag-select-0680
  */
  if( p->selFlags & SF_Distinct ){
    sDistinct.tabTnct = pParse->nTab++;
@@ -150826,7 +151743,7 @@ SQLITE_PRIVATE int sqlite3Select(
  }

  if( !isAgg && pGroupBy==0 ){
-
    /* No aggregate functions and no GROUP BY clause */
+
    /* No aggregate functions and no GROUP BY clause.  tag-select-0700 */
    u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
                   | (p->selFlags & SF_FixedLimit);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -150899,8 +151816,8 @@ SQLITE_PRIVATE int sqlite3Select(
      sqlite3WhereEnd(pWInfo);
    }
  }else{
-
    /* This case when there exist aggregate functions or a GROUP BY clause
-
    ** or both */
+
    /* This case is for when there exist aggregate functions or a GROUP BY
+
    ** clause or both.  tag-select-0800 */
    NameContext sNC;    /* Name context for processing aggregate information */
    int iAMem;          /* First Mem address for storing current GROUP BY */
    int iBMem;          /* First Mem address for previous GROUP BY */
@@ -151019,7 +151936,7 @@ SQLITE_PRIVATE int sqlite3Select(


    /* Processing for aggregates with GROUP BY is very different and
-
    ** much more complex than aggregates without a GROUP BY.
+
    ** much more complex than aggregates without a GROUP BY.  tag-select-0810
    */
    if( pGroupBy ){
      KeyInfo *pKeyInfo;  /* Keying information for the group by clause */
@@ -151206,12 +152123,25 @@ SQLITE_PRIVATE int sqlite3Select(
                          sortOut, sortPTab);
      }
      for(j=0; j<pGroupBy->nExpr; j++){
+
        int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
+

        if( groupBySort ){
          sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
        }else{
          pAggInfo->directMode = 1;
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
        }
+

+
        if( iOrderByCol ){
+
          Expr *pX = p->pEList->a[iOrderByCol-1].pExpr;
+
          Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX);
+
          if( ALWAYS(pBase!=0)
+
           && pBase->op!=TK_AGG_COLUMN
+
           && pBase->op!=TK_REGISTER
+
          ){
+
            sqlite3ExprToRegister(pX, iAMem+j);
+
          }
+
        }
      }
      sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
                          (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
@@ -151227,9 +152157,9 @@ SQLITE_PRIVATE int sqlite3Select(
      ** and resets the aggregate accumulator registers in preparation
      ** for the next GROUP BY batch.
      */
-
      sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
      sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output one row"));
+
      sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
      sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
      VdbeComment((v, "check abort flag"));
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
@@ -151303,9 +152233,12 @@ SQLITE_PRIVATE int sqlite3Select(
      }
    } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
    else {
+
      /* Aggregate functions without GROUP BY. tag-select-0820 */
      Table *pTab;
      if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
-
        /* If isSimpleCount() returns a pointer to a Table structure, then
+
        /* tag-select-0821
+
        **
+
        ** If isSimpleCount() returns a pointer to a Table structure, then
        ** the SQL statement is of the form:
        **
        **   SELECT count(*) FROM <tbl>
@@ -151364,6 +152297,8 @@ SQLITE_PRIVATE int sqlite3Select(
        sqlite3VdbeAddOp1(v, OP_Close, iCsr);
        explainSimpleCount(pParse, pTab, pBest);
      }else{
+
        /* The general case of an aggregate query without GROUP BY
+
        ** tag-select-0822 */
        int regAcc = 0;           /* "populate accumulators" flag */
        ExprList *pDistinct = 0;
        u16 distFlag = 0;
@@ -151452,7 +152387,7 @@ SQLITE_PRIVATE int sqlite3Select(
  }

  /* If there is an ORDER BY clause, then we need to sort the results
-
  ** and send them to the callback one by one.
+
  ** and send them to the callback one by one.  tag-select-0900
  */
  if( sSort.pOrderBy ){
    assert( p->pEList==pEList );
@@ -151475,6 +152410,7 @@ select_end:
  assert( db->mallocFailed==0 || pParse->nErr!=0 );
  sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
+
  /* Internal self-checks.  tag-select-1000 */
  if( pAggInfo && !db->mallocFailed ){
#if TREETRACE_ENABLED
    if( sqlite3TreeTrace & 0x20 ){
@@ -151864,8 +152800,10 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
  ** name on pTableName if we are reparsing out of the schema table
  */
  if( db->init.busy && iDb!=1 ){
-
    sqlite3DbFree(db, pTableName->a[0].zDatabase);
-
    pTableName->a[0].zDatabase = 0;
+
    assert( pTableName->a[0].fg.fixedSchema==0 );
+
    assert( pTableName->a[0].fg.isSubquery==0 );
+
    sqlite3DbFree(db, pTableName->a[0].u4.zDatabase);
+
    pTableName->a[0].u4.zDatabase = 0;
  }

  /* If the trigger name was unqualified, and the table is a temp table,
@@ -152343,7 +153281,8 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr)
  }

  assert( pName->nSrc==1 );
-
  zDb = pName->a[0].zDatabase;
+
  assert( pName->a[0].fg.fixedSchema==0 && pName->a[0].fg.isSubquery==0 );
+
  zDb = pName->a[0].u4.zDatabase;
  zName = pName->a[0].zName;
  assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
@@ -152580,7 +153519,9 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(
    Schema *pSchema = pStep->pTrig->pSchema;
    pSrc->a[0].zName = zName;
    if( pSchema!=db->aDb[1].pSchema ){
-
      pSrc->a[0].pSchema = pSchema;
+
      assert( pSrc->a[0].fg.fixedSchema || pSrc->a[0].u4.zDatabase==0 );
+
      pSrc->a[0].u4.pSchema = pSchema;
+
      pSrc->a[0].fg.fixedSchema = 1;
    }
    if( pStep->pFrom ){
      SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
@@ -152693,7 +153634,7 @@ static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
  pSrc = pSelect->pSrc;
  assert( pSrc!=0 );
  for(i=0; i<pSrc->nSrc; i++){
-
    if( pSrc->a[i].pTab==pWalker->u.pTab ){
+
    if( pSrc->a[i].pSTab==pWalker->u.pTab ){
      testcase( pSelect->selFlags & SF_Correlated );
      pSelect->selFlags |= SF_Correlated;
      pWalker->eCode = 1;
@@ -152764,7 +153705,7 @@ static void codeReturningTrigger(
  sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
  sSelect.pSrc = &sFrom;
  sFrom.nSrc = 1;
-
  sFrom.a[0].pTab = pTab;
+
  sFrom.a[0].pSTab = pTab;
  sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
  sFrom.a[0].iCursor = -1;
  sqlite3SelectPrep(pParse, &sSelect, 0);
@@ -153475,7 +154416,7 @@ static void updateFromSelect(
  Expr *pLimit2 = 0;
  ExprList *pOrderBy2 = 0;
  sqlite3 *db = pParse->db;
-
  Table *pTab = pTabList->a[0].pTab;
+
  Table *pTab = pTabList->a[0].pSTab;
  SrcList *pSrc;
  Expr *pWhere2;
  int eDest;
@@ -153499,8 +154440,8 @@ static void updateFromSelect(
  if( pSrc ){
    assert( pSrc->a[0].fg.notCte );
    pSrc->a[0].iCursor = -1;
-
    pSrc->a[0].pTab->nTabRef--;
-
    pSrc->a[0].pTab = 0;
+
    pSrc->a[0].pSTab->nTabRef--;
+
    pSrc->a[0].pSTab = 0;
  }
  if( pPk ){
    for(i=0; i<pPk->nKeyCol; i++){
@@ -154748,7 +155689,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
  int nClause = 0;        /* Counter of ON CONFLICT clauses */

  assert( pTabList->nSrc==1 );
-
  assert( pTabList->a[0].pTab!=0 );
+
  assert( pTabList->a[0].pSTab!=0 );
  assert( pUpsert!=0 );
  assert( pUpsert->pUpsertTarget!=0 );

@@ -154767,7 +155708,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
    if( rc ) return rc;

    /* Check to see if the conflict target matches the rowid. */
-
    pTab = pTabList->a[0].pTab;
+
    pTab = pTabList->a[0].pSTab;
    pTarget = pUpsert->pUpsertTarget;
    iCursor = pTabList->a[0].iCursor;
    if( HasRowid(pTab)
@@ -155138,6 +156079,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
  const char *zDbMain;    /* Schema name of database to vacuum */
  const char *zOut;       /* Name of output file */
  u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */
+
  u64 iRandom;            /* Random value used for zDbVacuum[] */
+
  char zDbVacuum[42];     /* Name of the ATTACH-ed database used for vacuum */
+


  if( !db->autoCommit ){
    sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -155178,27 +156122,29 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
  pMain = db->aDb[iDb].pBt;
  isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));

-
  /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
+
  /* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma
  ** can be set to 'off' for this file, as it is not recovered if a crash
  ** occurs anyway. The integrity of the database is maintained by a
  ** (possibly synchronous) transaction opened on the main database before
  ** sqlite3BtreeCopyFile() is called.
  **
  ** An optimization would be to use a non-journaled pager.
-
  ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
+
  ** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but
  ** that actually made the VACUUM run slower.  Very little journalling
  ** actually occurs when doing a vacuum since the vacuum_db is initially
  ** empty.  Only the journal header is written.  Apparently it takes more
  ** time to parse and run the PRAGMA to turn journalling off than it does
  ** to write the journal header file.
  */
+
  sqlite3_randomness(sizeof(iRandom),&iRandom);
+
  sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom);
  nDb = db->nDb;
-
  rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
+
  rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum);
  db->openFlags = saved_openFlags;
  if( rc!=SQLITE_OK ) goto end_of_vacuum;
  assert( (db->nDb-1)==nDb );
  pDb = &db->aDb[nDb];
-
  assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
+
  assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
  pTemp = pDb->pBt;
  if( pOut ){
    sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
@@ -155275,11 +156221,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
  ** the contents to the temporary database.
  */
  rc = execSqlF(db, pzErrMsg,
-
      "SELECT'INSERT INTO vacuum_db.'||quote(name)"
+
      "SELECT'INSERT INTO %s.'||quote(name)"
      "||' SELECT*FROM\"%w\".'||quote(name)"
-
      "FROM vacuum_db.sqlite_schema "
+
      "FROM %s.sqlite_schema "
      "WHERE type='table'AND coalesce(rootpage,1)>0",
-
      zDbMain
+
      zDbVacuum, zDbMain, zDbVacuum
  );
  assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
  db->mDbFlags &= ~DBFLAG_Vacuum;
@@ -155291,11 +156237,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
  ** from the schema table.
  */
  rc = execSqlF(db, pzErrMsg,
-
      "INSERT INTO vacuum_db.sqlite_schema"
+
      "INSERT INTO %s.sqlite_schema"
      " SELECT*FROM \"%w\".sqlite_schema"
      " WHERE type IN('view','trigger')"
      " OR(type='table'AND rootpage=0)",
-
      zDbMain
+
      zDbVacuum, zDbMain
  );
  if( rc ) goto end_of_vacuum;

@@ -156259,6 +157205,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
      Table *pNew = sParse.pNewTable;
      Index *pIdx;
      pTab->aCol = pNew->aCol;
+
      assert( IsOrdinaryTable(pNew) );
      sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
      pTab->nNVCol = pTab->nCol = pNew->nCol;
      pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
@@ -156933,11 +157880,13 @@ struct WhereLoop {
      u16 nTop;              /* Size of TOP vector */
      u16 nDistinctCol;      /* Index columns used to sort for DISTINCT */
      Index *pIndex;         /* Index used, or NULL */
+
      ExprList *pOrderBy;    /* ORDER BY clause if this is really a subquery */
    } btree;
    struct {               /* Information for virtual tables */
      int idxNum;            /* Index number */
      u32 needFree : 1;      /* True if sqlite3_free(idxStr) is needed */
      u32 bOmitOffset : 1;   /* True to let virtual table handle offset */
+
      u32 bIdxNumHex : 1;    /* Show idxNum as hex in EXPLAIN QUERY PLAN */
      i8 isOrdered;          /* True if satisfies ORDER BY */
      u16 omitMask;          /* Terms that may be omitted */
      char *idxStr;          /* Index identifier string */
@@ -156950,6 +157899,8 @@ struct WhereLoop {
  /**** whereLoopXfer() copies fields above ***********************/
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
  u16 nLSlot;           /* Number of slots allocated for aLTerm[] */
+
  LogEst rStarDelta;    /* Cost delta due to star-schema heuristic.  Not
+
                        ** initialized unless pWInfo->nOutStarDelta>0 */
  WhereTerm **aLTerm;   /* WhereTerms used */
  WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
  WhereTerm *aLTermSpace[3];  /* Initial aLTerm[] space */
@@ -157272,6 +158223,7 @@ struct WhereInfo {
  unsigned untestedTerms :1;   /* Not all WHERE terms resolved by outer loop */
  unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
  unsigned sorted :1;          /* True if really sorted (not just grouped) */
+
  LogEst nOutStarDelta;     /* Artifical nOut reduction for star-query */
  LogEst nRowOut;           /* Estimated number of output rows */
  int iTop;                 /* The very beginning of the WHERE loop */
  int iEndWhere;            /* End of the WHERE clause itself */
@@ -157423,7 +158375,8 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
#define WHERE_BLOOMFILTER  0x00400000  /* Consider using a Bloom-filter */
#define WHERE_SELFCULL     0x00800000  /* nOut reduced by extra WHERE terms */
#define WHERE_OMIT_OFFSET  0x01000000  /* Set offset counter to zero */
-
                      /*   0x02000000  -- available for reuse */
+
#define WHERE_COROUTINE    0x02000000  /* Implemented by co-routine.
+
                                       ** NB: False-negatives are possible */
#define WHERE_EXPRIDX      0x04000000  /* Uses an index-on-expressions */

#endif /* !defined(SQLITE_WHEREINT_H) */
@@ -157568,7 +158521,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
      assert( pLoop->u.btree.pIndex!=0 );
      pIdx = pLoop->u.btree.pIndex;
      assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
-
      if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
+
      if( !HasRowid(pItem->pSTab) && IsPrimaryKeyIndex(pIdx) ){
        if( isSearch ){
          zFmt = "PRIMARY KEY";
        }
@@ -157611,7 +158564,9 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
    }
#ifndef SQLITE_OMIT_VIRTUALTABLE
    else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
-
      sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
+
      sqlite3_str_appendall(&str, " VIRTUAL TABLE INDEX ");
+
      sqlite3_str_appendf(&str,
+
                  pLoop->u.vtab.bIdxNumHex ? "0x%x:%s" : "%d:%s",
                  pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
    }
#endif
@@ -157629,7 +158584,8 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
    zMsg = sqlite3StrAccumFinish(&str);
    sqlite3ExplainBreakpoint("",zMsg);
    ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
-
                            pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
+
                            pParse->addrExplain, pLoop->rRun,
+
                            zMsg, P4_DYNAMIC);
  }
  return ret;
}
@@ -157664,7 +158620,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
  sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem);
  pLoop = pLevel->pWLoop;
  if( pLoop->wsFlags & WHERE_IPK ){
-
    const Table *pTab = pItem->pTab;
+
    const Table *pTab = pItem->pSTab;
    if( pTab->iPKey>=0 ){
      sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName);
    }else{
@@ -157727,7 +158683,9 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
        sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
      }
    }else{
-
      int addr = pSrclist->a[pLvl->iFrom].addrFillSub;
+
      int addr;
+
      assert( pSrclist->a[pLvl->iFrom].fg.isSubquery );
+
      addr = pSrclist->a[pLvl->iFrom].u4.pSubq->addrFillSub;
      VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-1);
      assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine );
      assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr );
@@ -157871,6 +158829,39 @@ static void updateRangeAffinityStr(
  }
}

+
/*
+
** The pOrderBy->a[].u.x.iOrderByCol values might be incorrect because
+
** columns might have been rearranged in the result set.  This routine
+
** fixes them up.
+
**
+
** pEList is the new result set.  The pEList->a[].u.x.iOrderByCol values
+
** contain the *old* locations of each expression.  This is a temporary
+
** use of u.x.iOrderByCol, not its intended use.  The caller must reset
+
** u.x.iOrderByCol back to zero for all entries in pEList before the
+
** caller returns.
+
**
+
** This routine changes pOrderBy->a[].u.x.iOrderByCol values from
+
** pEList->a[N].u.x.iOrderByCol into N+1.  (The "+1" is because of the 1-based
+
** indexing used by iOrderByCol.)  Or if no match, iOrderByCol is set to zero.
+
*/
+
static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){
+
  int i, j;
+
  if( pOrderBy==0 ) return;
+
  for(i=0; i<pOrderBy->nExpr; i++){
+
    int t = pOrderBy->a[i].u.x.iOrderByCol;
+
    if( t==0 ) continue;
+
    for(j=0; j<pEList->nExpr; j++){
+
      if( pEList->a[j].u.x.iOrderByCol==t ){
+
        pOrderBy->a[i].u.x.iOrderByCol = j+1;
+
        break;
+
      }
+
    }
+
    if( j>=pEList->nExpr ){
+
      pOrderBy->a[i].u.x.iOrderByCol = 0;
+
    }
+
  }
+
}
+


/*
** pX is an expression of the form:  (vector) IN (SELECT ...)
@@ -157934,6 +158925,7 @@ static Expr *removeUnindexableInClauseTerms(
          if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
          pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
          pOrigRhs->a[iField].pExpr = 0;
+
          if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
          if( pOrigLhs ){
            assert( pOrigLhs->a[iField].pExpr!=0 );
            pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
@@ -157956,18 +158948,16 @@ static Expr *removeUnindexableInClauseTerms(
        sqlite3ExprDelete(db, pNew->pLeft);
        pNew->pLeft = p;
      }
-
      if( pSelect->pOrderBy ){
-
        /* If the SELECT statement has an ORDER BY clause, zero the
-
        ** iOrderByCol variables. These are set to non-zero when an
-
        ** ORDER BY term exactly matches one of the terms of the
-
        ** result-set. Since the result-set of the SELECT statement may
-
        ** have been modified or reordered, these variables are no longer
-
        ** set correctly.  Since setting them is just an optimization,
-
        ** it's easiest just to zero them here.  */
-
        ExprList *pOrderBy = pSelect->pOrderBy;
-
        for(i=0; i<pOrderBy->nExpr; i++){
-
          pOrderBy->a[i].u.x.iOrderByCol = 0;
-
        }
+

+
      /* If either the ORDER BY clause or the GROUP BY clause contains
+
      ** references to result-set columns, those references might now be
+
      ** obsolete.  So fix them up.
+
      */
+
      assert( pRhs!=0 || db->mallocFailed );
+
      if( pRhs ){
+
        adjustOrderByCol(pSelect->pOrderBy, pRhs);
+
        adjustOrderByCol(pSelect->pGroupBy, pRhs);
+
        for(i=0; i<pRhs->nExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0;
      }

#if 0
@@ -157982,6 +158972,147 @@ static Expr *removeUnindexableInClauseTerms(
}


+
#ifndef SQLITE_OMIT_SUBQUERY
+
/*
+
** Generate code for a single X IN (....) term of the WHERE clause.
+
**
+
** This is a special-case of codeEqualityTerm() that works for IN operators
+
** only.  It is broken out into a subroutine because this case is
+
** uncommon and by splitting it off into a subroutine, the common case
+
** runs faster.
+
**
+
** The current value for the constraint is left in  register iTarget.
+
** This routine sets up a loop that will iterate over all values of X.
+
*/
+
static SQLITE_NOINLINE void codeINTerm(
+
  Parse *pParse,      /* The parsing context */
+
  WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
+
  WhereLevel *pLevel, /* The level of the FROM clause we are working on */
+
  int iEq,            /* Index of the equality term within this level */
+
  int bRev,           /* True for reverse-order IN operations */
+
  int iTarget         /* Attempt to leave results in this register */
+
){
+
  Expr *pX = pTerm->pExpr;
+
  int eType = IN_INDEX_NOOP;
+
  int iTab;
+
  struct InLoop *pIn;
+
  WhereLoop *pLoop = pLevel->pWLoop;
+
  Vdbe *v = pParse->pVdbe;
+
  int i;
+
  int nEq = 0;
+
  int *aiMap = 0;
+

+
  if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+
    && pLoop->u.btree.pIndex!=0
+
    && pLoop->u.btree.pIndex->aSortOrder[iEq]
+
  ){
+
    testcase( iEq==0 );
+
    testcase( bRev );
+
    bRev = !bRev;
+
  }
+
  assert( pX->op==TK_IN );
+

+
  for(i=0; i<iEq; i++){
+
    if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
+
      disableTerm(pLevel, pTerm);
+
      return;
+
    }
+
  }
+
  for(i=iEq;i<pLoop->nLTerm; i++){
+
    assert( pLoop->aLTerm[i]!=0 );
+
    if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
+
  }
+

+
  iTab = 0;
+
  if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
+
    eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
+
  }else{
+
    Expr *pExpr = pTerm->pExpr;
+
    if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
+
      sqlite3 *db = pParse->db;
+
      pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
+
      if( !db->mallocFailed ){
+
        aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
+
        eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
+
        pExpr->iTable = iTab;
+
      }
+
      sqlite3ExprDelete(db, pX);
+
    }else{
+
      int n = sqlite3ExprVectorSize(pX->pLeft);
+
      aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
+
      eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
+
    }
+
    pX = pExpr;
+
  }
+

+
  if( eType==IN_INDEX_INDEX_DESC ){
+
    testcase( bRev );
+
    bRev = !bRev;
+
  }
+
  sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
+
  VdbeCoverageIf(v, bRev);
+
  VdbeCoverageIf(v, !bRev);
+

+
  assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+
  pLoop->wsFlags |= WHERE_IN_ABLE;
+
  if( pLevel->u.in.nIn==0 ){
+
    pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
+
  }
+
  if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
+
    pLoop->wsFlags |= WHERE_IN_EARLYOUT;
+
  }
+

+
  i = pLevel->u.in.nIn;
+
  pLevel->u.in.nIn += nEq;
+
  pLevel->u.in.aInLoop =
+
     sqlite3WhereRealloc(pTerm->pWC->pWInfo,
+
                         pLevel->u.in.aInLoop,
+
                         sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
+
  pIn = pLevel->u.in.aInLoop;
+
  if( pIn ){
+
    int iMap = 0;               /* Index in aiMap[] */
+
    pIn += i;
+
    for(i=iEq;i<pLoop->nLTerm; i++){
+
      if( pLoop->aLTerm[i]->pExpr==pX ){
+
        int iOut = iTarget + i - iEq;
+
        if( eType==IN_INDEX_ROWID ){
+
          pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
+
        }else{
+
          int iCol = aiMap ? aiMap[iMap++] : 0;
+
          pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
+
        }
+
        sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
+
        if( i==iEq ){
+
          pIn->iCur = iTab;
+
          pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
+
          if( iEq>0 ){
+
            pIn->iBase = iTarget - i;
+
            pIn->nPrefix = i;
+
          }else{
+
            pIn->nPrefix = 0;
+
          }
+
        }else{
+
          pIn->eEndLoopOp = OP_Noop;
+
        }
+
        pIn++;
+
      }
+
    }
+
    testcase( iEq>0
+
              && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
+
              && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
+
    if( iEq>0
+
     && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
+
    ){
+
      sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
+
    }
+
  }else{
+
    pLevel->u.in.nIn = 0;
+
  }
+
  sqlite3DbFree(pParse->db, aiMap);
+
}
+
#endif
+

+

/*
** Generate code for a single equality term of the WHERE clause.  An equality
** term can be either X=expr or X IN (...).   pTerm is the term to be
@@ -158006,7 +159137,6 @@ static int codeEqualityTerm(
  int iTarget         /* Attempt to leave results in this register */
){
  Expr *pX = pTerm->pExpr;
-
  Vdbe *v = pParse->pVdbe;
  int iReg;                  /* Register holding results */

  assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
@@ -158015,125 +159145,12 @@ static int codeEqualityTerm(
    iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
  }else if( pX->op==TK_ISNULL ){
    iReg = iTarget;
-
    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
+
    sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
  }else{
-
    int eType = IN_INDEX_NOOP;
-
    int iTab;
-
    struct InLoop *pIn;
-
    WhereLoop *pLoop = pLevel->pWLoop;
-
    int i;
-
    int nEq = 0;
-
    int *aiMap = 0;
-

-
    if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
-
      && pLoop->u.btree.pIndex!=0
-
      && pLoop->u.btree.pIndex->aSortOrder[iEq]
-
    ){
-
      testcase( iEq==0 );
-
      testcase( bRev );
-
      bRev = !bRev;
-
    }
    assert( pX->op==TK_IN );
    iReg = iTarget;
-

-
    for(i=0; i<iEq; i++){
-
      if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
-
        disableTerm(pLevel, pTerm);
-
        return iTarget;
-
      }
-
    }
-
    for(i=iEq;i<pLoop->nLTerm; i++){
-
      assert( pLoop->aLTerm[i]!=0 );
-
      if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
-
    }
-

-
    iTab = 0;
-
    if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
-
      eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
-
    }else{
-
      Expr *pExpr = pTerm->pExpr;
-
      if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
-
        sqlite3 *db = pParse->db;
-
        pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
-
        if( !db->mallocFailed ){
-
          aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
-
          eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
-
          pExpr->iTable = iTab;
-
        }
-
        sqlite3ExprDelete(db, pX);
-
      }else{
-
        int n = sqlite3ExprVectorSize(pX->pLeft);
-
        aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
-
        eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
-
      }
-
      pX = pExpr;
-
    }
-

-
    if( eType==IN_INDEX_INDEX_DESC ){
-
      testcase( bRev );
-
      bRev = !bRev;
-
    }
-
    sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
-
    VdbeCoverageIf(v, bRev);
-
    VdbeCoverageIf(v, !bRev);
-

-
    assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
-
    pLoop->wsFlags |= WHERE_IN_ABLE;
-
    if( pLevel->u.in.nIn==0 ){
-
      pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
-
    }
-
    if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
-
      pLoop->wsFlags |= WHERE_IN_EARLYOUT;
-
    }
-

-
    i = pLevel->u.in.nIn;
-
    pLevel->u.in.nIn += nEq;
-
    pLevel->u.in.aInLoop =
-
       sqlite3WhereRealloc(pTerm->pWC->pWInfo,
-
                           pLevel->u.in.aInLoop,
-
                           sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
-
    pIn = pLevel->u.in.aInLoop;
-
    if( pIn ){
-
      int iMap = 0;               /* Index in aiMap[] */
-
      pIn += i;
-
      for(i=iEq;i<pLoop->nLTerm; i++){
-
        if( pLoop->aLTerm[i]->pExpr==pX ){
-
          int iOut = iReg + i - iEq;
-
          if( eType==IN_INDEX_ROWID ){
-
            pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
-
          }else{
-
            int iCol = aiMap ? aiMap[iMap++] : 0;
-
            pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
-
          }
-
          sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
-
          if( i==iEq ){
-
            pIn->iCur = iTab;
-
            pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
-
            if( iEq>0 ){
-
              pIn->iBase = iReg - i;
-
              pIn->nPrefix = i;
-
            }else{
-
              pIn->nPrefix = 0;
-
            }
-
          }else{
-
            pIn->eEndLoopOp = OP_Noop;
-
          }
-
          pIn++;
-
        }
-
      }
-
      testcase( iEq>0
-
                && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
-
                && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
-
      if( iEq>0
-
       && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
-
      ){
-
        sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
-
      }
-
    }else{
-
      pLevel->u.in.nIn = 0;
-
    }
-
    sqlite3DbFree(pParse->db, aiMap);
+
    codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget);
#endif
  }

@@ -158805,7 +159822,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
  iCur = pTabItem->iCursor;
  pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
  bRev = (pWInfo->revMask>>iLevel)&1;
-
  VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
+
  VdbeModuleComment((v, "Begin WHERE-loop%d: %s",
+
                     iLevel, pTabItem->pSTab->zName));
#if WHERETRACE_ENABLED /* 0x4001 */
  if( sqlite3WhereTrace & 0x1 ){
    sqlite3DebugPrintf("Coding level %d of %d:  notReady=%llx  iFrom=%d\n",
@@ -158860,11 +159878,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(

  /* Special case of a FROM clause subquery implemented as a co-routine */
  if( pTabItem->fg.viaCoroutine ){
-
    int regYield = pTabItem->regReturn;
-
    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
+
    int regYield;
+
    Subquery *pSubq;
+
    assert( pTabItem->fg.isSubquery && pTabItem->u4.pSubq!=0 );
+
    pSubq = pTabItem->u4.pSubq;
+
    regYield = pSubq->regReturn;
+
    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub);
    pLevel->p2 =  sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
    VdbeCoverage(v);
-
    VdbeComment((v, "next row of %s", pTabItem->pTab->zName));
+
    VdbeComment((v, "next row of %s", pTabItem->pSTab->zName));
    pLevel->op = OP_Goto;
  }else

@@ -159593,7 +160615,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
    int untestedTerms = 0;             /* Some terms not completely tested */
    int ii;                            /* Loop counter */
    Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
-
    Table *pTab = pTabItem->pTab;
+
    Table *pTab = pTabItem->pSTab;

    pTerm = pLoop->aLTerm[0];
    assert( pTerm!=0 );
@@ -160052,7 +161074,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
    ** least once.  This is accomplished by storing the PK for the row in
    ** both the iMatch index and the regBloom Bloom filter.
    */
-
    pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab;
+
    pTab = pWInfo->pTabList->a[pLevel->iFrom].pSTab;
    if( HasRowid(pTab) ){
      r = sqlite3GetTempRange(pParse, 2);
      sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1);
@@ -160159,7 +161181,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
  Bitmask mAll = 0;
  int k;

-
  ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
+
  ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
  sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
                                  pRJ->regReturn);
  for(k=0; k<iLevel; k++){
@@ -160169,9 +161191,13 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
    pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom];
    mAll |= pWInfo->a[k].pWLoop->maskSelf;
    if( pRight->fg.viaCoroutine ){
+
      Subquery *pSubq;
+
      assert( pRight->fg.isSubquery && pRight->u4.pSubq!=0 );
+
      pSubq = pRight->u4.pSubq;
+
      assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 );
      sqlite3VdbeAddOp3(
-
          v, OP_Null, 0, pRight->regResult,
-
          pRight->regResult + pRight->pSelect->pEList->nExpr-1
+
          v, OP_Null, 0, pSubq->regResult,
+
          pSubq->regResult + pSubq->pSelect->pEList->nExpr-1
      );
    }
    sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
@@ -160209,7 +161235,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
    int nPk;
    int jmp;
    int addrCont = sqlite3WhereContinueLabel(pSubWInfo);
-
    Table *pTab = pTabItem->pTab;
+
    Table *pTab = pTabItem->pSTab;
    if( HasRowid(pTab) ){
      sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r);
      nPk = 1;
@@ -160342,7 +161368,12 @@ static int allowedOp(int op){
  assert( TK_LT>TK_EQ && TK_LT<TK_GE );
  assert( TK_LE>TK_EQ && TK_LE<TK_GE );
  assert( TK_GE==TK_EQ+4 );
-
  return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
+
  assert( TK_IN<TK_EQ );
+
  assert( TK_IS<TK_EQ );
+
  assert( TK_ISNULL<TK_EQ );
+
  if( op>TK_GE ) return 0;
+
  if( op>=TK_EQ ) return 1;
+
  return op==TK_IN || op==TK_ISNULL || op==TK_IS;
}

/*
@@ -160375,15 +161406,16 @@ static u16 exprCommute(Parse *pParse, Expr *pExpr){
static u16 operatorMask(int op){
  u16 c;
  assert( allowedOp(op) );
-
  if( op==TK_IN ){
+
  if( op>=TK_EQ ){
+
    assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
+
    c = (u16)(WO_EQ<<(op-TK_EQ));
+
  }else if( op==TK_IN ){
    c = WO_IN;
  }else if( op==TK_ISNULL ){
    c = WO_ISNULL;
-
  }else if( op==TK_IS ){
-
    c = WO_IS;
  }else{
-
    assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
-
    c = (u16)(WO_EQ<<(op-TK_EQ));
+
    assert( op==TK_IS );
+
    c = WO_IS;
  }
  assert( op!=TK_ISNULL || c==WO_ISNULL );
  assert( op!=TK_IN || c==WO_IN );
@@ -160454,12 +161486,26 @@ static int isLikeOrGlob(
     z = (u8*)pRight->u.zToken;
  }
  if( z ){
-

-
    /* Count the number of prefix characters prior to the first wildcard */
+
    /* Count the number of prefix bytes prior to the first wildcard.
+
    ** or U+fffd character.  If the underlying database has a UTF16LE
+
    ** encoding, then only consider ASCII characters.  Note that the
+
    ** encoding of z[] is UTF8 - we are dealing with only UTF8 here in
+
    ** this code, but the database engine itself might be processing
+
    ** content using a different encoding. */
    cnt = 0;
    while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
      cnt++;
-
      if( c==wc[3] && z[cnt]!=0 ) cnt++;
+
      if( c==wc[3] && z[cnt]>0 && z[cnt]<0x80 ){
+
        cnt++;
+
      }else if( c>=0x80 ){
+
        const u8 *z2 = z+cnt-1;
+
        if( sqlite3Utf8Read(&z2)==0xfffd || ENC(db)==SQLITE_UTF16LE ){
+
          cnt--;
+
          break;
+
        }else{
+
          cnt = (int)(z2-z);
+
        }
+
      }
    }

    /* The optimization is possible only if (1) the pattern does not begin
@@ -160470,11 +161516,11 @@ static int isLikeOrGlob(
    ** range search. The third is because the caller assumes that the pattern
    ** consists of at least one character after all escapes have been
    ** removed.  */
-
    if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){
+
    if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){
      Expr *pPrefix;

      /* A "complete" match if the pattern ends with "*" or "%" */
-
      *pisComplete = c==wc[0] && z[cnt+1]==0;
+
      *pisComplete = c==wc[0] && z[cnt+1]==0 && ENC(db)!=SQLITE_UTF16LE;

      /* Get the pattern prefix.  Remove all escapes from the prefix. */
      pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
@@ -160670,6 +161716,13 @@ static int isAuxiliaryVtabOperator(
        }
      }
    }
+
  }else if( pExpr->op>=TK_EQ ){
+
    /* Comparison operators are a common case.  Save a few comparisons for
+
    ** that common case by terminating early. */
+
    assert( TK_NE < TK_EQ );
+
    assert( TK_ISNOT < TK_EQ );
+
    assert( TK_NOTNULL < TK_EQ );
+
    return 0;
  }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
    int res = 0;
    Expr *pLeft = pExpr->pLeft;
@@ -161186,7 +162239,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
    if( ALWAYS(pSrc!=0) ){
      int i;
      for(i=0; i<pSrc->nSrc; i++){
-
        mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
+
        if( pSrc->a[i].fg.isSubquery ){
+
          mask |= exprSelectUsage(pMaskSet, pSrc->a[i].u4.pSubq->pSelect);
+
        }
        if( pSrc->a[i].fg.isUsing==0 ){
          mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn);
        }
@@ -161224,7 +162279,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2(
  int iCur;
  do{
    iCur = pFrom->a[j].iCursor;
-
    for(pIdx=pFrom->a[j].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+
    for(pIdx=pFrom->a[j].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
      if( pIdx->aColExpr==0 ) continue;
      for(i=0; i<pIdx->nKeyCol; i++){
        if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
@@ -161268,7 +162323,7 @@ static int exprMightBeIndexed(

  for(i=0; i<pFrom->nSrc; i++){
    Index *pIdx;
-
    for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+
    for(pIdx=pFrom->a[i].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
      if( pIdx->aColExpr ){
        return exprMightBeIndexed2(pFrom,aiCurCol,pExpr,i);
      }
@@ -161811,7 +162866,7 @@ static void whereAddLimitExpr(
  Expr *pNew;
  int iVal = 0;

-
  if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
+
  if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
    Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
    if( pVal==0 ) return;
    ExprSetProperty(pVal, EP_IntValue);
@@ -161856,7 +162911,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Selec
  assert( p!=0 && p->pLimit!=0 );                 /* 1 -- checked by caller */
  if( p->pGroupBy==0
   && (p->selFlags & (SF_Distinct|SF_Aggregate))==0             /* 2 */
-
   && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab))       /* 3 */
+
   && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pSTab))      /* 3 */
  ){
    ExprList *pOrderBy = p->pOrderBy;
    int iCsr = p->pSrc->a[0].iCursor;
@@ -162077,7 +163132,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
  Expr *pColRef;
  Expr *pTerm;
  if( pItem->fg.isTabFunc==0 ) return;
-
  pTab = pItem->pTab;
+
  pTab = pItem->pSTab;
  assert( pTab!=0 );
  pArgs = pItem->u1.pFuncArg;
  if( pArgs==0 ) return;
@@ -162761,7 +163816,7 @@ static int isDistinctRedundant(
  ** clause is redundant. */
  if( pTabList->nSrc!=1 ) return 0;
  iBase = pTabList->a[0].iCursor;
-
  pTab = pTabList->a[0].pTab;
+
  pTab = pTabList->a[0].pSTab;

  /* If any of the expressions is an IPK column on table iBase, then return
  ** true. Note: The (p->iTable==iBase) part of this test may be false if the
@@ -162836,6 +163891,12 @@ static void translateColumnToCopy(
  VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
  int iEnd = sqlite3VdbeCurrentAddr(v);
  if( pParse->db->mallocFailed ) return;
+
#ifdef SQLITE_DEBUG
+
  if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
+
    printf("CHECKING for column-to-copy on cursor %d for %d..%d\n",
+
            iTabCur, iStart, iEnd);
+
  }
+
#endif
  for(; iStart<iEnd; iStart++, pOp++){
    if( pOp->p1!=iTabCur ) continue;
    if( pOp->opcode==OP_Column ){
@@ -162957,6 +164018,40 @@ static int constraintCompatibleWithOuterJoin(
  return 1;
}

+
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+
/*
+
** Return true if column iCol of table pTab seem like it might be a
+
** good column to use as part of a query-time index.
+
**
+
** Current algorithm (subject to improvement!):
+
**
+
**   1.   If iCol is already the left-most column of some other index,
+
**        then return false.
+
**
+
**   2.   If iCol is part of an existing index that has an aiRowLogEst of
+
**        more than 20, then return false.
+
**
+
**   3.   If no disqualifying conditions above are found, return true.
+
*/
+
static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
+
  const Table *pTab,
+
  int iCol
+
){
+
  const Index *pIdx;
+
  for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
+
    int j;
+
    for(j=0; j<pIdx->nKeyCol; j++){
+
       if( pIdx->aiColumn[j]==iCol ){
+
         if( j==0 ) return 0;
+
         if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0;
+
         break;
+
       }
+
    }
+
  }
+
  return 1;
+
}
+
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+



#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -162971,6 +164066,8 @@ static int termCanDriveIndex(
  const Bitmask notReady         /* Tables in outer loops of the join */
){
  char aff;
+
  int leftCol;
+

  if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
  if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
  assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
@@ -162981,11 +164078,12 @@ static int termCanDriveIndex(
  }
  if( (pTerm->prereqRight & notReady)!=0 ) return 0;
  assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
-
  if( pTerm->u.x.leftColumn<0 ) return 0;
-
  aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
+
  leftCol = pTerm->u.x.leftColumn;
+
  if( leftCol<0 ) return 0;
+
  aff = pSrc->pSTab->aCol[leftCol].affinity;
  if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
  testcase( pTerm->pExpr->op==TK_IS );
-
  return 1;
+
  return columnIsGoodIndexCandidate(pSrc->pSTab, leftCol);
}
#endif

@@ -163093,7 +164191,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
  nKeyCol = 0;
  pTabList = pWC->pWInfo->pTabList;
  pSrc = &pTabList->a[pLevel->iFrom];
-
  pTable = pSrc->pTab;
+
  pTable = pSrc->pSTab;
  pWCEnd = &pWC->a[pWC->nTerm];
  pLoop = pLevel->pWLoop;
  idxCols = 0;
@@ -163235,12 +164333,17 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
  /* Fill the automatic index with content */
  assert( pSrc == &pWC->pWInfo->pTabList->a[pLevel->iFrom] );
  if( pSrc->fg.viaCoroutine ){
-
    int regYield = pSrc->regReturn;
+
    int regYield;
+
    Subquery *pSubq;
+
    assert( pSrc->fg.isSubquery );
+
    pSubq = pSrc->u4.pSubq;
+
    assert( pSubq!=0 );
+
    regYield = pSubq->regReturn;
    addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
-
    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSrc->addrFillSub);
+
    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub);
    addrTop =  sqlite3VdbeAddOp1(v, OP_Yield, regYield);
    VdbeCoverage(v);
-
    VdbeComment((v, "next row of %s", pSrc->pTab->zName));
+
    VdbeComment((v, "next row of %s", pSrc->pSTab->zName));
  }else{
    addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
  }
@@ -163262,11 +164365,12 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
  if( pSrc->fg.viaCoroutine ){
+
    assert( pSrc->fg.isSubquery && pSrc->u4.pSubq!=0 );
    sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
    testcase( pParse->db->mallocFailed );
    assert( pLevel->iIdxCur>0 );
    translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
-
                          pSrc->regResult, pLevel->iIdxCur);
+
                          pSrc->u4.pSubq->regResult, pLevel->iIdxCur);
    sqlite3VdbeGoto(v, addrTop);
    pSrc->fg.viaCoroutine = 0;
  }else{
@@ -163357,7 +164461,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
    iSrc = pLevel->iFrom;
    pItem = &pTabList->a[iSrc];
    assert( pItem!=0 );
-
    pTab = pItem->pTab;
+
    pTab = pItem->pSTab;
    assert( pTab!=0 );
    sz = sqlite3LogEstToInt(pTab->nRowLogEst);
    if( sz<10000 ){
@@ -163388,7 +164492,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
      int r1 = sqlite3GetTempRange(pParse, n);
      int jj;
      for(jj=0; jj<n; jj++){
-
        assert( pIdx->pTable==pItem->pTab );
+
        assert( pIdx->pTable==pItem->pSTab );
        sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj);
      }
      sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n);
@@ -163427,6 +164531,20 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
+
** Return term iTerm of the WhereClause passed as the first argument. Terms
+
** are numbered from 0 upwards, starting with the terms in pWC->a[], then
+
** those in pWC->pOuter->a[] (if any), and so on.
+
*/
+
static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){
+
  WhereClause *p;
+
  for(p=pWC; p; p=p->pOuter){
+
    if( iTerm<p->nTerm ) return &p->a[iTerm];
+
    iTerm -= p->nTerm;
+
  }
+
  return 0;
+
}
+

+
/*
** Allocate and populate an sqlite3_index_info structure. It is the
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to freeIndexInfo().
@@ -163452,9 +164570,10 @@ static sqlite3_index_info *allocateIndexInfo(
  const Table *pTab;
  int eDistinct = 0;
  ExprList *pOrderBy = pWInfo->pOrderBy;
+
  WhereClause *p;

  assert( pSrc!=0 );
-
  pTab = pSrc->pTab;
+
  pTab = pSrc->pSTab;
  assert( pTab!=0 );
  assert( IsVirtual(pTab) );

@@ -163462,28 +164581,30 @@ static sqlite3_index_info *allocateIndexInfo(
  ** Mark each term with the TERM_OK flag.  Set nTerm to the number of
  ** terms found.
  */
-
  for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
-
    pTerm->wtFlags &= ~TERM_OK;
-
    if( pTerm->leftCursor != pSrc->iCursor ) continue;
-
    if( pTerm->prereqRight & mUnusable ) continue;
-
    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
-
    testcase( pTerm->eOperator & WO_IN );
-
    testcase( pTerm->eOperator & WO_ISNULL );
-
    testcase( pTerm->eOperator & WO_IS );
-
    testcase( pTerm->eOperator & WO_ALL );
-
    if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
-
    if( pTerm->wtFlags & TERM_VNULL ) continue;
+
  for(p=pWC, nTerm=0; p; p=p->pOuter){
+
    for(i=0, pTerm=p->a; i<p->nTerm; i++, pTerm++){
+
      pTerm->wtFlags &= ~TERM_OK;
+
      if( pTerm->leftCursor != pSrc->iCursor ) continue;
+
      if( pTerm->prereqRight & mUnusable ) continue;
+
      assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+
      testcase( pTerm->eOperator & WO_IN );
+
      testcase( pTerm->eOperator & WO_ISNULL );
+
      testcase( pTerm->eOperator & WO_IS );
+
      testcase( pTerm->eOperator & WO_ALL );
+
      if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
+
      if( pTerm->wtFlags & TERM_VNULL ) continue;

-
    assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
-
    assert( pTerm->u.x.leftColumn>=XN_ROWID );
-
    assert( pTerm->u.x.leftColumn<pTab->nCol );
-
    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
-
     && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
-
    ){
-
      continue;
+
      assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
+
      assert( pTerm->u.x.leftColumn>=XN_ROWID );
+
      assert( pTerm->u.x.leftColumn<pTab->nCol );
+
      if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
+
          && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
+
        ){
+
        continue;
+
      }
+
      nTerm++;
+
      pTerm->wtFlags |= TERM_OK;
    }
-
    nTerm++;
-
    pTerm->wtFlags |= TERM_OK;
  }

  /* If the ORDER BY clause contains only columns in the current
@@ -163558,53 +164679,69 @@ static sqlite3_index_info *allocateIndexInfo(
  pIdxInfo->aConstraint = pIdxCons;
  pIdxInfo->aOrderBy = pIdxOrderBy;
  pIdxInfo->aConstraintUsage = pUsage;
+
  pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
+
  if( HasRowid(pTab)==0 ){
+
    /* Ensure that all bits associated with PK columns are set. This is to
+
    ** ensure they are available for cases like RIGHT joins or OR loops. */
+
    Index *pPk = sqlite3PrimaryKeyIndex((Table*)pTab);
+
    assert( pPk!=0 );
+
    for(i=0; i<pPk->nKeyCol; i++){
+
      int iCol = pPk->aiColumn[i];
+
      assert( iCol>=0 );
+
      if( iCol>=BMS-1 ) iCol = BMS-1;
+
      pIdxInfo->colUsed |= MASKBIT(iCol);
+
    }
+
  }
  pHidden->pWC = pWC;
  pHidden->pParse = pParse;
  pHidden->eDistinct = eDistinct;
  pHidden->mIn = 0;
-
  for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
-
    u16 op;
-
    if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
-
    pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
-
    pIdxCons[j].iTermOffset = i;
-
    op = pTerm->eOperator & WO_ALL;
-
    if( op==WO_IN ){
-
      if( (pTerm->wtFlags & TERM_SLICE)==0 ){
-
        pHidden->mIn |= SMASKBIT32(j);
-
      }
-
      op = WO_EQ;
-
    }
-
    if( op==WO_AUX ){
-
      pIdxCons[j].op = pTerm->eMatchOp;
-
    }else if( op & (WO_ISNULL|WO_IS) ){
-
      if( op==WO_ISNULL ){
-
        pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
-
      }else{
-
        pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
-
      }
-
    }else{
-
      pIdxCons[j].op = (u8)op;
-
      /* The direct assignment in the previous line is possible only because
-
      ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical.  The
-
      ** following asserts verify this fact. */
-
      assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
-
      assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
-
      assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
-
      assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
-
      assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
-
      assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
-

-
      if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
-
       && sqlite3ExprIsVector(pTerm->pExpr->pRight)
-
      ){
-
        testcase( j!=i );
-
        if( j<16 ) mNoOmit |= (1 << j);
-
        if( op==WO_LT ) pIdxCons[j].op = WO_LE;
-
        if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+
  for(p=pWC, i=j=0; p; p=p->pOuter){
+
    int nLast = i+p->nTerm;;
+
    for(pTerm=p->a; i<nLast; i++, pTerm++){
+
      u16 op;
+
      if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
+
      pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
+
      pIdxCons[j].iTermOffset = i;
+
      op = pTerm->eOperator & WO_ALL;
+
      if( op==WO_IN ){
+
        if( (pTerm->wtFlags & TERM_SLICE)==0 ){
+
          pHidden->mIn |= SMASKBIT32(j);
+
        }
+
        op = WO_EQ;
+
      }
+
      if( op==WO_AUX ){
+
        pIdxCons[j].op = pTerm->eMatchOp;
+
      }else if( op & (WO_ISNULL|WO_IS) ){
+
        if( op==WO_ISNULL ){
+
          pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
+
        }else{
+
          pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
+
        }
+
      }else{
+
        pIdxCons[j].op = (u8)op;
+
        /* The direct assignment in the previous line is possible only because
+
        ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical.  The
+
        ** following asserts verify this fact. */
+
        assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
+
        assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
+
        assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
+
        assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
+
        assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
+
        assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
+

+
        if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
+
            && sqlite3ExprIsVector(pTerm->pExpr->pRight)
+
          ){
+
          testcase( j!=i );
+
          if( j<16 ) mNoOmit |= (1 << j);
+
          if( op==WO_LT ) pIdxCons[j].op = WO_LE;
+
          if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+
        }
      }
-
    }

-
    j++;
+
      j++;
+
    }
  }
  assert( j==nTerm );
  pIdxInfo->nConstraint = j;
@@ -163625,6 +164762,17 @@ static sqlite3_index_info *allocateIndexInfo(
}

/*
+
** Free and zero the sqlite3_index_info.idxStr value if needed.
+
*/
+
static void freeIdxStr(sqlite3_index_info *pIdxInfo){
+
  if( pIdxInfo->needToFreeIdxStr ){
+
    sqlite3_free(pIdxInfo->idxStr);
+
    pIdxInfo->idxStr = 0;
+
    pIdxInfo->needToFreeIdxStr = 0;
+
  }
+
}
+

+
/*
** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
** and possibly modified by xBestIndex methods.
*/
@@ -163639,6 +164787,7 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
    sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
    pHidden->aRhs[i] = 0;
  }
+
  freeIdxStr(pIdxInfo);
  sqlite3DbFree(db, pIdxInfo);
}

@@ -163659,9 +164808,11 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
** that this is required.
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
-
  sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
  int rc;
+
  sqlite3_vtab *pVtab;

+
  assert( IsVirtual(pTab) );
+
  pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
  whereTraceIndexInfoInputs(p, pTab);
  pParse->db->nSchemaLock++;
  rc = pVtab->pModule->xBestIndex(pVtab, p);
@@ -164432,7 +165583,7 @@ SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause
    WhereInfo *pWInfo = pWC->pWInfo;
    int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
    SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
-
    Table *pTab = pItem->pTab;
+
    Table *pTab = pItem->pSTab;
    Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
    sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
                       p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
@@ -164604,7 +165755,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
** and Y has additional constraints that might speed the search that X lacks
** but the cost of running X is not more than the cost of running Y.
**
-
** In other words, return true if the cost relationwship between X and Y
+
** In other words, return true if the cost relationship between X and Y
** is inverted and needs to be adjusted.
**
** Case 1:
@@ -164990,7 +166141,7 @@ static void whereLoopOutputAdjust(
          Expr *pRight = pTerm->pExpr->pRight;
          int k = 0;
          testcase( pTerm->pExpr->op==TK_IS );
-
          if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
+
          if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
            k = 10;
          }else{
            k = 20;
@@ -165287,7 +166438,7 @@ static int whereLoopAddBtreeIndex(
       || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
      ){
        if( iCol==XN_ROWID || pProbe->uniqNotNull
-
         || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
+
         || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ))
        ){
          pNew->wsFlags |= WHERE_ONEROW;
        }else{
@@ -165420,7 +166571,7 @@ static int whereLoopAddBtreeIndex(
    **   2.  Stepping forward in the index pNew->nOut times to find all
    **       additional matching entries.
    */
-
    assert( pSrc->pTab->szTabRow>0 );
+
    assert( pSrc->pSTab->szTabRow>0 );
    if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
      /* The pProbe->szIdxRow is low for an IPK table since the interior
      ** pages are small.  Thus szIdxRow gives a good estimate of seek cost.
@@ -165428,7 +166579,7 @@ static int whereLoopAddBtreeIndex(
      ** under-estimate the scanning cost. */
      rCostIdx = pNew->nOut + 16;
    }else{
-
      rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
+
      rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pSTab->szTabRow;
    }
    rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);

@@ -165893,9 +167044,9 @@ static int whereLoopAddBtree(
  pWInfo = pBuilder->pWInfo;
  pTabList = pWInfo->pTabList;
  pSrc = pTabList->a + pNew->iTab;
-
  pTab = pSrc->pTab;
+
  pTab = pSrc->pSTab;
  pWC = pBuilder->pWC;
-
  assert( !IsVirtual(pSrc->pTab) );
+
  assert( !IsVirtual(pSrc->pSTab) );

  if( pSrc->fg.isIndexedBy ){
    assert( pSrc->fg.isCte==0 );
@@ -165920,7 +167071,7 @@ static int whereLoopAddBtree(
    sPk.idxType = SQLITE_IDXTYPE_IPK;
    aiRowEstPk[0] = pTab->nRowLogEst;
    aiRowEstPk[1] = 0;
-
    pFirst = pSrc->pTab->pIndex;
+
    pFirst = pSrc->pSTab->pIndex;
    if( pSrc->fg.notIndexed==0 ){
      /* The real indices of the table are only considered if the
      ** NOT INDEXED qualifier is omitted from the FROM clause */
@@ -166010,6 +167161,7 @@ static int whereLoopAddBtree(
    pNew->prereq = mPrereq;
    pNew->nOut = rSize;
    pNew->u.btree.pIndex = pProbe;
+
    pNew->u.btree.pOrderBy = 0;
    b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);

    /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
@@ -166039,6 +167191,10 @@ static int whereLoopAddBtree(
#endif
      ApplyCostMultiplier(pNew->rRun, pTab->costMult);
      whereLoopOutputAdjust(pWC, pNew, rSize);
+
      if( pSrc->fg.isSubquery ){
+
        if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE;
+
        pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
+
      }
      rc = whereLoopInsert(pBuilder, pNew);
      pNew->nOut = rSize;
      if( rc ) break;
@@ -166241,7 +167397,7 @@ static int whereLoopAddVirtualOne(
  ** arguments mUsable and mExclude. */
  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
  for(i=0; i<nConstraint; i++, pIdxCons++){
-
    WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
+
    WhereTerm *pTerm = termFromWhereClause(pWC, pIdxCons->iTermOffset);
    pIdxCons->usable = 0;
    if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
     && (pTerm->eOperator & mExclude)==0
@@ -166260,11 +167416,10 @@ static int whereLoopAddVirtualOne(
  pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
  pIdxInfo->estimatedRows = 25;
  pIdxInfo->idxFlags = 0;
-
  pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
  pHidden->mHandleIn = 0;

  /* Invoke the virtual table xBestIndex() method */
-
  rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
+
  rc = vtabBestIndex(pParse, pSrc->pSTab, pIdxInfo);
  if( rc ){
    if( rc==SQLITE_CONSTRAINT ){
      /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
@@ -166272,6 +167427,7 @@ static int whereLoopAddVirtualOne(
      ** Make no entries in the loop table.
      */
      WHERETRACE(0xffffffff, ("  ^^^^--- non-viable plan rejected!\n"));
+
      freeIdxStr(pIdxInfo);
      return SQLITE_OK;
    }
    return rc;
@@ -166289,18 +167445,17 @@ static int whereLoopAddVirtualOne(
      int j = pIdxCons->iTermOffset;
      if( iTerm>=nConstraint
       || j<0
-
       || j>=pWC->nTerm
+
       || (pTerm = termFromWhereClause(pWC, j))==0
       || pNew->aLTerm[iTerm]!=0
       || pIdxCons->usable==0
      ){
-
        sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
-
        testcase( pIdxInfo->needToFreeIdxStr );
+
        sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName);
+
        freeIdxStr(pIdxInfo);
        return SQLITE_ERROR;
      }
      testcase( iTerm==nConstraint-1 );
      testcase( j==0 );
      testcase( j==pWC->nTerm-1 );
-
      pTerm = &pWC->a[j];
      pNew->prereq |= pTerm->prereqRight;
      assert( iTerm<pNew->nLSlot );
      pNew->aLTerm[iTerm] = pTerm;
@@ -166345,11 +167500,7 @@ static int whereLoopAddVirtualOne(
        ** the plan cannot be used. In these cases set variable *pbRetryLimit
        ** to true to tell the caller to retry with LIMIT and OFFSET
        ** disabled. */
-
        if( pIdxInfo->needToFreeIdxStr ){
-
          sqlite3_free(pIdxInfo->idxStr);
-
          pIdxInfo->idxStr = 0;
-
          pIdxInfo->needToFreeIdxStr = 0;
-
        }
+
        freeIdxStr(pIdxInfo);
        *pbRetryLimit = 1;
        return SQLITE_OK;
      }
@@ -166361,8 +167512,8 @@ static int whereLoopAddVirtualOne(
    if( pNew->aLTerm[i]==0 ){
      /* The non-zero argvIdx values must be contiguous.  Raise an
      ** error if they are not */
-
      sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
-
      testcase( pIdxInfo->needToFreeIdxStr );
+
      sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName);
+
      freeIdxStr(pIdxInfo);
      return SQLITE_ERROR;
    }
  }
@@ -166373,6 +167524,7 @@ static int whereLoopAddVirtualOne(
  pNew->u.vtab.idxStr = pIdxInfo->idxStr;
  pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
      pIdxInfo->nOrderBy : 0);
+
  pNew->u.vtab.bIdxNumHex = (pIdxInfo->idxFlags&SQLITE_INDEX_SCAN_HEX)!=0;
  pNew->rSetup = 0;
  pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
  pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
@@ -166417,7 +167569,7 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int
  if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
    CollSeq *pC = 0;
    int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
-
    Expr *pX = pHidden->pWC->a[iTerm].pExpr;
+
    Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr;
    if( pX->pLeft ){
      pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
    }
@@ -166463,7 +167615,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(
    rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */
  }else{
    if( pH->aRhs[iCons]==0 ){
-
      WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
+
      WhereTerm *pTerm = termFromWhereClause(
+
          pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset
+
      );
      rc = sqlite3ValueFromExpr(
          pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
          SQLITE_AFF_BLOB, &pH->aRhs[iCons]
@@ -166561,7 +167715,7 @@ static int whereLoopAddVirtual(
  pWC = pBuilder->pWC;
  pNew = pBuilder->pNew;
  pSrc = &pWInfo->pTabList->a[pNew->iTab];
-
  assert( IsVirtual(pSrc->pTab) );
+
  assert( IsVirtual(pSrc->pSTab) );
  p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit);
  if( p==0 ) return SQLITE_NOMEM_BKPT;
  pNew->rSetup = 0;
@@ -166575,7 +167729,7 @@ static int whereLoopAddVirtual(
  }

  /* First call xBestIndex() with all constraints usable. */
-
  WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
+
  WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pSTab->zName));
  WHERETRACE(0x800, ("  VirtualOne: all usable\n"));
  rc = whereLoopAddVirtualOne(
      pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry
@@ -166619,9 +167773,8 @@ static int whereLoopAddVirtual(
      Bitmask mNext = ALLBITS;
      assert( mNext>0 );
      for(i=0; i<nConstraint; i++){
-
        Bitmask mThis = (
-
            pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
-
        );
+
        int iTerm = p->aConstraint[i].iTermOffset;
+
        Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq;
        if( mThis>mPrev && mThis<mNext ) mNext = mThis;
      }
      mPrev = mNext;
@@ -166657,9 +167810,8 @@ static int whereLoopAddVirtual(
    }
  }

-
  if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
  freeIndexInfo(pParse->db, p);
-
  WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
+
  WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pSTab->zName, rc));
  return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -166731,7 +167883,7 @@ static int whereLoopAddOr(
        }
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
        if( IsVirtual(pItem->pTab) ){
+
        if( IsVirtual(pItem->pSTab) ){
          rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
        }else
#endif
@@ -166845,7 +167997,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
      mPrereq = 0;
    }
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
    if( IsVirtual(pItem->pTab) ){
+
    if( IsVirtual(pItem->pSTab) ){
      SrcItem *p;
      for(p=&pItem[1]; p<pEnd; p++){
        if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){
@@ -166877,6 +168029,97 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
  return rc;
}

+
/* Implementation of the order-by-subquery optimization:
+
**
+
** WhereLoop pLoop, which the iLoop-th term of the nested loop, is really
+
** a subquery or CTE that has an ORDER BY clause.  See if any of the terms
+
** in the subquery ORDER BY clause will satisfy pOrderBy from the outer
+
** query.  Mark off all satisfied terms (by setting bits in *pOBSat) and
+
** return TRUE if they do.  If not, return false.
+
**
+
** Example:
+
**
+
**    CREATE TABLE t1(a,b,c, PRIMARY KEY(a,b));
+
**    CREATE TABLE t2(x,y);
+
**    WITH t3(p,q) AS MATERIALIZED (SELECT x+y, x-y FROM t2 ORDER BY x+y)
+
**       SELECT * FROM t3 JOIN t1 ON a=q ORDER BY p, b;
+
**
+
** The CTE named "t3" comes out in the natural order of "p", so the first
+
** first them of "ORDER BY p,b" is satisfied by a sequential scan of "t3"
+
** and sorting only needs to occur on the second term "b".
+
**
+
** Limitations:
+
**
+
** (1)  The optimization is not applied if the outer ORDER BY contains
+
**      a COLLATE clause.  The optimization might be applied if the
+
**      outer ORDER BY uses NULLS FIRST, NULLS LAST, ASC, and/or DESC as
+
**      long as the subquery ORDER BY does the same.  But if the
+
**      outer ORDER BY uses COLLATE, even a redundant COLLATE, the
+
**      optimization is bypassed.
+
**
+
** (2)  The subquery ORDER BY terms must exactly match subquery result
+
**      columns, including any COLLATE annotations.  This routine relies
+
**      on iOrderByCol to do matching between order by terms and result
+
**      columns, and iOrderByCol will not be set if the result column
+
**      and ORDER BY collations differ.
+
**
+
** (3)  The subquery and outer ORDER BY can be in opposite directions as
+
**      long as  the subquery is materialized.  If the subquery is
+
**      implemented as a co-routine, the sort orders must be in the same
+
**      direction because there is no way to run a co-routine backwards.
+
*/
+
static SQLITE_NOINLINE int wherePathMatchSubqueryOB(
+
  WhereInfo *pWInfo,      /* The WHERE clause */
+
  WhereLoop *pLoop,       /* The nested loop term that is a subquery */
+
  int iLoop,              /* Which level of the nested loop.  0==outermost */
+
  int iCur,               /* Cursor used by the this loop */
+
  ExprList *pOrderBy,     /* The ORDER BY clause on the whole query */
+
  Bitmask *pRevMask,      /* When loops need to go in reverse order */
+
  Bitmask *pOBSat         /* Which terms of pOrderBy are satisfied so far */
+
){
+
  int iOB;                /* Index into pOrderBy->a[] */
+
  int jSub;               /* Index into pSubOB->a[] */
+
  u8 rev = 0;             /* True if iOB and jSub sort in opposite directions */
+
  u8 revIdx = 0;          /* Sort direction for jSub */
+
  Expr *pOBExpr;          /* Current term of outer ORDER BY */
+
  ExprList *pSubOB;       /* Complete ORDER BY on the subquery */
+

+
  pSubOB = pLoop->u.btree.pOrderBy;
+
  assert( pSubOB!=0 );
+
  for(iOB=0; (MASKBIT(iOB) & *pOBSat)!=0; iOB++){}
+
  for(jSub=0; jSub<pSubOB->nExpr && iOB<pOrderBy->nExpr; jSub++, iOB++){
+
    if( pSubOB->a[jSub].u.x.iOrderByCol==0 ) break;
+
    pOBExpr = pOrderBy->a[iOB].pExpr;
+
    if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) break;
+
    if( pOBExpr->iTable!=iCur ) break;
+
    if( pOBExpr->iColumn!=pSubOB->a[jSub].u.x.iOrderByCol-1 ) break;
+
    if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
+
      u8 sfOB = pOrderBy->a[iOB].fg.sortFlags;   /* sortFlags for iOB */
+
      u8 sfSub = pSubOB->a[jSub].fg.sortFlags;   /* sortFlags for jSub */
+
      if( (sfSub & KEYINFO_ORDER_BIGNULL) != (sfOB & KEYINFO_ORDER_BIGNULL) ){
+
        break;
+
      }
+
      revIdx = sfSub & KEYINFO_ORDER_DESC;
+
      if( jSub>0 ){
+
        if( (rev^revIdx)!=(sfOB & KEYINFO_ORDER_DESC) ){
+
          break;
+
        }
+
      }else{
+
        rev = revIdx ^ (sfOB & KEYINFO_ORDER_DESC);
+
        if( rev ){
+
          if( (pLoop->wsFlags & WHERE_COROUTINE)!=0 ){
+
            /* Cannot run a co-routine in reverse order */
+
            break;
+
          }
+
          *pRevMask |= MASKBIT(iLoop);
+
        }
+
      }
+
    }
+
    *pOBSat |= MASKBIT(iOB);
+
  }
+
  return jSub>0;
+
}
+

/*
** Examine a WherePath (with the addition of the extra WhereLoop of the 6th
** parameters) to see if it outputs rows in the requested ORDER BY
@@ -167022,9 +168265,18 @@ static i8 wherePathSatisfiesOrderBy(

    if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
      if( pLoop->wsFlags & WHERE_IPK ){
+
        if( pLoop->u.btree.pOrderBy
+
         && OptimizationEnabled(db, SQLITE_OrderBySubq)
+
         &&  wherePathMatchSubqueryOB(pWInfo,pLoop,iLoop,iCur,
+
                                     pOrderBy,pRevMask, &obSat)
+
        ){
+
          nColumn = 0;
+
          isOrderDistinct = 0;
+
        }else{
+
          nColumn = 1;
+
        }
        pIndex = 0;
        nKeyCol = 0;
-
        nColumn = 1;
      }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
        return 0;
      }else{
@@ -167034,7 +168286,7 @@ static i8 wherePathSatisfiesOrderBy(
        assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
                          || !HasRowid(pIndex->pTable));
        /* All relevant terms of the index must also be non-NULL in order
-
        ** for isOrderDistinct to be true.  So the isOrderDistint value
+
        ** for isOrderDistinct to be true.  So the isOrderDistinct value
        ** computed here might be a false positive.  Corrections will be
        ** made at tag-20210426-1 below */
        isOrderDistinct = IsUniqueIndex(pIndex)
@@ -167119,7 +168371,7 @@ static i8 wherePathSatisfiesOrderBy(
        }

        /* Find the ORDER BY term that corresponds to the j-th column
-
        ** of the index and mark that ORDER BY term off
+
        ** of the index and mark that ORDER BY term having been satisfied.
        */
        isMatch = 0;
        for(i=0; bOnce && i<nOrderBy; i++){
@@ -167327,6 +168579,83 @@ static LogEst whereSortingCost(
}

/*
+
** Compute the maximum number of paths in the solver algorithm, for
+
** queries that have three or more terms in the FROM clause.  Queries with
+
** two or fewer FROM clause terms are handled by the caller.
+
**
+
** Query planning is NP-hard.  We must limit the number of paths at
+
** each step of the solver search algorithm to avoid exponential behavior.
+
**
+
** The value returned is a tuning parameter.  Currently the value is:
+
**
+
**     18    for star queries
+
**     12    otherwise
+
**
+
** For the purposes of SQLite, a star-query is defined as a query
+
** with a large central table that is joined against four or more
+
** smaller tables.  The central table is called the "fact" table.
+
** The smaller tables that get joined are "dimension tables".
+
**
+
** SIDE EFFECT:  (and really the whole point of this subroutine)
+
**
+
** If pWInfo describes a star-query, then the cost on WhereLoops for the
+
** fact table is reduced.  This heuristic helps keep fact tables in
+
** outer loops.  Without this heuristic, paths with fact tables in outer
+
** loops tend to get pruned by the mxChoice limit on the number of paths,
+
** resulting in poor query plans.  The total amount of heuristic cost
+
** adjustment is stored in pWInfo->nOutStarDelta and the cost adjustment
+
** for each WhereLoop is stored in its rStarDelta field.
+
*/
+
static int computeMxChoice(WhereInfo *pWInfo, LogEst nRowEst){
+
  int nLoop = pWInfo->nLevel;    /* Number of terms in the join */
+
  if( nRowEst==0 && nLoop>=5 ){
+
    /* Check to see if we are dealing with a star schema and if so, reduce
+
    ** the cost of fact tables relative to dimension tables, as a heuristic
+
    ** to help keep the fact tables in outer loops.
+
    */
+
    int iLoop;                /* Counter over join terms */
+
    Bitmask m;                /* Bitmask for current loop */
+
    assert( pWInfo->nOutStarDelta==0 );
+
    for(iLoop=0, m=1; iLoop<nLoop; iLoop++, m<<=1){
+
      WhereLoop *pWLoop;        /* For looping over WhereLoops */
+
      int nDep = 0;             /* Number of dimension tables */
+
      LogEst rDelta;            /* Heuristic cost adjustment */
+
      Bitmask mSeen = 0;        /* Mask of dimension tables */
+
      for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+
        if( (pWLoop->prereq & m)!=0 && (pWLoop->maskSelf & mSeen)==0 ){
+
          nDep++;
+
          mSeen |= pWLoop->maskSelf;
+
        }
+
      }
+
      if( nDep<=3 ) continue;
+
      rDelta = 15*(nDep-3);
+
#ifdef WHERETRACE_ENABLED /* 0x4 */
+
      if( sqlite3WhereTrace&0x4 ){
+
         SrcItem *pItem = pWInfo->pTabList->a + iLoop;
+
         sqlite3DebugPrintf("Fact-table %s: %d dimensions, cost reduced %d\n",
+
             pItem->zAlias ? pItem->zAlias : pItem->pSTab->zName,
+
             nDep, rDelta);
+
      }
+
#endif
+
      if( pWInfo->nOutStarDelta==0 ){
+
        for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+
          pWLoop->rStarDelta = 0;
+
        }
+
      }
+
      pWInfo->nOutStarDelta += rDelta;
+
      for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+
        if( pWLoop->maskSelf==m ){
+
          pWLoop->rRun -= rDelta;
+
          pWLoop->nOut -= rDelta;
+
          pWLoop->rStarDelta = rDelta;
+
        }
+
      }
+
    }
+
  }
+
  return pWInfo->nOutStarDelta>0 ? 18 : 12;
+
}
+

+
/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
** attempts to find the lowest cost path that visits each WhereLoop
** once.  This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -167361,13 +168690,25 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){

  pParse = pWInfo->pParse;
  nLoop = pWInfo->nLevel;
-
  /* TUNING: For simple queries, only the best path is tracked.
-
  ** For 2-way joins, the 5 best paths are followed.
-
  ** For joins of 3 or more tables, track the 10 best paths */
-
  mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
-
  assert( nLoop<=pWInfo->pTabList->nSrc );
  WHERETRACE(0x002, ("---- begin solver.  (nRowEst=%d, nQueryLoop=%d)\n",
                     nRowEst, pParse->nQueryLoop));
+
  /* TUNING: mxChoice is the maximum number of possible paths to preserve
+
  ** at each step.  Based on the number of loops in the FROM clause:
+
  **
+
  **     nLoop      mxChoice
+
  **     -----      --------
+
  **       1            1            // the most common case
+
  **       2            5
+
  **       3+        12 or 18        // see computeMxChoice()
+
  */
+
  if( nLoop<=1 ){
+
    mxChoice = 1;
+
  }else if( nLoop==2 ){
+
    mxChoice = 5;
+
  }else{
+
    mxChoice = computeMxChoice(pWInfo, nRowEst);
+
  }
+
  assert( nLoop<=pWInfo->pTabList->nSrc );

  /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
  ** case the purpose of this call is to estimate the number of rows returned
@@ -167450,7 +168791,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){

        /* At this point, pWLoop is a candidate to be the next loop.
        ** Compute its cost */
-
        rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
+
        rUnsorted = pWLoop->rRun + pFrom->nRow;
+
        if( pWLoop->rSetup ){
+
          rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup, rUnsorted);
+
        }
        rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
        nOut = pFrom->nRow + pWLoop->nOut;
        maskNew = pFrom->maskLoop | pWLoop->maskSelf;
@@ -167495,6 +168839,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
        ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
        ** of legal values for isOrdered, -1..64.
        */
+
        testcase( nTo==0 );
        for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
          if( pTo->maskLoop==maskNew
           && ((pTo->isOrdered^isOrdered)&0x80)==0
@@ -167611,16 +168956,28 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){

#ifdef WHERETRACE_ENABLED  /* >=2 */
    if( sqlite3WhereTrace & 0x02 ){
+
      LogEst rMin, rFloor = 0;
+
      int nDone = 0;
      sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
-
      for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
-
        sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
-
           wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
-
           pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
-
        if( pTo->isOrdered>0 ){
-
          sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
-
        }else{
-
          sqlite3DebugPrintf("\n");
+
      while( nDone<nTo ){
+
        rMin = 0x7fff;
+
        for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
+
          if( pTo->rCost>rFloor && pTo->rCost<rMin ) rMin = pTo->rCost;
+
        }
+
        for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
+
          if( pTo->rCost==rMin ){
+
            sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
+
               wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+
               pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
+
            if( pTo->isOrdered>0 ){
+
              sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
+
            }else{
+
              sqlite3DebugPrintf("\n");
+
            }
+
            nDone++;
+
          }
        }
+
        rFloor = rMin;
      }
    }
#endif
@@ -167715,7 +169072,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
    }
  }

-
  pWInfo->nRowOut = pFrom->nRow;
+
  pWInfo->nRowOut = pFrom->nRow + pWInfo->nOutStarDelta;

  /* Free temporary memory and return success */
  sqlite3StackFreeNN(pParse->db, pSpace);
@@ -167826,7 +169183,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
  if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0;
  assert( pWInfo->pTabList->nSrc>=1 );
  pItem = pWInfo->pTabList->a;
-
  pTab = pItem->pTab;
+
  pTab = pItem->pSTab;
  if( IsVirtual(pTab) ) return 0;
  if( pItem->fg.isIndexedBy || pItem->fg.notIndexed ){
    testcase( pItem->fg.isIndexedBy );
@@ -168016,6 +169373,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
    WhereTerm *pTerm, *pEnd;
    SrcItem *pItem;
    WhereLoop *pLoop;
+
    Bitmask m1;
    pLoop = pWInfo->a[i].pWLoop;
    pItem = &pWInfo->pTabList->a[pLoop->iTab];
    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
@@ -168042,7 +169400,10 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
      }
    }
    if( pTerm<pEnd ) continue;
-
    WHERETRACE(0xffffffff, ("-> drop loop %c not used\n", pLoop->cId));
+
    WHERETRACE(0xffffffff,("-> omit unused FROM-clause term %c\n",pLoop->cId));
+
    m1 = MASKBIT(i)-1;
+
    testcase( ((pWInfo->revMask>>1) & ~m1)!=0 );
+
    pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
    notReady &= ~pLoop->maskSelf;
    for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
      if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
@@ -168089,7 +169450,7 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
    WhereLoop *pLoop = pWInfo->a[i].pWLoop;
    const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ);
    SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
-
    Table *pTab = pItem->pTab;
+
    Table *pTab = pItem->pSTab;
    if( (pTab->tabFlags & TF_HasStat1)==0 ) break;
    pTab->tabFlags |= TF_MaybeReanalyze;
    if( i>=1
@@ -168109,62 +169470,11 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
      }
    }
    nSearch += pLoop->nOut;
+
    if( pWInfo->nOutStarDelta ) nSearch += pLoop->rStarDelta;
  }
}

/*
-
** Expression Node callback for sqlite3ExprCanReturnSubtype().
-
**
-
** Only a function call is able to return a subtype.  So if the node
-
** is not a function call, return WRC_Prune immediately.
-
**
-
** A function call is able to return a subtype if it has the
-
** SQLITE_RESULT_SUBTYPE property.
-
**
-
** Assume that every function is able to pass-through a subtype from
-
** one of its argument (using sqlite3_result_value()).  Most functions
-
** are not this way, but we don't have a mechanism to distinguish those
-
** that are from those that are not, so assume they all work this way.
-
** That means that if one of its arguments is another function and that
-
** other function is able to return a subtype, then this function is
-
** able to return a subtype.
-
*/
-
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
-
  int n;
-
  FuncDef *pDef;
-
  sqlite3 *db;
-
  if( pExpr->op!=TK_FUNCTION ){
-
    return WRC_Prune;
-
  }
-
  assert( ExprUseXList(pExpr) );
-
  db = pWalker->pParse->db;
-
  n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
-
  pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
-
  if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
-
    pWalker->eCode = 1;
-
    return WRC_Prune;
-
  }
-
  return WRC_Continue;
-
}
-

-
/*
-
** Return TRUE if expression pExpr is able to return a subtype.
-
**
-
** A TRUE return does not guarantee that a subtype will be returned.
-
** It only indicates that a subtype return is possible.  False positives
-
** are acceptable as they only disable an optimization.  False negatives,
-
** on the other hand, can lead to incorrect answers.
-
*/
-
static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
-
  Walker w;
-
  memset(&w, 0, sizeof(w));
-
  w.pParse = pParse;
-
  w.xExprCallback = exprNodeCanReturnSubtype;
-
  sqlite3WalkExpr(&w, pExpr);
-
  return w.eCode;
-
}
-

-
/*
** The index pIdx is used by a query and contains one or more expressions.
** In other words pIdx is an index on an expression.  iIdxCur is the cursor
** number for the index and iDataCur is the cursor number for the corresponding
@@ -168197,12 +169507,6 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
      continue;
    }
    if( sqlite3ExprIsConstant(0,pExpr) ) continue;
-
    if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
-
      /* Functions that might set a subtype should not be replaced by the
-
      ** value taken from an expression index since the index omits the
-
      ** subtype.  https://sqlite.org/forum/forumpost/68d284c86b082c3e */
-
      continue;
-
    }
    p = sqlite3DbMallocRaw(pParse->db,  sizeof(IndexedExpr));
    if( p==0 ) break;
    p->pIENext = pParse->pIdxEpr;
@@ -168245,8 +169549,8 @@ static SQLITE_NOINLINE void whereReverseScanOrder(WhereInfo *pWInfo){
    SrcItem *pItem = &pWInfo->pTabList->a[ii];
    if( !pItem->fg.isCte
     || pItem->u2.pCteUse->eM10d!=M10d_Yes
-
     || NEVER(pItem->pSelect==0)
-
     || pItem->pSelect->pOrderBy==0
+
     || NEVER(pItem->fg.isSubquery==0)
+
     || pItem->u4.pSubq->pSelect->pOrderBy==0
    ){
      pWInfo->revMask |= MASKBIT(ii);
    }
@@ -168625,7 +169929,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
    if( db->mallocFailed ) goto whereBeginError;
    if( pWInfo->pOrderBy ){
       whereInterstageHeuristic(pWInfo);
-
       wherePathSolver(pWInfo, pWInfo->nRowOut+1);
+
       wherePathSolver(pWInfo, pWInfo->nRowOut<0 ? 1 : pWInfo->nRowOut+1);
       if( db->mallocFailed ) goto whereBeginError;
    }

@@ -168736,15 +170040,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
    int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
    int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
-
    assert( !(wsFlags & WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pTab) );
+
    assert( !(wsFlags&WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pSTab) );
    if( bOnerow || (
        0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
-
     && !IsVirtual(pTabList->a[0].pTab)
+
     && !IsVirtual(pTabList->a[0].pSTab)
     && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
     && OptimizationEnabled(db, SQLITE_OnePass)
    )){
      pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
-
      if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
+
      if( HasRowid(pTabList->a[0].pSTab) && (wsFlags & WHERE_IDX_ONLY) ){
        if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
          bFordelete = OPFLAG_FORDELETE;
        }
@@ -168762,7 +170066,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
    SrcItem *pTabItem;

    pTabItem = &pTabList->a[pLevel->iFrom];
-
    pTab = pTabItem->pTab;
+
    pTab = pTabItem->pSTab;
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    pLoop = pLevel->pWLoop;
    if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){
@@ -168833,7 +170137,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
        iIndexCur = pLevel->iTabCur;
        op = 0;
      }else if( pWInfo->eOnePass!=ONEPASS_OFF ){
-
        Index *pJ = pTabItem->pTab->pIndex;
+
        Index *pJ = pTabItem->pSTab->pIndex;
        iIndexCur = iAuxArg;
        assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
        while( ALWAYS(pJ) && pJ!=pIx ){
@@ -168900,7 +170204,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
      sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
      pRJ->regReturn = ++pParse->nMem;
      sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
-
      assert( pTab==pTabItem->pTab );
+
      assert( pTab==pTabItem->pSTab );
      if( HasRowid(pTab) ){
        KeyInfo *pInfo;
        sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1);
@@ -168939,13 +170243,18 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
    wsFlags = pLevel->pWLoop->wsFlags;
    pSrc = &pTabList->a[pLevel->iFrom];
    if( pSrc->fg.isMaterialized ){
-
      if( pSrc->fg.isCorrelated ){
-
        sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
+
      Subquery *pSubq;
+
      int iOnce = 0;
+
      assert( pSrc->fg.isSubquery );
+
      pSubq = pSrc->u4.pSubq;
+
      if( pSrc->fg.isCorrelated==0 ){
+
        iOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
      }else{
-
        int iOnce = sqlite3VdbeAddOp0(v, OP_Once);  VdbeCoverage(v);
-
        sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
-
        sqlite3VdbeJumpHere(v, iOnce);
+
        iOnce = 0;
      }
+
      sqlite3VdbeAddOp2(v, OP_Gosub, pSubq->regReturn, pSubq->addrFillSub);
+
      VdbeComment((v, "materialize %!S", pSrc));
+
      if( iOnce )  sqlite3VdbeJumpHere(v, iOnce);
    }
    assert( pTabList == pWInfo->pTabList );
    if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){
@@ -169158,9 +170467,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
        assert( pLevel->iTabCur==pSrc->iCursor );
        if( pSrc->fg.viaCoroutine ){
          int m, n;
-
          n = pSrc->regResult;
-
          assert( pSrc->pTab!=0 );
-
          m = pSrc->pTab->nCol;
+
          assert( pSrc->fg.isSubquery );
+
          n = pSrc->u4.pSubq->regResult;
+
          assert( pSrc->pSTab!=0 );
+
          m = pSrc->pSTab->nCol;
          sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
        }
        sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
@@ -169184,7 +170494,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
      sqlite3VdbeJumpHere(v, addr);
    }
    VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
-
                     pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
+
                     pWInfo->pTabList->a[pLevel->iFrom].pSTab->zName));
  }

  assert( pWInfo->nLevel<=pTabList->nSrc );
@@ -169193,7 +170503,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
    VdbeOp *pOp, *pLastOp;
    Index *pIdx = 0;
    SrcItem *pTabItem = &pTabList->a[pLevel->iFrom];
-
    Table *pTab = pTabItem->pTab;
+
    Table *pTab = pTabItem->pSTab;
    assert( pTab!=0 );
    pLoop = pLevel->pWLoop;

@@ -169212,9 +170522,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
    */
    if( pTabItem->fg.viaCoroutine ){
      testcase( pParse->db->mallocFailed );
-
      assert( pTabItem->regResult>=0 );
+
      assert( pTabItem->fg.isSubquery );
+
      assert( pTabItem->u4.pSubq->regResult>=0 );
      translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
-
                            pTabItem->regResult, 0);
+
                            pTabItem->u4.pSubq->regResult, 0);
      continue;
    }

@@ -170256,7 +171567,7 @@ static ExprList *exprListAppendList(
        int iDummy;
        Expr *pSub;
        pSub = sqlite3ExprSkipCollateAndLikely(pDup);
-
        if( sqlite3ExprIsInteger(pSub, &iDummy) ){
+
        if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){
          pSub->op = TK_NULL;
          pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
          pSub->u.zToken = 0;
@@ -170424,9 +171735,10 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
    assert( pSub!=0 || p->pSrc==0 ); /* Due to db->mallocFailed test inside
                                     ** of sqlite3DbMallocRawNN() called from
                                     ** sqlite3SrcListAppend() */
-
    if( p->pSrc ){
+
    if( p->pSrc==0 ){
+
      sqlite3SelectDelete(db, pSub);
+
    }else if( sqlite3SrcItemAttachSubquery(pParse, &p->pSrc->a[0], pSub, 0) ){
      Table *pTab2;
-
      p->pSrc->a[0].pSelect = pSub;
      p->pSrc->a[0].fg.isCorrelated = 1;
      sqlite3SrcListAssignCursors(pParse, p->pSrc);
      pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
@@ -170440,7 +171752,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
      }else{
        memcpy(pTab, pTab2, sizeof(Table));
        pTab->tabFlags |= TF_Ephemeral;
-
        p->pSrc->a[0].pTab = pTab;
+
        p->pSrc->a[0].pSTab = pTab;
        pTab = pTab2;
        memset(&w, 0, sizeof(w));
        w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
@@ -170448,8 +171760,6 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
        w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
        sqlite3WalkSelect(&w, pSub);
      }
-
    }else{
-
      sqlite3SelectDelete(db, pSub);
    }
    if( db->mallocFailed ) rc = SQLITE_NOMEM;

@@ -170736,10 +172046,15 @@ SQLITE_PRIVATE int sqlite3WindowCompare(
** and initialize registers and cursors used by sqlite3WindowCodeStep().
*/
SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
-
  int nEphExpr = pSelect->pSrc->a[0].pSelect->pEList->nExpr;
-
  Window *pMWin = pSelect->pWin;
  Window *pWin;
-
  Vdbe *v = sqlite3GetVdbe(pParse);
+
  int nEphExpr;
+
  Window *pMWin;
+
  Vdbe *v;
+

+
  assert( pSelect->pSrc->a[0].fg.isSubquery );
+
  nEphExpr = pSelect->pSrc->a[0].u4.pSubq->pSelect->pEList->nExpr;
+
  pMWin = pSelect->pWin;
+
  v = sqlite3GetVdbe(pParse);

  sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr);
  sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
@@ -172136,7 +173451,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
  Vdbe *v = sqlite3GetVdbe(pParse);
  int csrWrite;                   /* Cursor used to write to eph. table */
  int csrInput = p->pSrc->a[0].iCursor;     /* Cursor of sub-select */
-
  int nInput = p->pSrc->a[0].pTab->nCol;    /* Number of cols returned by sub */
+
  int nInput = p->pSrc->a[0].pSTab->nCol;   /* Number of cols returned by sub */
  int iInput;                               /* To iterate through sub cols */
  int addrNe;                     /* Address of OP_Ne */
  int addrGosubFlush = 0;         /* Address of OP_Gosub to flush: */
@@ -172733,132 +174048,132 @@ static void updateDeleteLimitError(
#define TK_OR                             43
#define TK_AND                            44
#define TK_IS                             45
-
#define TK_MATCH                          46
-
#define TK_LIKE_KW                        47
-
#define TK_BETWEEN                        48
-
#define TK_IN                             49
-
#define TK_ISNULL                         50
-
#define TK_NOTNULL                        51
-
#define TK_NE                             52
-
#define TK_EQ                             53
-
#define TK_GT                             54
-
#define TK_LE                             55
-
#define TK_LT                             56
-
#define TK_GE                             57
-
#define TK_ESCAPE                         58
-
#define TK_ID                             59
-
#define TK_COLUMNKW                       60
-
#define TK_DO                             61
-
#define TK_FOR                            62
-
#define TK_IGNORE                         63
-
#define TK_INITIALLY                      64
-
#define TK_INSTEAD                        65
-
#define TK_NO                             66
-
#define TK_KEY                            67
-
#define TK_OF                             68
-
#define TK_OFFSET                         69
-
#define TK_PRAGMA                         70
-
#define TK_RAISE                          71
-
#define TK_RECURSIVE                      72
-
#define TK_REPLACE                        73
-
#define TK_RESTRICT                       74
-
#define TK_ROW                            75
-
#define TK_ROWS                           76
-
#define TK_TRIGGER                        77
-
#define TK_VACUUM                         78
-
#define TK_VIEW                           79
-
#define TK_VIRTUAL                        80
-
#define TK_WITH                           81
-
#define TK_NULLS                          82
-
#define TK_FIRST                          83
-
#define TK_LAST                           84
-
#define TK_CURRENT                        85
-
#define TK_FOLLOWING                      86
-
#define TK_PARTITION                      87
-
#define TK_PRECEDING                      88
-
#define TK_RANGE                          89
-
#define TK_UNBOUNDED                      90
-
#define TK_EXCLUDE                        91
-
#define TK_GROUPS                         92
-
#define TK_OTHERS                         93
-
#define TK_TIES                           94
-
#define TK_GENERATED                      95
-
#define TK_ALWAYS                         96
-
#define TK_MATERIALIZED                   97
-
#define TK_REINDEX                        98
-
#define TK_RENAME                         99
-
#define TK_CTIME_KW                       100
-
#define TK_ANY                            101
-
#define TK_BITAND                         102
-
#define TK_BITOR                          103
-
#define TK_LSHIFT                         104
-
#define TK_RSHIFT                         105
-
#define TK_PLUS                           106
-
#define TK_MINUS                          107
-
#define TK_STAR                           108
-
#define TK_SLASH                          109
-
#define TK_REM                            110
-
#define TK_CONCAT                         111
-
#define TK_PTR                            112
-
#define TK_COLLATE                        113
-
#define TK_BITNOT                         114
-
#define TK_ON                             115
-
#define TK_INDEXED                        116
-
#define TK_STRING                         117
-
#define TK_JOIN_KW                        118
-
#define TK_CONSTRAINT                     119
-
#define TK_DEFAULT                        120
-
#define TK_NULL                           121
-
#define TK_PRIMARY                        122
-
#define TK_UNIQUE                         123
-
#define TK_CHECK                          124
-
#define TK_REFERENCES                     125
-
#define TK_AUTOINCR                       126
-
#define TK_INSERT                         127
-
#define TK_DELETE                         128
-
#define TK_UPDATE                         129
-
#define TK_SET                            130
-
#define TK_DEFERRABLE                     131
-
#define TK_FOREIGN                        132
-
#define TK_DROP                           133
-
#define TK_UNION                          134
-
#define TK_ALL                            135
-
#define TK_EXCEPT                         136
-
#define TK_INTERSECT                      137
-
#define TK_SELECT                         138
-
#define TK_VALUES                         139
-
#define TK_DISTINCT                       140
-
#define TK_DOT                            141
-
#define TK_FROM                           142
-
#define TK_JOIN                           143
-
#define TK_USING                          144
-
#define TK_ORDER                          145
-
#define TK_GROUP                          146
-
#define TK_HAVING                         147
-
#define TK_LIMIT                          148
-
#define TK_WHERE                          149
-
#define TK_RETURNING                      150
-
#define TK_INTO                           151
-
#define TK_NOTHING                        152
-
#define TK_FLOAT                          153
-
#define TK_BLOB                           154
-
#define TK_INTEGER                        155
-
#define TK_VARIABLE                       156
-
#define TK_CASE                           157
-
#define TK_WHEN                           158
-
#define TK_THEN                           159
-
#define TK_ELSE                           160
-
#define TK_INDEX                          161
-
#define TK_ALTER                          162
-
#define TK_ADD                            163
-
#define TK_WINDOW                         164
-
#define TK_OVER                           165
-
#define TK_FILTER                         166
-
#define TK_COLUMN                         167
-
#define TK_AGG_FUNCTION                   168
-
#define TK_AGG_COLUMN                     169
-
#define TK_TRUEFALSE                      170
-
#define TK_ISNOT                          171
+
#define TK_ISNOT                          46
+
#define TK_MATCH                          47
+
#define TK_LIKE_KW                        48
+
#define TK_BETWEEN                        49
+
#define TK_IN                             50
+
#define TK_ISNULL                         51
+
#define TK_NOTNULL                        52
+
#define TK_NE                             53
+
#define TK_EQ                             54
+
#define TK_GT                             55
+
#define TK_LE                             56
+
#define TK_LT                             57
+
#define TK_GE                             58
+
#define TK_ESCAPE                         59
+
#define TK_ID                             60
+
#define TK_COLUMNKW                       61
+
#define TK_DO                             62
+
#define TK_FOR                            63
+
#define TK_IGNORE                         64
+
#define TK_INITIALLY                      65
+
#define TK_INSTEAD                        66
+
#define TK_NO                             67
+
#define TK_KEY                            68
+
#define TK_OF                             69
+
#define TK_OFFSET                         70
+
#define TK_PRAGMA                         71
+
#define TK_RAISE                          72
+
#define TK_RECURSIVE                      73
+
#define TK_REPLACE                        74
+
#define TK_RESTRICT                       75
+
#define TK_ROW                            76
+
#define TK_ROWS                           77
+
#define TK_TRIGGER                        78
+
#define TK_VACUUM                         79
+
#define TK_VIEW                           80
+
#define TK_VIRTUAL                        81
+
#define TK_WITH                           82
+
#define TK_NULLS                          83
+
#define TK_FIRST                          84
+
#define TK_LAST                           85
+
#define TK_CURRENT                        86
+
#define TK_FOLLOWING                      87
+
#define TK_PARTITION                      88
+
#define TK_PRECEDING                      89
+
#define TK_RANGE                          90
+
#define TK_UNBOUNDED                      91
+
#define TK_EXCLUDE                        92
+
#define TK_GROUPS                         93
+
#define TK_OTHERS                         94
+
#define TK_TIES                           95
+
#define TK_GENERATED                      96
+
#define TK_ALWAYS                         97
+
#define TK_MATERIALIZED                   98
+
#define TK_REINDEX                        99
+
#define TK_RENAME                         100
+
#define TK_CTIME_KW                       101
+
#define TK_ANY                            102
+
#define TK_BITAND                         103
+
#define TK_BITOR                          104
+
#define TK_LSHIFT                         105
+
#define TK_RSHIFT                         106
+
#define TK_PLUS                           107
+
#define TK_MINUS                          108
+
#define TK_STAR                           109
+
#define TK_SLASH                          110
+
#define TK_REM                            111
+
#define TK_CONCAT                         112
+
#define TK_PTR                            113
+
#define TK_COLLATE                        114
+
#define TK_BITNOT                         115
+
#define TK_ON                             116
+
#define TK_INDEXED                        117
+
#define TK_STRING                         118
+
#define TK_JOIN_KW                        119
+
#define TK_CONSTRAINT                     120
+
#define TK_DEFAULT                        121
+
#define TK_NULL                           122
+
#define TK_PRIMARY                        123
+
#define TK_UNIQUE                         124
+
#define TK_CHECK                          125
+
#define TK_REFERENCES                     126
+
#define TK_AUTOINCR                       127
+
#define TK_INSERT                         128
+
#define TK_DELETE                         129
+
#define TK_UPDATE                         130
+
#define TK_SET                            131
+
#define TK_DEFERRABLE                     132
+
#define TK_FOREIGN                        133
+
#define TK_DROP                           134
+
#define TK_UNION                          135
+
#define TK_ALL                            136
+
#define TK_EXCEPT                         137
+
#define TK_INTERSECT                      138
+
#define TK_SELECT                         139
+
#define TK_VALUES                         140
+
#define TK_DISTINCT                       141
+
#define TK_DOT                            142
+
#define TK_FROM                           143
+
#define TK_JOIN                           144
+
#define TK_USING                          145
+
#define TK_ORDER                          146
+
#define TK_GROUP                          147
+
#define TK_HAVING                         148
+
#define TK_LIMIT                          149
+
#define TK_WHERE                          150
+
#define TK_RETURNING                      151
+
#define TK_INTO                           152
+
#define TK_NOTHING                        153
+
#define TK_FLOAT                          154
+
#define TK_BLOB                           155
+
#define TK_INTEGER                        156
+
#define TK_VARIABLE                       157
+
#define TK_CASE                           158
+
#define TK_WHEN                           159
+
#define TK_THEN                           160
+
#define TK_ELSE                           161
+
#define TK_INDEX                          162
+
#define TK_ALTER                          163
+
#define TK_ADD                            164
+
#define TK_WINDOW                         165
+
#define TK_OVER                           166
+
#define TK_FILTER                         167
+
#define TK_COLUMN                         168
+
#define TK_AGG_FUNCTION                   169
+
#define TK_AGG_COLUMN                     170
+
#define TK_TRUEFALSE                      171
#define TK_FUNCTION                       172
#define TK_UPLUS                          173
#define TK_UMINUS                         174
@@ -172939,7 +174254,7 @@ static void updateDeleteLimitError(
#define YYCODETYPE unsigned short int
#define YYNOCODE 322
#define YYACTIONTYPE unsigned short int
-
#define YYWILDCARD 101
+
#define YYWILDCARD 102
#define sqlite3ParserTOKENTYPE Token
typedef union {
  int yyinit;
@@ -173076,446 +174391,452 @@ typedef union {
**  yy_default[]       Default action for each state.
**
*********** Begin parsing tables **********************************************/
-
#define YY_ACTTAB_COUNT (2142)
+
#define YY_ACTTAB_COUNT (2207)
static const YYACTIONTYPE yy_action[] = {
-
 /*     0 */   576,  128,  125,  232, 1622,  549,  576, 1290, 1281,  576,
-
 /*    10 */   328,  576, 1300,  212,  576,  128,  125,  232,  578,  412,
-
 /*    20 */   578,  391, 1542,   51,   51,  523,  405, 1293,  529,   51,
-
 /*    30 */    51,  983,   51,   51,   81,   81, 1107,   61,   61,  984,
-
 /*    40 */  1107, 1292,  380,  135,  136,   90, 1228, 1228, 1063, 1066,
-
 /*    50 */  1053, 1053,  133,  133,  134,  134,  134,  134, 1577,  412,
-
 /*    60 */   287,  287,    7,  287,  287,  422, 1050, 1050, 1064, 1067,
-
 /*    70 */   289,  556,  492,  573,  524,  561,  573,  497,  561,  482,
-
 /*    80 */   530,  262,  229,  135,  136,   90, 1228, 1228, 1063, 1066,
-
 /*    90 */  1053, 1053,  133,  133,  134,  134,  134,  134,  128,  125,
-
 /*   100 */   232, 1506,  132,  132,  132,  132,  131,  131,  130,  130,
-
 /*   110 */   130,  129,  126,  450, 1204, 1255,    1,    1,  582,    2,
-
 /*   120 */  1259, 1571,  420, 1582,  379,  320, 1174,  153, 1174, 1584,
-
 /*   130 */   412,  378, 1582,  543, 1341,  330,  111,  570,  570,  570,
-
 /*   140 */   293, 1054,  132,  132,  132,  132,  131,  131,  130,  130,
-
 /*   150 */   130,  129,  126,  450,  135,  136,   90, 1228, 1228, 1063,
-
 /*   160 */  1066, 1053, 1053,  133,  133,  134,  134,  134,  134,  287,
-
 /*   170 */   287, 1204, 1205, 1204,  255,  287,  287,  510,  507,  506,
-
 /*   180 */   137,  455,  573,  212,  561,  447,  446,  505,  573, 1616,
-
 /*   190 */   561,  134,  134,  134,  134,  127,  400,  243,  132,  132,
-
 /*   200 */   132,  132,  131,  131,  130,  130,  130,  129,  126,  450,
-
 /*   210 */   282,  471,  345,  132,  132,  132,  132,  131,  131,  130,
-
 /*   220 */   130,  130,  129,  126,  450,  574,  155,  936,  936,  454,
-
 /*   230 */   227,  521, 1236,  412, 1236,  134,  134,  134,  134,  132,
-
 /*   240 */   132,  132,  132,  131,  131,  130,  130,  130,  129,  126,
-
 /*   250 */   450,  130,  130,  130,  129,  126,  450,  135,  136,   90,
-
 /*   260 */  1228, 1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,
-
 /*   270 */   134,  134,  128,  125,  232,  450,  576,  412,  397, 1249,
-
 /*   280 */   180,   92,   93,  132,  132,  132,  132,  131,  131,  130,
-
 /*   290 */   130,  130,  129,  126,  450,  381,  387, 1204,  383,   81,
-
 /*   300 */    81,  135,  136,   90, 1228, 1228, 1063, 1066, 1053, 1053,
-
 /*   310 */   133,  133,  134,  134,  134,  134,  132,  132,  132,  132,
-
 /*   320 */   131,  131,  130,  130,  130,  129,  126,  450,  131,  131,
-
 /*   330 */   130,  130,  130,  129,  126,  450,  556, 1204,  302,  319,
-
 /*   340 */   567,  121,  568,  480,    4,  555, 1149, 1657, 1628, 1657,
-
 /*   350 */    45,  128,  125,  232, 1204, 1205, 1204, 1250,  571, 1169,
-
 /*   360 */   132,  132,  132,  132,  131,  131,  130,  130,  130,  129,
-
 /*   370 */   126,  450, 1169,  287,  287, 1169, 1019,  576,  422, 1019,
-
 /*   380 */   412,  451, 1602,  582,    2, 1259,  573,   44,  561,   95,
-
 /*   390 */   320,  110,  153,  565, 1204, 1205, 1204,  522,  522, 1341,
-
 /*   400 */    81,   81,    7,   44,  135,  136,   90, 1228, 1228, 1063,
-
 /*   410 */  1066, 1053, 1053,  133,  133,  134,  134,  134,  134,  295,
-
 /*   420 */  1149, 1658, 1040, 1658, 1204, 1147,  319,  567,  119,  119,
-
 /*   430 */   343,  466,  331,  343,  287,  287,  120,  556,  451,  577,
-
 /*   440 */   451, 1169, 1169, 1028,  319,  567,  438,  573,  210,  561,
-
 /*   450 */  1339, 1451,  546,  531, 1169, 1169, 1598, 1169, 1169,  416,
-
 /*   460 */   319,  567,  243,  132,  132,  132,  132,  131,  131,  130,
-
 /*   470 */   130,  130,  129,  126,  450, 1028, 1028, 1030, 1031,   35,
-
 /*   480 */    44, 1204, 1205, 1204,  472,  287,  287, 1328,  412, 1307,
-
 /*   490 */   372, 1595,  359,  225,  454, 1204,  195, 1328,  573, 1147,
-
 /*   500 */   561, 1333, 1333,  274,  576, 1188,  576,  340,   46,  196,
-
 /*   510 */   537,  217,  135,  136,   90, 1228, 1228, 1063, 1066, 1053,
-
 /*   520 */  1053,  133,  133,  134,  134,  134,  134,   19,   19,   19,
-
 /*   530 */    19,  412,  581, 1204, 1259,  511, 1204,  319,  567,  320,
-
 /*   540 */   944,  153,  425,  491,  430,  943, 1204,  488, 1341, 1450,
-
 /*   550 */   532, 1277, 1204, 1205, 1204,  135,  136,   90, 1228, 1228,
-
 /*   560 */  1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,  134,
-
 /*   570 */   575,  132,  132,  132,  132,  131,  131,  130,  130,  130,
-
 /*   580 */   129,  126,  450,  287,  287,  528,  287,  287,  372, 1595,
-
 /*   590 */  1204, 1205, 1204, 1204, 1205, 1204,  573,  486,  561,  573,
-
 /*   600 */   889,  561,  412, 1204, 1205, 1204,  886,   40,   22,   22,
-
 /*   610 */   220,  243,  525, 1449,  132,  132,  132,  132,  131,  131,
-
 /*   620 */   130,  130,  130,  129,  126,  450,  135,  136,   90, 1228,
-
 /*   630 */  1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,
-
 /*   640 */   134,  412,  180,  454, 1204,  879,  255,  287,  287,  510,
-
 /*   650 */   507,  506,  372, 1595, 1568, 1331, 1331,  576,  889,  505,
-
 /*   660 */   573,   44,  561,  559, 1207,  135,  136,   90, 1228, 1228,
-
 /*   670 */  1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,  134,
-
 /*   680 */    81,   81,  422,  576,  377,  132,  132,  132,  132,  131,
-
 /*   690 */   131,  130,  130,  130,  129,  126,  450,  297,  287,  287,
-
 /*   700 */   460, 1204, 1205, 1204, 1204,  534,   19,   19,  448,  448,
-
 /*   710 */   448,  573,  412,  561,  230,  436, 1187,  535,  319,  567,
-
 /*   720 */   363,  432, 1207, 1435,  132,  132,  132,  132,  131,  131,
-
 /*   730 */   130,  130,  130,  129,  126,  450,  135,  136,   90, 1228,
-
 /*   740 */  1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,
-
 /*   750 */   134,  412,  211,  949, 1169, 1041, 1110, 1110,  494,  547,
-
 /*   760 */   547, 1204, 1205, 1204,    7,  539, 1570, 1169,  376,  576,
-
 /*   770 */  1169,    5, 1204,  486,    3,  135,  136,   90, 1228, 1228,
-
 /*   780 */  1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,  134,
-
 /*   790 */   576,  513,   19,   19,  427,  132,  132,  132,  132,  131,
-
 /*   800 */   131,  130,  130,  130,  129,  126,  450,  305, 1204,  433,
-
 /*   810 */   225, 1204,  385,   19,   19,  273,  290,  371,  516,  366,
-
 /*   820 */   515,  260,  412,  538, 1568,  549, 1024,  362,  437, 1204,
-
 /*   830 */  1205, 1204,  902, 1552,  132,  132,  132,  132,  131,  131,
-
 /*   840 */   130,  130,  130,  129,  126,  450,  135,  136,   90, 1228,
-
 /*   850 */  1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,
-
 /*   860 */   134,  412, 1435,  514, 1281, 1204, 1205, 1204, 1204, 1205,
-
 /*   870 */  1204,  903,   48,  342, 1568, 1568, 1279, 1627, 1568,  911,
-
 /*   880 */   576,  129,  126,  450,  110,  135,  136,   90, 1228, 1228,
-
 /*   890 */  1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,  134,
-
 /*   900 */   265,  576,  459,   19,   19,  132,  132,  132,  132,  131,
-
 /*   910 */   131,  130,  130,  130,  129,  126,  450, 1345,  204,  576,
-
 /*   920 */   459,  458,   50,   47,   19,   19,   49,  434, 1105,  573,
-
 /*   930 */   497,  561,  412,  428,  108, 1224, 1569, 1554,  376,  205,
-
 /*   940 */   550,  550,   81,   81,  132,  132,  132,  132,  131,  131,
-
 /*   950 */   130,  130,  130,  129,  126,  450,  135,  136,   90, 1228,
-
 /*   960 */  1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,
-
 /*   970 */   134,  480,  576, 1204,  576, 1541,  412, 1435,  969,  315,
-
 /*   980 */  1659,  398,  284,  497,  969,  893, 1569, 1569,  376,  376,
-
 /*   990 */  1569,  461,  376, 1224,  459,   80,   80,   81,   81,  497,
-
 /*  1000 */   374,  114,   90, 1228, 1228, 1063, 1066, 1053, 1053,  133,
-
 /*  1010 */   133,  134,  134,  134,  134,  132,  132,  132,  132,  131,
-
 /*  1020 */   131,  130,  130,  130,  129,  126,  450, 1204, 1505,  576,
-
 /*  1030 */  1204, 1205, 1204, 1366,  316,  486,  281,  281,  497,  431,
-
 /*  1040 */   557,  288,  288,  402, 1340,  471,  345,  298,  429,  573,
-
 /*  1050 */   576,  561,   81,   81,  573,  374,  561,  971,  386,  132,
-
 /*  1060 */   132,  132,  132,  131,  131,  130,  130,  130,  129,  126,
-
 /*  1070 */   450,  231,  117,   81,   81,  287,  287,  231,  287,  287,
-
 /*  1080 */   576, 1511,  576, 1336, 1204, 1205, 1204,  139,  573,  556,
-
 /*  1090 */   561,  573,  412,  561,  441,  456,  969,  213,  558, 1511,
-
 /*  1100 */  1513, 1550,  969,  143,  143,  145,  145, 1368,  314,  478,
-
 /*  1110 */   444,  970,  412,  850,  851,  852,  135,  136,   90, 1228,
-
 /*  1120 */  1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,
-
 /*  1130 */   134,  357,  412,  397, 1148,  304,  135,  136,   90, 1228,
-
 /*  1140 */  1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,
-
 /*  1150 */   134, 1575,  323,    6,  862,    7,  135,  124,   90, 1228,
-
 /*  1160 */  1228, 1063, 1066, 1053, 1053,  133,  133,  134,  134,  134,
-
 /*  1170 */   134,  409,  408, 1511,  212,  132,  132,  132,  132,  131,
-
 /*  1180 */   131,  130,  130,  130,  129,  126,  450,  411,  118, 1204,
-
 /*  1190 */   116,   10,  352,  265,  355,  132,  132,  132,  132,  131,
-
 /*  1200 */   131,  130,  130,  130,  129,  126,  450,  576,  324,  306,
-
 /*  1210 */   576,  306, 1250,  469,  158,  132,  132,  132,  132,  131,
-
 /*  1220 */   131,  130,  130,  130,  129,  126,  450,  207, 1224, 1126,
-
 /*  1230 */    65,   65,  470,   66,   66,  412,  447,  446,  882,  531,
-
 /*  1240 */   335,  258,  257,  256, 1127, 1233, 1204, 1205, 1204,  327,
-
 /*  1250 */  1235,  874,  159,  576,   16,  480, 1085, 1040, 1234, 1128,
-
 /*  1260 */   136,   90, 1228, 1228, 1063, 1066, 1053, 1053,  133,  133,
-
 /*  1270 */   134,  134,  134,  134, 1029,  576,   81,   81, 1028, 1040,
-
 /*  1280 */   922,  576,  463, 1236,  576, 1236, 1224,  502,  107, 1435,
-
 /*  1290 */   923,    6,  576,  410, 1498,  882, 1029,  480,   21,   21,
-
 /*  1300 */  1028,  332, 1380,  334,   53,   53,  497,   81,   81,  874,
-
 /*  1310 */  1028, 1028, 1030,  445,  259,   19,   19,  533,  132,  132,
-
 /*  1320 */   132,  132,  131,  131,  130,  130,  130,  129,  126,  450,
-
 /*  1330 */   551,  301, 1028, 1028, 1030,  107,  532,  545,  121,  568,
-
 /*  1340 */  1188,    4, 1126, 1576,  449,  576,  462,    7, 1282,  418,
-
 /*  1350 */   462,  350, 1435,  576,  518,  571,  544, 1127,  121,  568,
-
 /*  1360 */   442,    4, 1188,  464,  533, 1180, 1223,    9,   67,   67,
-
 /*  1370 */   487,  576, 1128,  303,  410,  571,   54,   54,  451,  576,
-
 /*  1380 */   123,  944,  576,  417,  576,  333,  943, 1379,  576,  236,
-
 /*  1390 */   565,  576, 1574,  564,   68,   68,    7,  576,  451,  362,
-
 /*  1400 */   419,  182,   69,   69,  541,   70,   70,   71,   71,  540,
-
 /*  1410 */   565,   72,   72,  484,   55,   55,  473, 1180,  296, 1040,
-
 /*  1420 */    56,   56,  296,  493,  541,  119,  119,  410, 1573,  542,
-
 /*  1430 */   569,  418,    7,  120, 1244,  451,  577,  451,  465, 1040,
-
 /*  1440 */  1028,  576, 1557,  552,  476,  119,  119,  527,  259,  121,
-
 /*  1450 */   568,  240,    4,  120,  576,  451,  577,  451,  576,  477,
-
 /*  1460 */  1028,  576,  156,  576,   57,   57,  571,  576,  286,  229,
-
 /*  1470 */   410,  336, 1028, 1028, 1030, 1031,   35,   59,   59,  219,
-
 /*  1480 */   983,   60,   60,  220,   73,   73,   74,   74,  984,  451,
-
 /*  1490 */    75,   75, 1028, 1028, 1030, 1031,   35,   96,  216,  291,
-
 /*  1500 */   552,  565, 1188,  318,  395,  395,  394,  276,  392,  576,
-
 /*  1510 */   485,  859,  474, 1311,  410,  541,  576,  417, 1530, 1144,
-
 /*  1520 */   540,  399, 1188,  292,  237, 1153,  326,   38,   23,  576,
-
 /*  1530 */  1040,  576,   20,   20,  325,  299,  119,  119,  164,   76,
-
 /*  1540 */    76, 1529,  121,  568,  120,    4,  451,  577,  451,  203,
-
 /*  1550 */   576, 1028,  141,  141,  142,  142,  576,  322,   39,  571,
-
 /*  1560 */   341, 1021,  110,  264,  239,  901,  900,  423,  242,  908,
-
 /*  1570 */   909,  370,  173,   77,   77,   43,  479, 1310,  264,   62,
-
 /*  1580 */    62,  369,  451, 1028, 1028, 1030, 1031,   35, 1601, 1192,
-
 /*  1590 */   453, 1092,  238,  291,  565,  163, 1309,  110,  395,  395,
-
 /*  1600 */   394,  276,  392,  986,  987,  859,  481,  346,  264,  110,
-
 /*  1610 */  1032,  489,  576, 1188,  503, 1088,  261,  261,  237,  576,
-
 /*  1620 */   326,  121,  568, 1040,    4,  347, 1376,  413,  325,  119,
-
 /*  1630 */   119,  948,  319,  567,  351,   78,   78,  120,  571,  451,
-
 /*  1640 */   577,  451,   79,   79, 1028,  354,  356,  576,  360, 1092,
-
 /*  1650 */   110,  576,  974,  942,  264,  123,  457,  358,  239,  576,
-
 /*  1660 */   519,  451,  939, 1104,  123, 1104,  173,  576, 1032,   43,
-
 /*  1670 */    63,   63, 1324,  565,  168,  168, 1028, 1028, 1030, 1031,
-
 /*  1680 */    35,  576,  169,  169, 1308,  872,  238,  157, 1589,  576,
-
 /*  1690 */    86,   86,  365,   89,  568,  375,    4, 1103,  941, 1103,
-
 /*  1700 */   123,  576, 1040, 1389,   64,   64, 1188, 1434,  119,  119,
-
 /*  1710 */   571,  576,   82,   82,  563,  576,  120,  165,  451,  577,
-
 /*  1720 */   451,  413, 1362, 1028,  144,  144,  319,  567,  576, 1374,
-
 /*  1730 */   562,  498,  279,  451,   83,   83, 1439,  576,  166,  166,
-
 /*  1740 */   576, 1289,  554,  576, 1280,  565,  576,   12,  576, 1268,
-
 /*  1750 */   457,  146,  146, 1267,  576, 1028, 1028, 1030, 1031,   35,
-
 /*  1760 */   140,  140, 1269,  167,  167, 1609,  160,  160, 1359,  150,
-
 /*  1770 */   150,  149,  149,  311, 1040,  576,  312,  147,  147,  313,
-
 /*  1780 */   119,  119,  222,  235,  576, 1188,  396,  576,  120,  576,
-
 /*  1790 */   451,  577,  451, 1192,  453, 1028,  508,  291,  148,  148,
-
 /*  1800 */  1421, 1612,  395,  395,  394,  276,  392,   85,   85,  859,
-
 /*  1810 */    87,   87,   84,   84,  553,  576,  294,  576, 1426,  338,
-
 /*  1820 */   339, 1425,  237,  300,  326, 1416, 1409, 1028, 1028, 1030,
-
 /*  1830 */  1031,   35,  325,  344,  403,  483,  226, 1307,   52,   52,
-
 /*  1840 */    58,   58,  368, 1371, 1502,  566, 1501,  121,  568,  221,
-
 /*  1850 */     4,  208,  268,  209,  390, 1244, 1549, 1188, 1372, 1370,
-
 /*  1860 */  1369, 1547,  239,  184,  571,  233,  421, 1241,   95,  218,
-
 /*  1870 */   173, 1507,  193,   43,   91,   94,  178,  186,  467,  188,
-
 /*  1880 */   468, 1422,   13,  189,  190,  191,  501,  451,  245,  108,
-
 /*  1890 */   238,  401, 1428, 1427, 1430,  475,  404, 1496,  197,  565,
-
 /*  1900 */    14,  490,  249,  101, 1518,  496,  349,  280,  251,  201,
-
 /*  1910 */   353,  499,  252,  406, 1270,  253,  517, 1327, 1326,  435,
-
 /*  1920 */  1325, 1318,  103,  893, 1296,  413,  227,  407, 1040, 1626,
-
 /*  1930 */   319,  567, 1625, 1297,  119,  119,  439,  367, 1317, 1295,
-
 /*  1940 */  1624,  526,  120,  440,  451,  577,  451, 1594,  309, 1028,
-
 /*  1950 */   310,  373,  266,  267,  457, 1580, 1579,  443,  138, 1394,
-
 /*  1960 */   552, 1393,   11, 1483,  384,  115,  317, 1350,  109,  536,
-
 /*  1970 */    42,  579,  382,  214, 1349,  388, 1198,  389,  275,  277,
-
 /*  1980 */   278, 1028, 1028, 1030, 1031,   35,  580, 1265,  414, 1260,
-
 /*  1990 */   170,  415,  183, 1534, 1535, 1533,  171,  154,  307, 1532,
-
 /*  2000 */   846,  223,  224,   88,  452,  215,  172,  321,  234, 1102,
-
 /*  2010 */   152, 1188, 1100,  329,  185,  174, 1223,  925,  187,  241,
-
 /*  2020 */   337,  244, 1116,  192,  175,  176,  424,  426,   97,  194,
-
 /*  2030 */    98,   99,  100,  177, 1119, 1115,  246,  247,  161,   24,
-
 /*  2040 */   248,  348, 1238,  264, 1108,  250,  495,  199,  198,   15,
-
 /*  2050 */   861,  500,  369,  254,  504,  509,  512,  200,  102,   25,
-
 /*  2060 */   179,  361,   26,  364,  104,  891,  308,  162,  105,  904,
-
 /*  2070 */   520,  106, 1185, 1069, 1155,   17,  228,   27, 1154,  283,
-
 /*  2080 */   285,  263,  978,  202,  972,  123,   28, 1175,   29,   30,
-
 /*  2090 */  1179, 1171,   31, 1173, 1160,   41,   32,  206,  548,   33,
-
 /*  2100 */   110, 1178, 1083,    8,  112, 1070,  113, 1068, 1072,   34,
-
 /*  2110 */  1073,  560, 1125,  269, 1124,  270,   36,   18, 1194, 1033,
-
 /*  2120 */   873,  151,  122,   37,  393,  271,  272,  572,  181, 1193,
-
 /*  2130 */  1256, 1256, 1256,  935, 1256, 1256, 1256, 1256, 1256, 1256,
-
 /*  2140 */  1256, 1617,
+
 /*     0 */   130,  127,  234,  282,  282, 1328,  576, 1307,  460,  289,
+
 /*    10 */   289,  576, 1622,  381,  576, 1328,  573,  576,  562,  413,
+
 /*    20 */  1300, 1542,  573,  481,  562,  524,  460,  459,  558,   82,
+
 /*    30 */    82,  983,  294,  375,   51,   51,  498,   61,   61,  984,
+
 /*    40 */    82,   82, 1577,  137,  138,   91,    7, 1228, 1228, 1063,
+
 /*    50 */  1066, 1053, 1053,  135,  135,  136,  136,  136,  136,  413,
+
 /*    60 */   288,  288,  182,  288,  288,  481,  536,  288,  288,  130,
+
 /*    70 */   127,  234,  432,  573,  525,  562,  573,  557,  562, 1290,
+
 /*    80 */   573,  421,  562,  137,  138,   91,  559, 1228, 1228, 1063,
+
 /*    90 */  1066, 1053, 1053,  135,  135,  136,  136,  136,  136,  296,
+
 /*   100 */   460,  398, 1249,  134,  134,  134,  134,  133,  133,  132,
+
 /*   110 */   132,  132,  131,  128,  451,   44, 1050, 1050, 1064, 1067,
+
 /*   120 */  1255,    1,    1,  582,    2, 1259,  581, 1174, 1259, 1174,
+
 /*   130 */   321,  413,  155,  321, 1584,  155,  379,  112,  498, 1341,
+
 /*   140 */   456,  299, 1341,  134,  134,  134,  134,  133,  133,  132,
+
 /*   150 */   132,  132,  131,  128,  451,  137,  138,   91, 1105, 1228,
+
 /*   160 */  1228, 1063, 1066, 1053, 1053,  135,  135,  136,  136,  136,
+
 /*   170 */   136, 1204,  320,  567,  288,  288,  283,  288,  288,  523,
+
 /*   180 */   523, 1250,  139, 1541,    7,  214,  503,  573, 1169,  562,
+
 /*   190 */   573, 1054,  562,  136,  136,  136,  136,  129,  401,  547,
+
 /*   200 */   487, 1169,  245, 1568, 1169,  245,  133,  133,  132,  132,
+
 /*   210 */   132,  131,  128,  451,  261,  134,  134,  134,  134,  133,
+
 /*   220 */   133,  132,  132,  132,  131,  128,  451,  451, 1204, 1205,
+
 /*   230 */  1204,  130,  127,  234,  455,  413,  182,  455,  130,  127,
+
 /*   240 */   234,  134,  134,  134,  134,  133,  133,  132,  132,  132,
+
 /*   250 */   131,  128,  451,  136,  136,  136,  136,  538,  576,  137,
+
 /*   260 */   138,   91,  261, 1228, 1228, 1063, 1066, 1053, 1053,  135,
+
 /*   270 */   135,  136,  136,  136,  136,   44,  472,  346, 1204,  472,
+
 /*   280 */   346,   51,   51,  418,   93,  157,  134,  134,  134,  134,
+
 /*   290 */   133,  133,  132,  132,  132,  131,  128,  451,  166,  363,
+
 /*   300 */   298,  134,  134,  134,  134,  133,  133,  132,  132,  132,
+
 /*   310 */   131,  128,  451, 1293,  461, 1570,  423,  377,  275,  134,
+
 /*   320 */   134,  134,  134,  133,  133,  132,  132,  132,  131,  128,
+
 /*   330 */   451,  418,  320,  567, 1292, 1204, 1205, 1204,  257,  413,
+
 /*   340 */   483,  511,  508,  507,   94,  132,  132,  132,  131,  128,
+
 /*   350 */   451,  506, 1204,  548,  548,  388,  576,  384,    7,  413,
+
 /*   360 */   550,  229,  522,  137,  138,   91,  530, 1228, 1228, 1063,
+
 /*   370 */  1066, 1053, 1053,  135,  135,  136,  136,  136,  136,   51,
+
 /*   380 */    51, 1582,  380,  137,  138,   91,  331, 1228, 1228, 1063,
+
 /*   390 */  1066, 1053, 1053,  135,  135,  136,  136,  136,  136,  320,
+
 /*   400 */   567,  288,  288,  320,  567, 1602,  582,    2, 1259, 1204,
+
 /*   410 */  1205, 1204, 1628,  321,  573,  155,  562,  576, 1511,  264,
+
 /*   420 */   231,  520, 1341,  134,  134,  134,  134,  133,  133,  132,
+
 /*   430 */   132,  132,  131,  128,  451,  519, 1511, 1513, 1333, 1333,
+
 /*   440 */    82,   82,  498,  134,  134,  134,  134,  133,  133,  132,
+
 /*   450 */   132,  132,  131,  128,  451, 1435,  257,  288,  288,  511,
+
 /*   460 */   508,  507,  944, 1568,  413, 1019, 1204,  943,  360,  506,
+
 /*   470 */   573, 1598,  562,   44,  575,  551,  551,  557, 1107, 1582,
+
 /*   480 */   544,  576, 1107,   40,  417,  245,  531, 1505,  137,  138,
+
 /*   490 */    91,  219, 1228, 1228, 1063, 1066, 1053, 1053,  135,  135,
+
 /*   500 */   136,  136,  136,  136,   81,   81, 1281, 1204,  413,  553,
+
 /*   510 */  1511,   48,  512,  448,  447,  493,  578,  455,  578,  344,
+
 /*   520 */    45, 1204, 1233, 1204, 1205, 1204,  428, 1235,  158,  882,
+
 /*   530 */   320,  567,  137,  138,   91, 1234, 1228, 1228, 1063, 1066,
+
 /*   540 */  1053, 1053,  135,  135,  136,  136,  136,  136,  134,  134,
+
 /*   550 */   134,  134,  133,  133,  132,  132,  132,  131,  128,  451,
+
 /*   560 */  1236,  576, 1236,  329, 1204, 1205, 1204,  387,  492,  403,
+
 /*   570 */  1040,  382,  489,  123,  568, 1569,    4,  377, 1204, 1205,
+
 /*   580 */  1204,  570,  570,  570,   82,   82,  882, 1029, 1331, 1331,
+
 /*   590 */   571, 1028,  134,  134,  134,  134,  133,  133,  132,  132,
+
 /*   600 */   132,  131,  128,  451,  288,  288, 1281, 1204,  576,  423,
+
 /*   610 */   576, 1568,  413,  423,  452,  378,  886,  573, 1279,  562,
+
 /*   620 */    46,  557,  532, 1028, 1028, 1030,  565,  130,  127,  234,
+
 /*   630 */   556,   82,   82,   82,   82,  479,  137,  138,   91,  462,
+
 /*   640 */  1228, 1228, 1063, 1066, 1053, 1053,  135,  135,  136,  136,
+
 /*   650 */   136,  136, 1188,  487, 1506, 1040,  413,    6, 1204,   50,
+
 /*   660 */   879,  121,  121,  948, 1204, 1205, 1204,  358,  557,  122,
+
 /*   670 */   316,  452,  577,  452,  535, 1204, 1028,  439,  303,  212,
+
 /*   680 */   137,  138,   91,  213, 1228, 1228, 1063, 1066, 1053, 1053,
+
 /*   690 */   135,  135,  136,  136,  136,  136,  134,  134,  134,  134,
+
 /*   700 */   133,  133,  132,  132,  132,  131,  128,  451, 1028, 1028,
+
 /*   710 */  1030, 1031,   35,  288,  288, 1204, 1205, 1204, 1040, 1339,
+
 /*   720 */   533,  123,  568, 1569,    4,  377,  573, 1019,  562,  353,
+
 /*   730 */  1277,  356, 1204, 1205, 1204, 1029,  488, 1188,  571, 1028,
+
 /*   740 */   134,  134,  134,  134,  133,  133,  132,  132,  132,  131,
+
 /*   750 */   128,  451,  576,  343,  288,  288,  449,  449,  449,  971,
+
 /*   760 */   413, 1627,  452,  911, 1187,  288,  288,  573,  464,  562,
+
 /*   770 */   238, 1028, 1028, 1030,  565,   82,   82,  498,  573,  411,
+
 /*   780 */   562,  344,  467,  332,  137,  138,   91,  197, 1228, 1228,
+
 /*   790 */  1063, 1066, 1053, 1053,  135,  135,  136,  136,  136,  136,
+
 /*   800 */  1188,  528, 1169, 1040,  413, 1110, 1110,  495, 1041,  121,
+
 /*   810 */   121, 1204,  317,  540,  862, 1169, 1244,  122, 1169,  452,
+
 /*   820 */   577,  452, 1340,  198, 1028, 1204,  481,  526,  137,  138,
+
 /*   830 */    91,  560, 1228, 1228, 1063, 1066, 1053, 1053,  135,  135,
+
 /*   840 */   136,  136,  136,  136,  134,  134,  134,  134,  133,  133,
+
 /*   850 */   132,  132,  132,  131,  128,  451, 1028, 1028, 1030, 1031,
+
 /*   860 */    35, 1204,  288,  288, 1204,  477,  288,  288, 1204, 1205,
+
 /*   870 */  1204,  539,  481,  437,  470,  573, 1451,  562,  364,  573,
+
 /*   880 */  1153,  562, 1204, 1205, 1204, 1188,    5,  576,  134,  134,
+
 /*   890 */   134,  134,  133,  133,  132,  132,  132,  131,  128,  451,
+
 /*   900 */   221,  214,  302,   96, 1149, 1657,  232, 1657,  413,  392,
+
 /*   910 */    19,   19, 1024,  949,  406,  373, 1595, 1085, 1204, 1205,
+
 /*   920 */  1204, 1204, 1205, 1204, 1204,  426, 1149, 1658,  413, 1658,
+
 /*   930 */  1659,  399,  137,  138,   91,    3, 1228, 1228, 1063, 1066,
+
 /*   940 */  1053, 1053,  135,  135,  136,  136,  136,  136,  304, 1311,
+
 /*   950 */   514, 1204,  137,  138,   91, 1498, 1228, 1228, 1063, 1066,
+
 /*   960 */  1053, 1053,  135,  135,  136,  136,  136,  136,  434,  131,
+
 /*   970 */   128,  451,  375, 1204,  274,  291,  372,  517,  367,  516,
+
 /*   980 */   262, 1204, 1205, 1204, 1147,  227,  363,  448,  447, 1435,
+
 /*   990 */  1568, 1310,  134,  134,  134,  134,  133,  133,  132,  132,
+
 /*  1000 */   132,  131,  128,  451, 1568,  576, 1147,  487, 1204, 1205,
+
 /*  1010 */  1204,  442,  134,  134,  134,  134,  133,  133,  132,  132,
+
 /*  1020 */   132,  131,  128,  451,  386,  576,  485,  576,   19,   19,
+
 /*  1030 */  1204, 1205, 1204, 1345, 1236,  970, 1236,  574,   47,  936,
+
 /*  1040 */   936,  473,  413,  431, 1552,  573, 1125,  562,   19,   19,
+
 /*  1050 */    19,   19,   49,  336,  850,  851,  852,  111, 1368,  315,
+
 /*  1060 */   429,  576,  413,  433,  341,  306,  137,  138,   91,  115,
+
 /*  1070 */  1228, 1228, 1063, 1066, 1053, 1053,  135,  135,  136,  136,
+
 /*  1080 */   136,  136,  576, 1309,   82,   82,  137,  138,   91,  529,
+
 /*  1090 */  1228, 1228, 1063, 1066, 1053, 1053,  135,  135,  136,  136,
+
 /*  1100 */   136,  136, 1569,  222,  377,   19,   19,  305, 1126, 1169,
+
 /*  1110 */   398, 1148,   22,   22,  498,  333, 1569,  335,  377,  576,
+
 /*  1120 */   438,  445, 1169, 1127,  486, 1169,  134,  134,  134,  134,
+
 /*  1130 */   133,  133,  132,  132,  132,  131,  128,  451, 1128,  576,
+
 /*  1140 */   902,  576,  145,  145,    6,  576,  134,  134,  134,  134,
+
 /*  1150 */   133,  133,  132,  132,  132,  131,  128,  451,  214, 1336,
+
 /*  1160 */   922,  576,   19,   19,   19,   19, 1282,  419,   19,   19,
+
 /*  1170 */   923,  412,  515,  141,  576, 1169,  413,  206,  465,  207,
+
 /*  1180 */   903,  215, 1575,  552,  147,  147,    7,  227, 1169,  411,
+
 /*  1190 */  1250, 1169,  120,  307,  117,  307,  413,   66,   66,  334,
+
 /*  1200 */   137,  138,   91,  119, 1228, 1228, 1063, 1066, 1053, 1053,
+
 /*  1210 */   135,  135,  136,  136,  136,  136,  413,  285,  209,  969,
+
 /*  1220 */   137,  138,   91,  471, 1228, 1228, 1063, 1066, 1053, 1053,
+
 /*  1230 */   135,  135,  136,  136,  136,  136,  435,   10, 1450,  267,
+
 /*  1240 */   137,  126,   91, 1435, 1228, 1228, 1063, 1066, 1053, 1053,
+
 /*  1250 */   135,  135,  136,  136,  136,  136, 1435, 1435,  410,  409,
+
 /*  1260 */   134,  134,  134,  134,  133,  133,  132,  132,  132,  131,
+
 /*  1270 */   128,  451,  576,  969,  576, 1224,  498,  373, 1595, 1554,
+
 /*  1280 */   134,  134,  134,  134,  133,  133,  132,  132,  132,  131,
+
 /*  1290 */   128,  451,  532,  457,  576,   82,   82,   82,   82,  111,
+
 /*  1300 */   134,  134,  134,  134,  133,  133,  132,  132,  132,  131,
+
 /*  1310 */   128,  451,  109,  233,  430, 1576,  546,   67,   67,    7,
+
 /*  1320 */   413,  351,  550, 1550,  260,  259,  258,  494,  443,  569,
+
 /*  1330 */   419,  983,  446, 1224,  450,  545, 1207,  576,  969,  984,
+
 /*  1340 */   413,  475, 1449, 1574, 1180,  138,   91,    7, 1228, 1228,
+
 /*  1350 */  1063, 1066, 1053, 1053,  135,  135,  136,  136,  136,  136,
+
 /*  1360 */    21,   21,  267,  576,  300, 1126,   91,  233, 1228, 1228,
+
 /*  1370 */  1063, 1066, 1053, 1053,  135,  135,  136,  136,  136,  136,
+
 /*  1380 */  1127,  373, 1595,  161, 1573,   16,   53,   53,    7,  108,
+
 /*  1390 */   533,   38,  969,  125, 1207, 1128, 1180,  576, 1224,  123,
+
 /*  1400 */   568,  893,    4,  324,  134,  134,  134,  134,  133,  133,
+
 /*  1410 */   132,  132,  132,  131,  128,  451,  571,  564,  534,  576,
+
 /*  1420 */    68,   68,  576,   39,  134,  134,  134,  134,  133,  133,
+
 /*  1430 */   132,  132,  132,  131,  128,  451,  576,  160, 1571, 1223,
+
 /*  1440 */   452,  576,   54,   54,  576,   69,   69,  576, 1366,  576,
+
 /*  1450 */   420,  184,  565,  463,  297,  576, 1224,  463,  297,   70,
+
 /*  1460 */    70,  576,   44,  474,   71,   71,  576,   72,   72,  576,
+
 /*  1470 */    73,   73,   55,   55,  411,  874,  242,  576,   56,   56,
+
 /*  1480 */   576, 1040,  576,  478,   57,   57,  576,  121,  121,   59,
+
 /*  1490 */    59,   23,   60,   60,  411,  122,  319,  452,  577,  452,
+
 /*  1500 */    74,   74, 1028,   75,   75,   76,   76,  411,  290,   20,
+
 /*  1510 */    20,  108,  287,  231,  553,  123,  568,  325,    4,  320,
+
 /*  1520 */   567,   97,  218,  944, 1144,  328,  400,  576,  943,  576,
+
 /*  1530 */  1380,  424,  571,  874, 1028, 1028, 1030, 1031,   35,  293,
+
 /*  1540 */   534,  576, 1104,  576, 1104,    9,  576,  342,  576,  111,
+
 /*  1550 */    77,   77,  143,  143,  576,  205,  452,  222, 1379,  889,
+
 /*  1560 */   576,  901,  900, 1188,  144,  144,   78,   78,  565,   62,
+
 /*  1570 */    62,   79,   79,  323, 1021,  576,  266,   63,   63,  908,
+
 /*  1580 */   909, 1589,  542,   80,   80,  576,  371,  541,  123,  568,
+
 /*  1590 */   480,    4,  266,  482,  244,  266,  370, 1040,   64,   64,
+
 /*  1600 */   576,  466,  576,  121,  121,  571, 1557,  576,  170,  170,
+
 /*  1610 */   576,  122,  576,  452,  577,  452,  576,  889, 1028,  576,
+
 /*  1620 */   165,  576,  111,  171,  171,   87,   87,  337, 1616,  452,
+
 /*  1630 */    65,   65, 1530,   83,   83,  146,  146,  986,  987,   84,
+
 /*  1640 */    84,  565,  168,  168,  148,  148, 1092,  347, 1032,  111,
+
 /*  1650 */  1028, 1028, 1030, 1031,   35,  542, 1103,  576, 1103,  576,
+
 /*  1660 */   543,  123,  568,  504,    4,  263,  576,  361, 1529,  111,
+
 /*  1670 */  1040, 1088,  576,  263,  576,  490,  121,  121,  571, 1188,
+
 /*  1680 */   142,  142,  169,  169,  122,  576,  452,  577,  452,  162,
+
 /*  1690 */   162, 1028,  576,  563,  576,  152,  152,  151,  151,  348,
+
 /*  1700 */  1376,  974,  452,  266, 1092,  942, 1032,  125,  149,  149,
+
 /*  1710 */   939,  576,  125,  576,  565,  150,  150,   86,   86,  872,
+
 /*  1720 */   352,  159,  576, 1028, 1028, 1030, 1031,   35,  542,  941,
+
 /*  1730 */   576,  125,  355,  541,   88,   88,   85,   85,  357,  359,
+
 /*  1740 */  1324, 1308,  366, 1040,  376,   52,   52,  499, 1389,  121,
+
 /*  1750 */   121, 1434, 1188,   58,   58, 1362, 1374,  122, 1439,  452,
+
 /*  1760 */   577,  452, 1289,  167, 1028, 1280,  280, 1268, 1267, 1269,
+
 /*  1770 */  1609, 1359,  312,  313,   12,  314,  397, 1421,  224, 1416,
+
 /*  1780 */   295,  237, 1409,  339,  340, 1426,  301,  345,  484,  228,
+
 /*  1790 */  1371, 1307, 1372, 1370, 1425,  404, 1028, 1028, 1030, 1031,
+
 /*  1800 */    35, 1601, 1192,  454,  509,  369,  292, 1502,  210, 1501,
+
 /*  1810 */  1369,  396,  396,  395,  277,  393,  211,  566,  859, 1612,
+
 /*  1820 */  1244,  123,  568,  391,    4, 1188,  223,  270, 1549, 1547,
+
 /*  1830 */  1241,  239,  186,  327,  422,   96,  195,  220,  571,  235,
+
 /*  1840 */   180,  326,  188,  468,  190, 1507,  191,  192,   92,  193,
+
 /*  1850 */   469,   95, 1422,   13,  502,  247, 1430,  109,  199,  402,
+
 /*  1860 */   476,  405,  452, 1496, 1428, 1427,   14,  491,  251,  102,
+
 /*  1870 */   497, 1518,  241,  281,  565,  253,  203,  354,  500,  254,
+
 /*  1880 */   175, 1270,  407,   43,  350,  518, 1327,  436,  255, 1326,
+
 /*  1890 */  1325, 1318,  104,  893, 1626,  229,  408,  440, 1625,  441,
+
 /*  1900 */   240,  310, 1296, 1040,  311, 1317,  527, 1594, 1297,  121,
+
 /*  1910 */   121,  368, 1295, 1624,  268,  269, 1580,  122, 1579,  452,
+
 /*  1920 */   577,  452,  374,  444, 1028, 1394, 1393,  140,  553,   90,
+
 /*  1930 */   568,   11,    4, 1483,  383,  414,  385,  110,  116,  216,
+
 /*  1940 */   320,  567, 1350,  555,   42,  318,  571,  537, 1349,  389,
+
 /*  1950 */   390,  579, 1198,  276,  279,  278, 1028, 1028, 1030, 1031,
+
 /*  1960 */    35,  580,  415, 1265,  458, 1260,  416,  185, 1534,  172,
+
 /*  1970 */   452, 1535,  173,  156,  308,  846, 1533, 1532,  453,  217,
+
 /*  1980 */   225,   89,  565,  174,  322, 1188,  226,  236, 1102,  154,
+
 /*  1990 */  1100,  330,  176,  187, 1223,  189,  925,  338,  243, 1116,
+
 /*  2000 */   246,  194,  177,  178,  425,  427,   98,   99,  196,  100,
+
 /*  2010 */   101, 1040,  179, 1119,  248, 1115,  249,  121,  121,   24,
+
 /*  2020 */   163,  250,  349, 1108,  266,  122, 1238,  452,  577,  452,
+
 /*  2030 */  1192,  454, 1028,  200,  292,  496,  252,  201,  861,  396,
+
 /*  2040 */   396,  395,  277,  393,   15,  501,  859,  370,  292,  256,
+
 /*  2050 */   202,  554,  505,  396,  396,  395,  277,  393,  103,  239,
+
 /*  2060 */   859,  327,   25,   26, 1028, 1028, 1030, 1031,   35,  326,
+
 /*  2070 */   362,  510,  891,  239,  365,  327,  513,  904,  105,  309,
+
 /*  2080 */   164,  181,   27,  326,  106,  521,  107, 1185, 1069, 1155,
+
 /*  2090 */    17, 1154,  284, 1188,  286,  978,  265,  204,  125, 1171,
+
 /*  2100 */   241,  230,  972, 1175,   28, 1160,   29, 1179,  175, 1173,
+
 /*  2110 */    30,   43,   31, 1178,  241,   32,   41,  549,    8,   33,
+
 /*  2120 */   208,  111,  175, 1083, 1070,   43,  113, 1068,  240,  114,
+
 /*  2130 */  1072,   34, 1073,  561, 1124,  118,  271,   36,   18, 1194,
+
 /*  2140 */  1033,  873,  240,  935,  124,   37,  272,  273, 1617,  572,
+
 /*  2150 */   183,  153,  394, 1193, 1256, 1256, 1256, 1256, 1256, 1256,
+
 /*  2160 */  1256, 1256, 1256,  414, 1256, 1256, 1256, 1256,  320,  567,
+
 /*  2170 */  1256, 1256, 1256, 1256, 1256, 1256, 1256,  414, 1256, 1256,
+
 /*  2180 */  1256, 1256,  320,  567, 1256, 1256, 1256, 1256, 1256, 1256,
+
 /*  2190 */  1256, 1256,  458, 1256, 1256, 1256, 1256, 1256, 1256, 1256,
+
 /*  2200 */  1256, 1256, 1256, 1256, 1256, 1256,  458,
};
static const YYCODETYPE yy_lookahead[] = {
-
 /*     0 */   194,  276,  277,  278,  216,  194,  194,  217,  194,  194,
-
 /*    10 */   194,  194,  224,  194,  194,  276,  277,  278,  204,   19,
-
 /*    20 */   206,  202,  297,  217,  218,  205,  207,  217,  205,  217,
-
 /*    30 */   218,   31,  217,  218,  217,  218,   29,  217,  218,   39,
-
 /*    40 */    33,  217,  220,   43,   44,   45,   46,   47,   48,   49,
-
 /*    50 */    50,   51,   52,   53,   54,   55,   56,   57,  312,   19,
-
 /*    60 */   240,  241,  316,  240,  241,  194,   46,   47,   48,   49,
-
 /*    70 */    22,  254,   65,  253,  254,  255,  253,  194,  255,  194,
-
 /*    80 */   263,  258,  259,   43,   44,   45,   46,   47,   48,   49,
-
 /*    90 */    50,   51,   52,   53,   54,   55,   56,   57,  276,  277,
-
 /*   100 */   278,  285,  102,  103,  104,  105,  106,  107,  108,  109,
-
 /*   110 */   110,  111,  112,  113,   59,  186,  187,  188,  189,  190,
-
 /*   120 */   191,  310,  239,  317,  318,  196,   86,  198,   88,  317,
-
 /*   130 */    19,  319,  317,  318,  205,  264,   25,  211,  212,  213,
-
 /*   140 */   205,  121,  102,  103,  104,  105,  106,  107,  108,  109,
-
 /*   150 */   110,  111,  112,  113,   43,   44,   45,   46,   47,   48,
-
 /*   160 */    49,   50,   51,   52,   53,   54,   55,   56,   57,  240,
-
 /*   170 */   241,  116,  117,  118,  119,  240,  241,  122,  123,  124,
-
 /*   180 */    69,  298,  253,  194,  255,  106,  107,  132,  253,  141,
-
 /*   190 */   255,   54,   55,   56,   57,   58,  207,  268,  102,  103,
-
 /*   200 */   104,  105,  106,  107,  108,  109,  110,  111,  112,  113,
-
 /*   210 */   214,  128,  129,  102,  103,  104,  105,  106,  107,  108,
-
 /*   220 */   109,  110,  111,  112,  113,  134,   25,  136,  137,  300,
-
 /*   230 */   165,  166,  153,   19,  155,   54,   55,   56,   57,  102,
-
 /*   240 */   103,  104,  105,  106,  107,  108,  109,  110,  111,  112,
-
 /*   250 */   113,  108,  109,  110,  111,  112,  113,   43,   44,   45,
-
 /*   260 */    46,   47,   48,   49,   50,   51,   52,   53,   54,   55,
-
 /*   270 */    56,   57,  276,  277,  278,  113,  194,   19,   22,   23,
-
 /*   280 */   194,   67,   24,  102,  103,  104,  105,  106,  107,  108,
-
 /*   290 */   109,  110,  111,  112,  113,  220,  250,   59,  252,  217,
-
 /*   300 */   218,   43,   44,   45,   46,   47,   48,   49,   50,   51,
-
 /*   310 */    52,   53,   54,   55,   56,   57,  102,  103,  104,  105,
-
 /*   320 */   106,  107,  108,  109,  110,  111,  112,  113,  106,  107,
-
 /*   330 */   108,  109,  110,  111,  112,  113,  254,   59,  205,  138,
-
 /*   340 */   139,   19,   20,  194,   22,  263,   22,   23,  231,   25,
-
 /*   350 */    72,  276,  277,  278,  116,  117,  118,  101,   36,   76,
-
 /*   360 */   102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
-
 /*   370 */   112,  113,   89,  240,  241,   92,   73,  194,  194,   73,
-
 /*   380 */    19,   59,  188,  189,  190,  191,  253,   81,  255,  151,
-
 /*   390 */   196,   25,  198,   71,  116,  117,  118,  311,  312,  205,
-
 /*   400 */   217,  218,  316,   81,   43,   44,   45,   46,   47,   48,
-
 /*   410 */    49,   50,   51,   52,   53,   54,   55,   56,   57,  270,
-
 /*   420 */    22,   23,  100,   25,   59,  101,  138,  139,  106,  107,
-
 /*   430 */   127,  128,  129,  127,  240,  241,  114,  254,  116,  117,
-
 /*   440 */   118,   76,   76,  121,  138,  139,  263,  253,  264,  255,
-
 /*   450 */   205,  275,   87,   19,   89,   89,  194,   92,   92,  199,
-
 /*   460 */   138,  139,  268,  102,  103,  104,  105,  106,  107,  108,
-
 /*   470 */   109,  110,  111,  112,  113,  153,  154,  155,  156,  157,
-
 /*   480 */    81,  116,  117,  118,  129,  240,  241,  224,   19,  226,
-
 /*   490 */   314,  315,   23,   25,  300,   59,   22,  234,  253,  101,
-
 /*   500 */   255,  236,  237,   26,  194,  183,  194,  152,   72,   22,
-
 /*   510 */   145,  150,   43,   44,   45,   46,   47,   48,   49,   50,
-
 /*   520 */    51,   52,   53,   54,   55,   56,   57,  217,  218,  217,
-
 /*   530 */   218,   19,  189,   59,  191,   23,   59,  138,  139,  196,
-
 /*   540 */   135,  198,  232,  283,  232,  140,   59,  287,  205,  275,
-
 /*   550 */   116,  205,  116,  117,  118,   43,   44,   45,   46,   47,
-
 /*   560 */    48,   49,   50,   51,   52,   53,   54,   55,   56,   57,
-
 /*   570 */   194,  102,  103,  104,  105,  106,  107,  108,  109,  110,
-
 /*   580 */   111,  112,  113,  240,  241,  194,  240,  241,  314,  315,
-
 /*   590 */   116,  117,  118,  116,  117,  118,  253,  194,  255,  253,
-
 /*   600 */    59,  255,   19,  116,  117,  118,   23,   22,  217,  218,
-
 /*   610 */   142,  268,  205,  275,  102,  103,  104,  105,  106,  107,
-
 /*   620 */   108,  109,  110,  111,  112,  113,   43,   44,   45,   46,
-
 /*   630 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
-
 /*   640 */    57,   19,  194,  300,   59,   23,  119,  240,  241,  122,
-
 /*   650 */   123,  124,  314,  315,  194,  236,  237,  194,  117,  132,
-
 /*   660 */   253,   81,  255,  205,   59,   43,   44,   45,   46,   47,
-
 /*   670 */    48,   49,   50,   51,   52,   53,   54,   55,   56,   57,
-
 /*   680 */   217,  218,  194,  194,  194,  102,  103,  104,  105,  106,
-
 /*   690 */   107,  108,  109,  110,  111,  112,  113,  294,  240,  241,
-
 /*   700 */   120,  116,  117,  118,   59,  194,  217,  218,  211,  212,
-
 /*   710 */   213,  253,   19,  255,  194,   19,   23,  254,  138,  139,
-
 /*   720 */    24,  232,  117,  194,  102,  103,  104,  105,  106,  107,
-
 /*   730 */   108,  109,  110,  111,  112,  113,   43,   44,   45,   46,
-
 /*   740 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
-
 /*   750 */    57,   19,  264,  108,   76,   23,  127,  128,  129,  311,
-
 /*   760 */   312,  116,  117,  118,  316,   87,  306,   89,  308,  194,
-
 /*   770 */    92,   22,   59,  194,   22,   43,   44,   45,   46,   47,
-
 /*   780 */    48,   49,   50,   51,   52,   53,   54,   55,   56,   57,
-
 /*   790 */   194,   95,  217,  218,  265,  102,  103,  104,  105,  106,
-
 /*   800 */   107,  108,  109,  110,  111,  112,  113,  232,   59,  113,
-
 /*   810 */    25,   59,  194,  217,  218,  119,  120,  121,  122,  123,
-
 /*   820 */   124,  125,   19,  145,  194,  194,   23,  131,  232,  116,
-
 /*   830 */   117,  118,   35,  194,  102,  103,  104,  105,  106,  107,
-
 /*   840 */   108,  109,  110,  111,  112,  113,   43,   44,   45,   46,
-
 /*   850 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
-
 /*   860 */    57,   19,  194,   66,  194,  116,  117,  118,  116,  117,
-
 /*   870 */   118,   74,  242,  294,  194,  194,  206,   23,  194,   25,
-
 /*   880 */   194,  111,  112,  113,   25,   43,   44,   45,   46,   47,
-
 /*   890 */    48,   49,   50,   51,   52,   53,   54,   55,   56,   57,
-
 /*   900 */    24,  194,  194,  217,  218,  102,  103,  104,  105,  106,
-
 /*   910 */   107,  108,  109,  110,  111,  112,  113,  241,  232,  194,
-
 /*   920 */   212,  213,  242,  242,  217,  218,  242,  130,   11,  253,
-
 /*   930 */   194,  255,   19,  265,  149,   59,  306,  194,  308,  232,
-
 /*   940 */   309,  310,  217,  218,  102,  103,  104,  105,  106,  107,
-
 /*   950 */   108,  109,  110,  111,  112,  113,   43,   44,   45,   46,
-
 /*   960 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
-
 /*   970 */    57,  194,  194,   59,  194,  239,   19,  194,   25,  254,
-
 /*   980 */   303,  304,   23,  194,   25,  126,  306,  306,  308,  308,
-
 /*   990 */   306,  271,  308,  117,  286,  217,  218,  217,  218,  194,
-
 /*  1000 */   194,  159,   45,   46,   47,   48,   49,   50,   51,   52,
-
 /*  1010 */    53,   54,   55,   56,   57,  102,  103,  104,  105,  106,
-
 /*  1020 */   107,  108,  109,  110,  111,  112,  113,   59,  239,  194,
-
 /*  1030 */   116,  117,  118,  260,  254,  194,  240,  241,  194,  233,
-
 /*  1040 */   205,  240,  241,  205,  239,  128,  129,  270,  265,  253,
-
 /*  1050 */   194,  255,  217,  218,  253,  194,  255,  143,  280,  102,
-
 /*  1060 */   103,  104,  105,  106,  107,  108,  109,  110,  111,  112,
-
 /*  1070 */   113,  118,  159,  217,  218,  240,  241,  118,  240,  241,
-
 /*  1080 */   194,  194,  194,  239,  116,  117,  118,   22,  253,  254,
-
 /*  1090 */   255,  253,   19,  255,  233,  194,  143,   24,  263,  212,
-
 /*  1100 */   213,  194,  143,  217,  218,  217,  218,  261,  262,  271,
-
 /*  1110 */   254,  143,   19,    7,    8,    9,   43,   44,   45,   46,
-
 /*  1120 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
-
 /*  1130 */    57,   16,   19,   22,   23,  294,   43,   44,   45,   46,
-
 /*  1140 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
-
 /*  1150 */    57,  312,  194,  214,   21,  316,   43,   44,   45,   46,
-
 /*  1160 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
-
 /*  1170 */    57,  106,  107,  286,  194,  102,  103,  104,  105,  106,
-
 /*  1180 */   107,  108,  109,  110,  111,  112,  113,  207,  158,   59,
-
 /*  1190 */   160,   22,   77,   24,   79,  102,  103,  104,  105,  106,
-
 /*  1200 */   107,  108,  109,  110,  111,  112,  113,  194,  194,  229,
-
 /*  1210 */   194,  231,  101,   80,   22,  102,  103,  104,  105,  106,
-
 /*  1220 */   107,  108,  109,  110,  111,  112,  113,  288,   59,   12,
-
 /*  1230 */   217,  218,  293,  217,  218,   19,  106,  107,   59,   19,
-
 /*  1240 */    16,  127,  128,  129,   27,  115,  116,  117,  118,  194,
-
 /*  1250 */   120,   59,   22,  194,   24,  194,  123,  100,  128,   42,
-
 /*  1260 */    44,   45,   46,   47,   48,   49,   50,   51,   52,   53,
-
 /*  1270 */    54,   55,   56,   57,  117,  194,  217,  218,  121,  100,
-
 /*  1280 */    63,  194,  245,  153,  194,  155,  117,   19,  115,  194,
-
 /*  1290 */    73,  214,  194,  256,  161,  116,  117,  194,  217,  218,
-
 /*  1300 */   121,   77,  194,   79,  217,  218,  194,  217,  218,  117,
-
 /*  1310 */   153,  154,  155,  254,   46,  217,  218,  144,  102,  103,
-
 /*  1320 */   104,  105,  106,  107,  108,  109,  110,  111,  112,  113,
-
 /*  1330 */   232,  270,  153,  154,  155,  115,  116,   66,   19,   20,
-
 /*  1340 */   183,   22,   12,  312,  254,  194,  262,  316,  209,  210,
-
 /*  1350 */   266,  239,  194,  194,  108,   36,   85,   27,   19,   20,
-
 /*  1360 */   265,   22,  183,  245,  144,   94,   25,   48,  217,  218,
-
 /*  1370 */   293,  194,   42,  270,  256,   36,  217,  218,   59,  194,
-
 /*  1380 */    25,  135,  194,  115,  194,  161,  140,  194,  194,   15,
-
 /*  1390 */    71,  194,  312,   63,  217,  218,  316,  194,   59,  131,
-
 /*  1400 */   301,  302,  217,  218,   85,  217,  218,  217,  218,   90,
-
 /*  1410 */    71,  217,  218,   19,  217,  218,  245,  146,  262,  100,
-
 /*  1420 */   217,  218,  266,  265,   85,  106,  107,  256,  312,   90,
-
 /*  1430 */   209,  210,  316,  114,   60,  116,  117,  118,  194,  100,
-
 /*  1440 */   121,  194,  194,  145,  115,  106,  107,   19,   46,   19,
-
 /*  1450 */    20,   24,   22,  114,  194,  116,  117,  118,  194,  245,
-
 /*  1460 */   121,  194,  164,  194,  217,  218,   36,  194,  258,  259,
-
 /*  1470 */   256,  194,  153,  154,  155,  156,  157,  217,  218,  150,
-
 /*  1480 */    31,  217,  218,  142,  217,  218,  217,  218,   39,   59,
-
 /*  1490 */   217,  218,  153,  154,  155,  156,  157,  149,  150,    5,
-
 /*  1500 */   145,   71,  183,  245,   10,   11,   12,   13,   14,  194,
-
 /*  1510 */   116,   17,  129,  227,  256,   85,  194,  115,  194,   23,
-
 /*  1520 */    90,   25,  183,   99,   30,   97,   32,   22,   22,  194,
-
 /*  1530 */   100,  194,  217,  218,   40,  152,  106,  107,   23,  217,
-
 /*  1540 */   218,  194,   19,   20,  114,   22,  116,  117,  118,  257,
-
 /*  1550 */   194,  121,  217,  218,  217,  218,  194,  133,   53,   36,
-
 /*  1560 */    23,   23,   25,   25,   70,  120,  121,   61,  141,    7,
-
 /*  1570 */     8,  121,   78,  217,  218,   81,   23,  227,   25,  217,
-
 /*  1580 */   218,  131,   59,  153,  154,  155,  156,  157,    0,    1,
-
 /*  1590 */     2,   59,   98,    5,   71,   23,  227,   25,   10,   11,
-
 /*  1600 */    12,   13,   14,   83,   84,   17,   23,   23,   25,   25,
-
 /*  1610 */    59,  194,  194,  183,   23,   23,   25,   25,   30,  194,
-
 /*  1620 */    32,   19,   20,  100,   22,  194,  194,  133,   40,  106,
-
 /*  1630 */   107,  108,  138,  139,  194,  217,  218,  114,   36,  116,
-
 /*  1640 */   117,  118,  217,  218,  121,  194,  194,  194,   23,  117,
-
 /*  1650 */    25,  194,   23,   23,   25,   25,  162,  194,   70,  194,
-
 /*  1660 */   145,   59,   23,  153,   25,  155,   78,  194,  117,   81,
-
 /*  1670 */   217,  218,  194,   71,  217,  218,  153,  154,  155,  156,
-
 /*  1680 */   157,  194,  217,  218,  194,   23,   98,   25,  321,  194,
-
 /*  1690 */   217,  218,  194,   19,   20,  194,   22,  153,   23,  155,
-
 /*  1700 */    25,  194,  100,  194,  217,  218,  183,  194,  106,  107,
-
 /*  1710 */    36,  194,  217,  218,  237,  194,  114,  243,  116,  117,
-
 /*  1720 */   118,  133,  194,  121,  217,  218,  138,  139,  194,  194,
-
 /*  1730 */   194,  290,  289,   59,  217,  218,  194,  194,  217,  218,
-
 /*  1740 */   194,  194,  140,  194,  194,   71,  194,  244,  194,  194,
-
 /*  1750 */   162,  217,  218,  194,  194,  153,  154,  155,  156,  157,
-
 /*  1760 */   217,  218,  194,  217,  218,  194,  217,  218,  257,  217,
-
 /*  1770 */   218,  217,  218,  257,  100,  194,  257,  217,  218,  257,
-
 /*  1780 */   106,  107,  215,  299,  194,  183,  192,  194,  114,  194,
-
 /*  1790 */   116,  117,  118,    1,    2,  121,  221,    5,  217,  218,
-
 /*  1800 */   273,  197,   10,   11,   12,   13,   14,  217,  218,   17,
-
 /*  1810 */   217,  218,  217,  218,  140,  194,  246,  194,  273,  295,
-
 /*  1820 */   247,  273,   30,  247,   32,  269,  269,  153,  154,  155,
-
 /*  1830 */   156,  157,   40,  246,  273,  295,  230,  226,  217,  218,
-
 /*  1840 */   217,  218,  220,  261,  220,  282,  220,   19,   20,  244,
-
 /*  1850 */    22,  250,  141,  250,  246,   60,  201,  183,  261,  261,
-
 /*  1860 */   261,  201,   70,  299,   36,  299,  201,   38,  151,  150,
-
 /*  1870 */    78,  285,   22,   81,  296,  296,   43,  235,   18,  238,
-
 /*  1880 */   201,  274,  272,  238,  238,  238,   18,   59,  200,  149,
-
 /*  1890 */    98,  247,  274,  274,  235,  247,  247,  247,  235,   71,
-
 /*  1900 */   272,  201,  200,  158,  292,   62,  291,  201,  200,   22,
-
 /*  1910 */   201,  222,  200,  222,  201,  200,  115,  219,  219,   64,
-
 /*  1920 */   219,  228,   22,  126,  221,  133,  165,  222,  100,  225,
-
 /*  1930 */   138,  139,  225,  219,  106,  107,   24,  219,  228,  219,
-
 /*  1940 */   219,  307,  114,  113,  116,  117,  118,  315,  284,  121,
-
 /*  1950 */   284,  222,  201,   91,  162,  320,  320,   82,  148,  267,
-
 /*  1960 */   145,  267,   22,  279,  201,  158,  281,  251,  147,  146,
-
 /*  1970 */    25,  203,  250,  249,  251,  248,   13,  247,  195,  195,
-
 /*  1980 */     6,  153,  154,  155,  156,  157,  193,  193,  305,  193,
-
 /*  1990 */   208,  305,  302,  214,  214,  214,  208,  223,  223,  214,
-
 /*  2000 */     4,  215,  215,  214,    3,   22,  208,  163,   15,   23,
-
 /*  2010 */    16,  183,   23,  139,  151,  130,   25,   20,  142,   24,
-
 /*  2020 */    16,  144,    1,  142,  130,  130,   61,   37,   53,  151,
-
 /*  2030 */    53,   53,   53,  130,  116,    1,   34,  141,    5,   22,
-
 /*  2040 */   115,  161,   75,   25,   68,  141,   41,  115,   68,   24,
-
 /*  2050 */    20,   19,  131,  125,   67,   67,   96,   22,   22,   22,
-
 /*  2060 */    37,   23,   22,   24,   22,   59,   67,   23,  149,   28,
-
 /*  2070 */    22,   25,   23,   23,   23,   22,  141,   34,   97,   23,
-
 /*  2080 */    23,   34,  116,   22,  143,   25,   34,   75,   34,   34,
-
 /*  2090 */    75,   88,   34,   86,   23,   22,   34,   25,   24,   34,
-
 /*  2100 */    25,   93,   23,   44,  142,   23,  142,   23,   23,   22,
-
 /*  2110 */    11,   25,   23,   25,   23,   22,   22,   22,    1,   23,
-
 /*  2120 */    23,   23,   22,   22,   15,  141,  141,   25,   25,    1,
-
 /*  2130 */   322,  322,  322,  135,  322,  322,  322,  322,  322,  322,
-
 /*  2140 */   322,  141,  322,  322,  322,  322,  322,  322,  322,  322,
-
 /*  2150 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
-
 /*  2160 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
-
 /*  2170 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
-
 /*  2180 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
-
 /*  2190 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
-
 /*  2200 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
+
 /*     0 */   276,  277,  278,  240,  241,  224,  194,  226,  194,  240,
+
 /*    10 */   241,  194,  216,  220,  194,  234,  253,  194,  255,   19,
+
 /*    20 */   224,  297,  253,  194,  255,  205,  212,  213,  205,  217,
+
 /*    30 */   218,   31,  205,  194,  217,  218,  194,  217,  218,   39,
+
 /*    40 */   217,  218,  312,   43,   44,   45,  316,   47,   48,   49,
+
 /*    50 */    50,   51,   52,   53,   54,   55,   56,   57,   58,   19,
+
 /*    60 */   240,  241,  194,  240,  241,  194,  254,  240,  241,  276,
+
 /*    70 */   277,  278,  233,  253,  254,  255,  253,  254,  255,  217,
+
 /*    80 */   253,  239,  255,   43,   44,   45,  263,   47,   48,   49,
+
 /*    90 */    50,   51,   52,   53,   54,   55,   56,   57,   58,  270,
+
 /*   100 */   286,   22,   23,  103,  104,  105,  106,  107,  108,  109,
+
 /*   110 */   110,  111,  112,  113,  114,   82,   47,   48,   49,   50,
+
 /*   120 */   186,  187,  188,  189,  190,  191,  189,   87,  191,   89,
+
 /*   130 */   196,   19,  198,  196,  317,  198,  319,   25,  194,  205,
+
 /*   140 */   298,  270,  205,  103,  104,  105,  106,  107,  108,  109,
+
 /*   150 */   110,  111,  112,  113,  114,   43,   44,   45,   11,   47,
+
 /*   160 */    48,   49,   50,   51,   52,   53,   54,   55,   56,   57,
+
 /*   170 */    58,   60,  139,  140,  240,  241,  214,  240,  241,  311,
+
 /*   180 */   312,  102,   70,  239,  316,  194,   19,  253,   77,  255,
+
 /*   190 */   253,  122,  255,   55,   56,   57,   58,   59,  207,   88,
+
 /*   200 */   194,   90,  268,  194,   93,  268,  107,  108,  109,  110,
+
 /*   210 */   111,  112,  113,  114,   47,  103,  104,  105,  106,  107,
+
 /*   220 */   108,  109,  110,  111,  112,  113,  114,  114,  117,  118,
+
 /*   230 */   119,  276,  277,  278,  300,   19,  194,  300,  276,  277,
+
 /*   240 */   278,  103,  104,  105,  106,  107,  108,  109,  110,  111,
+
 /*   250 */   112,  113,  114,   55,   56,   57,   58,  146,  194,   43,
+
 /*   260 */    44,   45,   47,   47,   48,   49,   50,   51,   52,   53,
+
 /*   270 */    54,   55,   56,   57,   58,   82,  129,  130,   60,  129,
+
 /*   280 */   130,  217,  218,  116,   68,   25,  103,  104,  105,  106,
+
 /*   290 */   107,  108,  109,  110,  111,  112,  113,  114,   23,  132,
+
 /*   300 */   294,  103,  104,  105,  106,  107,  108,  109,  110,  111,
+
 /*   310 */   112,  113,  114,  217,  121,  306,  194,  308,   26,  103,
+
 /*   320 */   104,  105,  106,  107,  108,  109,  110,  111,  112,  113,
+
 /*   330 */   114,  116,  139,  140,  217,  117,  118,  119,  120,   19,
+
 /*   340 */   194,  123,  124,  125,   24,  109,  110,  111,  112,  113,
+
 /*   350 */   114,  133,   60,  311,  312,  250,  194,  252,  316,   19,
+
 /*   360 */   194,  166,  167,   43,   44,   45,  205,   47,   48,   49,
+
 /*   370 */    50,   51,   52,   53,   54,   55,   56,   57,   58,  217,
+
 /*   380 */   218,  317,  318,   43,   44,   45,  264,   47,   48,   49,
+
 /*   390 */    50,   51,   52,   53,   54,   55,   56,   57,   58,  139,
+
 /*   400 */   140,  240,  241,  139,  140,  188,  189,  190,  191,  117,
+
 /*   410 */   118,  119,  231,  196,  253,  198,  255,  194,  194,  258,
+
 /*   420 */   259,  146,  205,  103,  104,  105,  106,  107,  108,  109,
+
 /*   430 */   110,  111,  112,  113,  114,  109,  212,  213,  236,  237,
+
 /*   440 */   217,  218,  194,  103,  104,  105,  106,  107,  108,  109,
+
 /*   450 */   110,  111,  112,  113,  114,  194,  120,  240,  241,  123,
+
 /*   460 */   124,  125,  136,  194,   19,   74,   60,  141,   23,  133,
+
 /*   470 */   253,  194,  255,   82,  194,  309,  310,  254,   29,  317,
+
 /*   480 */   318,  194,   33,   22,  199,  268,  263,  239,   43,   44,
+
 /*   490 */    45,  151,   47,   48,   49,   50,   51,   52,   53,   54,
+
 /*   500 */    55,   56,   57,   58,  217,  218,  194,   60,   19,  146,
+
 /*   510 */   286,  242,   23,  107,  108,   66,  204,  300,  206,  128,
+
 /*   520 */    73,   60,  116,  117,  118,  119,  265,  121,  165,   60,
+
 /*   530 */   139,  140,   43,   44,   45,  129,   47,   48,   49,   50,
+
 /*   540 */    51,   52,   53,   54,   55,   56,   57,   58,  103,  104,
+
 /*   550 */   105,  106,  107,  108,  109,  110,  111,  112,  113,  114,
+
 /*   560 */   154,  194,  156,  194,  117,  118,  119,  280,  283,  205,
+
 /*   570 */   101,  220,  287,   19,   20,  306,   22,  308,  117,  118,
+
 /*   580 */   119,  211,  212,  213,  217,  218,  117,  118,  236,  237,
+
 /*   590 */    36,  122,  103,  104,  105,  106,  107,  108,  109,  110,
+
 /*   600 */   111,  112,  113,  114,  240,  241,  194,   60,  194,  194,
+
 /*   610 */   194,  194,   19,  194,   60,  194,   23,  253,  206,  255,
+
 /*   620 */    73,  254,   19,  154,  155,  156,   72,  276,  277,  278,
+
 /*   630 */   263,  217,  218,  217,  218,  271,   43,   44,   45,  271,
+
 /*   640 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
+
 /*   650 */    57,   58,  183,  194,  285,  101,   19,  214,   60,  242,
+
 /*   660 */    23,  107,  108,  109,  117,  118,  119,   16,  254,  115,
+
 /*   670 */   254,  117,  118,  119,  194,   60,  122,  263,  205,  264,
+
 /*   680 */    43,   44,   45,  264,   47,   48,   49,   50,   51,   52,
+
 /*   690 */    53,   54,   55,   56,   57,   58,  103,  104,  105,  106,
+
 /*   700 */   107,  108,  109,  110,  111,  112,  113,  114,  154,  155,
+
 /*   710 */   156,  157,  158,  240,  241,  117,  118,  119,  101,  205,
+
 /*   720 */   117,   19,   20,  306,   22,  308,  253,   74,  255,   78,
+
 /*   730 */   205,   80,  117,  118,  119,  118,  293,  183,   36,  122,
+
 /*   740 */   103,  104,  105,  106,  107,  108,  109,  110,  111,  112,
+
 /*   750 */   113,  114,  194,  294,  240,  241,  211,  212,  213,  144,
+
 /*   760 */    19,   23,   60,   25,   23,  240,  241,  253,  245,  255,
+
 /*   770 */    15,  154,  155,  156,   72,  217,  218,  194,  253,  256,
+
 /*   780 */   255,  128,  129,  130,   43,   44,   45,   22,   47,   48,
+
 /*   790 */    49,   50,   51,   52,   53,   54,   55,   56,   57,   58,
+
 /*   800 */   183,   19,   77,  101,   19,  128,  129,  130,   23,  107,
+
 /*   810 */   108,   60,  254,   88,   21,   90,   61,  115,   93,  117,
+
 /*   820 */   118,  119,  239,   22,  122,   60,  194,  205,   43,   44,
+
 /*   830 */    45,  205,   47,   48,   49,   50,   51,   52,   53,   54,
+
 /*   840 */    55,   56,   57,   58,  103,  104,  105,  106,  107,  108,
+
 /*   850 */   109,  110,  111,  112,  113,  114,  154,  155,  156,  157,
+
 /*   860 */   158,   60,  240,  241,   60,  116,  240,  241,  117,  118,
+
 /*   870 */   119,  146,  194,   19,   81,  253,  275,  255,   24,  253,
+
 /*   880 */    98,  255,  117,  118,  119,  183,   22,  194,  103,  104,
+
 /*   890 */   105,  106,  107,  108,  109,  110,  111,  112,  113,  114,
+
 /*   900 */   151,  194,  270,  152,   22,   23,  194,   25,   19,  202,
+
 /*   910 */   217,  218,   23,  109,  207,  314,  315,  124,  117,  118,
+
 /*   920 */   119,  117,  118,  119,   60,  232,   22,   23,   19,   25,
+
 /*   930 */   303,  304,   43,   44,   45,   22,   47,   48,   49,   50,
+
 /*   940 */    51,   52,   53,   54,   55,   56,   57,   58,  270,  227,
+
 /*   950 */    96,   60,   43,   44,   45,  162,   47,   48,   49,   50,
+
 /*   960 */    51,   52,   53,   54,   55,   56,   57,   58,  114,  112,
+
 /*   970 */   113,  114,  194,   60,  120,  121,  122,  123,  124,  125,
+
 /*   980 */   126,  117,  118,  119,  102,   25,  132,  107,  108,  194,
+
 /*   990 */   194,  227,  103,  104,  105,  106,  107,  108,  109,  110,
+
 /*  1000 */   111,  112,  113,  114,  194,  194,  102,  194,  117,  118,
+
 /*  1010 */   119,  233,  103,  104,  105,  106,  107,  108,  109,  110,
+
 /*  1020 */   111,  112,  113,  114,  194,  194,   19,  194,  217,  218,
+
 /*  1030 */   117,  118,  119,  241,  154,  144,  156,  135,  242,  137,
+
 /*  1040 */   138,  130,   19,  232,  194,  253,   23,  255,  217,  218,
+
 /*  1050 */   217,  218,  242,   16,    7,    8,    9,   25,  261,  262,
+
 /*  1060 */   265,  194,   19,  232,  153,  232,   43,   44,   45,  160,
+
 /*  1070 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
+
 /*  1080 */    57,   58,  194,  227,  217,  218,   43,   44,   45,  194,
+
 /*  1090 */    47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
+
 /*  1100 */    57,   58,  306,  143,  308,  217,  218,  294,   12,   77,
+
 /*  1110 */    22,   23,  217,  218,  194,   78,  306,   80,  308,  194,
+
 /*  1120 */   232,  254,   90,   27,  117,   93,  103,  104,  105,  106,
+
 /*  1130 */   107,  108,  109,  110,  111,  112,  113,  114,   42,  194,
+
 /*  1140 */    35,  194,  217,  218,  214,  194,  103,  104,  105,  106,
+
 /*  1150 */   107,  108,  109,  110,  111,  112,  113,  114,  194,  239,
+
 /*  1160 */    64,  194,  217,  218,  217,  218,  209,  210,  217,  218,
+
 /*  1170 */    74,  207,   67,   22,  194,   77,   19,  232,  245,  232,
+
 /*  1180 */    75,   24,  312,  232,  217,  218,  316,   25,   90,  256,
+
 /*  1190 */   102,   93,  159,  229,  161,  231,   19,  217,  218,  162,
+
 /*  1200 */    43,   44,   45,  160,   47,   48,   49,   50,   51,   52,
+
 /*  1210 */    53,   54,   55,   56,   57,   58,   19,   23,  288,   25,
+
 /*  1220 */    43,   44,   45,  293,   47,   48,   49,   50,   51,   52,
+
 /*  1230 */    53,   54,   55,   56,   57,   58,  131,   22,  275,   24,
+
 /*  1240 */    43,   44,   45,  194,   47,   48,   49,   50,   51,   52,
+
 /*  1250 */    53,   54,   55,   56,   57,   58,  194,  194,  107,  108,
+
 /*  1260 */   103,  104,  105,  106,  107,  108,  109,  110,  111,  112,
+
 /*  1270 */   113,  114,  194,   25,  194,   60,  194,  314,  315,  194,
+
 /*  1280 */   103,  104,  105,  106,  107,  108,  109,  110,  111,  112,
+
 /*  1290 */   113,  114,   19,  194,  194,  217,  218,  217,  218,   25,
+
 /*  1300 */   103,  104,  105,  106,  107,  108,  109,  110,  111,  112,
+
 /*  1310 */   113,  114,  150,  119,  265,  312,   67,  217,  218,  316,
+
 /*  1320 */    19,  239,  194,  194,  128,  129,  130,  265,  265,  209,
+
 /*  1330 */   210,   31,  254,  118,  254,   86,   60,  194,  144,   39,
+
 /*  1340 */    19,  130,  275,  312,   95,   44,   45,  316,   47,   48,
+
 /*  1350 */    49,   50,   51,   52,   53,   54,   55,   56,   57,   58,
+
 /*  1360 */   217,  218,   24,  194,  153,   12,   45,  119,   47,   48,
+
 /*  1370 */    49,   50,   51,   52,   53,   54,   55,   56,   57,   58,
+
 /*  1380 */    27,  314,  315,   22,  312,   24,  217,  218,  316,  116,
+
 /*  1390 */   117,   22,  144,   25,  118,   42,  147,  194,   60,   19,
+
 /*  1400 */    20,  127,   22,  194,  103,  104,  105,  106,  107,  108,
+
 /*  1410 */   109,  110,  111,  112,  113,  114,   36,   64,  145,  194,
+
 /*  1420 */   217,  218,  194,   54,  103,  104,  105,  106,  107,  108,
+
 /*  1430 */   109,  110,  111,  112,  113,  114,  194,   22,  310,   25,
+
 /*  1440 */    60,  194,  217,  218,  194,  217,  218,  194,  260,  194,
+
 /*  1450 */   301,  302,   72,  262,  262,  194,  118,  266,  266,  217,
+
 /*  1460 */   218,  194,   82,  245,  217,  218,  194,  217,  218,  194,
+
 /*  1470 */   217,  218,  217,  218,  256,   60,   24,  194,  217,  218,
+
 /*  1480 */   194,  101,  194,  245,  217,  218,  194,  107,  108,  217,
+
 /*  1490 */   218,   22,  217,  218,  256,  115,  245,  117,  118,  119,
+
 /*  1500 */   217,  218,  122,  217,  218,  217,  218,  256,   22,  217,
+
 /*  1510 */   218,  116,  258,  259,  146,   19,   20,  194,   22,  139,
+
 /*  1520 */   140,  150,  151,  136,   23,  194,   25,  194,  141,  194,
+
 /*  1530 */   194,   62,   36,  118,  154,  155,  156,  157,  158,  100,
+
 /*  1540 */   145,  194,  154,  194,  156,   49,  194,   23,  194,   25,
+
 /*  1550 */   217,  218,  217,  218,  194,  257,   60,  143,  194,   60,
+
 /*  1560 */   194,  121,  122,  183,  217,  218,  217,  218,   72,  217,
+
 /*  1570 */   218,  217,  218,  134,   23,  194,   25,  217,  218,    7,
+
 /*  1580 */     8,  321,   86,  217,  218,  194,  122,   91,   19,   20,
+
 /*  1590 */    23,   22,   25,   23,  142,   25,  132,  101,  217,  218,
+
 /*  1600 */   194,  194,  194,  107,  108,   36,  194,  194,  217,  218,
+
 /*  1610 */   194,  115,  194,  117,  118,  119,  194,  118,  122,  194,
+
 /*  1620 */    23,  194,   25,  217,  218,  217,  218,  194,  142,   60,
+
 /*  1630 */   217,  218,  194,  217,  218,  217,  218,   84,   85,  217,
+
 /*  1640 */   218,   72,  217,  218,  217,  218,   60,   23,   60,   25,
+
 /*  1650 */   154,  155,  156,  157,  158,   86,  154,  194,  156,  194,
+
 /*  1660 */    91,   19,   20,   23,   22,   25,  194,   23,  194,   25,
+
 /*  1670 */   101,   23,  194,   25,  194,  194,  107,  108,   36,  183,
+
 /*  1680 */   217,  218,  217,  218,  115,  194,  117,  118,  119,  217,
+
 /*  1690 */   218,  122,  194,  237,  194,  217,  218,  217,  218,  194,
+
 /*  1700 */   194,   23,   60,   25,  118,   23,  118,   25,  217,  218,
+
 /*  1710 */    23,  194,   25,  194,   72,  217,  218,  217,  218,   23,
+
 /*  1720 */   194,   25,  194,  154,  155,  156,  157,  158,   86,   23,
+
 /*  1730 */   194,   25,  194,   91,  217,  218,  217,  218,  194,  194,
+
 /*  1740 */   194,  194,  194,  101,  194,  217,  218,  290,  194,  107,
+
 /*  1750 */   108,  194,  183,  217,  218,  194,  194,  115,  194,  117,
+
 /*  1760 */   118,  119,  194,  243,  122,  194,  289,  194,  194,  194,
+
 /*  1770 */   194,  257,  257,  257,  244,  257,  192,  273,  215,  269,
+
 /*  1780 */   246,  299,  269,  295,  247,  273,  247,  246,  295,  230,
+
 /*  1790 */   261,  226,  261,  261,  273,  273,  154,  155,  156,  157,
+
 /*  1800 */   158,    0,    1,    2,  221,  220,    5,  220,  250,  220,
+
 /*  1810 */   261,   10,   11,   12,   13,   14,  250,  282,   17,  197,
+
 /*  1820 */    61,   19,   20,  246,   22,  183,  244,  142,  201,  201,
+
 /*  1830 */    38,   30,  299,   32,  201,  152,   22,  151,   36,  299,
+
 /*  1840 */    43,   40,  235,   18,  238,  285,  238,  238,  296,  238,
+
 /*  1850 */   201,  296,  274,  272,   18,  200,  235,  150,  235,  247,
+
 /*  1860 */   247,  247,   60,  247,  274,  274,  272,  201,  200,  159,
+
 /*  1870 */    63,  292,   71,  201,   72,  200,   22,  201,  222,  200,
+
 /*  1880 */    79,  201,  222,   82,  291,  116,  219,   65,  200,  219,
+
 /*  1890 */   219,  228,   22,  127,  225,  166,  222,   24,  225,  114,
+
 /*  1900 */    99,  284,  221,  101,  284,  228,  307,  315,  219,  107,
+
 /*  1910 */   108,  219,  219,  219,  201,   92,  320,  115,  320,  117,
+
 /*  1920 */   118,  119,  222,   83,  122,  267,  267,  149,  146,   19,
+
 /*  1930 */    20,   22,   22,  279,  250,  134,  201,  148,  159,  249,
+
 /*  1940 */   139,  140,  251,  141,   25,  281,   36,  147,  251,  248,
+
 /*  1950 */   247,  203,   13,  195,    6,  195,  154,  155,  156,  157,
+
 /*  1960 */   158,  193,  305,  193,  163,  193,  305,  302,  214,  208,
+
 /*  1970 */    60,  214,  208,  223,  223,    4,  214,  214,    3,   22,
+
 /*  1980 */   215,  214,   72,  208,  164,  183,  215,   15,   23,   16,
+
 /*  1990 */    23,  140,  131,  152,   25,  143,   20,   16,   24,    1,
+
 /*  2000 */   145,  143,  131,  131,   62,   37,   54,   54,  152,   54,
+
 /*  2010 */    54,  101,  131,  117,   34,    1,  142,  107,  108,   22,
+
 /*  2020 */     5,  116,  162,   69,   25,  115,   76,  117,  118,  119,
+
 /*  2030 */     1,    2,  122,   69,    5,   41,  142,  116,   20,   10,
+
 /*  2040 */    11,   12,   13,   14,   24,   19,   17,  132,    5,  126,
+
 /*  2050 */    22,  141,   68,   10,   11,   12,   13,   14,   22,   30,
+
 /*  2060 */    17,   32,   22,   22,  154,  155,  156,  157,  158,   40,
+
 /*  2070 */    23,   68,   60,   30,   24,   32,   97,   28,   22,   68,
+
 /*  2080 */    23,   37,   34,   40,  150,   22,   25,   23,   23,   23,
+
 /*  2090 */    22,   98,   23,  183,   23,  117,   34,   22,   25,   89,
+
 /*  2100 */    71,  142,  144,   76,   34,   23,   34,   76,   79,   87,
+
 /*  2110 */    34,   82,   34,   94,   71,   34,   22,   24,   44,   34,
+
 /*  2120 */    25,   25,   79,   23,   23,   82,  143,   23,   99,  143,
+
 /*  2130 */    23,   22,   11,   25,   23,   25,   22,   22,   22,    1,
+
 /*  2140 */    23,   23,   99,  136,   22,   22,  142,  142,  142,   25,
+
 /*  2150 */    25,   23,   15,    1,  322,  322,  322,  322,  322,  322,
+
 /*  2160 */   322,  322,  322,  134,  322,  322,  322,  322,  139,  140,
+
 /*  2170 */   322,  322,  322,  322,  322,  322,  322,  134,  322,  322,
+
 /*  2180 */   322,  322,  139,  140,  322,  322,  322,  322,  322,  322,
+
 /*  2190 */   322,  322,  163,  322,  322,  322,  322,  322,  322,  322,
+
 /*  2200 */   322,  322,  322,  322,  322,  322,  163,  322,  322,  322,
 /*  2210 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
 /*  2220 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
 /*  2230 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
@@ -173527,118 +174848,125 @@ static const YYCODETYPE yy_lookahead[] = {
 /*  2290 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
 /*  2300 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
 /*  2310 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
-
 /*  2320 */   322,  322,  322,  322,  322,  322,  322,  322,
+
 /*  2320 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
+
 /*  2330 */   322,  322,  322,  322,  322,  322,  322,  322,  322,  322,
+
 /*  2340 */   186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
+
 /*  2350 */   186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
+
 /*  2360 */   186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
+
 /*  2370 */   186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
+
 /*  2380 */   186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
+
 /*  2390 */   186,  186,  186,
};
#define YY_SHIFT_COUNT    (582)
#define YY_SHIFT_MIN      (0)
-
#define YY_SHIFT_MAX      (2128)
+
#define YY_SHIFT_MAX      (2152)
static const unsigned short int yy_shift_ofst[] = {
-
 /*     0 */  1792, 1588, 1494,  322,  322,  399,  306, 1319, 1339, 1430,
-
 /*    10 */  1828, 1828, 1828,  580,  399,  399,  399,  399,  399,    0,
-
 /*    20 */     0,  214, 1093, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-
 /*    30 */  1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1130, 1130,
-
 /*    40 */   365,  365,   55,  278,  436,  713,  713,  201,  201,  201,
-
 /*    50 */   201,   40,  111,  258,  361,  469,  512,  583,  622,  693,
-
 /*    60 */   732,  803,  842,  913, 1073, 1093, 1093, 1093, 1093, 1093,
-
 /*    70 */  1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
-
 /*    80 */  1093, 1093, 1093, 1113, 1093, 1216,  957,  957, 1523, 1602,
-
 /*    90 */  1674, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-
 /*   100 */  1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-
 /*   110 */  1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-
 /*   120 */  1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-
 /*   130 */  1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-
 /*   140 */   137,  181,  181,  181,  181,  181,  181,  181,   96,  222,
-
 /*   150 */   143,  477,  713, 1133, 1268,  713,  713,   79,   79,  713,
-
 /*   160 */   770,   83,   65,   65,   65,  288,  162,  162, 2142, 2142,
-
 /*   170 */   696,  696,  696,  238,  474,  474,  474,  474, 1217, 1217,
-
 /*   180 */   678,  477,  324,  398,  713,  713,  713,  713,  713,  713,
-
 /*   190 */   713,  713,  713,  713,  713,  713,  713,  713,  713,  713,
-
 /*   200 */   713,  713,  713, 1220,  366,  366,  713,  917,  283,  283,
-
 /*   210 */   434,  434,  605,  605, 1298, 2142, 2142, 2142, 2142, 2142,
-
 /*   220 */  2142, 2142, 1179, 1157, 1157,  487,  527,  585,  645,  749,
-
 /*   230 */   914,  968,  752,  713,  713,  713,  713,  713,  713,  713,
-
 /*   240 */   713,  713,  713,  303,  713,  713,  713,  713,  713,  713,
-
 /*   250 */   713,  713,  713,  713,  713,  713,  797,  797,  797,  713,
-
 /*   260 */   713,  713,  959,  713,  713,  713, 1169, 1271,  713,  713,
-
 /*   270 */  1330,  713,  713,  713,  713,  713,  713,  713,  713,  629,
-
 /*   280 */     7,   91,  876,  876,  876,  876,  953,   91,   91, 1246,
-
 /*   290 */  1065, 1106, 1374, 1329, 1348,  468, 1348, 1394,  785, 1329,
-
 /*   300 */  1329,  785, 1329,  468, 1394,  859,  854, 1402, 1449, 1449,
-
 /*   310 */  1449, 1173, 1173, 1173, 1173, 1355, 1355, 1030, 1341,  405,
-
 /*   320 */  1230, 1795, 1795, 1711, 1711, 1829, 1829, 1711, 1717, 1719,
-
 /*   330 */  1850, 1833, 1860, 1860, 1860, 1860, 1711, 1868, 1740, 1719,
-
 /*   340 */  1719, 1740, 1850, 1833, 1740, 1833, 1740, 1711, 1868, 1745,
-
 /*   350 */  1843, 1711, 1868, 1887, 1711, 1868, 1711, 1868, 1887, 1801,
-
 /*   360 */  1801, 1801, 1855, 1900, 1900, 1887, 1801, 1797, 1801, 1855,
-
 /*   370 */  1801, 1801, 1761, 1912, 1830, 1830, 1887, 1711, 1862, 1862,
-
 /*   380 */  1875, 1875, 1810, 1815, 1940, 1711, 1807, 1810, 1821, 1823,
-
 /*   390 */  1740, 1945, 1963, 1963, 1974, 1974, 1974, 2142, 2142, 2142,
-
 /*   400 */  2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
-
 /*   410 */  2142, 2142,   20, 1224,  256, 1111, 1115, 1114, 1192, 1496,
-
 /*   420 */  1424, 1505, 1427,  355, 1383, 1537, 1506, 1538, 1553, 1583,
-
 /*   430 */  1584, 1591, 1625,  541, 1445, 1562, 1450, 1572, 1515, 1428,
-
 /*   440 */  1532, 1592, 1629, 1520, 1630, 1639, 1510, 1544, 1662, 1675,
-
 /*   450 */  1551,   48, 1996, 2001, 1983, 1844, 1993, 1994, 1986, 1989,
-
 /*   460 */  1874, 1863, 1885, 1991, 1991, 1995, 1876, 1997, 1877, 2004,
-
 /*   470 */  2021, 1881, 1894, 1991, 1895, 1965, 1990, 1991, 1878, 1975,
-
 /*   480 */  1977, 1978, 1979, 1903, 1918, 2002, 1896, 2034, 2033, 2017,
-
 /*   490 */  1925, 1880, 1976, 2018, 1980, 1967, 2005, 1904, 1932, 2025,
-
 /*   500 */  2030, 2032, 1921, 1928, 2035, 1987, 2036, 2037, 2038, 2040,
-
 /*   510 */  1988, 2006, 2039, 1960, 2041, 2042, 1999, 2023, 2044, 2043,
-
 /*   520 */  1919, 2048, 2049, 2050, 2046, 2051, 2053, 1981, 1935, 2056,
-
 /*   530 */  2057, 1966, 2047, 2061, 1941, 2060, 2052, 2054, 2055, 2058,
-
 /*   540 */  2003, 2012, 2007, 2059, 2015, 2008, 2062, 2071, 2073, 2074,
-
 /*   550 */  2072, 2075, 2065, 1962, 1964, 2079, 2060, 2082, 2084, 2085,
-
 /*   560 */  2087, 2086, 2089, 2088, 2091, 2093, 2099, 2094, 2095, 2096,
-
 /*   570 */  2097, 2100, 2101, 2102, 1998, 1984, 1985, 2000, 2103, 2098,
-
 /*   580 */  2109, 2117, 2128,
+
 /*     0 */  2029, 1801, 2043, 1380, 1380,   33,  391, 1496, 1569, 1642,
+
 /*    10 */   702,  702,  702,  193,   33,   33,   33,   33,   33,    0,
+
 /*    20 */     0,  216, 1177,  702,  702,  702,  702,  702,  702,  702,
+
 /*    30 */   702,  702,  702,  702,  702,  702,  702,  702,  406,  406,
+
 /*    40 */   111,  111,  218,  447,  547,  598,  598,  260,  260,  260,
+
 /*    50 */   260,   40,  112,  320,  340,  445,  489,  593,  637,  741,
+
 /*    60 */   785,  889,  909, 1023, 1043, 1157, 1177, 1177, 1177, 1177,
+
 /*    70 */  1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177,
+
 /*    80 */  1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321,  554,
+
 /*    90 */  1802, 1910,  702,  702,  702,  702,  702,  702,  702,  702,
+
 /*   100 */   702,  702,  702,  702,  702,  702,  702,  702,  702,  702,
+
 /*   110 */   702,  702,  702,  702,  702,  702,  702,  702,  702,  702,
+
 /*   120 */   702,  702,  702,  702,  702,  702,  702,  702,  702,  702,
+
 /*   130 */   702,  702,  702,  702,  702,  702,  702,  702,  702,  702,
+
 /*   140 */   702,  702,  138,  198,  198,  198,  198,  198,  198,  198,
+
 /*   150 */   183,   99,  236,  292,  598,  793,  167,  598,  598,  880,
+
 /*   160 */   880,  598,  857,  150,  195,  195,  195,  264,  113,  113,
+
 /*   170 */  2207, 2207,  854,  854,  854,  751,  765,  765,  765,  765,
+
 /*   180 */  1096, 1096,  725,  292,  882,  904,  598,  598,  598,  598,
+
 /*   190 */   598,  598,  598,  598,  598,  598,  598,  598,  598,  598,
+
 /*   200 */   598,  598,  598,  598,  598, 1273, 1032, 1032,  598,  147,
+
 /*   210 */  1098, 1098,  603,  603, 1276, 1276,  363, 2207, 2207, 2207,
+
 /*   220 */  2207, 2207, 2207, 2207,  469,  617,  617,  801,  336,  461,
+
 /*   230 */   804,  864,  615,  891,  913,  598,  598,  598,  598,  598,
+
 /*   240 */   598,  598,  598,  598,  598,  653,  598,  598,  598,  598,
+
 /*   250 */   598,  598,  598,  598,  598,  598,  598,  598, 1105, 1105,
+
 /*   260 */  1105,  598,  598,  598, 1194,  598,  598,  598, 1215, 1249,
+
 /*   270 */   598, 1353,  598,  598,  598,  598,  598,  598,  598,  598,
+
 /*   280 */   677,  449,  902, 1338, 1338, 1338, 1338, 1248,  902,  902,
+
 /*   290 */   326, 1151, 1047,  755,  749, 1371,  960, 1371, 1007, 1162,
+
 /*   300 */   749,  749, 1162,  749,  960, 1007, 1274,  738,  215, 1300,
+
 /*   310 */  1300, 1300, 1395, 1395, 1395, 1395, 1368, 1368, 1033, 1414,
+
 /*   320 */  1387, 1361, 1759, 1759, 1685, 1685, 1792, 1792, 1685, 1683,
+
 /*   330 */  1686, 1814, 1797, 1825, 1825, 1825, 1825, 1685, 1836, 1707,
+
 /*   340 */  1686, 1686, 1707, 1814, 1797, 1707, 1797, 1707, 1685, 1836,
+
 /*   350 */  1710, 1807, 1685, 1836, 1854, 1685, 1836, 1685, 1836, 1854,
+
 /*   360 */  1769, 1769, 1769, 1822, 1870, 1870, 1854, 1769, 1766, 1769,
+
 /*   370 */  1822, 1769, 1769, 1729, 1873, 1785, 1785, 1854, 1685, 1823,
+
 /*   380 */  1823, 1840, 1840, 1778, 1782, 1909, 1685, 1779, 1778, 1789,
+
 /*   390 */  1800, 1707, 1919, 1939, 1939, 1948, 1948, 1948, 2207, 2207,
+
 /*   400 */  2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207,
+
 /*   410 */  2207, 2207, 2207,   69, 1037,   79, 1088,  651, 1196, 1415,
+
 /*   420 */  1501, 1439, 1369, 1452,  911, 1211, 1524, 1469, 1551, 1567,
+
 /*   430 */  1570, 1624, 1640, 1644, 1499, 1440, 1572, 1464, 1597,  275,
+
 /*   440 */   782, 1586, 1648, 1678, 1553, 1682, 1687, 1388, 1502, 1696,
+
 /*   450 */  1706, 1588, 1486, 1971, 1975, 1957, 1820, 1972, 1973, 1965,
+
 /*   460 */  1967, 1851, 1841, 1861, 1969, 1969, 1974, 1852, 1976, 1855,
+
 /*   470 */  1981, 1998, 1858, 1871, 1969, 1872, 1942, 1968, 1969, 1856,
+
 /*   480 */  1952, 1953, 1955, 1956, 1881, 1896, 1980, 1874, 2014, 2015,
+
 /*   490 */  1997, 1905, 1860, 1954, 1999, 1964, 1950, 1994, 1894, 1921,
+
 /*   500 */  2020, 2018, 2026, 1915, 1923, 2028, 1984, 2036, 2040, 2047,
+
 /*   510 */  2041, 2003, 2012, 2050, 1979, 2049, 2056, 2011, 2044, 2057,
+
 /*   520 */  2048, 1934, 2063, 2064, 2065, 2061, 2066, 2068, 1993, 1959,
+
 /*   530 */  2069, 2071, 1978, 2062, 2075, 1958, 2073, 2070, 2072, 2076,
+
 /*   540 */  2078, 2010, 2027, 2022, 2074, 2031, 2019, 2081, 2082, 2094,
+
 /*   550 */  2093, 2095, 2096, 2085, 1983, 1986, 2100, 2073, 2101, 2104,
+
 /*   560 */  2107, 2109, 2108, 2110, 2111, 2114, 2121, 2115, 2116, 2117,
+
 /*   570 */  2118, 2122, 2123, 2124, 2007, 2004, 2005, 2006, 2125, 2128,
+
 /*   580 */  2137, 2138, 2152,
};
-
#define YY_REDUCE_COUNT (411)
-
#define YY_REDUCE_MIN   (-275)
-
#define YY_REDUCE_MAX   (1798)
+
#define YY_REDUCE_COUNT (412)
+
#define YY_REDUCE_MIN   (-276)
+
#define YY_REDUCE_MAX   (1775)
static const short yy_reduce_ofst[] = {
-
 /*     0 */   -71,  194,  343,  835, -180, -177,  838, -194, -188, -185,
-
 /*    10 */  -183,   82,  183,  -65,  133,  245,  346,  407,  458, -178,
-
 /*    20 */    75, -275,   -4,  310,  312,  489,  575,  596,  463,  686,
-
 /*    30 */   707,  725,  780, 1098,  856,  778, 1059, 1090,  708,  887,
-
 /*    40 */    86,  448,  980,  630,  680,  681,  684,  796,  801,  796,
-
 /*    50 */   801, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
 /*    60 */  -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
 /*    70 */  -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
 /*    80 */  -261, -261, -261, -261, -261, -261, -261, -261,  391,  886,
-
 /*    90 */   888, 1013, 1016, 1081, 1087, 1151, 1159, 1177, 1185, 1188,
-
 /*   100 */  1190, 1194, 1197, 1203, 1247, 1260, 1264, 1267, 1269, 1273,
-
 /*   110 */  1315, 1322, 1335, 1337, 1356, 1362, 1418, 1425, 1453, 1457,
-
 /*   120 */  1465, 1473, 1487, 1495, 1507, 1517, 1521, 1534, 1543, 1546,
-
 /*   130 */  1549, 1552, 1554, 1560, 1581, 1590, 1593, 1595, 1621, 1623,
-
 /*   140 */  -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
 /*   150 */  -261, -186, -117,  260,  263,  460,  631,  -74,  497, -181,
-
 /*   160 */  -261,  939,  176,  274,  338,  676, -261, -261, -261, -261,
-
 /*   170 */  -212, -212, -212, -184,  149,  777, 1061, 1103,  265,  419,
-
 /*   180 */  -254,  670,  677,  677,  -11, -129,  184,  488,  736,  789,
-
 /*   190 */   805,  844,  403,  529,  579,  668,  783,  841, 1158, 1112,
-
 /*   200 */   806,  861, 1095,  846,  839, 1031, -189, 1077, 1080, 1116,
-
 /*   210 */  1084, 1156, 1139, 1221,   46, 1099, 1037, 1118, 1171, 1214,
-
 /*   220 */  1210, 1258, -210, -190, -176, -115,  117,  262,  376,  490,
-
 /*   230 */   511,  520,  618,  639,  743,  901,  907,  958, 1014, 1055,
-
 /*   240 */  1108, 1193, 1244,  720, 1248, 1277, 1324, 1347, 1417, 1431,
-
 /*   250 */  1432, 1440, 1451, 1452, 1463, 1478, 1286, 1350, 1369, 1490,
-
 /*   260 */  1498, 1501,  773, 1509, 1513, 1528, 1292, 1367, 1535, 1536,
-
 /*   270 */  1477, 1542,  376, 1547, 1550, 1555, 1559, 1568, 1571, 1441,
-
 /*   280 */  1443, 1474, 1511, 1516, 1519, 1522,  773, 1474, 1474, 1503,
-
 /*   290 */  1567, 1594, 1484, 1527, 1556, 1570, 1557, 1524, 1573, 1545,
-
 /*   300 */  1548, 1576, 1561, 1587, 1540, 1575, 1606, 1611, 1622, 1624,
-
 /*   310 */  1626, 1582, 1597, 1598, 1599, 1601, 1603, 1563, 1608, 1605,
-
 /*   320 */  1604, 1564, 1566, 1655, 1660, 1578, 1579, 1665, 1586, 1607,
-
 /*   330 */  1610, 1642, 1641, 1645, 1646, 1647, 1679, 1688, 1644, 1618,
-
 /*   340 */  1619, 1648, 1628, 1659, 1649, 1663, 1650, 1700, 1702, 1612,
-
 /*   350 */  1615, 1706, 1708, 1689, 1709, 1712, 1713, 1715, 1691, 1698,
-
 /*   360 */  1699, 1701, 1693, 1704, 1707, 1705, 1714, 1703, 1718, 1710,
-
 /*   370 */  1720, 1721, 1632, 1634, 1664, 1666, 1729, 1751, 1635, 1636,
-
 /*   380 */  1692, 1694, 1716, 1722, 1684, 1763, 1685, 1723, 1724, 1727,
-
 /*   390 */  1730, 1768, 1783, 1784, 1793, 1794, 1796, 1683, 1686, 1690,
-
 /*   400 */  1782, 1779, 1780, 1781, 1785, 1788, 1774, 1775, 1786, 1787,
-
 /*   410 */  1789, 1798,
+
 /*     0 */   -66,  217,  -63, -177, -180,  161,  364,   64, -183,  162,
+
 /*    10 */   223,  367,  414, -173,  473,  514,  525,  622,  626, -207,
+
 /*    20 */   351, -276,  -38,  693,  811,  831,  833,  888, -188,  945,
+
 /*    30 */   947,  416,  558,  951,  867,  287, 1078, 1080, -186,  224,
+
 /*    40 */  -132,   42,  964,  269,  417,  796,  810, -237, -231, -237,
+
 /*    50 */  -231,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
 /*    60 */   -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
 /*    70 */   -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
 /*    80 */   -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  895,
+
 /*    90 */   925,  967,  980, 1100, 1143, 1169, 1203, 1225, 1228, 1242,
+
 /*   100 */  1247, 1250, 1253, 1255, 1261, 1267, 1272, 1275, 1283, 1286,
+
 /*   110 */  1288, 1292, 1333, 1335, 1347, 1349, 1352, 1354, 1360, 1366,
+
 /*   120 */  1381, 1391, 1406, 1408, 1413, 1416, 1418, 1422, 1425, 1427,
+
 /*   130 */  1463, 1465, 1472, 1478, 1480, 1491, 1498, 1500, 1517, 1519,
+
 /*   140 */  1528, 1536,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
 /*   150 */   -45,  -45,  -45,  312, -158,  285, -219,    9,  166,  370,
+
 /*   160 */   545,  707,  -45,  930,  601,  963, 1067,  792,  -45,  -45,
+
 /*   170 */   -45,  -45, -204, -204, -204,  369, -171, -129,  632,  678,
+
 /*   180 */   202,  352, -270,  412,  627,  627,   -9,  122,  415,  419,
+
 /*   190 */   -56,  248,  583,  920,    6,  261,  459,  795, 1049,  813,
+
 /*   200 */  1062, 1082, -161,  778, 1063,  797,  870, 1003, 1128,  443,
+
 /*   210 */  1031, 1072, 1191, 1192,  957, 1120,  105, 1149,  523,  933,
+
 /*   220 */  1218, 1238, 1254, 1251, -138,   96,  117,  146,  181,  277,
+
 /*   230 */   280,  421,  480,  712,  830,  850, 1085, 1099, 1129, 1209,
+
 /*   240 */  1323, 1331, 1336, 1364, 1407,  368, 1412, 1433, 1438, 1474,
+
 /*   250 */  1481, 1505, 1506, 1526, 1538, 1544, 1545, 1546,  722,  764,
+
 /*   260 */   856, 1547, 1548, 1550, 1188, 1554, 1557, 1561, 1298, 1260,
+
 /*   270 */  1562, 1456, 1564,  280, 1568, 1571, 1573, 1574, 1575, 1576,
+
 /*   280 */  1457, 1477, 1520, 1514, 1515, 1516, 1518, 1188, 1520, 1520,
+
 /*   290 */  1530, 1563, 1584, 1482, 1504, 1510, 1534, 1513, 1488, 1537,
+
 /*   300 */  1512, 1521, 1539, 1522, 1541, 1493, 1583, 1559, 1565, 1585,
+
 /*   310 */  1587, 1589, 1529, 1531, 1532, 1549, 1558, 1566, 1535, 1577,
+
 /*   320 */  1582, 1622, 1533, 1540, 1627, 1628, 1552, 1555, 1633, 1560,
+
 /*   330 */  1578, 1581, 1607, 1606, 1608, 1609, 1611, 1649, 1655, 1612,
+
 /*   340 */  1590, 1591, 1613, 1594, 1621, 1614, 1623, 1616, 1666, 1668,
+
 /*   350 */  1579, 1593, 1672, 1675, 1656, 1676, 1679, 1680, 1688, 1660,
+
 /*   360 */  1667, 1670, 1671, 1663, 1669, 1673, 1674, 1689, 1681, 1692,
+
 /*   370 */  1677, 1693, 1694, 1592, 1599, 1617, 1620, 1700, 1713, 1596,
+
 /*   380 */  1598, 1658, 1659, 1691, 1684, 1654, 1735, 1664, 1697, 1690,
+
 /*   390 */  1701, 1703, 1748, 1758, 1760, 1768, 1770, 1772, 1657, 1661,
+
 /*   400 */  1665, 1761, 1754, 1757, 1762, 1763, 1764, 1750, 1751, 1765,
+
 /*   410 */  1771, 1767, 1775,
};
static const YYACTIONTYPE yy_default[] = {
 /*     0 */  1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254,
@@ -173647,57 +174975,57 @@ static const YYACTIONTYPE yy_default[] = {
 /*    30 */  1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254,
 /*    40 */  1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254,
 /*    50 */  1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254,
-
 /*    60 */  1492, 1493, 1254, 1254, 1254, 1543, 1545, 1508, 1420, 1419,
-
 /*    70 */  1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, 1486,
-
 /*    80 */  1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, 1254,
+
 /*    60 */  1492, 1493, 1254, 1254, 1254, 1254, 1543, 1545, 1508, 1420,
+
 /*    70 */  1419, 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488,
+
 /*    80 */  1486, 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254,
 /*    90 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   100 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   110 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   120 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   130 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   140 */  1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, 1456, 1458,
-
 /*   150 */  1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, 1254, 1254,
-
 /*   160 */  1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, 1473, 1472,
-
 /*   170 */  1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   180 */  1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   140 */  1254, 1254, 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457,
+
 /*   150 */  1456, 1458, 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254,
+
 /*   160 */  1254, 1254, 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461,
+
 /*   170 */  1473, 1472, 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254,
+
 /*   180 */  1254, 1254, 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   190 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   200 */  1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, 1578, 1578,
-
 /*   210 */  1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, 1358, 1358,
-
 /*   220 */  1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   230 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, 1546, 1254,
-
 /*   240 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   200 */  1254, 1254, 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287,
+
 /*   210 */  1578, 1578, 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358,
+
 /*   220 */  1358, 1358, 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   230 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548,
+
 /*   240 */  1546, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   250 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   260 */  1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, 1254, 1254,
-
 /*   270 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, 1254,
-
 /*   280 */  1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, 1357,
-
 /*   290 */  1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, 1423,
-
 /*   300 */  1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, 1397,
-
 /*   310 */  1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, 1357,
-
 /*   320 */  1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, 1638,
-
 /*   330 */  1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, 1638,
-
 /*   340 */  1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, 1525,
-
 /*   350 */  1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, 1330,
-
 /*   360 */  1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, 1319,
-
 /*   370 */  1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, 1588,
-
 /*   380 */  1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, 1401,
-
 /*   390 */  1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, 1558,
-
 /*   400 */  1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, 1288,
-
 /*   410 */  1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, 1254,
-
 /*   420 */  1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   430 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1564,
-
 /*   440 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   450 */  1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, 1254,
-
 /*   460 */  1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, 1254,
-
 /*   470 */  1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, 1254,
-
 /*   480 */  1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, 1254,
-
 /*   490 */  1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, 1254,
+
 /*   260 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254,
+
 /*   270 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608,
+
 /*   280 */  1254, 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342,
+
 /*   290 */  1357, 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410,
+
 /*   300 */  1423, 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397,
+
 /*   310 */  1397, 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364,
+
 /*   320 */  1357, 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509,
+
 /*   330 */  1638, 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410,
+
 /*   340 */  1638, 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272,
+
 /*   350 */  1525, 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499,
+
 /*   360 */  1330, 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330,
+
 /*   370 */  1319, 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588,
+
 /*   380 */  1588, 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403,
+
 /*   390 */  1401, 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660,
+
 /*   400 */  1558, 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288,
+
 /*   410 */  1288, 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618,
+
 /*   420 */  1254, 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   430 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   440 */  1564, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   450 */  1254, 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254,
+
 /*   460 */  1254, 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254,
+
 /*   470 */  1254, 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254,
+
 /*   480 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254,
+
 /*   490 */  1254, 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254,
 /*   500 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   510 */  1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   510 */  1254, 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   520 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   530 */  1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, 1254,
+
 /*   530 */  1254, 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254,
 /*   540 */  1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
-
 /*   550 */  1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, 1254,
-
 /*   560 */  1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+
 /*   550 */  1254, 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254,
+
 /*   560 */  1254, 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
 /*   570 */  1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254,
 /*   580 */  1266, 1254, 1254,
};
@@ -173721,52 +175049,53 @@ static const YYACTIONTYPE yy_default[] = {
static const YYCODETYPE yyFallback[] = {
    0,  /*          $ => nothing */
    0,  /*       SEMI => nothing */
-
   59,  /*    EXPLAIN => ID */
-
   59,  /*      QUERY => ID */
-
   59,  /*       PLAN => ID */
-
   59,  /*      BEGIN => ID */
+
   60,  /*    EXPLAIN => ID */
+
   60,  /*      QUERY => ID */
+
   60,  /*       PLAN => ID */
+
   60,  /*      BEGIN => ID */
    0,  /* TRANSACTION => nothing */
-
   59,  /*   DEFERRED => ID */
-
   59,  /*  IMMEDIATE => ID */
-
   59,  /*  EXCLUSIVE => ID */
+
   60,  /*   DEFERRED => ID */
+
   60,  /*  IMMEDIATE => ID */
+
   60,  /*  EXCLUSIVE => ID */
    0,  /*     COMMIT => nothing */
-
   59,  /*        END => ID */
-
   59,  /*   ROLLBACK => ID */
-
   59,  /*  SAVEPOINT => ID */
-
   59,  /*    RELEASE => ID */
+
   60,  /*        END => ID */
+
   60,  /*   ROLLBACK => ID */
+
   60,  /*  SAVEPOINT => ID */
+
   60,  /*    RELEASE => ID */
    0,  /*         TO => nothing */
    0,  /*      TABLE => nothing */
    0,  /*     CREATE => nothing */
-
   59,  /*         IF => ID */
+
   60,  /*         IF => ID */
    0,  /*        NOT => nothing */
    0,  /*     EXISTS => nothing */
-
   59,  /*       TEMP => ID */
+
   60,  /*       TEMP => ID */
    0,  /*         LP => nothing */
    0,  /*         RP => nothing */
    0,  /*         AS => nothing */
    0,  /*      COMMA => nothing */
-
   59,  /*    WITHOUT => ID */
-
   59,  /*      ABORT => ID */
-
   59,  /*     ACTION => ID */
-
   59,  /*      AFTER => ID */
-
   59,  /*    ANALYZE => ID */
-
   59,  /*        ASC => ID */
-
   59,  /*     ATTACH => ID */
-
   59,  /*     BEFORE => ID */
-
   59,  /*         BY => ID */
-
   59,  /*    CASCADE => ID */
-
   59,  /*       CAST => ID */
-
   59,  /*   CONFLICT => ID */
-
   59,  /*   DATABASE => ID */
-
   59,  /*       DESC => ID */
-
   59,  /*     DETACH => ID */
-
   59,  /*       EACH => ID */
-
   59,  /*       FAIL => ID */
+
   60,  /*    WITHOUT => ID */
+
   60,  /*      ABORT => ID */
+
   60,  /*     ACTION => ID */
+
   60,  /*      AFTER => ID */
+
   60,  /*    ANALYZE => ID */
+
   60,  /*        ASC => ID */
+
   60,  /*     ATTACH => ID */
+
   60,  /*     BEFORE => ID */
+
   60,  /*         BY => ID */
+
   60,  /*    CASCADE => ID */
+
   60,  /*       CAST => ID */
+
   60,  /*   CONFLICT => ID */
+
   60,  /*   DATABASE => ID */
+
   60,  /*       DESC => ID */
+
   60,  /*     DETACH => ID */
+
   60,  /*       EACH => ID */
+
   60,  /*       FAIL => ID */
    0,  /*         OR => nothing */
    0,  /*        AND => nothing */
    0,  /*         IS => nothing */
-
   59,  /*      MATCH => ID */
-
   59,  /*    LIKE_KW => ID */
+
    0,  /*      ISNOT => nothing */
+
   60,  /*      MATCH => ID */
+
   60,  /*    LIKE_KW => ID */
    0,  /*    BETWEEN => nothing */
    0,  /*         IN => nothing */
    0,  /*     ISNULL => nothing */
@@ -173779,47 +175108,47 @@ static const YYCODETYPE yyFallback[] = {
    0,  /*         GE => nothing */
    0,  /*     ESCAPE => nothing */
    0,  /*         ID => nothing */
-
   59,  /*   COLUMNKW => ID */
-
   59,  /*         DO => ID */
-
   59,  /*        FOR => ID */
-
   59,  /*     IGNORE => ID */
-
   59,  /*  INITIALLY => ID */
-
   59,  /*    INSTEAD => ID */
-
   59,  /*         NO => ID */
-
   59,  /*        KEY => ID */
-
   59,  /*         OF => ID */
-
   59,  /*     OFFSET => ID */
-
   59,  /*     PRAGMA => ID */
-
   59,  /*      RAISE => ID */
-
   59,  /*  RECURSIVE => ID */
-
   59,  /*    REPLACE => ID */
-
   59,  /*   RESTRICT => ID */
-
   59,  /*        ROW => ID */
-
   59,  /*       ROWS => ID */
-
   59,  /*    TRIGGER => ID */
-
   59,  /*     VACUUM => ID */
-
   59,  /*       VIEW => ID */
-
   59,  /*    VIRTUAL => ID */
-
   59,  /*       WITH => ID */
-
   59,  /*      NULLS => ID */
-
   59,  /*      FIRST => ID */
-
   59,  /*       LAST => ID */
-
   59,  /*    CURRENT => ID */
-
   59,  /*  FOLLOWING => ID */
-
   59,  /*  PARTITION => ID */
-
   59,  /*  PRECEDING => ID */
-
   59,  /*      RANGE => ID */
-
   59,  /*  UNBOUNDED => ID */
-
   59,  /*    EXCLUDE => ID */
-
   59,  /*     GROUPS => ID */
-
   59,  /*     OTHERS => ID */
-
   59,  /*       TIES => ID */
-
   59,  /*  GENERATED => ID */
-
   59,  /*     ALWAYS => ID */
-
   59,  /* MATERIALIZED => ID */
-
   59,  /*    REINDEX => ID */
-
   59,  /*     RENAME => ID */
-
   59,  /*   CTIME_KW => ID */
+
   60,  /*   COLUMNKW => ID */
+
   60,  /*         DO => ID */
+
   60,  /*        FOR => ID */
+
   60,  /*     IGNORE => ID */
+
   60,  /*  INITIALLY => ID */
+
   60,  /*    INSTEAD => ID */
+
   60,  /*         NO => ID */
+
   60,  /*        KEY => ID */
+
   60,  /*         OF => ID */
+
   60,  /*     OFFSET => ID */
+
   60,  /*     PRAGMA => ID */
+
   60,  /*      RAISE => ID */
+
   60,  /*  RECURSIVE => ID */
+
   60,  /*    REPLACE => ID */
+
   60,  /*   RESTRICT => ID */
+
   60,  /*        ROW => ID */
+
   60,  /*       ROWS => ID */
+
   60,  /*    TRIGGER => ID */
+
   60,  /*     VACUUM => ID */
+
   60,  /*       VIEW => ID */
+
   60,  /*    VIRTUAL => ID */
+
   60,  /*       WITH => ID */
+
   60,  /*      NULLS => ID */
+
   60,  /*      FIRST => ID */
+
   60,  /*       LAST => ID */
+
   60,  /*    CURRENT => ID */
+
   60,  /*  FOLLOWING => ID */
+
   60,  /*  PARTITION => ID */
+
   60,  /*  PRECEDING => ID */
+
   60,  /*      RANGE => ID */
+
   60,  /*  UNBOUNDED => ID */
+
   60,  /*    EXCLUDE => ID */
+
   60,  /*     GROUPS => ID */
+
   60,  /*     OTHERS => ID */
+
   60,  /*       TIES => ID */
+
   60,  /*  GENERATED => ID */
+
   60,  /*     ALWAYS => ID */
+
   60,  /* MATERIALIZED => ID */
+
   60,  /*    REINDEX => ID */
+
   60,  /*     RENAME => ID */
+
   60,  /*   CTIME_KW => ID */
    0,  /*        ANY => nothing */
    0,  /*     BITAND => nothing */
    0,  /*      BITOR => nothing */
@@ -173890,7 +175219,6 @@ static const YYCODETYPE yyFallback[] = {
    0,  /* AGG_FUNCTION => nothing */
    0,  /* AGG_COLUMN => nothing */
    0,  /*  TRUEFALSE => nothing */
-
    0,  /*      ISNOT => nothing */
    0,  /*   FUNCTION => nothing */
    0,  /*      UPLUS => nothing */
    0,  /*     UMINUS => nothing */
@@ -174034,132 +175362,132 @@ static const char *const yyTokenName[] = {
  /*   43 */ "OR",
  /*   44 */ "AND",
  /*   45 */ "IS",
-
  /*   46 */ "MATCH",
-
  /*   47 */ "LIKE_KW",
-
  /*   48 */ "BETWEEN",
-
  /*   49 */ "IN",
-
  /*   50 */ "ISNULL",
-
  /*   51 */ "NOTNULL",
-
  /*   52 */ "NE",
-
  /*   53 */ "EQ",
-
  /*   54 */ "GT",
-
  /*   55 */ "LE",
-
  /*   56 */ "LT",
-
  /*   57 */ "GE",
-
  /*   58 */ "ESCAPE",
-
  /*   59 */ "ID",
-
  /*   60 */ "COLUMNKW",
-
  /*   61 */ "DO",
-
  /*   62 */ "FOR",
-
  /*   63 */ "IGNORE",
-
  /*   64 */ "INITIALLY",
-
  /*   65 */ "INSTEAD",
-
  /*   66 */ "NO",
-
  /*   67 */ "KEY",
-
  /*   68 */ "OF",
-
  /*   69 */ "OFFSET",
-
  /*   70 */ "PRAGMA",
-
  /*   71 */ "RAISE",
-
  /*   72 */ "RECURSIVE",
-
  /*   73 */ "REPLACE",
-
  /*   74 */ "RESTRICT",
-
  /*   75 */ "ROW",
-
  /*   76 */ "ROWS",
-
  /*   77 */ "TRIGGER",
-
  /*   78 */ "VACUUM",
-
  /*   79 */ "VIEW",
-
  /*   80 */ "VIRTUAL",
-
  /*   81 */ "WITH",
-
  /*   82 */ "NULLS",
-
  /*   83 */ "FIRST",
-
  /*   84 */ "LAST",
-
  /*   85 */ "CURRENT",
-
  /*   86 */ "FOLLOWING",
-
  /*   87 */ "PARTITION",
-
  /*   88 */ "PRECEDING",
-
  /*   89 */ "RANGE",
-
  /*   90 */ "UNBOUNDED",
-
  /*   91 */ "EXCLUDE",
-
  /*   92 */ "GROUPS",
-
  /*   93 */ "OTHERS",
-
  /*   94 */ "TIES",
-
  /*   95 */ "GENERATED",
-
  /*   96 */ "ALWAYS",
-
  /*   97 */ "MATERIALIZED",
-
  /*   98 */ "REINDEX",
-
  /*   99 */ "RENAME",
-
  /*  100 */ "CTIME_KW",
-
  /*  101 */ "ANY",
-
  /*  102 */ "BITAND",
-
  /*  103 */ "BITOR",
-
  /*  104 */ "LSHIFT",
-
  /*  105 */ "RSHIFT",
-
  /*  106 */ "PLUS",
-
  /*  107 */ "MINUS",
-
  /*  108 */ "STAR",
-
  /*  109 */ "SLASH",
-
  /*  110 */ "REM",
-
  /*  111 */ "CONCAT",
-
  /*  112 */ "PTR",
-
  /*  113 */ "COLLATE",
-
  /*  114 */ "BITNOT",
-
  /*  115 */ "ON",
-
  /*  116 */ "INDEXED",
-
  /*  117 */ "STRING",
-
  /*  118 */ "JOIN_KW",
-
  /*  119 */ "CONSTRAINT",
-
  /*  120 */ "DEFAULT",
-
  /*  121 */ "NULL",
-
  /*  122 */ "PRIMARY",
-
  /*  123 */ "UNIQUE",
-
  /*  124 */ "CHECK",
-
  /*  125 */ "REFERENCES",
-
  /*  126 */ "AUTOINCR",
-
  /*  127 */ "INSERT",
-
  /*  128 */ "DELETE",
-
  /*  129 */ "UPDATE",
-
  /*  130 */ "SET",
-
  /*  131 */ "DEFERRABLE",
-
  /*  132 */ "FOREIGN",
-
  /*  133 */ "DROP",
-
  /*  134 */ "UNION",
-
  /*  135 */ "ALL",
-
  /*  136 */ "EXCEPT",
-
  /*  137 */ "INTERSECT",
-
  /*  138 */ "SELECT",
-
  /*  139 */ "VALUES",
-
  /*  140 */ "DISTINCT",
-
  /*  141 */ "DOT",
-
  /*  142 */ "FROM",
-
  /*  143 */ "JOIN",
-
  /*  144 */ "USING",
-
  /*  145 */ "ORDER",
-
  /*  146 */ "GROUP",
-
  /*  147 */ "HAVING",
-
  /*  148 */ "LIMIT",
-
  /*  149 */ "WHERE",
-
  /*  150 */ "RETURNING",
-
  /*  151 */ "INTO",
-
  /*  152 */ "NOTHING",
-
  /*  153 */ "FLOAT",
-
  /*  154 */ "BLOB",
-
  /*  155 */ "INTEGER",
-
  /*  156 */ "VARIABLE",
-
  /*  157 */ "CASE",
-
  /*  158 */ "WHEN",
-
  /*  159 */ "THEN",
-
  /*  160 */ "ELSE",
-
  /*  161 */ "INDEX",
-
  /*  162 */ "ALTER",
-
  /*  163 */ "ADD",
-
  /*  164 */ "WINDOW",
-
  /*  165 */ "OVER",
-
  /*  166 */ "FILTER",
-
  /*  167 */ "COLUMN",
-
  /*  168 */ "AGG_FUNCTION",
-
  /*  169 */ "AGG_COLUMN",
-
  /*  170 */ "TRUEFALSE",
-
  /*  171 */ "ISNOT",
+
  /*   46 */ "ISNOT",
+
  /*   47 */ "MATCH",
+
  /*   48 */ "LIKE_KW",
+
  /*   49 */ "BETWEEN",
+
  /*   50 */ "IN",
+
  /*   51 */ "ISNULL",
+
  /*   52 */ "NOTNULL",
+
  /*   53 */ "NE",
+
  /*   54 */ "EQ",
+
  /*   55 */ "GT",
+
  /*   56 */ "LE",
+
  /*   57 */ "LT",
+
  /*   58 */ "GE",
+
  /*   59 */ "ESCAPE",
+
  /*   60 */ "ID",
+
  /*   61 */ "COLUMNKW",
+
  /*   62 */ "DO",
+
  /*   63 */ "FOR",
+
  /*   64 */ "IGNORE",
+
  /*   65 */ "INITIALLY",
+
  /*   66 */ "INSTEAD",
+
  /*   67 */ "NO",
+
  /*   68 */ "KEY",
+
  /*   69 */ "OF",
+
  /*   70 */ "OFFSET",
+
  /*   71 */ "PRAGMA",
+
  /*   72 */ "RAISE",
+
  /*   73 */ "RECURSIVE",
+
  /*   74 */ "REPLACE",
+
  /*   75 */ "RESTRICT",
+
  /*   76 */ "ROW",
+
  /*   77 */ "ROWS",
+
  /*   78 */ "TRIGGER",
+
  /*   79 */ "VACUUM",
+
  /*   80 */ "VIEW",
+
  /*   81 */ "VIRTUAL",
+
  /*   82 */ "WITH",
+
  /*   83 */ "NULLS",
+
  /*   84 */ "FIRST",
+
  /*   85 */ "LAST",
+
  /*   86 */ "CURRENT",
+
  /*   87 */ "FOLLOWING",
+
  /*   88 */ "PARTITION",
+
  /*   89 */ "PRECEDING",
+
  /*   90 */ "RANGE",
+
  /*   91 */ "UNBOUNDED",
+
  /*   92 */ "EXCLUDE",
+
  /*   93 */ "GROUPS",
+
  /*   94 */ "OTHERS",
+
  /*   95 */ "TIES",
+
  /*   96 */ "GENERATED",
+
  /*   97 */ "ALWAYS",
+
  /*   98 */ "MATERIALIZED",
+
  /*   99 */ "REINDEX",
+
  /*  100 */ "RENAME",
+
  /*  101 */ "CTIME_KW",
+
  /*  102 */ "ANY",
+
  /*  103 */ "BITAND",
+
  /*  104 */ "BITOR",
+
  /*  105 */ "LSHIFT",
+
  /*  106 */ "RSHIFT",
+
  /*  107 */ "PLUS",
+
  /*  108 */ "MINUS",
+
  /*  109 */ "STAR",
+
  /*  110 */ "SLASH",
+
  /*  111 */ "REM",
+
  /*  112 */ "CONCAT",
+
  /*  113 */ "PTR",
+
  /*  114 */ "COLLATE",
+
  /*  115 */ "BITNOT",
+
  /*  116 */ "ON",
+
  /*  117 */ "INDEXED",
+
  /*  118 */ "STRING",
+
  /*  119 */ "JOIN_KW",
+
  /*  120 */ "CONSTRAINT",
+
  /*  121 */ "DEFAULT",
+
  /*  122 */ "NULL",
+
  /*  123 */ "PRIMARY",
+
  /*  124 */ "UNIQUE",
+
  /*  125 */ "CHECK",
+
  /*  126 */ "REFERENCES",
+
  /*  127 */ "AUTOINCR",
+
  /*  128 */ "INSERT",
+
  /*  129 */ "DELETE",
+
  /*  130 */ "UPDATE",
+
  /*  131 */ "SET",
+
  /*  132 */ "DEFERRABLE",
+
  /*  133 */ "FOREIGN",
+
  /*  134 */ "DROP",
+
  /*  135 */ "UNION",
+
  /*  136 */ "ALL",
+
  /*  137 */ "EXCEPT",
+
  /*  138 */ "INTERSECT",
+
  /*  139 */ "SELECT",
+
  /*  140 */ "VALUES",
+
  /*  141 */ "DISTINCT",
+
  /*  142 */ "DOT",
+
  /*  143 */ "FROM",
+
  /*  144 */ "JOIN",
+
  /*  145 */ "USING",
+
  /*  146 */ "ORDER",
+
  /*  147 */ "GROUP",
+
  /*  148 */ "HAVING",
+
  /*  149 */ "LIMIT",
+
  /*  150 */ "WHERE",
+
  /*  151 */ "RETURNING",
+
  /*  152 */ "INTO",
+
  /*  153 */ "NOTHING",
+
  /*  154 */ "FLOAT",
+
  /*  155 */ "BLOB",
+
  /*  156 */ "INTEGER",
+
  /*  157 */ "VARIABLE",
+
  /*  158 */ "CASE",
+
  /*  159 */ "WHEN",
+
  /*  160 */ "THEN",
+
  /*  161 */ "ELSE",
+
  /*  162 */ "INDEX",
+
  /*  163 */ "ALTER",
+
  /*  164 */ "ADD",
+
  /*  165 */ "WINDOW",
+
  /*  166 */ "OVER",
+
  /*  167 */ "FILTER",
+
  /*  168 */ "COLUMN",
+
  /*  169 */ "AGG_FUNCTION",
+
  /*  170 */ "AGG_COLUMN",
+
  /*  171 */ "TRUEFALSE",
  /*  172 */ "FUNCTION",
  /*  173 */ "UPLUS",
  /*  174 */ "UMINUS",
@@ -174597,7 +175925,7 @@ static const char *const yyRuleName[] = {
 /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
 /* 278 */ "trigger_cmd ::= scanpt select scanpt",
 /* 279 */ "expr ::= RAISE LP IGNORE RP",
-
 /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+
 /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP",
 /* 281 */ "raisetype ::= ROLLBACK",
 /* 282 */ "raisetype ::= ABORT",
 /* 283 */ "raisetype ::= FAIL",
@@ -175522,7 +176850,7 @@ static const YYCODETYPE yyRuleInfoLhs[] = {
   293,  /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
   293,  /* (278) trigger_cmd ::= scanpt select scanpt */
   218,  /* (279) expr ::= RAISE LP IGNORE RP */
-
   218,  /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
+
   218,  /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
   237,  /* (281) raisetype ::= ROLLBACK */
   237,  /* (282) raisetype ::= ABORT */
   237,  /* (283) raisetype ::= FAIL */
@@ -175936,7 +177264,7 @@ static const signed char yyRuleInfoNRhs[] = {
   -6,  /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
   -3,  /* (278) trigger_cmd ::= scanpt select scanpt */
   -4,  /* (279) expr ::= RAISE LP IGNORE RP */
-
   -6,  /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
+
   -6,  /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
   -1,  /* (281) raisetype ::= ROLLBACK */
   -1,  /* (282) raisetype ::= ABORT */
   -1,  /* (283) raisetype ::= FAIL */
@@ -176574,11 +177902,21 @@ static YYACTIONTYPE yy_reduce(
      if( yymsp[-5].minor.yy203 ){
        SrcItem *pNew = &yymsp[-5].minor.yy203->a[yymsp[-5].minor.yy203->nSrc-1];
        SrcItem *pOld = yymsp[-3].minor.yy203->a;
+
        assert( pOld->fg.fixedSchema==0 );
        pNew->zName = pOld->zName;
-
        pNew->zDatabase = pOld->zDatabase;
-
        pNew->pSelect = pOld->pSelect;
-
        if( pNew->pSelect && (pNew->pSelect->selFlags & SF_NestedFrom)!=0 ){
-
          pNew->fg.isNestedFrom = 1;
+
        assert( pOld->fg.fixedSchema==0 );
+
        if( pOld->fg.isSubquery ){
+
          pNew->fg.isSubquery = 1;
+
          pNew->u4.pSubq = pOld->u4.pSubq;
+
          pOld->u4.pSubq = 0;
+
          pOld->fg.isSubquery = 0;
+
          assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 );
+
          if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){
+
            pNew->fg.isNestedFrom = 1;
+
          }
+
        }else{
+
          pNew->u4.zDatabase = pOld->u4.zDatabase;
+
          pOld->u4.zDatabase = 0;
        }
        if( pOld->fg.isTabFunc ){
          pNew->u1.pFuncArg = pOld->u1.pFuncArg;
@@ -176586,8 +177924,7 @@ static YYACTIONTYPE yy_reduce(
          pOld->fg.isTabFunc = 0;
          pNew->fg.isTabFunc = 1;
        }
-
        pOld->zName = pOld->zDatabase = 0;
-
        pOld->pSelect = 0;
+
        pOld->zName = 0;
      }
      sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy203);
    }else{
@@ -177321,9 +178658,9 @@ static YYACTIONTYPE yy_reduce(
  }
}
        break;
-
      case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */
+
      case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */
{
-
  yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
+
  yymsp[-5].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy454, 0);
  if( yymsp[-5].minor.yy454 ) {
    yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144;
  }
@@ -179915,32 +181252,6 @@ SQLITE_API char *sqlite3_temp_directory = 0;
SQLITE_API char *sqlite3_data_directory = 0;

/*
-
** Determine whether or not high-precision (long double) floating point
-
** math works correctly on CPU currently running.
-
*/
-
static SQLITE_NOINLINE int hasHighPrecisionDouble(int rc){
-
  if( sizeof(LONGDOUBLE_TYPE)<=8 ){
-
    /* If the size of "long double" is not more than 8, then
-
    ** high-precision math is not possible. */
-
    return 0;
-
  }else{
-
    /* Just because sizeof(long double)>8 does not mean that the underlying
-
    ** hardware actually supports high-precision floating point.  For example,
-
    ** clearing the 0x100 bit in the floating-point control word on Intel
-
    ** processors will make long double work like double, even though long
-
    ** double takes up more space.  The only way to determine if long double
-
    ** actually works is to run an experiment. */
-
    LONGDOUBLE_TYPE a, b, c;
-
    rc++;
-
    a = 1.0+rc*0.1;
-
    b = 1.0e+18+rc*25.0;
-
    c = a+b;
-
    return b!=c;
-
  }
-
}
-

-

-
/*
** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
@@ -180134,13 +181445,6 @@ SQLITE_API int sqlite3_initialize(void){
    rc = SQLITE_EXTRA_INIT(0);
  }
#endif
-

-
  /* Experimentally determine if high-precision floating point is
-
  ** available. */
-
#ifndef SQLITE_OMIT_WSD
-
  sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc);
-
#endif
-

  return rc;
}

@@ -181681,7 +182985,8 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
  assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
  assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
  extraFlags = enc &  (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
-
                       SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE);
+
                       SQLITE_SUBTYPE|SQLITE_INNOCUOUS|
+
                       SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1);
  enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);

  /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE.  But
@@ -183236,6 +184541,7 @@ static int openDatabase(
  if( ((1<<(flags&7)) & 0x46)==0 ){
    rc = SQLITE_MISUSE_BKPT;  /* IMP: R-18321-05872 */
  }else{
+
    if( zFilename==0 ) zFilename = ":memory:";
    rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
  }
  if( rc!=SQLITE_OK ){
@@ -184148,6 +185454,18 @@ SQLITE_API int sqlite3_test_control(int op, ...){
      break;
    }

+
    /*  sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, sqlite3 *db, int *N)
+
    **
+
    ** Write the current optimization settings into *N.  A zero bit means that
+
    ** the optimization is on, and a 1 bit means that the optimization is off.
+
    */
+
    case SQLITE_TESTCTRL_GETOPT: {
+
      sqlite3 *db = va_arg(ap, sqlite3*);
+
      int *pN = va_arg(ap, int*);
+
      *pN = db->dbOptFlags;
+
      break;
+
    }
+

    /*   sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
    **
    ** If parameter onoff is 1, subsequent calls to localtime() fail.
@@ -184379,24 +185697,6 @@ SQLITE_API int sqlite3_test_control(int op, ...){
      break;
    }

-
#if !defined(SQLITE_OMIT_WSD)
-
    /* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X);
-
    **
-
    **   X<0     Make no changes to the bUseLongDouble.  Just report value.
-
    **   X==0    Disable bUseLongDouble
-
    **   X==1    Enable bUseLongDouble
-
    **   X>=2    Set bUseLongDouble to its default value for this platform
-
    */
-
    case SQLITE_TESTCTRL_USELONGDOUBLE: {
-
      int b = va_arg(ap, int);
-
      if( b>=2 ) b = hasHighPrecisionDouble(b);
-
      if( b>=0 ) sqlite3Config.bUseLongDouble = b>0;
-
      rc = sqlite3Config.bUseLongDouble!=0;
-
      break;
-
    }
-
#endif
-

-

#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
    /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
    **
@@ -184704,7 +186004,11 @@ SQLITE_API int sqlite3_snapshot_get(
    if( iDb==0 || iDb>1 ){
      Btree *pBt = db->aDb[iDb].pBt;
      if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
+
        Pager *pPager = sqlite3BtreePager(pBt);
+
        i64 dummy = 0;
+
        sqlite3PagerSnapshotOpen(pPager, (sqlite3_snapshot*)&dummy);
        rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
+
        sqlite3PagerSnapshotOpen(pPager, 0);
        if( rc==SQLITE_OK ){
          rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
        }
@@ -195475,11 +196779,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(

#ifdef SQLITE_TEST

-
#if defined(INCLUDE_SQLITE_TCL_H)
-
#  include "sqlite_tcl.h"
-
#else
-
#  include "tcl.h"
-
#endif
+
#include "tclsqlite.h"
/* #include <string.h> */

/*
@@ -202706,6 +204006,7 @@ static int fts3SnippetNextCandidate(SnippetIter *pIter){
      return 1;
    }

+
    assert( pIter->nSnippet>=0 );
    pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1;
    for(i=0; i<pIter->nPhrase; i++){
      SnippetPhrase *pPhrase = &pIter->aPhrase[i];
@@ -207699,7 +209000,9 @@ static u32 jsonLookupStep(
    zPath++;
    if( zPath[0]=='"' ){
      zKey = zPath + 1;
-
      for(i=1; zPath[i] && zPath[i]!='"'; i++){}
+
      for(i=1; zPath[i] && zPath[i]!='"'; i++){
+
        if( zPath[i]=='\\' && zPath[i+1]!=0 ) i++;
+
      }
      nKey = i-1;
      if( zPath[i] ){
        i++;
@@ -208709,10 +210012,16 @@ static void jsonExtractFunc(
      **     NUMBER   ==>  $[NUMBER]     // PG compatible
      **     LABEL    ==>  $.LABEL       // PG compatible
      **     [NUMBER] ==>  $[NUMBER]     // Not PG.  Purely for convenience
+
      **
+
      ** Updated 2024-05-27:  If the NUMBER is negative, then PG counts from
+
      ** the right of the array.  Hence for negative NUMBER:
+
      **
+
      **     NUMBER   ==>  $[#NUMBER]    // PG compatible
      */
      jsonStringInit(&jx, ctx);
      if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
        jsonAppendRawNZ(&jx, "[", 1);
+
        if( zPath[0]=='-' ) jsonAppendRawNZ(&jx,"#",1);
        jsonAppendRaw(&jx, zPath, nPath);
        jsonAppendRawNZ(&jx, "]", 2);
      }else if( jsonAllAlphanum(zPath, nPath) ){
@@ -218454,6 +219763,27 @@ struct RbuFrame {
  u32 iWalFrame;
};

+
#ifndef UNUSED_PARAMETER
+
/*
+
** The following macros are used to suppress compiler warnings and to
+
** make it clear to human readers when a function parameter is deliberately
+
** left unused within the body of a function. This usually happens when
+
** a function is called via a function pointer. For example the
+
** implementation of an SQL aggregate step callback may not use the
+
** parameter indicating the number of arguments passed to the aggregate,
+
** if it knows that this is enforced elsewhere.
+
**
+
** When a function parameter is not used at all within the body of a function,
+
** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
+
** However, these macros may also be used to suppress warnings related to
+
** parameters that may or may not be used depending on compilation options.
+
** For example those parameters only used in assert() statements. In these
+
** cases the parameters are named as per the usual conventions.
+
*/
+
#define UNUSED_PARAMETER(x) (void)(x)
+
#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
+
#endif
+

/*
** RBU handle.
**
@@ -218505,7 +219835,7 @@ struct sqlite3rbu {
  int rc;                         /* Value returned by last rbu_step() call */
  char *zErrmsg;                  /* Error message if rc!=SQLITE_OK */
  int nStep;                      /* Rows processed for current object */
-
  int nProgress;                  /* Rows processed for all objects */
+
  sqlite3_int64 nProgress;        /* Rows processed for all objects */
  RbuObjIter objiter;             /* Iterator for skipping through tbl/idx */
  const char *zVfsName;           /* Name of automatically created rbu vfs */
  rbu_file *pTargetFd;            /* File handle open on target db */
@@ -218622,7 +219952,7 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
     v = (v<<6) + c;
  }
  z--;
-
  *pLen -= z - zStart;
+
  *pLen -= (int)(z - zStart);
  *pz = (char*)z;
  return v;
}
@@ -218807,6 +220137,7 @@ static void rbuFossilDeltaFunc(
  char *aOut;

  assert( argc==2 );
+
  UNUSED_PARAMETER(argc);

  nOrig = sqlite3_value_bytes(argv[0]);
  aOrig = (const char*)sqlite3_value_blob(argv[0]);
@@ -220386,13 +221717,13 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
          else if( c==')' ){
            nParen--;
            if( nParen==0 ){
-
              int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
+
              int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
              pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
              i++;
              break;
            }
          }else if( c==',' && nParen==1 ){
-
            int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
+
            int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
            pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
            pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
          }else if( c=='"' || c=='\'' || c=='`' ){
@@ -221082,6 +222413,8 @@ static void rbuFileSuffix3(const char *zBase, char *z){
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4);
  }
+
#else
+
  UNUSED_PARAMETER2(zBase,z);
#endif
}

@@ -221666,7 +222999,7 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){
          "(%d, %Q), "
          "(%d, %Q), "
          "(%d, %d), "
-
          "(%d, %d), "
+
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %lld), "
@@ -222024,6 +223357,7 @@ static void rbuIndexCntFunc(
  sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);

  assert( nVal==1 );
+
  UNUSED_PARAMETER(nVal);

  rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
      sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
@@ -222299,7 +223633,7 @@ SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
){
  if( zTarget==0 ){ return rbuMisuseError(); }
  if( zState ){
-
    int n = strlen(zState);
+
    size_t n = strlen(zState);
    if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
      return rbuMisuseError();
    }
@@ -222516,6 +223850,7 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){
*/
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
  int rc = SQLITE_OK;
+
  UNUSED_PARAMETER(pArg);
#if defined(_WIN32_WCE)
  {
    LPWSTR zWideOld;
@@ -223420,6 +224755,9 @@ static int rbuVfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
** No-op.
*/
static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
+
  UNUSED_PARAMETER(pVfs);
+
  UNUSED_PARAMETER(a);
+
  UNUSED_PARAMETER(b);
  return 0;
}

@@ -223818,6 +225156,7 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
    pIdxInfo->orderByConsumed = 1;
    pIdxInfo->idxNum |= 0x08;
  }
+
  pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_HEX;

  return SQLITE_OK;
}
@@ -224475,7 +225814,13 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; }
**
** The data field of sqlite_dbpage table can be updated.  The new
** value must be a BLOB which is the correct page size, otherwise the
-
** update fails.  Rows may not be deleted or inserted.
+
** update fails.  INSERT operations also work, and operate as if they
+
** where REPLACE.  The size of the database can be extended by INSERT-ing
+
** new pages on the end.
+
**
+
** Rows may not be deleted.  However, doing an INSERT to page number N
+
** with NULL page data causes the N-th page and all subsequent pages to be
+
** deleted and the database to be truncated.
*/

/* #include "sqliteInt.h"   ** Requires access to internal data structures ** */
@@ -224498,6 +225843,8 @@ struct DbpageCursor {
struct DbpageTable {
  sqlite3_vtab base;              /* Base class.  Must be first */
  sqlite3 *db;                    /* The database */
+
  int iDbTrunc;                   /* Database to truncate */
+
  Pgno pgnoTrunc;                 /* Size to truncate to */
};

/* Columns */
@@ -224506,7 +225853,6 @@ struct DbpageTable {
#define DBPAGE_COLUMN_SCHEMA  2


-

/*
** Connect to or create a dbpagevfs virtual table.
*/
@@ -224768,11 +226114,11 @@ static int dbpageUpdate(
  DbPage *pDbPage = 0;
  int rc = SQLITE_OK;
  char *zErr = 0;
-
  const char *zSchema;
  int iDb;
  Btree *pBt;
  Pager *pPager;
  int szPage;
+
  int isInsert;

  (void)pRowid;
  if( pTab->db->flags & SQLITE_Defensive ){
@@ -224783,21 +226129,29 @@ static int dbpageUpdate(
    zErr = "cannot delete";
    goto update_fail;
  }
-
  pgno = sqlite3_value_int(argv[0]);
-
  if( sqlite3_value_type(argv[0])==SQLITE_NULL
-
   || (Pgno)sqlite3_value_int(argv[1])!=pgno
-
  ){
-
    zErr = "cannot insert";
-
    goto update_fail;
+
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
+
    pgno = (Pgno)sqlite3_value_int(argv[2]);
+
    isInsert = 1;
+
  }else{
+
    pgno = sqlite3_value_int(argv[0]);
+
    if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
+
      zErr = "cannot insert";
+
      goto update_fail;
+
    }
+
    isInsert = 0;
  }
-
  zSchema = (const char*)sqlite3_value_text(argv[4]);
-
  iDb = ALWAYS(zSchema) ? sqlite3FindDbName(pTab->db, zSchema) : -1;
-
  if( NEVER(iDb<0) ){
-
    zErr = "no such schema";
-
    goto update_fail;
+
  if( sqlite3_value_type(argv[4])==SQLITE_NULL ){
+
    iDb = 0;
+
  }else{
+
    const char *zSchema = (const char*)sqlite3_value_text(argv[4]);
+
    iDb = sqlite3FindDbName(pTab->db, zSchema);
+
    if( iDb<0 ){
+
      zErr = "no such schema";
+
      goto update_fail;
+
    }
  }
  pBt = pTab->db->aDb[iDb].pBt;
-
  if( NEVER(pgno<1) || NEVER(pBt==0) || NEVER(pgno>sqlite3BtreeLastPage(pBt)) ){
+
  if( pgno<1 || NEVER(pBt==0) ){
    zErr = "bad page number";
    goto update_fail;
  }
@@ -224805,18 +226159,25 @@ static int dbpageUpdate(
  if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
   || sqlite3_value_bytes(argv[3])!=szPage
  ){
-
    zErr = "bad page value";
-
    goto update_fail;
+
    if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert && pgno>1 ){
+
      /* "INSERT INTO dbpage($PGNO,NULL)" causes page number $PGNO and
+
      ** all subsequent pages to be deleted. */
+
      pTab->iDbTrunc = iDb;
+
      pgno--;
+
      pTab->pgnoTrunc = pgno;
+
    }else{
+
      zErr = "bad page value";
+
      goto update_fail;
+
    }
  }
  pPager = sqlite3BtreePager(pBt);
  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
  if( rc==SQLITE_OK ){
    const void *pData = sqlite3_value_blob(argv[3]);
-
    assert( pData!=0 || pTab->db->mallocFailed );
-
    if( pData
-
     && (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
-
    ){
-
      memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);
+
    if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
+
      unsigned char *aPage = sqlite3PagerGetData(pDbPage);
+
      memcpy(aPage, pData, szPage);
+
      pTab->pgnoTrunc = 0;
    }
  }
  sqlite3PagerUnref(pDbPage);
@@ -224840,9 +226201,31 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
    Btree *pBt = db->aDb[i].pBt;
    if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
  }
+
  pTab->pgnoTrunc = 0;
  return SQLITE_OK;
}

+
/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
+
*/
+
static int dbpageSync(sqlite3_vtab *pVtab){
+
  DbpageTable *pTab = (DbpageTable *)pVtab;
+
  if( pTab->pgnoTrunc>0 ){
+
    Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt;
+
    Pager *pPager = sqlite3BtreePager(pBt);
+
    sqlite3PagerTruncateImage(pPager, pTab->pgnoTrunc);
+
  }
+
  pTab->pgnoTrunc = 0;
+
  return SQLITE_OK;
+
}
+

+
/* Cancel any pending truncate.
+
*/
+
static int dbpageRollbackTo(sqlite3_vtab *pVtab, int notUsed1){
+
  DbpageTable *pTab = (DbpageTable *)pVtab;
+
  pTab->pgnoTrunc = 0;
+
  (void)notUsed1;
+
  return SQLITE_OK;
+
}

/*
** Invoke this routine to register the "dbpage" virtual table module
@@ -224864,14 +226247,14 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){
    dbpageRowid,                  /* xRowid - read data */
    dbpageUpdate,                 /* xUpdate */
    dbpageBegin,                  /* xBegin */
-
    0,                            /* xSync */
+
    dbpageSync,                   /* xSync */
    0,                            /* xCommit */
    0,                            /* xRollback */
    0,                            /* xFindMethod */
    0,                            /* xRename */
    0,                            /* xSavepoint */
    0,                            /* xRelease */
-
    0,                            /* xRollbackTo */
+
    dbpageRollbackTo,             /* xRollbackTo */
    0,                            /* xShadowName */
    0                             /* xIntegrity */
  };
@@ -224959,6 +226342,10 @@ struct SessionBuffer {
** input data. Input data may be supplied either as a single large buffer
** (e.g. sqlite3changeset_start()) or using a stream function (e.g.
**  sqlite3changeset_start_strm()).
+
**
+
** bNoDiscard:
+
**   If true, then the only time data is discarded is as a result of explicit
+
**   sessionDiscardData() calls. Not within every sessionInputBuffer() call.
*/
struct SessionInput {
  int bNoDiscard;                 /* If true, do not discard in InputBuffer() */
@@ -226642,16 +228029,19 @@ static void sessionPreupdateOneChange(
      for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
        sqlite3_value *p = 0;
        if( op!=SQLITE_INSERT ){
-
          TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p);
-
          assert( trc==SQLITE_OK );
+
          /* This may fail if the column has a non-NULL default and was added
+
          ** using ALTER TABLE ADD COLUMN after this record was created. */
+
          rc = pSession->hook.xOld(pSession->hook.pCtx, i, &p);
        }else if( pTab->abPK[i] ){
          TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p);
          assert( trc==SQLITE_OK );
        }

-
        /* This may fail if SQLite value p contains a utf-16 string that must
-
        ** be converted to utf-8 and an OOM error occurs while doing so. */
-
        rc = sessionSerializeValue(0, p, &nByte);
+
        if( rc==SQLITE_OK ){
+
          /* This may fail if SQLite value p contains a utf-16 string that must
+
          ** be converted to utf-8 and an OOM error occurs while doing so. */
+
          rc = sessionSerializeValue(0, p, &nByte);
+
        }
        if( rc!=SQLITE_OK ) goto error_out;
      }
      if( pTab->bRowid ){
@@ -230009,15 +231399,21 @@ static int sessionChangesetApply(
  int nTab = 0;                   /* Result of sqlite3Strlen30(zTab) */
  SessionApplyCtx sApply;         /* changeset_apply() context object */
  int bPatchset;
+
  u64 savedFlag = db->flags & SQLITE_FkNoAction;

  assert( xConflict!=0 );

+
  sqlite3_mutex_enter(sqlite3_db_mutex(db));
+
  if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){
+
    db->flags |= ((u64)SQLITE_FkNoAction);
+
    db->aDb[0].pSchema->schema_cookie -= 32;
+
  }
+

  pIter->in.bNoDiscard = 1;
  memset(&sApply, 0, sizeof(sApply));
  sApply.bRebase = (ppRebase && pnRebase);
  sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
  sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
-
  sqlite3_mutex_enter(sqlite3_db_mutex(db));
  if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
    rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
  }
@@ -230179,6 +231575,12 @@ static int sessionChangesetApply(
  sqlite3_free((char*)sApply.azCol);  /* cast works around VC++ bug */
  sqlite3_free((char*)sApply.constraints.aBuf);
  sqlite3_free((char*)sApply.rebase.aBuf);
+

+
  if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
+
    assert( db->flags & SQLITE_FkNoAction );
+
    db->flags &= ~((u64)SQLITE_FkNoAction);
+
    db->aDb[0].pSchema->schema_cookie -= 32;
+
  }
  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  return rc;
}
@@ -230207,12 +231609,6 @@ SQLITE_API int sqlite3changeset_apply_v2(
  sqlite3_changeset_iter *pIter;  /* Iterator to skip through changeset */
  int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
  int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
-
  u64 savedFlag = db->flags & SQLITE_FkNoAction;
-

-
  if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){
-
    db->flags |= ((u64)SQLITE_FkNoAction);
-
    db->aDb[0].pSchema->schema_cookie -= 32;
-
  }

  if( rc==SQLITE_OK ){
    rc = sessionChangesetApply(
@@ -230220,11 +231616,6 @@ SQLITE_API int sqlite3changeset_apply_v2(
    );
  }

-
  if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
-
    assert( db->flags & SQLITE_FkNoAction );
-
    db->flags &= ~((u64)SQLITE_FkNoAction);
-
    db->aDb[0].pSchema->schema_cookie -= 32;
-
  }
  return rc;
}

@@ -230545,6 +231936,9 @@ static int sessionChangesetExtendRecord(
    sessionAppendBlob(pOut, aRec, nRec, &rc);
    if( rc==SQLITE_OK && pTab->pDfltStmt==0 ){
      rc = sessionPrepareDfltStmt(pGrp->db, pTab, &pTab->pDfltStmt);
+
      if( rc==SQLITE_OK && SQLITE_ROW!=sqlite3_step(pTab->pDfltStmt) ){
+
        rc = sqlite3_errcode(pGrp->db);
+
      }
    }
    for(ii=nCol; rc==SQLITE_OK && ii<pTab->nCol; ii++){
      int eType = sqlite3_column_type(pTab->pDfltStmt, ii);
@@ -230561,6 +231955,7 @@ static int sessionChangesetExtendRecord(
          }
          if( SQLITE_OK==sessionBufferGrow(pOut, 8, &rc) ){
            sessionPutI64(&pOut->aBuf[pOut->nBuf], iVal);
+
            pOut->nBuf += 8;
          }
          break;
        }
@@ -230700,6 +232095,8 @@ static int sessionOneChangeToHash(
  u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
  int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;

+
  assert( nRec>0 );
+

  /* Ensure that only changesets, or only patchsets, but not a mixture
  ** of both, are being combined. It is an error to try to combine a
  ** changeset and a patchset.  */
@@ -230777,6 +232174,7 @@ static int sessionChangesetToHash(
  int nRec;
  int rc = SQLITE_OK;

+
  pIter->in.bNoDiscard = 1;
  while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
    rc = sessionOneChangeToHash(pGrp, pIter, bRebase);
    if( rc!=SQLITE_OK ) break;
@@ -231658,6 +233056,10 @@ struct Fts5PhraseIter {
**   (i.e. if it is a contentless table), then this API always iterates
**   through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
+
**   In all cases, matches are visited in (column ASC, offset ASC) order.
+
**   i.e. all those in column 0, sorted by offset, followed by those in
+
**   column 1, etc.
+
**
** xPhraseNext()
**   See xPhraseFirst above.
**
@@ -231724,9 +233126,32 @@ struct Fts5PhraseIter {
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option.
+
**
+
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+
**   If parameter iCol is less than zero, or greater than or equal to the
+
**   number of columns in the table, SQLITE_RANGE is returned.
+
**
+
**   Otherwise, this function attempts to retrieve the locale associated
+
**   with column iCol of the current row. Usually, there is no associated
+
**   locale, and output parameters (*pzLocale) and (*pnLocale) are set
+
**   to NULL and 0, respectively. However, if the fts5_locale() function
+
**   was used to associate a locale with the value when it was inserted
+
**   into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+
**   buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+
**   is set to the size in bytes of the buffer, not including the
+
**   nul-terminator.
+
**
+
**   If successful, SQLITE_OK is returned. Or, if an error occurs, an
+
**   SQLite error code is returned. The final value of the output parameters
+
**   is undefined in this case.
+
**
+
** xTokenize_v2:
+
**   Tokenize text using the tokenizer belonging to the FTS5 table. This
+
**   API is the same as the xTokenize() API, except that it allows a tokenizer
+
**   locale to be specified.
*/
struct Fts5ExtensionApi {
-
  int iVersion;                   /* Currently always set to 3 */
+
  int iVersion;                   /* Currently always set to 4 */

  void *(*xUserData)(Fts5Context*);

@@ -231768,6 +233193,15 @@ struct Fts5ExtensionApi {
      const char **ppToken, int *pnToken
  );
  int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+

+
  /* Below this point are iVersion>=4 only */
+
  int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+
  int (*xTokenize_v2)(Fts5Context*,
+
    const char *pText, int nText,      /* Text to tokenize */
+
    const char *pLocale, int nLocale,  /* Locale to pass to tokenizer */
+
    void *pCtx,                        /* Context passed to xToken() */
+
    int (*xToken)(void*, int, const char*, int, int, int)       /* Callback */
+
  );
};

/*
@@ -231788,7 +233222,7 @@ struct Fts5ExtensionApi {
**   A tokenizer instance is required to actually tokenize text.
**
**   The first argument passed to this function is a copy of the (void*)
-
**   pointer provided by the application when the fts5_tokenizer object
+
**   pointer provided by the application when the fts5_tokenizer_v2 object
**   was registered with FTS5 (the third argument to xCreateTokenizer()).
**   The second and third arguments are an array of nul-terminated strings
**   containing the tokenizer arguments, if any, specified following the
@@ -231812,7 +233246,7 @@ struct Fts5ExtensionApi {
**   argument passed to this function is a pointer to an Fts5Tokenizer object
**   returned by an earlier call to xCreate().
**
-
**   The second argument indicates the reason that FTS5 is requesting
+
**   The third argument indicates the reason that FTS5 is requesting
**   tokenization of the supplied text. This is always one of the following
**   four values:
**
@@ -231836,6 +233270,13 @@ struct Fts5ExtensionApi {
**            on a columnsize=0 database.
**   </ul>
**
+
**   The sixth and seventh arguments passed to xTokenize() - pLocale and
+
**   nLocale - are a pointer to a buffer containing the locale to use for
+
**   tokenization (e.g. "en_US") and its size in bytes, respectively. The
+
**   pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+
**   which case nLocale is always 0) to indicate that the tokenizer should
+
**   use its default locale.
+
**
**   For each token in the input string, the supplied callback xToken() must
**   be invoked. The first argument to it should be a copy of the pointer
**   passed as the second argument to xTokenize(). The third and fourth
@@ -231859,6 +233300,30 @@ struct Fts5ExtensionApi {
**   may abandon the tokenization and return any error code other than
**   SQLITE_OK or SQLITE_DONE.
**
+
**   If the tokenizer is registered using an fts5_tokenizer_v2 object,
+
**   then the xTokenize() method has two additional arguments - pLocale
+
**   and nLocale. These specify the locale that the tokenizer should use
+
**   for the current request. If pLocale and nLocale are both 0, then the
+
**   tokenizer should use its default locale. Otherwise, pLocale points to
+
**   an nLocale byte buffer containing the name of the locale to use as utf-8
+
**   text. pLocale is not nul-terminated.
+
**
+
** FTS5_TOKENIZER
+
**
+
** There is also an fts5_tokenizer object. This is an older, deprecated,
+
** version of fts5_tokenizer_v2. It is similar except that:
+
**
+
**  <ul>
+
**    <li> There is no "iVersion" field, and
+
**    <li> The xTokenize() method does not take a locale argument.
+
**  </ul>
+
**
+
** Legacy fts5_tokenizer tokenizers must be registered using the
+
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+
**
+
** Tokenizer implementations registered using either API may be retrieved
+
** using both xFindTokenizer() and xFindTokenizer_v2().
+
**
** SYNONYM SUPPORT
**
**   Custom tokenizers may also support synonyms. Consider a case in which a
@@ -231967,6 +233432,33 @@ struct Fts5ExtensionApi {
**   inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
+
typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+
struct fts5_tokenizer_v2 {
+
  int iVersion;             /* Currently always 2 */
+

+
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+
  void (*xDelete)(Fts5Tokenizer*);
+
  int (*xTokenize)(Fts5Tokenizer*,
+
      void *pCtx,
+
      int flags,            /* Mask of FTS5_TOKENIZE_* flags */
+
      const char *pText, int nText,
+
      const char *pLocale, int nLocale,
+
      int (*xToken)(
+
        void *pCtx,         /* Copy of 2nd argument to xTokenize() */
+
        int tflags,         /* Mask of FTS5_TOKEN_* flags */
+
        const char *pToken, /* Pointer to buffer containing token */
+
        int nToken,         /* Size of token in bytes */
+
        int iStart,         /* Byte offset of token within input text */
+
        int iEnd            /* Byte offset of end of token within input text */
+
      )
+
  );
+
};
+

+
/*
+
** New code should use the fts5_tokenizer_v2 type to define tokenizer
+
** implementations. The following type is included for legacy applications
+
** that still use it.
+
*/
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
@@ -231986,6 +233478,7 @@ struct fts5_tokenizer {
  );
};

+

/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY     0x0001
#define FTS5_TOKENIZE_PREFIX    0x0002
@@ -232005,7 +233498,7 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
-
  int iVersion;                   /* Currently always set to 2 */
+
  int iVersion;                   /* Currently always set to 3 */

  /* Create a new tokenizer */
  int (*xCreateTokenizer)(
@@ -232032,6 +233525,25 @@ struct fts5_api {
    fts5_extension_function xFunction,
    void (*xDestroy)(void*)
  );
+

+
  /* APIs below this point are only available if iVersion>=3 */
+

+
  /* Create a new tokenizer */
+
  int (*xCreateTokenizer_v2)(
+
    fts5_api *pApi,
+
    const char *zName,
+
    void *pUserData,
+
    fts5_tokenizer_v2 *pTokenizer,
+
    void (*xDestroy)(void*)
+
  );
+

+
  /* Find an existing tokenizer */
+
  int (*xFindTokenizer_v2)(
+
    fts5_api *pApi,
+
    const char *zName,
+
    void **ppUserData,
+
    fts5_tokenizer_v2 **ppTokenizer
+
  );
};

/*
@@ -232105,6 +233617,22 @@ typedef sqlite3_uint64 u64;
# define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)

+
/* The uptr type is an unsigned integer large enough to hold a pointer
+
*/
+
#if defined(HAVE_STDINT_H)
+
  typedef uintptr_t uptr;
+
#elif SQLITE_PTRSIZE==4
+
  typedef u32 uptr;
+
#else
+
  typedef u64 uptr;
+
#endif
+

+
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+
# define EIGHT_BYTE_ALIGNMENT(X)   ((((uptr)(X) - (uptr)0)&3)==0)
+
#else
+
# define EIGHT_BYTE_ALIGNMENT(X)   ((((uptr)(X) - (uptr)0)&7)==0)
+
#endif
+

#endif

/* Truncate very long tokens to this many bytes. Hard limit is
@@ -232188,6 +233716,18 @@ struct Fts5Colset {
*/

typedef struct Fts5Config Fts5Config;
+
typedef struct Fts5TokenizerConfig Fts5TokenizerConfig;
+

+
struct Fts5TokenizerConfig {
+
  Fts5Tokenizer *pTok;
+
  fts5_tokenizer_v2 *pApi2;
+
  fts5_tokenizer *pApi1;
+
  const char **azArg;
+
  int nArg;
+
  int ePattern;                   /* FTS_PATTERN_XXX constant */
+
  const char *pLocale;            /* Current locale to use */
+
  int nLocale;                    /* Size of pLocale in bytes */
+
};

/*
** An instance of the following structure encodes all information that can
@@ -232227,9 +233767,12 @@ typedef struct Fts5Config Fts5Config;
**
**       INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
**
+
** bLocale:
+
**   Set to true if locale=1 was specified when the table was created.
*/
struct Fts5Config {
  sqlite3 *db;                    /* Database handle */
+
  Fts5Global *pGlobal;            /* Global fts5 object for handle db */
  char *zDb;                      /* Database holding FTS index (e.g. "main") */
  char *zName;                    /* Name of FTS index */
  int nCol;                       /* Number of columns */
@@ -232239,16 +233782,17 @@ struct Fts5Config {
  int *aPrefix;                   /* Sizes in bytes of nPrefix prefix indexes */
  int eContent;                   /* An FTS5_CONTENT value */
  int bContentlessDelete;         /* "contentless_delete=" option (dflt==0) */
+
  int bContentlessUnindexed;      /* "contentless_unindexed=" option (dflt=0) */
  char *zContent;                 /* content table */
  char *zContentRowid;            /* "content_rowid=" option value */
  int bColumnsize;                /* "columnsize=" option value (dflt==1) */
  int bTokendata;                 /* "tokendata=" option value (dflt==0) */
+
  int bLocale;                    /* "locale=" option value (dflt==0) */
  int eDetail;                    /* FTS5_DETAIL_XXX value */
  char *zContentExprlist;
-
  Fts5Tokenizer *pTok;
-
  fts5_tokenizer *pTokApi;
+
  Fts5TokenizerConfig t;
  int bLock;                      /* True when table is preparing statement */
-
  int ePattern;                   /* FTS_PATTERN_XXX constant */
+


  /* Values loaded from the %_config table */
  int iVersion;                   /* fts5 file format 'version' */
@@ -232277,9 +233821,10 @@ struct Fts5Config {
#define FTS5_CURRENT_VERSION               4
#define FTS5_CURRENT_VERSION_SECUREDELETE  5

-
#define FTS5_CONTENT_NORMAL   0
-
#define FTS5_CONTENT_NONE     1
-
#define FTS5_CONTENT_EXTERNAL 2
+
#define FTS5_CONTENT_NORMAL    0
+
#define FTS5_CONTENT_NONE      1
+
#define FTS5_CONTENT_EXTERNAL  2
+
#define FTS5_CONTENT_UNINDEXED 3

#define FTS5_DETAIL_FULL      0
#define FTS5_DETAIL_NONE      1
@@ -232314,6 +233859,8 @@ static int sqlite3Fts5ConfigSetValue(Fts5Config*, const char*, sqlite3_value*, i

static int sqlite3Fts5ConfigParseRank(const char*, char**, char**);

+
static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...);
+

/*
** End of interface to code in fts5_config.c.
**************************************************************************/
@@ -232358,7 +233905,7 @@ static char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
static void sqlite3Fts5Put32(u8*, int);
static int sqlite3Fts5Get32(const u8*);

-
#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
+
#define FTS5_POS2COLUMN(iPos) (int)((iPos >> 32) & 0x7FFFFFFF)
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)

typedef struct Fts5PoslistReader Fts5PoslistReader;
@@ -232643,18 +234190,20 @@ struct Fts5Table {
  Fts5Index *pIndex;              /* Full-text index */
};

-
static int sqlite3Fts5GetTokenizer(
-
  Fts5Global*,
-
  const char **azArg,
-
  int nArg,
-
  Fts5Config*,
-
  char **pzErr
-
);
+
static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);

static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);

static int sqlite3Fts5FlushToDisk(Fts5Table*);

+
static void sqlite3Fts5ClearLocale(Fts5Config *pConfig);
+
static void sqlite3Fts5SetLocale(Fts5Config *pConfig, const char *pLoc, int nLoc);
+

+
static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal);
+
static int sqlite3Fts5DecodeLocaleValue(sqlite3_value *pVal,
+
    const char **ppText, int *pnText, const char **ppLoc, int *pnLoc
+
);
+

/*
** End of interface to code in fts5.c.
**************************************************************************/
@@ -232734,8 +234283,8 @@ static int sqlite3Fts5StorageRename(Fts5Storage*, const char *zName);
static int sqlite3Fts5DropAll(Fts5Config*);
static int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);

-
static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
-
static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
+
static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**, int);
+
static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, int, sqlite3_value**, i64*);
static int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);

static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg);
@@ -232760,6 +234309,9 @@ static int sqlite3Fts5StorageOptimize(Fts5Storage *p);
static int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge);
static int sqlite3Fts5StorageReset(Fts5Storage *p);

+
static void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage*);
+
static int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel);
+

/*
** End of interface to code in fts5_storage.c.
**************************************************************************/
@@ -232912,6 +234464,7 @@ static int sqlite3Fts5TokenizerPattern(
    int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
    Fts5Tokenizer *pTok
);
+
static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*);
/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/
@@ -234689,6 +236242,7 @@ static int fts5HighlightCb(
  return rc;
}

+

/*
** Implementation of highlight() function.
*/
@@ -234719,12 +236273,19 @@ static void fts5HighlightFunction(
    sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
    rc = SQLITE_OK;
  }else if( ctx.zIn ){
+
    const char *pLoc = 0;         /* Locale of column iCol */
+
    int nLoc = 0;                 /* Size of pLoc in bytes */
    if( rc==SQLITE_OK ){
      rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
    }

    if( rc==SQLITE_OK ){
-
      rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
+
      rc = pApi->xColumnLocale(pFts, iCol, &pLoc, &nLoc);
+
    }
+
    if( rc==SQLITE_OK ){
+
      rc = pApi->xTokenize_v2(
+
          pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx, fts5HighlightCb
+
      );
    }
    if( ctx.bOpen ){
      fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
@@ -234921,6 +236482,8 @@ static void fts5SnippetFunction(
  memset(&sFinder, 0, sizeof(Fts5SFinder));
  for(i=0; i<nCol; i++){
    if( iCol<0 || iCol==i ){
+
      const char *pLoc = 0;       /* Locale of column iCol */
+
      int nLoc = 0;               /* Size of pLoc in bytes */
      int nDoc;
      int nDocsize;
      int ii;
@@ -234928,8 +236491,10 @@ static void fts5SnippetFunction(
      sFinder.nFirst = 0;
      rc = pApi->xColumnText(pFts, i, &sFinder.zDoc, &nDoc);
      if( rc!=SQLITE_OK ) break;
-
      rc = pApi->xTokenize(pFts,
-
          sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb
+
      rc = pApi->xColumnLocale(pFts, i, &pLoc, &nLoc);
+
      if( rc!=SQLITE_OK ) break;
+
      rc = pApi->xTokenize_v2(pFts,
+
          sFinder.zDoc, nDoc, pLoc, nLoc, (void*)&sFinder, fts5SentenceFinderCb
      );
      if( rc!=SQLITE_OK ) break;
      rc = pApi->xColumnSize(pFts, i, &nDocsize);
@@ -234987,6 +236552,9 @@ static void fts5SnippetFunction(
    rc = pApi->xColumnSize(pFts, iBestCol, &nColSize);
  }
  if( ctx.zIn ){
+
    const char *pLoc = 0;         /* Locale of column iBestCol */
+
    int nLoc = 0;                 /* Bytes in pLoc */
+

    if( rc==SQLITE_OK ){
      rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
    }
@@ -235005,7 +236573,12 @@ static void fts5SnippetFunction(
    }

    if( rc==SQLITE_OK ){
-
      rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
+
      rc = pApi->xColumnLocale(pFts, iBestCol, &pLoc, &nLoc);
+
    }
+
    if( rc==SQLITE_OK ){
+
      rc = pApi->xTokenize_v2(
+
          pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx,fts5HighlightCb
+
      );
    }
    if( ctx.bOpen ){
      fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
@@ -235189,6 +236762,53 @@ static void fts5Bm25Function(
  }
}

+
/*
+
** Implementation of fts5_get_locale() function.
+
*/
+
static void fts5GetLocaleFunction(
+
  const Fts5ExtensionApi *pApi,   /* API offered by current FTS version */
+
  Fts5Context *pFts,              /* First arg to pass to pApi functions */
+
  sqlite3_context *pCtx,          /* Context for returning result/error */
+
  int nVal,                       /* Number of values in apVal[] array */
+
  sqlite3_value **apVal           /* Array of trailing arguments */
+
){
+
  int iCol = 0;
+
  int eType = 0;
+
  int rc = SQLITE_OK;
+
  const char *zLocale = 0;
+
  int nLocale = 0;
+

+
  /* xColumnLocale() must be available */
+
  assert( pApi->iVersion>=4 );
+

+
  if( nVal!=1 ){
+
    const char *z = "wrong number of arguments to function fts5_get_locale()";
+
    sqlite3_result_error(pCtx, z, -1);
+
    return;
+
  }
+

+
  eType = sqlite3_value_numeric_type(apVal[0]);
+
  if( eType!=SQLITE_INTEGER ){
+
    const char *z = "non-integer argument passed to function fts5_get_locale()";
+
    sqlite3_result_error(pCtx, z, -1);
+
    return;
+
  }
+

+
  iCol = sqlite3_value_int(apVal[0]);
+
  if( iCol<0 || iCol>=pApi->xColumnCount(pFts) ){
+
    sqlite3_result_error_code(pCtx, SQLITE_RANGE);
+
    return;
+
  }
+

+
  rc = pApi->xColumnLocale(pFts, iCol, &zLocale, &nLocale);
+
  if( rc!=SQLITE_OK ){
+
    sqlite3_result_error_code(pCtx, rc);
+
    return;
+
  }
+

+
  sqlite3_result_text(pCtx, zLocale, nLocale, SQLITE_TRANSIENT);
+
}
+

static int sqlite3Fts5AuxInit(fts5_api *pApi){
  struct Builtin {
    const char *zFunc;            /* Function name (nul-terminated) */
@@ -235196,9 +236816,10 @@ static int sqlite3Fts5AuxInit(fts5_api *pApi){
    fts5_extension_function xFunc;/* Callback function */
    void (*xDestroy)(void*);      /* Destructor function */
  } aBuiltin [] = {
-
    { "snippet",   0, fts5SnippetFunction, 0 },
-
    { "highlight", 0, fts5HighlightFunction, 0 },
-
    { "bm25",      0, fts5Bm25Function,    0 },
+
    { "snippet",         0, fts5SnippetFunction,   0 },
+
    { "highlight",       0, fts5HighlightFunction, 0 },
+
    { "bm25",            0, fts5Bm25Function,      0 },
+
    { "fts5_get_locale", 0, fts5GetLocaleFunction, 0 },
  };
  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* To iterate through builtin functions */
@@ -235863,7 +237484,6 @@ static int fts5ConfigSetEnum(
** eventually free any such error message using sqlite3_free().
*/
static int fts5ConfigParseSpecial(
-
  Fts5Global *pGlobal,
  Fts5Config *pConfig,            /* Configuration object to update */
  const char *zCmd,               /* Special command to parse */
  const char *zArg,               /* Argument to parse */
@@ -235871,6 +237491,7 @@ static int fts5ConfigParseSpecial(
){
  int rc = SQLITE_OK;
  int nCmd = (int)strlen(zCmd);
+

  if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){
    const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES;
    const char *p;
@@ -235927,12 +237548,11 @@ static int fts5ConfigParseSpecial(
  if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
    const char *p = (const char*)zArg;
    sqlite3_int64 nArg = strlen(zArg) + 1;
-
    char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
-
    char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
-
    char *pSpace = pDel;
+
    char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg);

-
    if( azArg && pSpace ){
-
      if( pConfig->pTok ){
+
    if( azArg ){
+
      char *pSpace = (char*)&azArg[nArg];
+
      if( pConfig->t.azArg ){
        *pzErr = sqlite3_mprintf("multiple tokenize=... directives");
        rc = SQLITE_ERROR;
      }else{
@@ -235955,16 +237575,14 @@ static int fts5ConfigParseSpecial(
          *pzErr = sqlite3_mprintf("parse error in tokenize directive");
          rc = SQLITE_ERROR;
        }else{
-
          rc = sqlite3Fts5GetTokenizer(pGlobal,
-
              (const char**)azArg, (int)nArg, pConfig,
-
              pzErr
-
          );
+
          pConfig->t.azArg = (const char**)azArg;
+
          pConfig->t.nArg = nArg;
+
          azArg = 0;
        }
      }
    }
-

    sqlite3_free(azArg);
-
    sqlite3_free(pDel);
+

    return rc;
  }

@@ -235993,6 +237611,16 @@ static int fts5ConfigParseSpecial(
    return rc;
  }

+
  if( sqlite3_strnicmp("contentless_unindexed", zCmd, nCmd)==0 ){
+
    if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
+
      *pzErr = sqlite3_mprintf("malformed contentless_delete=... directive");
+
      rc = SQLITE_ERROR;
+
    }else{
+
      pConfig->bContentlessUnindexed = (zArg[0]=='1');
+
    }
+
    return rc;
+
  }
+

  if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){
    if( pConfig->zContentRowid ){
      *pzErr = sqlite3_mprintf("multiple content_rowid=... directives");
@@ -236013,6 +237641,16 @@ static int fts5ConfigParseSpecial(
    return rc;
  }

+
  if( sqlite3_strnicmp("locale", zCmd, nCmd)==0 ){
+
    if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
+
      *pzErr = sqlite3_mprintf("malformed locale=... directive");
+
      rc = SQLITE_ERROR;
+
    }else{
+
      pConfig->bLocale = (zArg[0]=='1');
+
    }
+
    return rc;
+
  }
+

  if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){
    const Fts5Enum aDetail[] = {
      { "none", FTS5_DETAIL_NONE },
@@ -236042,16 +237680,6 @@ static int fts5ConfigParseSpecial(
}

/*
-
** Allocate an instance of the default tokenizer ("simple") at
-
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
-
** code if an error occurs.
-
*/
-
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
-
  assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
-
  return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
-
}
-

-
/*
** Gobble up the first bareword or quoted word from the input buffer zIn.
** Return a pointer to the character immediately following the last in
** the gobbled word if successful, or a NULL pointer otherwise (failed
@@ -236110,7 +237738,8 @@ static int fts5ConfigParseColumn(
  Fts5Config *p,
  char *zCol,
  char *zArg,
-
  char **pzErr
+
  char **pzErr,
+
  int *pbUnindexed
){
  int rc = SQLITE_OK;
  if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME)
@@ -236121,6 +237750,7 @@ static int fts5ConfigParseColumn(
  }else if( zArg ){
    if( 0==sqlite3_stricmp(zArg, "unindexed") ){
      p->abUnindexed[p->nCol] = 1;
+
      *pbUnindexed = 1;
    }else{
      *pzErr = sqlite3_mprintf("unrecognized column option: %s", zArg);
      rc = SQLITE_ERROR;
@@ -236141,11 +237771,26 @@ static int fts5ConfigMakeExprlist(Fts5Config *p){

  sqlite3Fts5BufferAppendPrintf(&rc, &buf, "T.%Q", p->zContentRowid);
  if( p->eContent!=FTS5_CONTENT_NONE ){
+
    assert( p->eContent==FTS5_CONTENT_EXTERNAL
+
         || p->eContent==FTS5_CONTENT_NORMAL
+
         || p->eContent==FTS5_CONTENT_UNINDEXED
+
    );
    for(i=0; i<p->nCol; i++){
      if( p->eContent==FTS5_CONTENT_EXTERNAL ){
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]);
-
      }else{
+
      }else if( p->eContent==FTS5_CONTENT_NORMAL || p->abUnindexed[i] ){
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i);
+
      }else{
+
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
+
      }
+
    }
+
  }
+
  if( p->eContent==FTS5_CONTENT_NORMAL && p->bLocale ){
+
    for(i=0; i<p->nCol; i++){
+
      if( p->abUnindexed[i]==0 ){
+
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.l%d", i);
+
      }else{
+
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
      }
    }
  }
@@ -236179,10 +237824,12 @@ static int sqlite3Fts5ConfigParse(
  Fts5Config *pRet;               /* New object to return */
  int i;
  sqlite3_int64 nByte;
+
  int bUnindexed = 0;             /* True if there are one or more UNINDEXED */

  *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
  if( pRet==0 ) return SQLITE_NOMEM;
  memset(pRet, 0, sizeof(Fts5Config));
+
  pRet->pGlobal = pGlobal;
  pRet->db = db;
  pRet->iCookie = -1;

@@ -236231,13 +237878,13 @@ static int sqlite3Fts5ConfigParse(
        rc = SQLITE_ERROR;
      }else{
        if( bOption ){
-
          rc = fts5ConfigParseSpecial(pGlobal, pRet,
+
          rc = fts5ConfigParseSpecial(pRet,
            ALWAYS(zOne)?zOne:"",
            zTwo?zTwo:"",
            pzErr
          );
        }else{
-
          rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
+
          rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr, &bUnindexed);
          zOne = 0;
        }
      }
@@ -236269,11 +237916,17 @@ static int sqlite3Fts5ConfigParse(
    rc = SQLITE_ERROR;
  }

-
  /* If a tokenizer= option was successfully parsed, the tokenizer has
-
  ** already been allocated. Otherwise, allocate an instance of the default
-
  ** tokenizer (unicode61) now.  */
-
  if( rc==SQLITE_OK && pRet->pTok==0 ){
-
    rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
+
  /* We only allow contentless_unindexed=1 if the table is actually a
+
  ** contentless one.
+
  */
+
  if( rc==SQLITE_OK
+
   && pRet->bContentlessUnindexed
+
   && pRet->eContent!=FTS5_CONTENT_NONE
+
  ){
+
    *pzErr = sqlite3_mprintf(
+
        "contentless_unindexed=1 requires a contentless table"
+
    );
+
    rc = SQLITE_ERROR;
  }

  /* If no zContent option was specified, fill in the default values. */
@@ -236284,6 +237937,9 @@ static int sqlite3Fts5ConfigParse(
    );
    if( pRet->eContent==FTS5_CONTENT_NORMAL ){
      zTail = "content";
+
    }else if( bUnindexed && pRet->bContentlessUnindexed ){
+
      pRet->eContent = FTS5_CONTENT_UNINDEXED;
+
      zTail = "content";
    }else if( pRet->bColumnsize ){
      zTail = "docsize";
    }
@@ -236317,9 +237973,14 @@ static int sqlite3Fts5ConfigParse(
static void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
  if( pConfig ){
    int i;
-
    if( pConfig->pTok ){
-
      pConfig->pTokApi->xDelete(pConfig->pTok);
+
    if( pConfig->t.pTok ){
+
      if( pConfig->t.pApi1 ){
+
        pConfig->t.pApi1->xDelete(pConfig->t.pTok);
+
      }else{
+
        pConfig->t.pApi2->xDelete(pConfig->t.pTok);
+
      }
    }
+
    sqlite3_free((char*)pConfig->t.azArg);
    sqlite3_free(pConfig->zDb);
    sqlite3_free(pConfig->zName);
    for(i=0; i<pConfig->nCol; i++){
@@ -236394,10 +238055,24 @@ static int sqlite3Fts5Tokenize(
  void *pCtx,                     /* Context passed to xToken() */
  int (*xToken)(void*, int, const char*, int, int, int)    /* Callback */
){
-
  if( pText==0 ) return SQLITE_OK;
-
  return pConfig->pTokApi->xTokenize(
-
      pConfig->pTok, pCtx, flags, pText, nText, xToken
-
  );
+
  int rc = SQLITE_OK;
+
  if( pText ){
+
    if( pConfig->t.pTok==0 ){
+
      rc = sqlite3Fts5LoadTokenizer(pConfig);
+
    }
+
    if( rc==SQLITE_OK ){
+
      if( pConfig->t.pApi1 ){
+
        rc = pConfig->t.pApi1->xTokenize(
+
            pConfig->t.pTok, pCtx, flags, pText, nText, xToken
+
        );
+
      }else{
+
        rc = pConfig->t.pApi2->xTokenize(pConfig->t.pTok, pCtx, flags,
+
            pText, nText, pConfig->t.pLocale, pConfig->t.nLocale, xToken
+
        );
+
      }
+
    }
+
  }
+
  return rc;
}

/*
@@ -236651,13 +238326,10 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
   && iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE
  ){
    rc = SQLITE_ERROR;
-
    if( pConfig->pzErrmsg ){
-
      assert( 0==*pConfig->pzErrmsg );
-
      *pConfig->pzErrmsg = sqlite3_mprintf("invalid fts5 file format "
-
          "(found %d, expected %d or %d) - run 'rebuild'",
-
          iVersion, FTS5_CURRENT_VERSION, FTS5_CURRENT_VERSION_SECUREDELETE
-
      );
-
    }
+
    sqlite3Fts5ConfigErrmsg(pConfig, "invalid fts5 file format "
+
        "(found %d, expected %d or %d) - run 'rebuild'",
+
        iVersion, FTS5_CURRENT_VERSION, FTS5_CURRENT_VERSION_SECUREDELETE
+
    );
  }else{
    pConfig->iVersion = iVersion;
  }
@@ -236669,6 +238341,29 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
}

/*
+
** Set (*pConfig->pzErrmsg) to point to an sqlite3_malloc()ed buffer
+
** containing the error message created using printf() style formatting
+
** string zFmt and its trailing arguments.
+
*/
+
static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){
+
  va_list ap;                     /* ... printf arguments */
+
  char *zMsg = 0;
+

+
  va_start(ap, zFmt);
+
  zMsg = sqlite3_vmprintf(zFmt, ap);
+
  if( pConfig->pzErrmsg ){
+
    assert( *pConfig->pzErrmsg==0 );
+
    *pConfig->pzErrmsg = zMsg;
+
  }else{
+
    sqlite3_free(zMsg);
+
  }
+

+
  va_end(ap);
+
}
+

+

+

+
/*
** 2014 May 31
**
** The author disclaims copyright to this source code.  In place of
@@ -236724,7 +238419,7 @@ struct Fts5Expr {

/*
** eType:
-
**   Expression node type. Always one of:
+
**   Expression node type. Usually one of:
**
**       FTS5_AND                 (nChild, apChild valid)
**       FTS5_OR                  (nChild, apChild valid)
@@ -236732,6 +238427,10 @@ struct Fts5Expr {
**       FTS5_STRING              (pNear valid)
**       FTS5_TERM                (pNear valid)
**
+
**   An expression node with eType==0 may also exist. It always matches zero
+
**   rows. This is created when a phrase containing no tokens is parsed.
+
**   e.g. "".
+
**
** iHeight:
**   Distance from this node to furthest leaf. This is always 0 for nodes
**   of type FTS5_STRING and FTS5_TERM. For all other nodes it is one
@@ -236952,11 +238651,12 @@ static int sqlite3Fts5ExprNew(
  }while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
  sqlite3Fts5ParserFree(pEngine, fts5ParseFree);

+
  assert( sParse.pExpr || sParse.rc!=SQLITE_OK );
  assert_expr_depth_ok(sParse.rc, sParse.pExpr);

  /* If the LHS of the MATCH expression was a user column, apply the
  ** implicit column-filter.  */
-
  if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
+
  if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
    int n = sizeof(Fts5Colset);
    Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
    if( pColset ){
@@ -236973,15 +238673,7 @@ static int sqlite3Fts5ExprNew(
      sParse.rc = SQLITE_NOMEM;
      sqlite3Fts5ParseNodeFree(sParse.pExpr);
    }else{
-
      if( !sParse.pExpr ){
-
        const int nByte = sizeof(Fts5ExprNode);
-
        pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte);
-
        if( pNew->pRoot ){
-
          pNew->pRoot->bEof = 1;
-
        }
-
      }else{
-
        pNew->pRoot = sParse.pExpr;
-
      }
+
      pNew->pRoot = sParse.pExpr;
      pNew->pIndex = 0;
      pNew->pConfig = pConfig;
      pNew->apExprPhrase = sParse.apPhrase;
@@ -237799,7 +239491,7 @@ static int fts5ExprNodeTest_STRING(
          }
        }else{
          Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
-
          if( pIter->iRowid==iLast || pIter->bEof ) continue;
+
          if( pIter->iRowid==iLast ) continue;
          bMatch = 0;
          if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
            return rc;
@@ -238321,9 +240013,6 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset(
  Fts5ExprNearset *pRet = 0;

  if( pParse->rc==SQLITE_OK ){
-
    if( pPhrase==0 ){
-
      return pNear;
-
    }
    if( pNear==0 ){
      sqlite3_int64 nByte;
      nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
@@ -238545,6 +240234,7 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm(
    }else if( sCtx.pPhrase->nTerm ){
      sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
    }
+
    assert( pParse->apPhrase!=0 );
    pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
  }

@@ -238564,7 +240254,7 @@ static int sqlite3Fts5ExprClonePhrase(
  Fts5ExprPhrase *pOrig = 0;      /* The phrase extracted from pExpr */
  Fts5Expr *pNew = 0;             /* Expression to return via *ppNew */
  TokenCtx sCtx = {0,0,0};        /* Context object for fts5ParseTokenize */
-
  if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
+
  if( !pExpr || iPhrase<0 || iPhrase>=pExpr->nPhrase ){
    rc = SQLITE_RANGE;
  }else{
    pOrig = pExpr->apExprPhrase[iPhrase];
@@ -238932,6 +240622,9 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
  }
}

+
/*
+
** Add pSub as a child of p.
+
*/
static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
  int ii = p->nChild;
  if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){
@@ -239076,19 +240769,23 @@ static Fts5ExprNode *sqlite3Fts5ParseNode(
                  "fts5: %s queries are not supported (detail!=full)",
                  pNear->nPhrase==1 ? "phrase": "NEAR"
              );
-
              sqlite3_free(pRet);
+
              sqlite3Fts5ParseNodeFree(pRet);
              pRet = 0;
+
              pNear = 0;
+
              assert( pLeft==0 && pRight==0 );
            }
          }
        }else{
+
          assert( pNear==0 );
          fts5ExprAddChildren(pRet, pLeft);
          fts5ExprAddChildren(pRet, pRight);
+
          pLeft = pRight = 0;
          if( pRet->iHeight>SQLITE_FTS5_MAX_EXPR_DEPTH ){
            sqlite3Fts5ParseError(pParse,
                "fts5 expression tree is too large (maximum depth %d)",
                SQLITE_FTS5_MAX_EXPR_DEPTH
            );
-
            sqlite3_free(pRet);
+
            sqlite3Fts5ParseNodeFree(pRet);
            pRet = 0;
          }
        }
@@ -239140,6 +240837,8 @@ static Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
        );

    if( pRight->eType==FTS5_EOF ){
+
      assert( pParse->apPhrase!=0 );
+
      assert( pParse->nPhrase>0 );
      assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
      sqlite3Fts5ParseNodeFree(pRight);
      pRet = pLeft;
@@ -239772,6 +241471,7 @@ static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){
  pNode->iRowid = iRowid;
  pNode->bEof = 0;
  switch( pNode->eType ){
+
    case 0:
    case FTS5_TERM:
    case FTS5_STRING:
      return (pNode->pNear->apPhrase[0]->poslist.n>0);
@@ -241355,11 +243055,12 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
    if( rc==SQLITE_OK ){
      u8 *aOut = 0;               /* Read blob data into this buffer */
      int nByte = sqlite3_blob_bytes(p->pReader);
-
      sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
+
      int szData = (sizeof(Fts5Data) + 7) & ~7;
+
      sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING;
      pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
      if( pRet ){
        pRet->nn = nByte;
-
        aOut = pRet->p = (u8*)&pRet[1];
+
        aOut = pRet->p = (u8*)pRet + szData;
      }else{
        rc = SQLITE_NOMEM;
      }
@@ -241382,6 +243083,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
  }

  assert( (pRet==0)==(p->rc!=SQLITE_OK) );
+
  assert( pRet==0 || EIGHT_BYTE_ALIGNMENT( pRet->p ) );
  return pRet;
}

@@ -242707,7 +244409,7 @@ static void fts5SegIterNext_None(

  if( iOff<pIter->iEndofDoclist ){
    /* Next entry is on the current page */
-
    i64 iDelta;
+
    u64 iDelta;
    iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
    pIter->iLeafOffset = iOff;
    pIter->iRowid += iDelta;
@@ -245411,6 +247113,11 @@ static int fts5IndexFindDeleteMerge(Fts5Index *p, Fts5Structure *pStruct){
          nBest = nPercent;
        }
      }
+

+
      /* If pLvl is already the input level to an ongoing merge, look no
+
      ** further for a merge candidate. The caller should be allowed to
+
      ** continue merging from pLvl first.  */
+
      if( pLvl->nMerge ) break;
    }
  }
  return iRet;
@@ -249335,7 +251042,7 @@ static int fts5structConnectMethod(

/*
** We must have a single struct=? constraint that will be passed through
-
** into the xFilter method.  If there is no valid stmt=? constraint,
+
** into the xFilter method.  If there is no valid struct=? constraint,
** then return an SQLITE_CONSTRAINT error.
*/
static int fts5structBestIndexMethod(
@@ -249677,9 +251384,18 @@ struct Fts5Global {
  Fts5TokenizerModule *pTok;      /* First in list of all tokenizer modules */
  Fts5TokenizerModule *pDfltTok;  /* Default tokenizer module */
  Fts5Cursor *pCsr;               /* First in list of all open cursors */
+
  u32 aLocaleHdr[4];
};

/*
+
** Size of header on fts5_locale() values. And macro to access a buffer
+
** containing a copy of the header from an Fts5Config pointer.
+
*/
+
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
+
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
+

+

+
/*
** Each auxiliary function registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pAux list.
@@ -249697,11 +251413,28 @@ struct Fts5Auxiliary {
** Each tokenizer module registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pTok list.
+
**
+
** bV2Native:
+
**  True if the tokenizer was registered using xCreateTokenizer_v2(), false
+
**  for xCreateTokenizer(). If this variable is true, then x2 is populated
+
**  with the routines as supplied by the caller and x1 contains synthesized
+
**  wrapper routines. In this case the user-data pointer passed to
+
**  x1.xCreate should be a pointer to the Fts5TokenizerModule structure,
+
**  not a copy of pUserData.
+
**
+
**  Of course, if bV2Native is false, then x1 contains the real routines and
+
**  x2 the synthesized ones. In this case a pointer to the Fts5TokenizerModule
+
**  object should be passed to x2.xCreate.
+
**
+
**  The synthesized wrapper routines are necessary for xFindTokenizer(_v2)
+
**  calls.
*/
struct Fts5TokenizerModule {
  char *zName;                    /* Name of tokenizer */
  void *pUserData;                /* User pointer passed to xCreate() */
-
  fts5_tokenizer x;               /* Tokenizer functions */
+
  int bV2Native;                  /* True if v2 native tokenizer */
+
  fts5_tokenizer x1;              /* Tokenizer functions */
+
  fts5_tokenizer_v2 x2;           /* V2 tokenizer functions */
  void (*xDestroy)(void*);        /* Destructor function */
  Fts5TokenizerModule *pNext;     /* Next registered tokenizer module */
};
@@ -249789,7 +251522,7 @@ struct Fts5Cursor {
  Fts5Auxiliary *pAux;            /* Currently executing extension function */
  Fts5Auxdata *pAuxdata;          /* First in linked list of saved aux-data */

-
  /* Cache used by auxiliary functions xInst() and xInstCount() */
+
  /* Cache used by auxiliary API functions xInst() and xInstCount() */
  Fts5PoslistReader *aInstIter;   /* One for each phrase */
  int nInstAlloc;                 /* Size of aInst[] array (entries / 3) */
  int nInstCount;                 /* Number of phrase instances */
@@ -249900,10 +251633,16 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
#endif

/*
-
** Return true if pTab is a contentless table.
+
** Return true if pTab is a contentless table. If parameter bIncludeUnindexed
+
** is true, this includes contentless tables that store UNINDEXED columns
+
** only.
*/
-
static int fts5IsContentless(Fts5FullTable *pTab){
-
  return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
+
static int fts5IsContentless(Fts5FullTable *pTab, int bIncludeUnindexed){
+
  int eContent = pTab->p.pConfig->eContent;
+
  return (
+
    eContent==FTS5_CONTENT_NONE
+
    || (bIncludeUnindexed && eContent==FTS5_CONTENT_UNINDEXED)
+
  );
}

/*
@@ -249971,8 +251710,12 @@ static int fts5InitVtab(
    assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
  }
  if( rc==SQLITE_OK ){
+
    pConfig->pzErrmsg = pzErr;
    pTab->p.pConfig = pConfig;
    pTab->pGlobal = pGlobal;
+
    if( bCreate || sqlite3Fts5TokenizerPreload(&pConfig->t) ){
+
      rc = sqlite3Fts5LoadTokenizer(pConfig);
+
    }
  }

  /* Open the index sub-system */
@@ -249994,11 +251737,7 @@ static int fts5InitVtab(

  /* Load the initial configuration */
  if( rc==SQLITE_OK ){
-
    assert( pConfig->pzErrmsg==0 );
-
    pConfig->pzErrmsg = pzErr;
-
    rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
-
    sqlite3Fts5IndexRollback(pTab->p.pIndex);
-
    pConfig->pzErrmsg = 0;
+
    rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie-1);
  }

  if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
@@ -250008,6 +251747,7 @@ static int fts5InitVtab(
    rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  }

+
  if( pConfig ) pConfig->pzErrmsg = 0;
  if( rc!=SQLITE_OK ){
    fts5FreeVtab(pTab);
    pTab = 0;
@@ -250075,10 +251815,10 @@ static int fts5UsePatternMatch(
){
  assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
  assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
-
  if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
+
  if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
    return 1;
  }
-
  if( pConfig->ePattern==FTS5_PATTERN_LIKE
+
  if( pConfig->t.ePattern==FTS5_PATTERN_LIKE
   && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
  ){
    return 1;
@@ -250125,10 +251865,10 @@ static int fts5UsePatternMatch(
** This function ensures that there is at most one "r" or "=". And that if
** there exists an "=" then there is no "<" or ">".
**
-
** Costs are assigned as follows:
+
** If an unusable MATCH operator is present in the WHERE clause, then
+
** SQLITE_CONSTRAINT is returned.
**
-
**  a) If an unusable MATCH operator is present in the WHERE clause, the
-
**     cost is unconditionally set to 1e50 (a really big number).
+
** Costs are assigned as follows:
**
**  a) If a MATCH operator is present, the cost depends on the other
**     constraints also present. As follows:
@@ -250161,7 +251901,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  int bSeenEq = 0;
  int bSeenGt = 0;
  int bSeenLt = 0;
-
  int bSeenMatch = 0;
+
  int nSeenMatch = 0;
  int bSeenRank = 0;


@@ -250192,18 +251932,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
      /* A MATCH operator or equivalent */
      if( p->usable==0 || iCol<0 ){
        /* As there exists an unusable MATCH constraint this is an
-
        ** unusable plan. Set a prohibitively high cost. */
-
        pInfo->estimatedCost = 1e50;
-
        assert( iIdxStr < pInfo->nConstraint*6 + 1 );
-
        idxStr[iIdxStr] = 0;
-
        return SQLITE_OK;
+
        ** unusable plan. Return SQLITE_CONSTRAINT. */
+
        return SQLITE_CONSTRAINT;
      }else{
        if( iCol==nCol+1 ){
          if( bSeenRank ) continue;
          idxStr[iIdxStr++] = 'r';
          bSeenRank = 1;
-
        }else if( iCol>=0 ){
-
          bSeenMatch = 1;
+
        }else{
+
          nSeenMatch++;
          idxStr[iIdxStr++] = 'M';
          sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
          idxStr += strlen(&idxStr[iIdxStr]);
@@ -250220,6 +251957,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
        idxStr += strlen(&idxStr[iIdxStr]);
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        assert( idxStr[iIdxStr]=='\0' );
+
        nSeenMatch++;
      }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
        idxStr[iIdxStr++] = '=';
        bSeenEq = 1;
@@ -250256,7 +251994,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  */
  if( pInfo->nOrderBy==1 ){
    int iSort = pInfo->aOrderBy[0].iColumn;
-
    if( iSort==(pConfig->nCol+1) && bSeenMatch ){
+
    if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){
      idxFlags |= FTS5_BI_ORDER_RANK;
    }else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
      idxFlags |= FTS5_BI_ORDER_ROWID;
@@ -250271,14 +252009,17 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){

  /* Calculate the estimated cost based on the flags set in idxFlags. */
  if( bSeenEq ){
-
    pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
-
    if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
+
    pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
+
    if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
  }else if( bSeenLt && bSeenGt ){
-
    pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
+
    pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
  }else if( bSeenLt || bSeenGt ){
-
    pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
+
    pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
  }else{
-
    pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
+
    pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
+
  }
+
  for(i=1; i<nSeenMatch; i++){
+
    pInfo->estimatedCost *= 0.4;
  }

  pInfo->idxNum = idxFlags;
@@ -250554,6 +252295,7 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
          }
        }else{
          rc = SQLITE_OK;
+
          CsrFlagSet(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
        }
        break;
      }
@@ -250583,7 +252325,7 @@ static int fts5PrepareStatement(
    rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
                            SQLITE_PREPARE_PERSISTENT, &pRet, 0);
    if( rc!=SQLITE_OK ){
-
      *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
+
      sqlite3Fts5ConfigErrmsg(pConfig, "%s", sqlite3_errmsg(pConfig->db));
    }
    sqlite3_free(zSql);
  }
@@ -250808,6 +252550,145 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
}

/*
+
** Set the error message on the virtual table passed as the first argument.
+
*/
+
static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
+
  va_list ap;                     /* ... printf arguments */
+
  va_start(ap, zFormat);
+
  sqlite3_free(p->p.base.zErrMsg);
+
  p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
+
  va_end(ap);
+
}
+

+
/*
+
** Arrange for subsequent calls to sqlite3Fts5Tokenize() to use the locale
+
** specified by pLocale/nLocale. The buffer indicated by pLocale must remain
+
** valid until after the final call to sqlite3Fts5Tokenize() that will use
+
** the locale.
+
*/
+
static void sqlite3Fts5SetLocale(
+
  Fts5Config *pConfig,
+
  const char *zLocale,
+
  int nLocale
+
){
+
  Fts5TokenizerConfig *pT = &pConfig->t;
+
  pT->pLocale = zLocale;
+
  pT->nLocale = nLocale;
+
}
+

+
/*
+
** Clear any locale configured by an earlier call to sqlite3Fts5SetLocale().
+
*/
+
static void sqlite3Fts5ClearLocale(Fts5Config *pConfig){
+
  sqlite3Fts5SetLocale(pConfig, 0, 0);
+
}
+

+
/*
+
** Return true if the value passed as the only argument is an
+
** fts5_locale() value.
+
*/
+
static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal){
+
  int ret = 0;
+
  if( sqlite3_value_type(pVal)==SQLITE_BLOB ){
+
    /* Call sqlite3_value_bytes() after sqlite3_value_blob() in this case.
+
    ** If the blob was created using zeroblob(), then sqlite3_value_blob()
+
    ** may call malloc(). If this malloc() fails, then the values returned
+
    ** by both value_blob() and value_bytes() will be 0. If value_bytes() were
+
    ** called first, then the NULL pointer returned by value_blob() might
+
    ** be dereferenced.  */
+
    const u8 *pBlob = sqlite3_value_blob(pVal);
+
    int nBlob = sqlite3_value_bytes(pVal);
+
    if( nBlob>FTS5_LOCALE_HDR_SIZE
+
     && 0==memcmp(pBlob, FTS5_LOCALE_HDR(pConfig), FTS5_LOCALE_HDR_SIZE)
+
    ){
+
      ret = 1;
+
    }
+
  }
+
  return ret;
+
}
+

+
/*
+
** Value pVal is guaranteed to be an fts5_locale() value, according to
+
** sqlite3Fts5IsLocaleValue(). This function extracts the text and locale
+
** from the value and returns them separately.
+
**
+
** If successful, SQLITE_OK is returned and (*ppText) and (*ppLoc) set
+
** to point to buffers containing the text and locale, as utf-8,
+
** respectively. In this case output parameters (*pnText) and (*pnLoc) are
+
** set to the sizes in bytes of these two buffers.
+
**
+
** Or, if an error occurs, then an SQLite error code is returned. The final
+
** value of the four output parameters is undefined in this case.
+
*/
+
static int sqlite3Fts5DecodeLocaleValue(
+
  sqlite3_value *pVal,
+
  const char **ppText,
+
  int *pnText,
+
  const char **ppLoc,
+
  int *pnLoc
+
){
+
  const char *p = sqlite3_value_blob(pVal);
+
  int n = sqlite3_value_bytes(pVal);
+
  int nLoc = 0;
+

+
  assert( sqlite3_value_type(pVal)==SQLITE_BLOB );
+
  assert( n>FTS5_LOCALE_HDR_SIZE );
+

+
  for(nLoc=FTS5_LOCALE_HDR_SIZE; p[nLoc]; nLoc++){
+
    if( nLoc==(n-1) ){
+
      return SQLITE_MISMATCH;
+
    }
+
  }
+
  *ppLoc = &p[FTS5_LOCALE_HDR_SIZE];
+
  *pnLoc = nLoc - FTS5_LOCALE_HDR_SIZE;
+

+
  *ppText = &p[nLoc+1];
+
  *pnText = n - nLoc - 1;
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Argument pVal is the text of a full-text search expression. It may or
+
** may not have been wrapped by fts5_locale(). This function extracts
+
** the text of the expression, and sets output variable (*pzText) to
+
** point to a nul-terminated buffer containing the expression.
+
**
+
** If pVal was an fts5_locale() value, then sqlite3Fts5SetLocale() is called
+
** to set the tokenizer to use the specified locale.
+
**
+
** If output variable (*pbFreeAndReset) is set to true, then the caller
+
** is required to (a) call sqlite3Fts5ClearLocale() to reset the tokenizer
+
** locale, and (b) call sqlite3_free() to free (*pzText).
+
*/
+
static int fts5ExtractExprText(
+
  Fts5Config *pConfig,            /* Fts5 configuration */
+
  sqlite3_value *pVal,            /* Value to extract expression text from */
+
  char **pzText,                  /* OUT: nul-terminated buffer of text */
+
  int *pbFreeAndReset             /* OUT: Free (*pzText) and clear locale */
+
){
+
  int rc = SQLITE_OK;
+

+
  if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+
    const char *pText = 0;
+
    int nText = 0;
+
    const char *pLoc = 0;
+
    int nLoc = 0;
+
    rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+
    *pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, pText);
+
    if( rc==SQLITE_OK ){
+
      sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+
    }
+
    *pbFreeAndReset = 1;
+
  }else{
+
    *pzText = (char*)sqlite3_value_text(pVal);
+
    *pbFreeAndReset = 0;
+
  }
+

+
  return rc;
+
}
+

+

+
/*
** This is the xFilter interface for the virtual table.  See
** the virtual table xFilter method documentation for additional
** information.
@@ -250841,13 +252722,7 @@ static int fts5FilterMethod(
  int iIdxStr = 0;
  Fts5Expr *pExpr = 0;

-
  if( pConfig->bLock ){
-
    pTab->p.base.zErrMsg = sqlite3_mprintf(
-
        "recursively defined fts5 content table"
-
    );
-
    return SQLITE_ERROR;
-
  }
-

+
  assert( pConfig->bLock==0 );
  if( pCsr->ePlan ){
    fts5FreeCursorComponents(pCsr);
    memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
@@ -250871,8 +252746,14 @@ static int fts5FilterMethod(
        pRank = apVal[i];
        break;
      case 'M': {
-
        const char *zText = (const char*)sqlite3_value_text(apVal[i]);
+
        char *zText = 0;
+
        int bFreeAndReset = 0;
+
        int bInternal = 0;
+

+
        rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
+
        if( rc!=SQLITE_OK ) goto filter_out;
        if( zText==0 ) zText = "";
+

        iCol = 0;
        do{
          iCol = iCol*10 + (idxStr[iIdxStr]-'0');
@@ -250884,7 +252765,7 @@ static int fts5FilterMethod(
          ** indicates that the MATCH expression is not a full text query,
          ** but a request for an internal parameter.  */
          rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
-
          goto filter_out;
+
          bInternal = 1;
        }else{
          char **pzErr = &pTab->p.base.zErrMsg;
          rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
@@ -250892,9 +252773,15 @@ static int fts5FilterMethod(
            rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
            pExpr = 0;
          }
-
          if( rc!=SQLITE_OK ) goto filter_out;
        }

+
        if( bFreeAndReset ){
+
          sqlite3_free(zText);
+
          sqlite3Fts5ClearLocale(pConfig);
+
        }
+

+
        if( bInternal || rc!=SQLITE_OK ) goto filter_out;
+

        break;
      }
      case 'L':
@@ -250982,9 +252869,7 @@ static int fts5FilterMethod(
      }
    }
  }else if( pConfig->zContent==0 ){
-
    *pConfig->pzErrmsg = sqlite3_mprintf(
-
        "%s: table does not support scanning", pConfig->zName
-
    );
+
    fts5SetVtabError(pTab,"%s: table does not support scanning",pConfig->zName);
    rc = SQLITE_ERROR;
  }else{
    /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
@@ -251027,9 +252912,13 @@ static i64 fts5CursorRowid(Fts5Cursor *pCsr){
  assert( pCsr->ePlan==FTS5_PLAN_MATCH
       || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
       || pCsr->ePlan==FTS5_PLAN_SOURCE
+
       || pCsr->ePlan==FTS5_PLAN_SCAN
+
       || pCsr->ePlan==FTS5_PLAN_ROWID
  );
  if( pCsr->pSorter ){
    return pCsr->pSorter->iRowid;
+
  }else if( pCsr->ePlan>=FTS5_PLAN_SCAN ){
+
    return sqlite3_column_int64(pCsr->pStmt, 0);
  }else{
    return sqlite3Fts5ExprRowid(pCsr->pExpr);
  }
@@ -251046,25 +252935,16 @@ static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  int ePlan = pCsr->ePlan;

  assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
-
  switch( ePlan ){
-
    case FTS5_PLAN_SPECIAL:
-
      *pRowid = 0;
-
      break;
-

-
    case FTS5_PLAN_SOURCE:
-
    case FTS5_PLAN_MATCH:
-
    case FTS5_PLAN_SORTED_MATCH:
-
      *pRowid = fts5CursorRowid(pCsr);
-
      break;
-

-
    default:
-
      *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
-
      break;
+
  if( ePlan==FTS5_PLAN_SPECIAL ){
+
    *pRowid = 0;
+
  }else{
+
    *pRowid = fts5CursorRowid(pCsr);
  }

  return SQLITE_OK;
}

+

/*
** If the cursor requires seeking (bSeekRequired flag is set), seek it.
** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise.
@@ -251101,8 +252981,13 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
      rc = sqlite3_reset(pCsr->pStmt);
      if( rc==SQLITE_OK ){
        rc = FTS5_CORRUPT;
+
        fts5SetVtabError((Fts5FullTable*)pTab,
+
            "fts5: missing row %lld from content table %s",
+
            fts5CursorRowid(pCsr),
+
            pTab->pConfig->zContent
+
        );
      }else if( pTab->pConfig->pzErrmsg ){
-
        *pTab->pConfig->pzErrmsg = sqlite3_mprintf(
+
        fts5SetVtabError((Fts5FullTable*)pTab,
            "%s", sqlite3_errmsg(pTab->pConfig->db)
        );
      }
@@ -251111,14 +252996,6 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
  return rc;
}

-
static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
-
  va_list ap;                     /* ... printf arguments */
-
  va_start(ap, zFormat);
-
  assert( p->p.base.zErrMsg==0 );
-
  p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
-
  va_end(ap);
-
}
-

/*
** This function is called to handle an FTS INSERT command. In other words,
** an INSERT statement of the form:
@@ -251156,7 +253033,7 @@ static int fts5SpecialInsert(
    }
    bLoadConfig = 1;
  }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
-
    if( pConfig->eContent==FTS5_CONTENT_NONE ){
+
    if( fts5IsContentless(pTab, 1) ){
      fts5SetVtabError(pTab,
          "'rebuild' may not be used with a contentless fts5 table"
      );
@@ -251212,7 +253089,7 @@ static int fts5SpecialDelete(
  int eType1 = sqlite3_value_type(apVal[1]);
  if( eType1==SQLITE_INTEGER ){
    sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
-
    rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]);
+
    rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2], 0);
  }
  return rc;
}
@@ -251225,7 +253102,7 @@ static void fts5StorageInsert(
){
  int rc = *pRc;
  if( rc==SQLITE_OK ){
-
    rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
+
    rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, 0, apVal, piRowid);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
@@ -251234,6 +253111,67 @@ static void fts5StorageInsert(
}

/*
+
**
+
** This function is called when the user attempts an UPDATE on a contentless
+
** table. Parameter bRowidModified is true if the UPDATE statement modifies
+
** the rowid value. Parameter apVal[] contains the new values for each user
+
** defined column of the fts5 table. pConfig is the configuration object of the
+
** table being updated (guaranteed to be contentless). The contentless_delete=1
+
** and contentless_unindexed=1 options may or may not be set.
+
**
+
** This function returns SQLITE_OK if the UPDATE can go ahead, or an SQLite
+
** error code if it cannot. In this case an error message is also loaded into
+
** pConfig. Output parameter (*pbContent) is set to true if the caller should
+
** update the %_content table only - not the FTS index or any other shadow
+
** table. This occurs when an UPDATE modifies only UNINDEXED columns of the
+
** table.
+
**
+
** An UPDATE may proceed if:
+
**
+
**   * The only columns modified are UNINDEXED columns, or
+
**
+
**   * The contentless_delete=1 option was specified and all of the indexed
+
**     columns (not a subset) have been modified.
+
*/
+
static int fts5ContentlessUpdate(
+
  Fts5Config *pConfig,
+
  sqlite3_value **apVal,
+
  int bRowidModified,
+
  int *pbContent
+
){
+
  int ii;
+
  int bSeenIndex = 0;             /* Have seen modified indexed column */
+
  int bSeenIndexNC = 0;           /* Have seen unmodified indexed column */
+
  int rc = SQLITE_OK;
+

+
  for(ii=0; ii<pConfig->nCol; ii++){
+
    if( pConfig->abUnindexed[ii]==0 ){
+
      if( sqlite3_value_nochange(apVal[ii]) ){
+
        bSeenIndexNC++;
+
      }else{
+
        bSeenIndex++;
+
      }
+
    }
+
  }
+

+
  if( bSeenIndex==0 && bRowidModified==0 ){
+
    *pbContent = 1;
+
  }else{
+
    if( bSeenIndexNC || pConfig->bContentlessDelete==0 ){
+
      rc = SQLITE_ERROR;
+
      sqlite3Fts5ConfigErrmsg(pConfig,
+
          (pConfig->bContentlessDelete ?
+
          "%s a subset of columns on fts5 contentless-delete table: %s" :
+
          "%s contentless fts5 table: %s")
+
          , "cannot UPDATE", pConfig->zName
+
      );
+
    }
+
  }
+

+
  return rc;
+
}
+

+
/*
** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
** inserted, updated or deleted.
@@ -251319,41 +253257,46 @@ static int fts5UpdateMethod(
    assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
    assert( nArg!=1 || eType0==SQLITE_INTEGER );

-
    /* Filter out attempts to run UPDATE or DELETE on contentless tables.
-
    ** This is not suported. Except - they are both supported if the CREATE
-
    ** VIRTUAL TABLE statement contained "contentless_delete=1". */
-
    if( eType0==SQLITE_INTEGER
-
     && pConfig->eContent==FTS5_CONTENT_NONE
-
     && pConfig->bContentlessDelete==0
-
    ){
-
      pTab->p.base.zErrMsg = sqlite3_mprintf(
-
          "cannot %s contentless fts5 table: %s",
-
          (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
-
      );
-
      rc = SQLITE_ERROR;
-
    }
-

    /* DELETE */
-
    else if( nArg==1 ){
-
      i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
-
      rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
-
      bUpdateOrDelete = 1;
+
    if( nArg==1 ){
+
      /* It is only possible to DELETE from a contentless table if the
+
      ** contentless_delete=1 flag is set. */
+
      if( fts5IsContentless(pTab, 1) && pConfig->bContentlessDelete==0 ){
+
        fts5SetVtabError(pTab,
+
            "cannot DELETE from contentless fts5 table: %s", pConfig->zName
+
        );
+
        rc = SQLITE_ERROR;
+
      }else{
+
        i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
+
        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
+
        bUpdateOrDelete = 1;
+
      }
    }

    /* INSERT or UPDATE */
    else{
      int eType1 = sqlite3_value_numeric_type(apVal[1]);

-
      if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
-
        rc = SQLITE_MISMATCH;
+
      /* It is an error to write an fts5_locale() value to a table without
+
      ** the locale=1 option. */
+
      if( pConfig->bLocale==0 ){
+
        int ii;
+
        for(ii=0; ii<pConfig->nCol; ii++){
+
          sqlite3_value *pVal = apVal[ii+2];
+
          if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+
            fts5SetVtabError(pTab, "fts5_locale() requires locale=1");
+
            rc = SQLITE_MISMATCH;
+
            goto update_out;
+
          }
+
        }
      }

-
      else if( eType0!=SQLITE_INTEGER ){
+
      if( eType0!=SQLITE_INTEGER ){
        /* An INSERT statement. If the conflict-mode is REPLACE, first remove
        ** the current entry (if any). */
        if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
          i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
-
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0);
          bUpdateOrDelete = 1;
        }
        fts5StorageInsert(&rc, pTab, apVal, pRowid);
@@ -251361,30 +253304,57 @@ static int fts5UpdateMethod(

      /* UPDATE */
      else{
+
        Fts5Storage *pStorage = pTab->pStorage;
        i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
        i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
-
        if( eType1==SQLITE_INTEGER && iOld!=iNew ){
+
        int bContent = 0;         /* Content only update */
+

+
        /* If this is a contentless table (including contentless_unindexed=1
+
        ** tables), check if the UPDATE may proceed.  */
+
        if( fts5IsContentless(pTab, 1) ){
+
          rc = fts5ContentlessUpdate(pConfig, &apVal[2], iOld!=iNew, &bContent);
+
          if( rc!=SQLITE_OK ) goto update_out;
+
        }
+

+
        if( eType1!=SQLITE_INTEGER ){
+
          rc = SQLITE_MISMATCH;
+
        }else if( iOld!=iNew ){
+
          assert( bContent==0 );
          if( eConflict==SQLITE_REPLACE ){
-
            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+
            rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
            if( rc==SQLITE_OK ){
-
              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+
              rc = sqlite3Fts5StorageDelete(pStorage, iNew, 0, 0);
            }
            fts5StorageInsert(&rc, pTab, apVal, pRowid);
          }else{
-
            rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
+
            rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld);
            if( rc==SQLITE_OK ){
-
              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+
              rc = sqlite3Fts5StorageContentInsert(pStorage, 0, apVal, pRowid);
            }
            if( rc==SQLITE_OK ){
-
              rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
+
              rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 0);
            }
+
            if( rc==SQLITE_OK ){
+
              rc = sqlite3Fts5StorageIndexInsert(pStorage, apVal, *pRowid);
+
            }
+
          }
+
        }else if( bContent ){
+
          /* This occurs when an UPDATE on a contentless table affects *only*
+
          ** UNINDEXED columns. This is a no-op for contentless_unindexed=0
+
          ** tables, or a write to the %_content table only for =1 tables.  */
+
          assert( fts5IsContentless(pTab, 1) );
+
          rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld);
+
          if( rc==SQLITE_OK ){
+
            rc = sqlite3Fts5StorageContentInsert(pStorage, 1, apVal, pRowid);
          }
        }else{
-
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+
          rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
          fts5StorageInsert(&rc, pTab, apVal, pRowid);
        }
        bUpdateOrDelete = 1;
+
        sqlite3Fts5StorageReleaseDeleteRow(pStorage);
      }
+

    }
  }

@@ -251401,6 +253371,7 @@ static int fts5UpdateMethod(
    }
  }

+
 update_out:
  pTab->p.pConfig->pzErrmsg = 0;
  return rc;
}
@@ -251422,9 +253393,11 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method.
*/
static int fts5BeginMethod(sqlite3_vtab *pVtab){
-
  fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
-
  fts5NewTransaction((Fts5FullTable*)pVtab);
-
  return SQLITE_OK;
+
  int rc = fts5NewTransaction((Fts5FullTable*)pVtab);
+
  if( rc==SQLITE_OK ){
+
    fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
+
  }
+
  return rc;
}

/*
@@ -251478,17 +253451,40 @@ static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
  return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
}

-
static int fts5ApiTokenize(
+
/*
+
** Implementation of xTokenize_v2() API.
+
*/
+
static int fts5ApiTokenize_v2(
  Fts5Context *pCtx,
  const char *pText, int nText,
+
  const char *pLoc, int nLoc,
  void *pUserData,
  int (*xToken)(void*, int, const char*, int, int, int)
){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
-
  return sqlite3Fts5Tokenize(
-
      pTab->pConfig, FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
+
  int rc = SQLITE_OK;
+

+
  sqlite3Fts5SetLocale(pTab->pConfig, pLoc, nLoc);
+
  rc = sqlite3Fts5Tokenize(pTab->pConfig,
+
      FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
  );
+
  sqlite3Fts5SetLocale(pTab->pConfig, 0, 0);
+

+
  return rc;
+
}
+

+
/*
+
** Implementation of xTokenize() API. This is just xTokenize_v2() with NULL/0
+
** passed as the locale.
+
*/
+
static int fts5ApiTokenize(
+
  Fts5Context *pCtx,
+
  const char *pText, int nText,
+
  void *pUserData,
+
  int (*xToken)(void*, int, const char*, int, int, int)
+
){
+
  return fts5ApiTokenize_v2(pCtx, pText, nText, 0, 0, pUserData, xToken);
}

static int fts5ApiPhraseCount(Fts5Context *pCtx){
@@ -251501,6 +253497,49 @@ static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
  return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
}

+
/*
+
** Argument pStmt is an SQL statement of the type used by Fts5Cursor. This
+
** function extracts the text value of column iCol of the current row.
+
** Additionally, if there is an associated locale, it invokes
+
** sqlite3Fts5SetLocale() to configure the tokenizer. In all cases the caller
+
** should invoke sqlite3Fts5ClearLocale() to clear the locale at some point
+
** after this function returns.
+
**
+
** If successful, (*ppText) is set to point to a buffer containing the text
+
** value as utf-8 and SQLITE_OK returned. (*pnText) is set to the size of that
+
** buffer in bytes. It is not guaranteed to be nul-terminated. If an error
+
** occurs, an SQLite error code is returned. The final values of the two
+
** output parameters are undefined in this case.
+
*/
+
static int fts5TextFromStmt(
+
  Fts5Config *pConfig,
+
  sqlite3_stmt *pStmt,
+
  int iCol,
+
  const char **ppText,
+
  int *pnText
+
){
+
  sqlite3_value *pVal = sqlite3_column_value(pStmt, iCol+1);
+
  const char *pLoc = 0;
+
  int nLoc = 0;
+
  int rc = SQLITE_OK;
+

+
  if( pConfig->bLocale
+
   && pConfig->eContent==FTS5_CONTENT_EXTERNAL
+
   && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+
  ){
+
    rc = sqlite3Fts5DecodeLocaleValue(pVal, ppText, pnText, &pLoc, &nLoc);
+
  }else{
+
    *ppText = (const char*)sqlite3_value_text(pVal);
+
    *pnText = sqlite3_value_bytes(pVal);
+
    if( pConfig->bLocale && pConfig->eContent==FTS5_CONTENT_NORMAL ){
+
      pLoc = (const char*)sqlite3_column_text(pStmt, iCol+1+pConfig->nCol);
+
      nLoc = sqlite3_column_bytes(pStmt, iCol+1+pConfig->nCol);
+
    }
+
  }
+
  sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+
  return rc;
+
}
+

static int fts5ApiColumnText(
  Fts5Context *pCtx,
  int iCol,
@@ -251510,28 +253549,35 @@ static int fts5ApiColumnText(
  int rc = SQLITE_OK;
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+

+
  assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
  if( iCol<0 || iCol>=pTab->pConfig->nCol ){
    rc = SQLITE_RANGE;
-
  }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
-
   || pCsr->ePlan==FTS5_PLAN_SPECIAL
-
  ){
+
  }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab), 0) ){
    *pz = 0;
    *pn = 0;
  }else{
    rc = fts5SeekCursor(pCsr, 0);
    if( rc==SQLITE_OK ){
-
      *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
-
      *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
+
      rc = fts5TextFromStmt(pTab->pConfig, pCsr->pStmt, iCol, pz, pn);
+
      sqlite3Fts5ClearLocale(pTab->pConfig);
    }
  }
  return rc;
}

+
/*
+
** This is called by various API functions - xInst, xPhraseFirst,
+
** xPhraseFirstColumn etc. - to obtain the position list for phrase iPhrase
+
** of the current row. This function works for both detail=full tables (in
+
** which case the position-list was read from the fts index) or for other
+
** detail= modes if the row content is available.
+
*/
static int fts5CsrPoslist(
-
  Fts5Cursor *pCsr,
-
  int iPhrase,
-
  const u8 **pa,
-
  int *pn
+
  Fts5Cursor *pCsr,               /* Fts5 cursor object */
+
  int iPhrase,                    /* Phrase to find position list for */
+
  const u8 **pa,                  /* OUT: Pointer to position list buffer */
+
  int *pn                         /* OUT: Size of (*pa) in bytes */
){
  Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
  int rc = SQLITE_OK;
@@ -251539,20 +253585,32 @@ static int fts5CsrPoslist(

  if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
    rc = SQLITE_RANGE;
+
  }else if( pConfig->eDetail!=FTS5_DETAIL_FULL
+
         && fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
+
  ){
+
    *pa = 0;
+
    *pn = 0;
+
    return SQLITE_OK;
  }else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
    if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
      Fts5PoslistPopulator *aPopulator;
      int i;
+

      aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
      if( aPopulator==0 ) rc = SQLITE_NOMEM;
+
      if( rc==SQLITE_OK ){
+
        rc = fts5SeekCursor(pCsr, 0);
+
      }
      for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
-
        int n; const char *z;
-
        rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
+
        const char *z = 0;
+
        int n = 0;
+
        rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
        if( rc==SQLITE_OK ){
          rc = sqlite3Fts5ExprPopulatePoslists(
              pConfig, pCsr->pExpr, aPopulator, i, z, n
          );
        }
+
        sqlite3Fts5ClearLocale(pConfig);
      }
      sqlite3_free(aPopulator);

@@ -251577,7 +253635,6 @@ static int fts5CsrPoslist(
    *pn = 0;
  }

-

  return rc;
}

@@ -251646,7 +253703,8 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
        aInst[0] = iBest;
        aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
        aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
-
        if( aInst[1]<0 || aInst[1]>=nCol ){
+
        assert( aInst[1]>=0 );
+
        if( aInst[1]>=nCol ){
          rc = FTS5_CORRUPT;
          break;
        }
@@ -251724,7 +253782,7 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
    if( pConfig->bColumnsize ){
      i64 iRowid = fts5CursorRowid(pCsr);
      rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
-
    }else if( pConfig->zContent==0 ){
+
    }else if( !pConfig->zContent || pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
      int i;
      for(i=0; i<pConfig->nCol; i++){
        if( pConfig->abUnindexed[i]==0 ){
@@ -251733,17 +253791,19 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
      }
    }else{
      int i;
+
      rc = fts5SeekCursor(pCsr, 0);
      for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
        if( pConfig->abUnindexed[i]==0 ){
-
          const char *z; int n;
-
          void *p = (void*)(&pCsr->aColumnSize[i]);
+
          const char *z = 0;
+
          int n = 0;
          pCsr->aColumnSize[i] = 0;
-
          rc = fts5ApiColumnText(pCtx, i, &z, &n);
+
          rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
          if( rc==SQLITE_OK ){
-
            rc = sqlite3Fts5Tokenize(
-
                pConfig, FTS5_TOKENIZE_AUX, z, n, p, fts5ColumnSizeCb
+
            rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_AUX,
+
                z, n, (void*)&pCsr->aColumnSize[i], fts5ColumnSizeCb
            );
          }
+
          sqlite3Fts5ClearLocale(pConfig);
        }
      }
    }
@@ -251823,11 +253883,10 @@ static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){
}

static void fts5ApiPhraseNext(
-
  Fts5Context *pUnused,
+
  Fts5Context *pCtx,
  Fts5PhraseIter *pIter,
  int *piCol, int *piOff
){
-
  UNUSED_PARAM(pUnused);
  if( pIter->a>=pIter->b ){
    *piCol = -1;
    *piOff = -1;
@@ -251835,8 +253894,12 @@ static void fts5ApiPhraseNext(
    int iVal;
    pIter->a += fts5GetVarint32(pIter->a, iVal);
    if( iVal==1 ){
+
      /* Avoid returning a (*piCol) value that is too large for the table,
+
      ** even if the position-list is corrupt. The caller might not be
+
      ** expecting it.  */
+
      int nCol = ((Fts5Table*)(((Fts5Cursor*)pCtx)->base.pVtab))->pConfig->nCol;
      pIter->a += fts5GetVarint32(pIter->a, iVal);
-
      *piCol = iVal;
+
      *piCol = (iVal>=nCol ? nCol-1 : iVal);
      *piOff = 0;
      pIter->a += fts5GetVarint32(pIter->a, iVal);
    }
@@ -251986,8 +254049,48 @@ static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
    int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
);

+
/*
+
** The xColumnLocale() API.
+
*/
+
static int fts5ApiColumnLocale(
+
  Fts5Context *pCtx,
+
  int iCol,
+
  const char **pzLocale,
+
  int *pnLocale
+
){
+
  int rc = SQLITE_OK;
+
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
+
  Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
+

+
  *pzLocale = 0;
+
  *pnLocale = 0;
+

+
  assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
+
  if( iCol<0 || iCol>=pConfig->nCol ){
+
    rc = SQLITE_RANGE;
+
  }else if(
+
      pConfig->abUnindexed[iCol]==0
+
   && 0==fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
+
   && pConfig->bLocale
+
  ){
+
    rc = fts5SeekCursor(pCsr, 0);
+
    if( rc==SQLITE_OK ){
+
      const char *zDummy = 0;
+
      int nDummy = 0;
+
      rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &zDummy, &nDummy);
+
      if( rc==SQLITE_OK ){
+
        *pzLocale = pConfig->t.pLocale;
+
        *pnLocale = pConfig->t.nLocale;
+
      }
+
      sqlite3Fts5ClearLocale(pConfig);
+
    }
+
  }
+

+
  return rc;
+
}
+

static const Fts5ExtensionApi sFts5Api = {
-
  3,                            /* iVersion */
+
  4,                            /* iVersion */
  fts5ApiUserData,
  fts5ApiColumnCount,
  fts5ApiRowCount,
@@ -252008,7 +254111,9 @@ static const Fts5ExtensionApi sFts5Api = {
  fts5ApiPhraseFirstColumn,
  fts5ApiPhraseNextColumn,
  fts5ApiQueryToken,
-
  fts5ApiInstToken
+
  fts5ApiInstToken,
+
  fts5ApiColumnLocale,
+
  fts5ApiTokenize_v2
};

/*
@@ -252059,6 +254164,7 @@ static void fts5ApiInvoke(
  sqlite3_value **argv
){
  assert( pCsr->pAux==0 );
+
  assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
  pCsr->pAux = pAux;
  pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
  pCsr->pAux = 0;
@@ -252072,6 +254178,21 @@ static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){
  return pCsr;
}

+
/*
+
** Parameter zFmt is a printf() style formatting string. This function
+
** formats it using the trailing arguments and returns the result as
+
** an error message to the context passed as the first argument.
+
*/
+
static void fts5ResultError(sqlite3_context *pCtx, const char *zFmt, ...){
+
  char *zErr = 0;
+
  va_list ap;
+
  va_start(ap, zFmt);
+
  zErr = sqlite3_vmprintf(zFmt, ap);
+
  sqlite3_result_error(pCtx, zErr, -1);
+
  sqlite3_free(zErr);
+
  va_end(ap);
+
}
+

static void fts5ApiCallback(
  sqlite3_context *context,
  int argc,
@@ -252087,12 +254208,13 @@ static void fts5ApiCallback(
  iCsrId = sqlite3_value_int64(argv[0]);

  pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
-
  if( pCsr==0 || pCsr->ePlan==0 ){
-
    char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
-
    sqlite3_result_error(context, zErr, -1);
-
    sqlite3_free(zErr);
+
  if( pCsr==0 || (pCsr->ePlan==0 || pCsr->ePlan==FTS5_PLAN_SPECIAL) ){
+
    fts5ResultError(context, "no such cursor: %lld", iCsrId);
  }else{
+
    sqlite3_vtab *pTab = pCsr->base.pVtab;
    fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
+
    sqlite3_free(pTab->zErrMsg);
+
    pTab->zErrMsg = 0;
  }
}

@@ -252210,8 +254332,8 @@ static int fts5ColumnMethod(
    ** auxiliary function.  */
    sqlite3_result_int64(pCtx, pCsr->iCsrId);
  }else if( iCol==pConfig->nCol+1 ){
-

    /* The value of the "rank" column. */
+

    if( pCsr->ePlan==FTS5_PLAN_SOURCE ){
      fts5PoslistBlob(pCtx, pCsr);
    }else if(
@@ -252222,20 +254344,32 @@ static int fts5ColumnMethod(
        fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
      }
    }
-
  }else if( !fts5IsContentless(pTab) ){
-
    pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
-
    rc = fts5SeekCursor(pCsr, 1);
-
    if( rc==SQLITE_OK ){
-
      sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
+
  }else{
+
    if( !sqlite3_vtab_nochange(pCtx) && pConfig->eContent!=FTS5_CONTENT_NONE ){
+
      pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
+
      rc = fts5SeekCursor(pCsr, 1);
+
      if( rc==SQLITE_OK ){
+
        sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
+
        if( pConfig->bLocale
+
         && pConfig->eContent==FTS5_CONTENT_EXTERNAL
+
         && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+
        ){
+
          const char *z = 0;
+
          int n = 0;
+
          rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &z, &n);
+
          if( rc==SQLITE_OK ){
+
            sqlite3_result_text(pCtx, z, n, SQLITE_TRANSIENT);
+
          }
+
          sqlite3Fts5ClearLocale(pConfig);
+
        }else{
+
          sqlite3_result_value(pCtx, pVal);
+
        }
+
      }
+

+
      pConfig->pzErrmsg = 0;
    }
-
    pConfig->pzErrmsg = 0;
-
  }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){
-
    char *zErr = sqlite3_mprintf("cannot UPDATE a subset of "
-
        "columns on fts5 contentless-delete table: %s", pConfig->zName
-
    );
-
    sqlite3_result_error(pCtx, zErr, -1);
-
    sqlite3_free(zErr);
  }
+

  return rc;
}

@@ -252375,47 +254509,210 @@ static int fts5CreateAux(
}

/*
-
** Register a new tokenizer. This is the implementation of the
-
** fts5_api.xCreateTokenizer() method.
+
** This function is used by xCreateTokenizer_v2() and xCreateTokenizer().
+
** It allocates and partially populates a new Fts5TokenizerModule object.
+
** The new object is already linked into the Fts5Global context before
+
** returning.
+
**
+
** If successful, SQLITE_OK is returned and a pointer to the new
+
** Fts5TokenizerModule object returned via output parameter (*ppNew). All
+
** that is required is for the caller to fill in the methods in
+
** Fts5TokenizerModule.x1 and x2, and to set Fts5TokenizerModule.bV2Native
+
** as appropriate.
+
**
+
** If an error occurs, an SQLite error code is returned and the final value
+
** of (*ppNew) undefined.
*/
-
static int fts5CreateTokenizer(
-
  fts5_api *pApi,                 /* Global context (one per db handle) */
+
static int fts5NewTokenizerModule(
+
  Fts5Global *pGlobal,            /* Global context (one per db handle) */
  const char *zName,              /* Name of new function */
  void *pUserData,                /* User data for aux. function */
-
  fts5_tokenizer *pTokenizer,     /* Tokenizer implementation */
-
  void(*xDestroy)(void*)          /* Destructor for pUserData */
+
  void(*xDestroy)(void*),         /* Destructor for pUserData */
+
  Fts5TokenizerModule **ppNew
){
-
  Fts5Global *pGlobal = (Fts5Global*)pApi;
-
  Fts5TokenizerModule *pNew;
-
  sqlite3_int64 nName;            /* Size of zName and its \0 terminator */
-
  sqlite3_int64 nByte;            /* Bytes of space to allocate */
  int rc = SQLITE_OK;
+
  Fts5TokenizerModule *pNew;
+
  sqlite3_int64 nName;          /* Size of zName and its \0 terminator */
+
  sqlite3_int64 nByte;          /* Bytes of space to allocate */

  nName = strlen(zName) + 1;
  nByte = sizeof(Fts5TokenizerModule) + nName;
-
  pNew = (Fts5TokenizerModule*)sqlite3_malloc64(nByte);
+
  *ppNew = pNew = (Fts5TokenizerModule*)sqlite3Fts5MallocZero(&rc, nByte);
  if( pNew ){
-
    memset(pNew, 0, (size_t)nByte);
    pNew->zName = (char*)&pNew[1];
    memcpy(pNew->zName, zName, nName);
    pNew->pUserData = pUserData;
-
    pNew->x = *pTokenizer;
    pNew->xDestroy = xDestroy;
    pNew->pNext = pGlobal->pTok;
    pGlobal->pTok = pNew;
    if( pNew->pNext==0 ){
      pGlobal->pDfltTok = pNew;
    }
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** An instance of this type is used as the Fts5Tokenizer object for
+
** wrapper tokenizers - those that provide access to a v1 tokenizer via
+
** the fts5_tokenizer_v2 API, and those that provide access to a v2 tokenizer
+
** via the fts5_tokenizer API.
+
*/
+
typedef struct Fts5VtoVTokenizer Fts5VtoVTokenizer;
+
struct Fts5VtoVTokenizer {
+
  int bV2Native;                  /* True if v2 native tokenizer */
+
  fts5_tokenizer x1;              /* Tokenizer functions */
+
  fts5_tokenizer_v2 x2;           /* V2 tokenizer functions */
+
  Fts5Tokenizer *pReal;
+
};
+

+
/*
+
** Create a wrapper tokenizer. The context argument pCtx points to the
+
** Fts5TokenizerModule object.
+
*/
+
static int fts5VtoVCreate(
+
  void *pCtx,
+
  const char **azArg,
+
  int nArg,
+
  Fts5Tokenizer **ppOut
+
){
+
  Fts5TokenizerModule *pMod = (Fts5TokenizerModule*)pCtx;
+
  Fts5VtoVTokenizer *pNew = 0;
+
  int rc = SQLITE_OK;
+

+
  pNew = (Fts5VtoVTokenizer*)sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
+
  if( rc==SQLITE_OK ){
+
    pNew->x1 = pMod->x1;
+
    pNew->x2 = pMod->x2;
+
    pNew->bV2Native = pMod->bV2Native;
+
    if( pMod->bV2Native ){
+
      rc = pMod->x2.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal);
+
    }else{
+
      rc = pMod->x1.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal);
+
    }
+
    if( rc!=SQLITE_OK ){
+
      sqlite3_free(pNew);
+
      pNew = 0;
+
    }
+
  }
+

+
  *ppOut = (Fts5Tokenizer*)pNew;
+
  return rc;
+
}
+

+
/*
+
** Delete an Fts5VtoVTokenizer wrapper tokenizer.
+
*/
+
static void fts5VtoVDelete(Fts5Tokenizer *pTok){
+
  Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
+
  if( p ){
+
    if( p->bV2Native ){
+
      p->x2.xDelete(p->pReal);
+
    }else{
+
      p->x1.xDelete(p->pReal);
+
    }
+
    sqlite3_free(p);
+
  }
+
}
+

+

+
/*
+
** xTokenizer method for a wrapper tokenizer that offers the v1 interface
+
** (no support for locales).
+
*/
+
static int fts5V1toV2Tokenize(
+
  Fts5Tokenizer *pTok,
+
  void *pCtx, int flags,
+
  const char *pText, int nText,
+
  int (*xToken)(void*, int, const char*, int, int, int)
+
){
+
  Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
+
  assert( p->bV2Native );
+
  return p->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
+
}
+

+
/*
+
** xTokenizer method for a wrapper tokenizer that offers the v2 interface
+
** (with locale support).
+
*/
+
static int fts5V2toV1Tokenize(
+
  Fts5Tokenizer *pTok,
+
  void *pCtx, int flags,
+
  const char *pText, int nText,
+
  const char *pLocale, int nLocale,
+
  int (*xToken)(void*, int, const char*, int, int, int)
+
){
+
  Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
+
  assert( p->bV2Native==0 );
+
  UNUSED_PARAM2(pLocale,nLocale);
+
  return p->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
+
}
+

+
/*
+
** Register a new tokenizer. This is the implementation of the
+
** fts5_api.xCreateTokenizer_v2() method.
+
*/
+
static int fts5CreateTokenizer_v2(
+
  fts5_api *pApi,                 /* Global context (one per db handle) */
+
  const char *zName,              /* Name of new function */
+
  void *pUserData,                /* User data for aux. function */
+
  fts5_tokenizer_v2 *pTokenizer,  /* Tokenizer implementation */
+
  void(*xDestroy)(void*)          /* Destructor for pUserData */
+
){
+
  Fts5Global *pGlobal = (Fts5Global*)pApi;
+
  int rc = SQLITE_OK;
+

+
  if( pTokenizer->iVersion>2 ){
+
    rc = SQLITE_ERROR;
  }else{
-
    rc = SQLITE_NOMEM;
+
    Fts5TokenizerModule *pNew = 0;
+
    rc = fts5NewTokenizerModule(pGlobal, zName, pUserData, xDestroy, &pNew);
+
    if( pNew ){
+
      pNew->x2 = *pTokenizer;
+
      pNew->bV2Native = 1;
+
      pNew->x1.xCreate = fts5VtoVCreate;
+
      pNew->x1.xTokenize = fts5V1toV2Tokenize;
+
      pNew->x1.xDelete = fts5VtoVDelete;
+
    }
  }

  return rc;
}

+
/*
+
** The fts5_api.xCreateTokenizer() method.
+
*/
+
static int fts5CreateTokenizer(
+
  fts5_api *pApi,                 /* Global context (one per db handle) */
+
  const char *zName,              /* Name of new function */
+
  void *pUserData,                /* User data for aux. function */
+
  fts5_tokenizer *pTokenizer,     /* Tokenizer implementation */
+
  void(*xDestroy)(void*)          /* Destructor for pUserData */
+
){
+
  Fts5TokenizerModule *pNew = 0;
+
  int rc = SQLITE_OK;
+

+
  rc = fts5NewTokenizerModule(
+
      (Fts5Global*)pApi, zName, pUserData, xDestroy, &pNew
+
  );
+
  if( pNew ){
+
    pNew->x1 = *pTokenizer;
+
    pNew->x2.xCreate = fts5VtoVCreate;
+
    pNew->x2.xTokenize = fts5V2toV1Tokenize;
+
    pNew->x2.xDelete = fts5VtoVDelete;
+
  }
+
  return rc;
+
}
+

+
/*
+
** Search the global context passed as the first argument for a tokenizer
+
** module named zName. If found, return a pointer to the Fts5TokenizerModule
+
** object. Otherwise, return NULL.
+
*/
static Fts5TokenizerModule *fts5LocateTokenizer(
-
  Fts5Global *pGlobal,
-
  const char *zName
+
  Fts5Global *pGlobal,            /* Global (one per db handle) object */
+
  const char *zName               /* Name of tokenizer module to find */
){
  Fts5TokenizerModule *pMod = 0;

@@ -252432,6 +254729,36 @@ static Fts5TokenizerModule *fts5LocateTokenizer(

/*
** Find a tokenizer. This is the implementation of the
+
** fts5_api.xFindTokenizer_v2() method.
+
*/
+
static int fts5FindTokenizer_v2(
+
  fts5_api *pApi,                 /* Global context (one per db handle) */
+
  const char *zName,              /* Name of tokenizer */
+
  void **ppUserData,
+
  fts5_tokenizer_v2 **ppTokenizer /* Populate this object */
+
){
+
  int rc = SQLITE_OK;
+
  Fts5TokenizerModule *pMod;
+

+
  pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName);
+
  if( pMod ){
+
    if( pMod->bV2Native ){
+
      *ppUserData = pMod->pUserData;
+
    }else{
+
      *ppUserData = (void*)pMod;
+
    }
+
    *ppTokenizer = &pMod->x2;
+
  }else{
+
    *ppTokenizer = 0;
+
    *ppUserData = 0;
+
    rc = SQLITE_ERROR;
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** Find a tokenizer. This is the implementation of the
** fts5_api.xFindTokenizer() method.
*/
static int fts5FindTokenizer(
@@ -252445,55 +254772,75 @@ static int fts5FindTokenizer(

  pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName);
  if( pMod ){
-
    *pTokenizer = pMod->x;
-
    *ppUserData = pMod->pUserData;
+
    if( pMod->bV2Native==0 ){
+
      *ppUserData = pMod->pUserData;
+
    }else{
+
      *ppUserData = (void*)pMod;
+
    }
+
    *pTokenizer = pMod->x1;
  }else{
-
    memset(pTokenizer, 0, sizeof(fts5_tokenizer));
+
    memset(pTokenizer, 0, sizeof(*pTokenizer));
+
    *ppUserData = 0;
    rc = SQLITE_ERROR;
  }

  return rc;
}

-
static int sqlite3Fts5GetTokenizer(
-
  Fts5Global *pGlobal,
-
  const char **azArg,
-
  int nArg,
-
  Fts5Config *pConfig,
-
  char **pzErr
-
){
-
  Fts5TokenizerModule *pMod;
+
/*
+
** Attempt to instantiate the tokenizer.
+
*/
+
static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig){
+
  const char **azArg = pConfig->t.azArg;
+
  const int nArg = pConfig->t.nArg;
+
  Fts5TokenizerModule *pMod = 0;
  int rc = SQLITE_OK;

-
  pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
+
  pMod = fts5LocateTokenizer(pConfig->pGlobal, nArg==0 ? 0 : azArg[0]);
  if( pMod==0 ){
    assert( nArg>0 );
    rc = SQLITE_ERROR;
-
    if( pzErr ) *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
+
    sqlite3Fts5ConfigErrmsg(pConfig, "no such tokenizer: %s", azArg[0]);
  }else{
-
    rc = pMod->x.xCreate(
-
        pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
+
    int (*xCreate)(void*, const char**, int, Fts5Tokenizer**) = 0;
+
    if( pMod->bV2Native ){
+
      xCreate = pMod->x2.xCreate;
+
      pConfig->t.pApi2 = &pMod->x2;
+
    }else{
+
      pConfig->t.pApi1 = &pMod->x1;
+
      xCreate = pMod->x1.xCreate;
+
    }
+

+
    rc = xCreate(pMod->pUserData,
+
        (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->t.pTok
    );
-
    pConfig->pTokApi = &pMod->x;
+

    if( rc!=SQLITE_OK ){
-
      if( pzErr && rc!=SQLITE_NOMEM ){
-
        *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+
      if( rc!=SQLITE_NOMEM ){
+
        sqlite3Fts5ConfigErrmsg(pConfig, "error in tokenizer constructor");
      }
-
    }else{
-
      pConfig->ePattern = sqlite3Fts5TokenizerPattern(
-
          pMod->x.xCreate, pConfig->pTok
+
    }else if( pMod->bV2Native==0 ){
+
      pConfig->t.ePattern = sqlite3Fts5TokenizerPattern(
+
          pMod->x1.xCreate, pConfig->t.pTok
      );
    }
  }

  if( rc!=SQLITE_OK ){
-
    pConfig->pTokApi = 0;
-
    pConfig->pTok = 0;
+
    pConfig->t.pApi1 = 0;
+
    pConfig->t.pApi2 = 0;
+
    pConfig->t.pTok = 0;
  }

  return rc;
}

+

+
/*
+
** xDestroy callback passed to sqlite3_create_module(). This is invoked
+
** when the db handle is being closed. Free memory associated with
+
** tokenizers and aux functions registered with this db handle.
+
*/
static void fts5ModuleDestroy(void *pCtx){
  Fts5TokenizerModule *pTok, *pNextTok;
  Fts5Auxiliary *pAux, *pNextAux;
@@ -252514,6 +254861,10 @@ static void fts5ModuleDestroy(void *pCtx){
  sqlite3_free(pGlobal);
}

+
/*
+
** Implementation of the fts5() function used by clients to obtain the
+
** API pointer.
+
*/
static void fts5Fts5Func(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
@@ -252537,7 +254888,68 @@ static void fts5SourceIdFunc(
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
-
  sqlite3_result_text(pCtx, "fts5: 2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33", -1, SQLITE_TRANSIENT);
+
  sqlite3_result_text(pCtx, "fts5: 2024-10-21 16:30:22 03a9703e27c44437c39363d0baf82db4ebc94538a0f28411c85dda156f82636e", -1, SQLITE_TRANSIENT);
+
}
+

+
/*
+
** Implementation of fts5_locale(LOCALE, TEXT) function.
+
**
+
** If parameter LOCALE is NULL, or a zero-length string, then a copy of
+
** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as
+
** text, and the value returned is a blob consisting of:
+
**
+
**     * The 4 bytes 0x00, 0xE0, 0xB2, 0xEb (FTS5_LOCALE_HEADER).
+
**     * The LOCALE, as utf-8 text, followed by
+
**     * 0x00, followed by
+
**     * The TEXT, as utf-8 text.
+
**
+
** There is no final nul-terminator following the TEXT value.
+
*/
+
static void fts5LocaleFunc(
+
  sqlite3_context *pCtx,          /* Function call context */
+
  int nArg,                       /* Number of args */
+
  sqlite3_value **apArg           /* Function arguments */
+
){
+
  const char *zLocale = 0;
+
  int nLocale = 0;
+
  const char *zText = 0;
+
  int nText = 0;
+

+
  assert( nArg==2 );
+
  UNUSED_PARAM(nArg);
+

+
  zLocale = (const char*)sqlite3_value_text(apArg[0]);
+
  nLocale = sqlite3_value_bytes(apArg[0]);
+

+
  zText = (const char*)sqlite3_value_text(apArg[1]);
+
  nText = sqlite3_value_bytes(apArg[1]);
+

+
  if( zLocale==0 || zLocale[0]=='\0' ){
+
    sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT);
+
  }else{
+
    Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx);
+
    u8 *pBlob = 0;
+
    u8 *pCsr = 0;
+
    int nBlob = 0;
+

+
    nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText;
+
    pBlob = (u8*)sqlite3_malloc(nBlob);
+
    if( pBlob==0 ){
+
      sqlite3_result_error_nomem(pCtx);
+
      return;
+
    }
+

+
    pCsr = pBlob;
+
    memcpy(pCsr, (const u8*)p->aLocaleHdr, FTS5_LOCALE_HDR_SIZE);
+
    pCsr += FTS5_LOCALE_HDR_SIZE;
+
    memcpy(pCsr, zLocale, nLocale);
+
    pCsr += nLocale;
+
    (*pCsr++) = 0x00;
+
    if( zText ) memcpy(pCsr, zText, nText);
+
    assert( &pCsr[nText]==&pBlob[nBlob] );
+

+
    sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
+
  }
}

/*
@@ -252632,10 +255044,22 @@ static int fts5Init(sqlite3 *db){
    void *p = (void*)pGlobal;
    memset(pGlobal, 0, sizeof(Fts5Global));
    pGlobal->db = db;
-
    pGlobal->api.iVersion = 2;
+
    pGlobal->api.iVersion = 3;
    pGlobal->api.xCreateFunction = fts5CreateAux;
    pGlobal->api.xCreateTokenizer = fts5CreateTokenizer;
    pGlobal->api.xFindTokenizer = fts5FindTokenizer;
+
    pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2;
+
    pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2;
+

+
    /* Initialize pGlobal->aLocaleHdr[] to a 128-bit pseudo-random vector.
+
    ** The constants below were generated randomly.  */
+
    sqlite3_randomness(sizeof(pGlobal->aLocaleHdr), pGlobal->aLocaleHdr);
+
    pGlobal->aLocaleHdr[0] ^= 0xF924976D;
+
    pGlobal->aLocaleHdr[1] ^= 0x16596E13;
+
    pGlobal->aLocaleHdr[2] ^= 0x7C80BEAA;
+
    pGlobal->aLocaleHdr[3] ^= 0x9B03A67F;
+
    assert( sizeof(pGlobal->aLocaleHdr)==16 );
+

    rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
@@ -252654,6 +255078,13 @@ static int fts5Init(sqlite3 *db){
          p, fts5SourceIdFunc, 0, 0
      );
    }
+
    if( rc==SQLITE_OK ){
+
      rc = sqlite3_create_function(
+
          db, "fts5_locale", 2,
+
          SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
+
          p, fts5LocaleFunc, 0, 0
+
      );
+
    }
  }

  /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
@@ -252728,13 +255159,40 @@ SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3 *db){

/* #include "fts5Int.h" */

+
/*
+
** pSavedRow:
+
**   SQL statement FTS5_STMT_LOOKUP2 is a copy of FTS5_STMT_LOOKUP, it
+
**   does a by-rowid lookup to retrieve a single row from the %_content
+
**   table or equivalent external-content table/view.
+
**
+
**   However, FTS5_STMT_LOOKUP2 is only used when retrieving the original
+
**   values for a row being UPDATEd. In that case, the SQL statement is
+
**   not reset and pSavedRow is set to point at it. This is so that the
+
**   insert operation that follows the delete may access the original
+
**   row values for any new values for which sqlite3_value_nochange() returns
+
**   true. i.e. if the user executes:
+
**
+
**        CREATE VIRTUAL TABLE ft USING fts5(a, b, c, locale=1);
+
**        ...
+
**        UPDATE fts SET a=?, b=? WHERE rowid=?;
+
**
+
**   then the value passed to the xUpdate() method of this table as the
+
**   new.c value is an sqlite3_value_nochange() value. So in this case it
+
**   must be read from the saved row stored in Fts5Storage.pSavedRow.
+
**
+
**   This is necessary - using sqlite3_value_nochange() instead of just having
+
**   SQLite pass the original value back via xUpdate() - so as not to discard
+
**   any locale information associated with such values.
+
**
+
*/
struct Fts5Storage {
  Fts5Config *pConfig;
  Fts5Index *pIndex;
  int bTotalsValid;               /* True if nTotalRow/aTotalSize[] are valid */
  i64 nTotalRow;                  /* Total number of rows in FTS table */
  i64 *aTotalSize;                /* Total sizes of each column */
-
  sqlite3_stmt *aStmt[11];
+
  sqlite3_stmt *pSavedRow;
+
  sqlite3_stmt *aStmt[12];
};


@@ -252748,14 +255206,15 @@ struct Fts5Storage {
# error "FTS5_STMT_LOOKUP mismatch"
#endif

-
#define FTS5_STMT_INSERT_CONTENT  3
-
#define FTS5_STMT_REPLACE_CONTENT 4
-
#define FTS5_STMT_DELETE_CONTENT  5
-
#define FTS5_STMT_REPLACE_DOCSIZE  6
-
#define FTS5_STMT_DELETE_DOCSIZE  7
-
#define FTS5_STMT_LOOKUP_DOCSIZE  8
-
#define FTS5_STMT_REPLACE_CONFIG 9
-
#define FTS5_STMT_SCAN 10
+
#define FTS5_STMT_LOOKUP2         3
+
#define FTS5_STMT_INSERT_CONTENT  4
+
#define FTS5_STMT_REPLACE_CONTENT 5
+
#define FTS5_STMT_DELETE_CONTENT  6
+
#define FTS5_STMT_REPLACE_DOCSIZE 7
+
#define FTS5_STMT_DELETE_DOCSIZE  8
+
#define FTS5_STMT_LOOKUP_DOCSIZE  9
+
#define FTS5_STMT_REPLACE_CONFIG 10
+
#define FTS5_STMT_SCAN           11

/*
** Prepare the two insert statements - Fts5Storage.pInsertContent and
@@ -252785,6 +255244,7 @@ static int fts5StorageGetStmt(
      "SELECT %s FROM %s T WHERE T.%Q >= ? AND T.%Q <= ? ORDER BY T.%Q ASC",
      "SELECT %s FROM %s T WHERE T.%Q <= ? AND T.%Q >= ? ORDER BY T.%Q DESC",
      "SELECT %s FROM %s T WHERE T.%Q=?",               /* LOOKUP  */
+
      "SELECT %s FROM %s T WHERE T.%Q=?",               /* LOOKUP2  */

      "INSERT INTO %Q.'%q_content' VALUES(%s)",         /* INSERT_CONTENT  */
      "REPLACE INTO %Q.'%q_content' VALUES(%s)",        /* REPLACE_CONTENT */
@@ -252800,6 +255260,8 @@ static int fts5StorageGetStmt(
    Fts5Config *pC = p->pConfig;
    char *zSql = 0;

+
    assert( ArraySize(azStmt)==ArraySize(p->aStmt) );
+

    switch( eStmt ){
      case FTS5_STMT_SCAN:
        zSql = sqlite3_mprintf(azStmt[eStmt],
@@ -252816,6 +255278,7 @@ static int fts5StorageGetStmt(
        break;

      case FTS5_STMT_LOOKUP:
+
      case FTS5_STMT_LOOKUP2:
        zSql = sqlite3_mprintf(azStmt[eStmt],
            pC->zContentExprlist, pC->zContent, pC->zContentRowid
        );
@@ -252823,20 +255286,35 @@ static int fts5StorageGetStmt(

      case FTS5_STMT_INSERT_CONTENT:
      case FTS5_STMT_REPLACE_CONTENT: {
-
        int nCol = pC->nCol + 1;
-
        char *zBind;
+
        char *zBind = 0;
        int i;

-
        zBind = sqlite3_malloc64(1 + nCol*2);
-
        if( zBind ){
-
          for(i=0; i<nCol; i++){
-
            zBind[i*2] = '?';
-
            zBind[i*2 + 1] = ',';
+
        assert( pC->eContent==FTS5_CONTENT_NORMAL
+
             || pC->eContent==FTS5_CONTENT_UNINDEXED
+
        );
+

+
        /* Add bindings for the "c*" columns - those that store the actual
+
        ** table content. If eContent==NORMAL, then there is one binding
+
        ** for each column. Or, if eContent==UNINDEXED, then there are only
+
        ** bindings for the UNINDEXED columns. */
+
        for(i=0; rc==SQLITE_OK && i<(pC->nCol+1); i++){
+
          if( !i || pC->eContent==FTS5_CONTENT_NORMAL || pC->abUnindexed[i-1] ){
+
            zBind = sqlite3Fts5Mprintf(&rc, "%z%s?%d", zBind, zBind?",":"",i+1);
          }
-
          zBind[i*2-1] = '\0';
-
          zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
-
          sqlite3_free(zBind);
        }
+

+
        /* Add bindings for any "l*" columns. Only non-UNINDEXED columns
+
        ** require these.  */
+
        if( pC->bLocale && pC->eContent==FTS5_CONTENT_NORMAL ){
+
          for(i=0; rc==SQLITE_OK && i<pC->nCol; i++){
+
            if( pC->abUnindexed[i]==0 ){
+
              zBind = sqlite3Fts5Mprintf(&rc, "%z,?%d", zBind, pC->nCol+i+2);
+
            }
+
          }
+
        }
+

+
        zSql = sqlite3Fts5Mprintf(&rc, azStmt[eStmt], pC->zDb, pC->zName,zBind);
+
        sqlite3_free(zBind);
        break;
      }

@@ -252862,7 +255340,7 @@ static int fts5StorageGetStmt(
      rc = SQLITE_NOMEM;
    }else{
      int f = SQLITE_PREPARE_PERSISTENT;
-
      if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
+
      if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB;
      p->pConfig->bLock++;
      rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
      p->pConfig->bLock--;
@@ -253022,9 +255500,11 @@ static int sqlite3Fts5StorageOpen(
  p->pIndex = pIndex;

  if( bCreate ){
-
    if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
+
    if( pConfig->eContent==FTS5_CONTENT_NORMAL
+
     || pConfig->eContent==FTS5_CONTENT_UNINDEXED
+
    ){
      int nDefn = 32 + pConfig->nCol*10;
-
      char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
+
      char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
      if( zDefn==0 ){
        rc = SQLITE_NOMEM;
      }else{
@@ -253033,8 +255513,20 @@ static int sqlite3Fts5StorageOpen(
        sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
        iOff = (int)strlen(zDefn);
        for(i=0; i<pConfig->nCol; i++){
-
          sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
-
          iOff += (int)strlen(&zDefn[iOff]);
+
          if( pConfig->eContent==FTS5_CONTENT_NORMAL
+
           || pConfig->abUnindexed[i]
+
          ){
+
            sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
+
            iOff += (int)strlen(&zDefn[iOff]);
+
          }
+
        }
+
        if( pConfig->bLocale ){
+
          for(i=0; i<pConfig->nCol; i++){
+
            if( pConfig->abUnindexed[i]==0 ){
+
              sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
+
              iOff += (int)strlen(&zDefn[iOff]);
+
            }
+
          }
        }
        rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
      }
@@ -253112,14 +255604,48 @@ static int fts5StorageInsertCallback(
}

/*
+
** This function is used as part of an UPDATE statement that modifies the
+
** rowid of a row. In that case, this function is called first to set
+
** Fts5Storage.pSavedRow to point to a statement that may be used to
+
** access the original values of the row being deleted - iDel.
+
**
+
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+
** It is not considered an error if row iDel does not exist. In this case
+
** pSavedRow is not set and SQLITE_OK returned.
+
*/
+
static int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel){
+
  int rc = SQLITE_OK;
+
  sqlite3_stmt *pSeek = 0;
+

+
  assert( p->pSavedRow==0 );
+
  rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+1, &pSeek, 0);
+
  if( rc==SQLITE_OK ){
+
    sqlite3_bind_int64(pSeek, 1, iDel);
+
    if( sqlite3_step(pSeek)!=SQLITE_ROW ){
+
      rc = sqlite3_reset(pSeek);
+
    }else{
+
      p->pSavedRow = pSeek;
+
    }
+
  }
+

+
  return rc;
+
}
+

+
/*
** If a row with rowid iDel is present in the %_content table, add the
** delete-markers to the FTS index necessary to delete it. Do not actually
** remove the %_content row at this time though.
+
**
+
** If parameter bSaveRow is true, then Fts5Storage.pSavedRow is left
+
** pointing to a statement (FTS5_STMT_LOOKUP2) that may be used to access
+
** the original values of the row being deleted. This is used by UPDATE
+
** statements.
*/
static int fts5StorageDeleteFromIndex(
  Fts5Storage *p,
  i64 iDel,
-
  sqlite3_value **apVal
+
  sqlite3_value **apVal,
+
  int bSaveRow                    /* True to set pSavedRow */
){
  Fts5Config *pConfig = p->pConfig;
  sqlite3_stmt *pSeek = 0;        /* SELECT to read row iDel from %_data */
@@ -253128,12 +255654,21 @@ static int fts5StorageDeleteFromIndex(
  int iCol;
  Fts5InsertCtx ctx;

+
  assert( bSaveRow==0 || apVal==0 );
+
  assert( bSaveRow==0 || bSaveRow==1 );
+
  assert( FTS5_STMT_LOOKUP2==FTS5_STMT_LOOKUP+1 );
+

  if( apVal==0 ){
-
    rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0);
-
    if( rc!=SQLITE_OK ) return rc;
-
    sqlite3_bind_int64(pSeek, 1, iDel);
-
    if( sqlite3_step(pSeek)!=SQLITE_ROW ){
-
      return sqlite3_reset(pSeek);
+
    if( p->pSavedRow && bSaveRow ){
+
      pSeek = p->pSavedRow;
+
      p->pSavedRow = 0;
+
    }else{
+
      rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+bSaveRow, &pSeek, 0);
+
      if( rc!=SQLITE_OK ) return rc;
+
      sqlite3_bind_int64(pSeek, 1, iDel);
+
      if( sqlite3_step(pSeek)!=SQLITE_ROW ){
+
        return sqlite3_reset(pSeek);
+
      }
    }
  }

@@ -253141,26 +255676,42 @@ static int fts5StorageDeleteFromIndex(
  ctx.iCol = -1;
  for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
    if( pConfig->abUnindexed[iCol-1]==0 ){
-
      const char *zText;
-
      int nText;
+
      sqlite3_value *pVal = 0;
+
      const char *pText = 0;
+
      int nText = 0;
+
      const char *pLoc = 0;
+
      int nLoc = 0;
+

      assert( pSeek==0 || apVal==0 );
      assert( pSeek!=0 || apVal!=0 );
      if( pSeek ){
-
        zText = (const char*)sqlite3_column_text(pSeek, iCol);
-
        nText = sqlite3_column_bytes(pSeek, iCol);
-
      }else if( ALWAYS(apVal) ){
-
        zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
-
        nText = sqlite3_value_bytes(apVal[iCol-1]);
+
        pVal = sqlite3_column_value(pSeek, iCol);
      }else{
-
        continue;
+
        pVal = apVal[iCol-1];
      }
-
      ctx.szCol = 0;
-
      rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
-
          zText, nText, (void*)&ctx, fts5StorageInsertCallback
-
      );
-
      p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
-
      if( p->aTotalSize[iCol-1]<0 ){
-
        rc = FTS5_CORRUPT;
+

+
      if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+
        rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+
      }else{
+
        pText = (const char*)sqlite3_value_text(pVal);
+
        nText = sqlite3_value_bytes(pVal);
+
        if( pConfig->bLocale && pSeek ){
+
          pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
+
          nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
+
        }
+
      }
+

+
      if( rc==SQLITE_OK ){
+
        sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+
        ctx.szCol = 0;
+
        rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
+
            pText, nText, (void*)&ctx, fts5StorageInsertCallback
+
        );
+
        p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
+
        if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
+
          rc = FTS5_CORRUPT;
+
        }
+
        sqlite3Fts5ClearLocale(pConfig);
      }
    }
  }
@@ -253170,12 +255721,30 @@ static int fts5StorageDeleteFromIndex(
    p->nTotalRow--;
  }

-
  rc2 = sqlite3_reset(pSeek);
-
  if( rc==SQLITE_OK ) rc = rc2;
+
  if( rc==SQLITE_OK && bSaveRow ){
+
    assert( p->pSavedRow==0 );
+
    p->pSavedRow = pSeek;
+
  }else{
+
    rc2 = sqlite3_reset(pSeek);
+
    if( rc==SQLITE_OK ) rc = rc2;
+
  }
  return rc;
}

/*
+
** Reset any saved statement pSavedRow. Zero pSavedRow as well. This
+
** should be called by the xUpdate() method of the fts5 table before
+
** returning from any operation that may have set Fts5Storage.pSavedRow.
+
*/
+
static void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage *pStorage){
+
  assert( pStorage->pSavedRow==0
+
       || pStorage->pSavedRow==pStorage->aStmt[FTS5_STMT_LOOKUP2]
+
  );
+
  sqlite3_reset(pStorage->pSavedRow);
+
  pStorage->pSavedRow = 0;
+
}
+

+
/*
** This function is called to process a DELETE on a contentless_delete=1
** table. It adds the tombstone required to delete the entry with rowid
** iDel. If successful, SQLITE_OK is returned. Or, if an error occurs,
@@ -253187,7 +255756,9 @@ static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){
  int rc = SQLITE_OK;

  assert( p->pConfig->bContentlessDelete );
-
  assert( p->pConfig->eContent==FTS5_CONTENT_NONE );
+
  assert( p->pConfig->eContent==FTS5_CONTENT_NONE
+
       || p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
+
  );

  /* Look up the origin of the document in the %_docsize table. Store
  ** this in stack variable iOrigin.  */
@@ -253231,12 +255802,12 @@ static int fts5StorageInsertDocsize(
        rc = sqlite3Fts5IndexGetOrigin(p->pIndex, &iOrigin);
        sqlite3_bind_int64(pReplace, 3, iOrigin);
      }
-
      if( rc==SQLITE_OK ){
-
        sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
-
        sqlite3_step(pReplace);
-
        rc = sqlite3_reset(pReplace);
-
        sqlite3_bind_null(pReplace, 2);
-
      }
+
    }
+
    if( rc==SQLITE_OK ){
+
      sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
+
      sqlite3_step(pReplace);
+
      rc = sqlite3_reset(pReplace);
+
      sqlite3_bind_null(pReplace, 2);
    }
  }
  return rc;
@@ -253290,7 +255861,12 @@ static int fts5StorageSaveTotals(Fts5Storage *p){
/*
** Remove a row from the FTS table.
*/
-
static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
+
static int sqlite3Fts5StorageDelete(
+
  Fts5Storage *p,                 /* Storage object */
+
  i64 iDel,                       /* Rowid to delete from table */
+
  sqlite3_value **apVal,          /* Optional - values to remove from index */
+
  int bSaveRow                    /* If true, set pSavedRow for deleted row */
+
){
  Fts5Config *pConfig = p->pConfig;
  int rc;
  sqlite3_stmt *pDel = 0;
@@ -253306,8 +255882,14 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **ap
  if( rc==SQLITE_OK ){
    if( p->pConfig->bContentlessDelete ){
      rc = fts5StorageContentlessDelete(p, iDel);
+
      if( rc==SQLITE_OK
+
       && bSaveRow
+
       && p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
+
      ){
+
        rc = sqlite3Fts5StorageFindDeleteRow(p, iDel);
+
      }
    }else{
-
      rc = fts5StorageDeleteFromIndex(p, iDel, apVal);
+
      rc = fts5StorageDeleteFromIndex(p, iDel, apVal, bSaveRow);
    }
  }

@@ -253322,7 +255904,9 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **ap
  }

  /* Delete the %_content record */
-
  if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
+
  if( pConfig->eContent==FTS5_CONTENT_NORMAL
+
   || pConfig->eContent==FTS5_CONTENT_UNINDEXED
+
  ){
    if( rc==SQLITE_OK ){
      rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
    }
@@ -253354,8 +255938,13 @@ static int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
  );
  if( rc==SQLITE_OK && pConfig->bColumnsize ){
    rc = fts5ExecPrintf(pConfig->db, 0,
-
        "DELETE FROM %Q.'%q_docsize';",
-
        pConfig->zDb, pConfig->zName
+
        "DELETE FROM %Q.'%q_docsize';", pConfig->zDb, pConfig->zName
+
    );
+
  }
+

+
  if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
+
    rc = fts5ExecPrintf(pConfig->db, 0,
+
        "DELETE FROM %Q.'%q_content';", pConfig->zDb, pConfig->zName
    );
  }

@@ -253396,14 +255985,36 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p){
    for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
      ctx.szCol = 0;
      if( pConfig->abUnindexed[ctx.iCol]==0 ){
-
        const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
-
        int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
-
        rc = sqlite3Fts5Tokenize(pConfig,
-
            FTS5_TOKENIZE_DOCUMENT,
-
            zText, nText,
-
            (void*)&ctx,
-
            fts5StorageInsertCallback
-
        );
+
        int nText = 0;            /* Size of pText in bytes */
+
        const char *pText = 0;    /* Pointer to buffer containing text value */
+
        int nLoc = 0;             /* Size of pLoc in bytes */
+
        const char *pLoc = 0;     /* Pointer to buffer containing text value */
+

+
        sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);
+
        if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
+
         && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+
        ){
+
          rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+
        }else{
+
          pText = (const char*)sqlite3_value_text(pVal);
+
          nText = sqlite3_value_bytes(pVal);
+
          if( pConfig->bLocale ){
+
            int iCol = ctx.iCol + 1 + pConfig->nCol;
+
            pLoc = (const char*)sqlite3_column_text(pScan, iCol);
+
            nLoc = sqlite3_column_bytes(pScan, iCol);
+
          }
+
        }
+

+
        if( rc==SQLITE_OK ){
+
          sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+
          rc = sqlite3Fts5Tokenize(pConfig,
+
              FTS5_TOKENIZE_DOCUMENT,
+
              pText, nText,
+
              (void*)&ctx,
+
              fts5StorageInsertCallback
+
          );
+
          sqlite3Fts5ClearLocale(pConfig);
+
        }
      }
      sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
      p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
@@ -253469,6 +256080,7 @@ static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
*/
static int sqlite3Fts5StorageContentInsert(
  Fts5Storage *p,
+
  int bReplace,                   /* True to use REPLACE instead of INSERT */
  sqlite3_value **apVal,
  i64 *piRowid
){
@@ -253476,7 +256088,9 @@ static int sqlite3Fts5StorageContentInsert(
  int rc = SQLITE_OK;

  /* Insert the new row into the %_content table. */
-
  if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
+
  if( pConfig->eContent!=FTS5_CONTENT_NORMAL
+
   && pConfig->eContent!=FTS5_CONTENT_UNINDEXED
+
  ){
    if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
      *piRowid = sqlite3_value_int64(apVal[1]);
    }else{
@@ -253485,9 +256099,52 @@ static int sqlite3Fts5StorageContentInsert(
  }else{
    sqlite3_stmt *pInsert = 0;    /* Statement to write %_content table */
    int i;                        /* Counter variable */
-
    rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
-
    for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
-
      rc = sqlite3_bind_value(pInsert, i, apVal[i]);
+

+
    assert( FTS5_STMT_INSERT_CONTENT+1==FTS5_STMT_REPLACE_CONTENT );
+
    assert( bReplace==0 || bReplace==1 );
+
    rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT+bReplace, &pInsert, 0);
+
    if( pInsert ) sqlite3_clear_bindings(pInsert);
+

+
    /* Bind the rowid value */
+
    sqlite3_bind_value(pInsert, 1, apVal[1]);
+

+
    /* Loop through values for user-defined columns. i=2 is the leftmost
+
    ** user-defined column. As is column 1 of pSavedRow.  */
+
    for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
+
      int bUnindexed = pConfig->abUnindexed[i-2];
+
      if( pConfig->eContent==FTS5_CONTENT_NORMAL || bUnindexed ){
+
        sqlite3_value *pVal = apVal[i];
+

+
        if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
+
          /* This is an UPDATE statement, and user-defined column (i-2) was not
+
          ** modified.  Retrieve the value from Fts5Storage.pSavedRow.  */
+
          pVal = sqlite3_column_value(p->pSavedRow, i-1);
+
          if( pConfig->bLocale && bUnindexed==0 ){
+
            sqlite3_bind_value(pInsert, pConfig->nCol + i,
+
                sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1)
+
            );
+
          }
+
        }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+
          const char *pText = 0;
+
          const char *pLoc = 0;
+
          int nText = 0;
+
          int nLoc = 0;
+
          assert( pConfig->bLocale );
+

+
          rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+
          if( rc==SQLITE_OK ){
+
            sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
+
            if( bUnindexed==0 ){
+
              int iLoc = pConfig->nCol + i;
+
              sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
+
            }
+
          }
+

+
          continue;
+
        }
+

+
        rc = sqlite3_bind_value(pInsert, i, pVal);
+
      }
    }
    if( rc==SQLITE_OK ){
      sqlite3_step(pInsert);
@@ -253522,14 +256179,38 @@ static int sqlite3Fts5StorageIndexInsert(
  for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
    ctx.szCol = 0;
    if( pConfig->abUnindexed[ctx.iCol]==0 ){
-
      const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
-
      int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
-
      rc = sqlite3Fts5Tokenize(pConfig,
-
          FTS5_TOKENIZE_DOCUMENT,
-
          zText, nText,
-
          (void*)&ctx,
-
          fts5StorageInsertCallback
-
      );
+
      int nText = 0;              /* Size of pText in bytes */
+
      const char *pText = 0;      /* Pointer to buffer containing text value */
+
      int nLoc = 0;               /* Size of pText in bytes */
+
      const char *pLoc = 0;       /* Pointer to buffer containing text value */
+

+
      sqlite3_value *pVal = apVal[ctx.iCol+2];
+
      if( p->pSavedRow && sqlite3_value_nochange(pVal) ){
+
        pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1);
+
        if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
+
          int iCol = ctx.iCol + 1 + pConfig->nCol;
+
          pLoc = (const char*)sqlite3_column_text(p->pSavedRow, iCol);
+
          nLoc = sqlite3_column_bytes(p->pSavedRow, iCol);
+
        }
+
      }else{
+
        pVal = apVal[ctx.iCol+2];
+
      }
+

+
      if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+
        rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+
      }else{
+
        pText = (const char*)sqlite3_value_text(pVal);
+
        nText = sqlite3_value_bytes(pVal);
+
      }
+

+
      if( rc==SQLITE_OK ){
+
        sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+
        rc = sqlite3Fts5Tokenize(pConfig,
+
            FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx,
+
            fts5StorageInsertCallback
+
        );
+
        sqlite3Fts5ClearLocale(pConfig);
+
      }
    }
    sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
    p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
@@ -253693,29 +256374,61 @@ static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
          rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
        }
        for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
-
          if( pConfig->abUnindexed[i] ) continue;
-
          ctx.iCol = i;
-
          ctx.szCol = 0;
-
          if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
-
            rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
-
          }
-
          if( rc==SQLITE_OK ){
-
            const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
-
            int nText = sqlite3_column_bytes(pScan, i+1);
-
            rc = sqlite3Fts5Tokenize(pConfig,
-
                FTS5_TOKENIZE_DOCUMENT,
-
                zText, nText,
-
                (void*)&ctx,
-
                fts5StorageIntegrityCallback
-
            );
-
          }
-
          if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
-
            rc = FTS5_CORRUPT;
-
          }
-
          aTotalSize[i] += ctx.szCol;
-
          if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
-
            sqlite3Fts5TermsetFree(ctx.pTermset);
-
            ctx.pTermset = 0;
+
          if( pConfig->abUnindexed[i]==0 ){
+
            const char *pText = 0;
+
            int nText = 0;
+
            const char *pLoc = 0;
+
            int nLoc = 0;
+
            sqlite3_value *pVal = sqlite3_column_value(pScan, i+1);
+

+
            if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
+
             && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+
            ){
+
              rc = sqlite3Fts5DecodeLocaleValue(
+
                  pVal, &pText, &nText, &pLoc, &nLoc
+
              );
+
            }else{
+
              if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
+
                int iCol = i + 1 + pConfig->nCol;
+
                pLoc = (const char*)sqlite3_column_text(pScan, iCol);
+
                nLoc = sqlite3_column_bytes(pScan, iCol);
+
              }
+
              pText = (const char*)sqlite3_value_text(pVal);
+
              nText = sqlite3_value_bytes(pVal);
+
            }
+

+
            ctx.iCol = i;
+
            ctx.szCol = 0;
+

+
            if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+
              rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
+
            }
+

+
            if( rc==SQLITE_OK ){
+
              sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+
              rc = sqlite3Fts5Tokenize(pConfig,
+
                  FTS5_TOKENIZE_DOCUMENT,
+
                  pText, nText,
+
                  (void*)&ctx,
+
                  fts5StorageIntegrityCallback
+
              );
+
              sqlite3Fts5ClearLocale(pConfig);
+
            }
+

+
            /* If this is not a columnsize=0 database, check that the number
+
            ** of tokens in the value matches the aColSize[] value read from
+
            ** the %_docsize table.  */
+
            if( rc==SQLITE_OK
+
             && pConfig->bColumnsize
+
             && ctx.szCol!=aColSize[i]
+
            ){
+
              rc = FTS5_CORRUPT;
+
            }
+
            aTotalSize[i] += ctx.szCol;
+
            if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+
              sqlite3Fts5TermsetFree(ctx.pTermset);
+
              ctx.pTermset = 0;
+
            }
          }
        }
        sqlite3Fts5TermsetFree(ctx.pTermset);
@@ -254022,7 +256735,7 @@ static int fts5AsciiCreate(
      int i;
      memset(p, 0, sizeof(AsciiTokenizer));
      memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar));
-
      for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
+
      for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
        const char *zArg = azArg[i+1];
        if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
          fts5AsciiAddExceptions(p, zArg, 1);
@@ -254033,7 +256746,6 @@ static int fts5AsciiCreate(
          rc = SQLITE_ERROR;
        }
      }
-
      if( rc==SQLITE_OK && i<nArg ) rc = SQLITE_ERROR;
      if( rc!=SQLITE_OK ){
        fts5AsciiDelete((Fts5Tokenizer*)p);
        p = 0;
@@ -254142,7 +256854,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
  c = *(zIn++);                                            \
  if( c>=0xc0 ){                                           \
    c = sqlite3Utf8Trans1[c-0xc0];                         \
-
    while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){            \
+
    while( zIn<zTerm && (*zIn & 0xc0)==0x80 ){             \
      c = (c<<6) + (0x3f & *(zIn++));                      \
    }                                                      \
    if( c<0x80                                             \
@@ -254325,7 +257037,7 @@ static int fts5UnicodeCreate(
      }

      /* Search for a "categories" argument */
-
      for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
+
      for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
        if( 0==sqlite3_stricmp(azArg[i], "categories") ){
          zCat = azArg[i+1];
        }
@@ -254334,7 +257046,7 @@ static int fts5UnicodeCreate(
        rc = unicodeSetCategories(p, zCat);
      }

-
      for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
+
      for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
        const char *zArg = azArg[i+1];
        if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
          if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
@@ -254359,8 +257071,6 @@ static int fts5UnicodeCreate(
          rc = SQLITE_ERROR;
        }
      }
-
      if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;
-

    }else{
      rc = SQLITE_NOMEM;
    }
@@ -254499,7 +257209,7 @@ static int fts5UnicodeTokenize(

typedef struct PorterTokenizer PorterTokenizer;
struct PorterTokenizer {
-
  fts5_tokenizer tokenizer;       /* Parent tokenizer module */
+
  fts5_tokenizer_v2 tokenizer_v2; /* Parent tokenizer module */
  Fts5Tokenizer *pTokenizer;      /* Parent tokenizer instance */
  char aBuf[FTS5_PORTER_MAX_TOKEN + 64];
};
@@ -254511,7 +257221,7 @@ static void fts5PorterDelete(Fts5Tokenizer *pTok){
  if( pTok ){
    PorterTokenizer *p = (PorterTokenizer*)pTok;
    if( p->pTokenizer ){
-
      p->tokenizer.xDelete(p->pTokenizer);
+
      p->tokenizer_v2.xDelete(p->pTokenizer);
    }
    sqlite3_free(p);
  }
@@ -254530,6 +257240,7 @@ static int fts5PorterCreate(
  PorterTokenizer *pRet;
  void *pUserdata = 0;
  const char *zBase = "unicode61";
+
  fts5_tokenizer_v2 *pV2 = 0;

  if( nArg>0 ){
    zBase = azArg[0];
@@ -254538,14 +257249,15 @@ static int fts5PorterCreate(
  pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer));
  if( pRet ){
    memset(pRet, 0, sizeof(PorterTokenizer));
-
    rc = pApi->xFindTokenizer(pApi, zBase, &pUserdata, &pRet->tokenizer);
+
    rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2);
  }else{
    rc = SQLITE_NOMEM;
  }
  if( rc==SQLITE_OK ){
    int nArg2 = (nArg>0 ? nArg-1 : 0);
-
    const char **azArg2 = (nArg2 ? &azArg[1] : 0);
-
    rc = pRet->tokenizer.xCreate(pUserdata, azArg2, nArg2, &pRet->pTokenizer);
+
    const char **az2 = (nArg2 ? &azArg[1] : 0);
+
    memcpy(&pRet->tokenizer_v2, pV2, sizeof(fts5_tokenizer_v2));
+
    rc = pRet->tokenizer_v2.xCreate(pUserdata, az2, nArg2, &pRet->pTokenizer);
  }

  if( rc!=SQLITE_OK ){
@@ -255196,6 +257908,7 @@ static int fts5PorterTokenize(
  void *pCtx,
  int flags,
  const char *pText, int nText,
+
  const char *pLoc, int nLoc,
  int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd)
){
  PorterTokenizer *p = (PorterTokenizer*)pTokenizer;
@@ -255203,8 +257916,8 @@ static int fts5PorterTokenize(
  sCtx.xToken = xToken;
  sCtx.pCtx = pCtx;
  sCtx.aBuf = p->aBuf;
-
  return p->tokenizer.xTokenize(
-
      p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
+
  return p->tokenizer_v2.xTokenize(
+
      p->pTokenizer, (void*)&sCtx, flags, pText, nText, pLoc, nLoc, fts5PorterCb
  );
}

@@ -255234,41 +257947,46 @@ static int fts5TriCreate(
  Fts5Tokenizer **ppOut
){
  int rc = SQLITE_OK;
-
  TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
+
  TrigramTokenizer *pNew = 0;
  UNUSED_PARAM(pUnused);
-
  if( pNew==0 ){
-
    rc = SQLITE_NOMEM;
+
  if( nArg%2 ){
+
    rc = SQLITE_ERROR;
  }else{
    int i;
-
    pNew->bFold = 1;
-
    pNew->iFoldParam = 0;
-
    for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
-
      const char *zArg = azArg[i+1];
-
      if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
-
        if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
-
          rc = SQLITE_ERROR;
+
    pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
+
    if( pNew==0 ){
+
      rc = SQLITE_NOMEM;
+
    }else{
+
      pNew->bFold = 1;
+
      pNew->iFoldParam = 0;
+

+
      for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
+
        const char *zArg = azArg[i+1];
+
        if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
+
          if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
+
            rc = SQLITE_ERROR;
+
          }else{
+
            pNew->bFold = (zArg[0]=='0');
+
          }
+
        }else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
+
          if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
+
            rc = SQLITE_ERROR;
+
          }else{
+
            pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
+
          }
        }else{
-
          pNew->bFold = (zArg[0]=='0');
-
        }
-
      }else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
-
        if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
          rc = SQLITE_ERROR;
-
        }else{
-
          pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
        }
-
      }else{
-
        rc = SQLITE_ERROR;
      }
-
    }
-
    if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;

-
    if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
-
      rc = SQLITE_ERROR;
-
    }
+
      if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
+
        rc = SQLITE_ERROR;
+
      }

-
    if( rc!=SQLITE_OK ){
-
      fts5TriDelete((Fts5Tokenizer*)pNew);
-
      pNew = 0;
+
      if( rc!=SQLITE_OK ){
+
        fts5TriDelete((Fts5Tokenizer*)pNew);
+
        pNew = 0;
+
      }
    }
  }
  *ppOut = (Fts5Tokenizer*)pNew;
@@ -255374,6 +258092,16 @@ static int sqlite3Fts5TokenizerPattern(
}

/*
+
** Return true if the tokenizer described by p->azArg[] is the trigram
+
** tokenizer. This tokenizer needs to be loaded before xBestIndex is
+
** called for the first time in order to correctly handle LIKE/GLOB.
+
*/
+
static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){
+
  return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram"));
+
}
+

+

+
/*
** Register all built-in tokenizers with FTS5.
*/
static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -255383,7 +258111,6 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
  } aBuiltin[] = {
    { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
    { "ascii",     {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
-
    { "porter",    {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
    { "trigram",   {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
  };

@@ -255398,7 +258125,20 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
        0
    );
  }
-

+
  if( rc==SQLITE_OK ){
+
    fts5_tokenizer_v2 sPorter = {
+
      2,
+
      fts5PorterCreate,
+
      fts5PorterDelete,
+
      fts5PorterTokenize
+
    };
+
    rc = pApi->xCreateTokenizer_v2(pApi,
+
        "porter",
+
        (void*)pApi,
+
        &sPorter,
+
        0
+
    );
+
  }
  return rc;
}

@@ -255768,6 +258508,9 @@ static int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
            default: return 1;          }
          break;

+

+
    default:
+
      return 1;
  }
  return 0;
}
@@ -256592,6 +259335,7 @@ struct Fts5VocabCursor {

  int nLeTerm;                    /* Size of zLeTerm in bytes */
  char *zLeTerm;                  /* (term <= $zLeTerm) paramater, or NULL */
+
  int colUsed;                    /* Copy of sqlite3_index_info.colUsed */

  /* These are used by 'col' tables only */
  int iCol;
@@ -256618,9 +259362,11 @@ struct Fts5VocabCursor {
/*
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
*/
-
#define FTS5_VOCAB_TERM_EQ 0x01
-
#define FTS5_VOCAB_TERM_GE 0x02
-
#define FTS5_VOCAB_TERM_LE 0x04
+
#define FTS5_VOCAB_TERM_EQ 0x0100
+
#define FTS5_VOCAB_TERM_GE 0x0200
+
#define FTS5_VOCAB_TERM_LE 0x0400
+

+
#define FTS5_VOCAB_COLUSED_MASK 0xFF


/*
@@ -256797,11 +259543,13 @@ static int fts5VocabBestIndexMethod(
  int iTermEq = -1;
  int iTermGe = -1;
  int iTermLe = -1;
-
  int idxNum = 0;
+
  int idxNum = (int)pInfo->colUsed;
  int nArg = 0;

  UNUSED_PARAM(pUnused);

+
  assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
+

  for(i=0; i<pInfo->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
    if( p->usable==0 ) continue;
@@ -256893,7 +259641,7 @@ static int fts5VocabOpenMethod(
      if( rc==SQLITE_OK ){
        pVTab->zErrMsg = sqlite3_mprintf(
            "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
-
            );
+
        );
        rc = SQLITE_ERROR;
      }
    }else{
@@ -257053,9 +259801,19 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){

        switch( pTab->eType ){
          case FTS5_VOCAB_ROW:
-
            if( eDetail==FTS5_DETAIL_FULL ){
-
              while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
-
                pCsr->aCnt[0]++;
+
            /* Do not bother counting the number of instances if the "cnt"
+
            ** column is not being read (according to colUsed).  */
+
            if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
+
              while( iPos<nPos ){
+
                u32 ii;
+
                fts5FastGetVarint32(pPos, iPos, ii);
+
                if( ii==1 ){
+
                  /* New column in the position list */
+
                  fts5FastGetVarint32(pPos, iPos, ii);
+
                }else{
+
                  /* An instance - increment pCsr->aCnt[] */
+
                  pCsr->aCnt[0]++;
+
                }
              }
            }
            pCsr->aDoc[0]++;
@@ -257153,6 +259911,7 @@ static int fts5VocabFilterMethod(
  if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
  if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
  if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
+
  pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);

  if( pEq ){
    zTerm = (const char *)sqlite3_value_text(pEq);
modified external/sqlite/sqlite3.h
@@ -146,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.46.1"
-
#define SQLITE_VERSION_NUMBER 3046001
-
#define SQLITE_SOURCE_ID      "2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33"
+
#define SQLITE_VERSION        "3.47.0"
+
#define SQLITE_VERSION_NUMBER 3047000
+
#define SQLITE_SOURCE_ID      "2024-10-21 16:30:22 03a9703e27c44437c39363d0baf82db4ebc94538a0f28411c85dda156f82636e"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -772,8 +772,8 @@ struct sqlite3_file {
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
-
** PENDING, or EXCLUSIVE lock on the file.  It returns true
-
** if such a lock exists and false otherwise.
+
** PENDING, or EXCLUSIVE lock on the file.  It returns, via its output
+
** pointer parameter, true if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom
** VFS implementations to directly control an open file using the
@@ -3570,8 +3570,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
**
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
** <dd>The database connection comes up in "extended result code mode".
-
** In other words, the database behaves has if
-
** [sqlite3_extended_result_codes(db,1)] where called on the database
+
** In other words, the database behaves as if
+
** [sqlite3_extended_result_codes(db,1)] were called on the database
** connection as soon as the connection is created. In addition to setting
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
** to return an extended result code.</dd>
@@ -4222,13 +4222,17 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** and sqlite3_prepare16_v3() use UTF-16.
**
** ^If the nByte argument is negative, then zSql is read up to the
-
** first zero terminator. ^If nByte is positive, then it is the
-
** number of bytes read from zSql.  ^If nByte is zero, then no prepared
+
** first zero terminator. ^If nByte is positive, then it is the maximum
+
** number of bytes read from zSql.  When nByte is positive, zSql is read
+
** up to the first zero terminator or until the nByte bytes have been read,
+
** whichever comes first.  ^If nByte is zero, then no prepared
** statement is generated.
** If the caller knows that the supplied string is nul-terminated, then
** there is a small performance advantage to passing an nByte parameter that
** is the number of bytes in the input string <i>including</i>
** the nul-terminator.
+
** Note that nByte measure the length of the input in bytes, not
+
** characters, even for the UTF-16 interfaces.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql.  These routines only
@@ -5599,7 +5603,7 @@ SQLITE_API int sqlite3_create_window_function(
** This flag instructs SQLite to omit some corner-case optimizations that
** might disrupt the operation of the [sqlite3_value_subtype()] function,
** causing it to return zero rather than the correct subtype().
-
** SQL functions that invokes [sqlite3_value_subtype()] should have this
+
** All SQL functions that invoke [sqlite3_value_subtype()] should have this
** property.  If the SQLITE_SUBTYPE property is omitted, then the return
** value from [sqlite3_value_subtype()] might sometimes be zero even though
** a non-zero subtype was specified by the function argument expression.
@@ -5615,6 +5619,15 @@ SQLITE_API int sqlite3_create_window_function(
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes.
+
**
+
** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd>
+
** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
+
** that internally orders the values provided to the first argument.  The
+
** ordered-set aggregate SQL notation with a single ORDER BY term can be
+
** used to invoke this function.  If the ordered-set aggregate notation is
+
** used on a function that lacks this flag, then an error is raised. Note
+
** that the ordered-set aggregate syntax is only available if SQLite is
+
** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
** </dd>
** </dl>
*/
@@ -5623,6 +5636,7 @@ SQLITE_API int sqlite3_create_window_function(
#define SQLITE_SUBTYPE          0x000100000
#define SQLITE_INNOCUOUS        0x000200000
#define SQLITE_RESULT_SUBTYPE   0x001000000
+
#define SQLITE_SELFORDER1       0x002000000

/*
** CAPI3REF: Deprecated Functions
@@ -5820,7 +5834,7 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
** one SQL function to another.  Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
-
** Every [application-defined SQL function] that invoke this interface
+
** Every [application-defined SQL function] that invokes this interface
** should include the [SQLITE_SUBTYPE] property in the text
** encoding argument when the function is [sqlite3_create_function|registered].
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
@@ -7427,9 +7441,11 @@ struct sqlite3_module {
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
-
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
-
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
-
** assumes that the strategy may visit at most one row.
+
** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
+
** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
+
** output to show the idxNum has hex instead of as decimal.  Another flag is
+
** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
+
** return at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
@@ -7493,7 +7509,9 @@ struct sqlite3_index_info {
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
-
#define SQLITE_INDEX_SCAN_UNIQUE      1     /* Scan visits at most 1 row */
+
#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
+
#define SQLITE_INDEX_SCAN_HEX    0x00000002 /* Display idxNum as hex */
+
                                            /* in EXPLAIN QUERY PLAN */

/*
** CAPI3REF: Virtual Table Constraint Operator Codes
@@ -8330,6 +8348,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_JSON_SELFCHECK          14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16  /* NOT USED */
+
#define SQLITE_TESTCTRL_GETOPT                  16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17  /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS      17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
@@ -8349,7 +8368,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_TRACEFLAGS              31
#define SQLITE_TESTCTRL_TUNE                    32
#define SQLITE_TESTCTRL_LOGEST                  33
-
#define SQLITE_TESTCTRL_USELONGDOUBLE           34
+
#define SQLITE_TESTCTRL_USELONGDOUBLE           34  /* NOT USED */
#define SQLITE_TESTCTRL_LAST                    34  /* Largest TESTCTRL */

/*
@@ -9325,6 +9344,16 @@ typedef struct sqlite3_backup sqlite3_backup;
** APIs are not strictly speaking threadsafe. If they are invoked at the
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
+
**
+
** <b>Alternatives To Using The Backup API</b>
+
**
+
** Other techniques for safely creating a consistent backup of an SQLite
+
** database include:
+
**
+
** <ul>
+
** <li> The [VACUUM INTO] command.
+
** <li> The [sqlite3_rsync] utility program.
+
** </ul>
*/
SQLITE_API sqlite3_backup *sqlite3_backup_init(
  sqlite3 *pDest,                        /* Destination database handle */
@@ -10524,6 +10553,14 @@ typedef struct sqlite3_snapshot {
** If there is not already a read-transaction open on schema S when
** this function is called, one is opened automatically.
**
+
** If a read-transaction is opened by this function, then it is guaranteed
+
** that the returned snapshot object may not be invalidated by a database
+
** writer or checkpointer until after the read-transaction is closed. This
+
** is not guaranteed if a read-transaction is already open when this
+
** function is called. In that case, any subsequent write or checkpoint
+
** operation on the database may invalidate the returned snapshot handle,
+
** even while the read-transaction remains open.
+
**
** The following must be true for this function to succeed. If any of
** the following statements are false when sqlite3_snapshot_get() is
** called, SQLITE_ERROR is returned. The final value of *P is undefined
@@ -10832,8 +10869,6 @@ SQLITE_API int sqlite3_deserialize(
#if defined(__wasi__)
# undef SQLITE_WASI
# define SQLITE_WASI 1
-
# undef SQLITE_OMIT_WAL
-
# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
# ifndef SQLITE_OMIT_LOAD_EXTENSION
#  define SQLITE_OMIT_LOAD_EXTENSION
# endif
@@ -13036,6 +13071,10 @@ struct Fts5PhraseIter {
**   (i.e. if it is a contentless table), then this API always iterates
**   through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
+
**   In all cases, matches are visited in (column ASC, offset ASC) order.
+
**   i.e. all those in column 0, sorted by offset, followed by those in
+
**   column 1, etc.
+
**
** xPhraseNext()
**   See xPhraseFirst above.
**
@@ -13102,9 +13141,32 @@ struct Fts5PhraseIter {
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option.
+
**
+
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+
**   If parameter iCol is less than zero, or greater than or equal to the
+
**   number of columns in the table, SQLITE_RANGE is returned.
+
**
+
**   Otherwise, this function attempts to retrieve the locale associated
+
**   with column iCol of the current row. Usually, there is no associated
+
**   locale, and output parameters (*pzLocale) and (*pnLocale) are set
+
**   to NULL and 0, respectively. However, if the fts5_locale() function
+
**   was used to associate a locale with the value when it was inserted
+
**   into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+
**   buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+
**   is set to the size in bytes of the buffer, not including the
+
**   nul-terminator.
+
**
+
**   If successful, SQLITE_OK is returned. Or, if an error occurs, an
+
**   SQLite error code is returned. The final value of the output parameters
+
**   is undefined in this case.
+
**
+
** xTokenize_v2:
+
**   Tokenize text using the tokenizer belonging to the FTS5 table. This
+
**   API is the same as the xTokenize() API, except that it allows a tokenizer
+
**   locale to be specified.
*/
struct Fts5ExtensionApi {
-
  int iVersion;                   /* Currently always set to 3 */
+
  int iVersion;                   /* Currently always set to 4 */

  void *(*xUserData)(Fts5Context*);

@@ -13146,6 +13208,15 @@ struct Fts5ExtensionApi {
      const char **ppToken, int *pnToken
  );
  int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+

+
  /* Below this point are iVersion>=4 only */
+
  int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+
  int (*xTokenize_v2)(Fts5Context*,
+
    const char *pText, int nText,      /* Text to tokenize */
+
    const char *pLocale, int nLocale,  /* Locale to pass to tokenizer */
+
    void *pCtx,                        /* Context passed to xToken() */
+
    int (*xToken)(void*, int, const char*, int, int, int)       /* Callback */
+
  );
};

/*
@@ -13166,7 +13237,7 @@ struct Fts5ExtensionApi {
**   A tokenizer instance is required to actually tokenize text.
**
**   The first argument passed to this function is a copy of the (void*)
-
**   pointer provided by the application when the fts5_tokenizer object
+
**   pointer provided by the application when the fts5_tokenizer_v2 object
**   was registered with FTS5 (the third argument to xCreateTokenizer()).
**   The second and third arguments are an array of nul-terminated strings
**   containing the tokenizer arguments, if any, specified following the
@@ -13190,7 +13261,7 @@ struct Fts5ExtensionApi {
**   argument passed to this function is a pointer to an Fts5Tokenizer object
**   returned by an earlier call to xCreate().
**
-
**   The second argument indicates the reason that FTS5 is requesting
+
**   The third argument indicates the reason that FTS5 is requesting
**   tokenization of the supplied text. This is always one of the following
**   four values:
**
@@ -13214,6 +13285,13 @@ struct Fts5ExtensionApi {
**            on a columnsize=0 database.
**   </ul>
**
+
**   The sixth and seventh arguments passed to xTokenize() - pLocale and
+
**   nLocale - are a pointer to a buffer containing the locale to use for
+
**   tokenization (e.g. "en_US") and its size in bytes, respectively. The
+
**   pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+
**   which case nLocale is always 0) to indicate that the tokenizer should
+
**   use its default locale.
+
**
**   For each token in the input string, the supplied callback xToken() must
**   be invoked. The first argument to it should be a copy of the pointer
**   passed as the second argument to xTokenize(). The third and fourth
@@ -13237,6 +13315,30 @@ struct Fts5ExtensionApi {
**   may abandon the tokenization and return any error code other than
**   SQLITE_OK or SQLITE_DONE.
**
+
**   If the tokenizer is registered using an fts5_tokenizer_v2 object,
+
**   then the xTokenize() method has two additional arguments - pLocale
+
**   and nLocale. These specify the locale that the tokenizer should use
+
**   for the current request. If pLocale and nLocale are both 0, then the
+
**   tokenizer should use its default locale. Otherwise, pLocale points to
+
**   an nLocale byte buffer containing the name of the locale to use as utf-8
+
**   text. pLocale is not nul-terminated.
+
**
+
** FTS5_TOKENIZER
+
**
+
** There is also an fts5_tokenizer object. This is an older, deprecated,
+
** version of fts5_tokenizer_v2. It is similar except that:
+
**
+
**  <ul>
+
**    <li> There is no "iVersion" field, and
+
**    <li> The xTokenize() method does not take a locale argument.
+
**  </ul>
+
**
+
** Legacy fts5_tokenizer tokenizers must be registered using the
+
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+
**
+
** Tokenizer implementations registered using either API may be retrieved
+
** using both xFindTokenizer() and xFindTokenizer_v2().
+
**
** SYNONYM SUPPORT
**
**   Custom tokenizers may also support synonyms. Consider a case in which a
@@ -13345,6 +13447,33 @@ struct Fts5ExtensionApi {
**   inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
+
typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+
struct fts5_tokenizer_v2 {
+
  int iVersion;             /* Currently always 2 */
+

+
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+
  void (*xDelete)(Fts5Tokenizer*);
+
  int (*xTokenize)(Fts5Tokenizer*,
+
      void *pCtx,
+
      int flags,            /* Mask of FTS5_TOKENIZE_* flags */
+
      const char *pText, int nText,
+
      const char *pLocale, int nLocale,
+
      int (*xToken)(
+
        void *pCtx,         /* Copy of 2nd argument to xTokenize() */
+
        int tflags,         /* Mask of FTS5_TOKEN_* flags */
+
        const char *pToken, /* Pointer to buffer containing token */
+
        int nToken,         /* Size of token in bytes */
+
        int iStart,         /* Byte offset of token within input text */
+
        int iEnd            /* Byte offset of end of token within input text */
+
      )
+
  );
+
};
+

+
/*
+
** New code should use the fts5_tokenizer_v2 type to define tokenizer
+
** implementations. The following type is included for legacy applications
+
** that still use it.
+
*/
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
@@ -13364,6 +13493,7 @@ struct fts5_tokenizer {
  );
};

+

/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY     0x0001
#define FTS5_TOKENIZE_PREFIX    0x0002
@@ -13383,7 +13513,7 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
-
  int iVersion;                   /* Currently always set to 2 */
+
  int iVersion;                   /* Currently always set to 3 */

  /* Create a new tokenizer */
  int (*xCreateTokenizer)(
@@ -13410,6 +13540,25 @@ struct fts5_api {
    fts5_extension_function xFunction,
    void (*xDestroy)(void*)
  );
+

+
  /* APIs below this point are only available if iVersion>=3 */
+

+
  /* Create a new tokenizer */
+
  int (*xCreateTokenizer_v2)(
+
    fts5_api *pApi,
+
    const char *zName,
+
    void *pUserData,
+
    fts5_tokenizer_v2 *pTokenizer,
+
    void (*xDestroy)(void*)
+
  );
+

+
  /* Find an existing tokenizer */
+
  int (*xFindTokenizer_v2)(
+
    fts5_api *pApi,
+
    const char *zName,
+
    void **ppUserData,
+
    fts5_tokenizer_v2 **ppTokenizer
+
  );
};

/*