diff --git a/cgosqlite/release_test.go b/cgosqlite/release_test.go index bbb0003..474d67f 100644 --- a/cgosqlite/release_test.go +++ b/cgosqlite/release_test.go @@ -5,7 +5,7 @@ package cgosqlite import "testing" func TestSQLiteVersion(t *testing.T) { - const want = "3.52.0" + const want = "3.51.2" got := SQLiteVersion() if got != want { t.Fatalf("wrong version, want %s, got %s", want, got) @@ -13,7 +13,7 @@ func TestSQLiteVersion(t *testing.T) { } func TestSQLiteVersionNumber(t *testing.T) { - const want = 3052000 + const want = 3051002 got := SQLiteVersionNumber() if got != want { t.Fatalf("wrong version, want %d, got %d", want, got) diff --git a/cgosqlite/shell.c.disabled b/cgosqlite/shell.c.disabled index fd244bf..f955f98 100644 --- a/cgosqlite/shell.c.disabled +++ b/cgosqlite/shell.c.disabled @@ -1,45 +1,21 @@ -/* -** This is the amalgamated source code to the "sqlite3" or "sqlite3.exe" -** command-line shell (CLI) for SQLite. This file is automatically -** generated by the tool/mkshellc.tcl script from the following sources: -** -** ext/expert/sqlite3expert.c -** ext/expert/sqlite3expert.h -** ext/intck/sqlite3intck.c -** ext/intck/sqlite3intck.h -** ext/misc/appendvfs.c -** ext/misc/base64.c -** ext/misc/base85.c -** ext/misc/completion.c -** ext/misc/decimal.c -** ext/misc/fileio.c -** ext/misc/ieee754.c -** ext/misc/memtrace.c -** ext/misc/pcachetrace.c -** ext/misc/regexp.c -** ext/misc/series.c -** ext/misc/sha1.c -** ext/misc/shathree.c -** ext/misc/sqlar.c -** ext/misc/sqlite3_stdio.c -** ext/misc/sqlite3_stdio.h -** ext/misc/stmtrand.c -** ext/misc/uint.c -** ext/misc/vfstrace.c -** ext/misc/windirent.h -** ext/misc/zipfile.c -** ext/qrf/qrf.c -** ext/qrf/qrf.h -** ext/recover/dbdata.c -** ext/recover/sqlite3recover.c -** ext/recover/sqlite3recover.h -** src/shell.c.in +/* DO NOT EDIT! +** This file is automatically generated by the script in the canonical +** SQLite source tree at tool/mkshellc.tcl. That script combines source +** code from various constituent source files of SQLite into this single +** "shell.c" file used to implement the SQLite command-line shell. +** +** Most of the code found below comes from the "src/shell.c.in" file in +** the canonical SQLite source tree. That main file contains "INCLUDE" +** lines that specify other files in the canonical source tree that are +** inserted to getnerate this complete program source file. +** +** The code from multiple files is combined into this single "shell.c" +** source file to help make the command-line program easier to compile. ** ** To modify this program, get a copy of the canonical SQLite source tree, -** edit the src/shell.c.in file and/or some of the other files that are -** listed above, then rerun the command "make shell.c". +** edit the src/shell.c.in" and/or some of the other files that are included +** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script. */ -/************************* Begin src/shell.c.in ******************/ /* ** 2001 September 15 ** @@ -51,7 +27,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains code to implement the "sqlite3" command line +** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. */ #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) @@ -73,6 +49,14 @@ typedef unsigned short int u16; # include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE) #endif +/* +** Determine if we are dealing with WinRT, which provides only a subset of +** the full Win32 API. +*/ +#if !defined(SQLITE_OS_WINRT) +# define SQLITE_OS_WINRT 0 +#endif + /* ** If SQLITE_SHELL_FIDDLE is defined then the shell is modified ** somewhat for use as a WASM module in a web browser. This flag @@ -81,10 +65,6 @@ typedef unsigned short int u16; ** and this build mode rewires the user input subsystem to account for ** that. */ -#if defined(SQLITE_SHELL_FIDDLE) -# undef SQLITE_OMIT_LOAD_EXTENSION -# define SQLITE_OMIT_LOAD_EXTENSION 1 -#endif /* ** Warning pragmas copied from msvc.h in the core. @@ -146,7 +126,6 @@ typedef unsigned char u8; #include #ifndef _WIN32 # include -# include #endif #if !defined(_WIN32) && !defined(WIN32) @@ -216,6 +195,9 @@ typedef unsigned char u8; #endif #if defined(_WIN32) || defined(WIN32) +# if SQLITE_OS_WINRT +# define SQLITE_OMIT_POPEN 1 +# else # include # include # define isatty(h) _isatty(h) @@ -230,6 +212,7 @@ typedef unsigned char u8; # endif # undef pclose # define pclose _pclose +# endif #else /* Make sure isatty() has a prototype. */ extern int isatty(int); @@ -260,6 +243,9 @@ typedef unsigned char u8; #define IsAlpha(X) isalpha((unsigned char)X) #if defined(_WIN32) || defined(WIN32) +#if SQLITE_OS_WINRT +#include +#endif #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include @@ -269,7 +255,7 @@ extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); #endif -/************************* Begin ext/misc/sqlite3_stdio.h ******************/ +/************************* Begin ../ext/misc/sqlite3_stdio.h ******************/ /* ** 2024-09-24 ** @@ -303,7 +289,6 @@ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); #ifdef _WIN32 /**** Definitions For Windows ****/ #include -#include #include FILE *sqlite3_fopen(const char *zFilename, const char *zMode); @@ -311,7 +296,6 @@ FILE *sqlite3_popen(const char *zCommand, const char *type); char *sqlite3_fgets(char *s, int size, FILE *stream); int sqlite3_fputs(const char *s, FILE *stream); int sqlite3_fprintf(FILE *stream, const char *format, ...); -int sqlite3_vfprintf(FILE *stream, const char *format, va_list); void sqlite3_fsetmode(FILE *stream, int mode); @@ -323,14 +307,13 @@ void sqlite3_fsetmode(FILE *stream, int mode); #define sqlite3_fgets fgets #define sqlite3_fputs fputs #define sqlite3_fprintf fprintf -#define sqlite3_vfprintf vfprintf #define sqlite3_fsetmode(F,X) /*no-op*/ #endif #endif /* _SQLITE3_STDIO_H_ */ -/************************* End ext/misc/sqlite3_stdio.h ********************/ -/************************* Begin ext/misc/sqlite3_stdio.c ******************/ +/************************* End ../ext/misc/sqlite3_stdio.h ********************/ +/************************* Begin ../ext/misc/sqlite3_stdio.c ******************/ /* ** 2024-09-24 ** @@ -591,7 +574,7 @@ int sqlite3_fputs(const char *z, FILE *out){ /* -** Work-alikes for fprintf() and vfprintf() from the standard C library. +** Work-alike for fprintf() from the standard C library. */ int sqlite3_fprintf(FILE *out, const char *zFormat, ...){ int rc; @@ -618,24 +601,6 @@ int sqlite3_fprintf(FILE *out, const char *zFormat, ...){ } return rc; } -int sqlite3_vfprintf(FILE *out, const char *zFormat, va_list ap){ - int rc; - if( UseWtextForOutput(out) ){ - /* When writing to the command-prompt in Windows, it is necessary - ** to use _O_WTEXT input mode and write UTF-16 characters. - */ - char *z; - z = sqlite3_vmprintf(zFormat, ap); - sqlite3_fputs(z, out); - rc = (int)strlen(z); - sqlite3_free(z); - }else{ - /* Writing to a file or other destination, just write bytes without - ** any translation. */ - rc = vfprintf(out, zFormat, ap); - } - return rc; -} /* ** Set the mode for an output stream. mode argument is typically _O_BINARY or @@ -654,699 +619,427 @@ void sqlite3_fsetmode(FILE *fp, int mode){ #endif /* defined(_WIN32) */ -/************************* End ext/misc/sqlite3_stdio.c ********************/ -/************************* Begin ext/qrf/qrf.h ******************/ -/* -** 2025-10-20 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Header file for the Result-Format or "resfmt" utility library for SQLite. -** See the resfmt.md documentation for additional information. -*/ -#ifndef SQLITE_QRF_H -#define SQLITE_QRF_H -#ifdef __cplusplus -extern "C" { -#endif -#include -/* #include "sqlite3.h" */ - -/* -** Specification used by clients to define the output format they want -*/ -typedef struct sqlite3_qrf_spec sqlite3_qrf_spec; -struct sqlite3_qrf_spec { - unsigned char iVersion; /* Version number of this structure */ - unsigned char eStyle; /* Formatting style. "box", "csv", etc... */ - unsigned char eEsc; /* How to escape control characters in text */ - unsigned char eText; /* Quoting style for text */ - unsigned char eTitle; /* Quating style for the text of column names */ - unsigned char eBlob; /* Quoting style for BLOBs */ - unsigned char bTitles; /* True to show column names */ - unsigned char bWordWrap; /* Try to wrap on word boundaries */ - unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */ - unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */ - unsigned char eTitleAlign; /* Alignment for column headers */ - unsigned char bSplitColumn; /* Wrap single-column output into many columns */ - unsigned char bBorder; /* Show outer border in Box and Table styles */ - short int nWrap; /* Wrap columns wider than this */ - short int nScreenWidth; /* Maximum overall table width */ - short int nLineLimit; /* Maximum number of lines for any row */ - short int nTitleLimit; /* Maximum number of characters in a title */ - int nCharLimit; /* Maximum number of characters in a cell */ - int nWidth; /* Number of entries in aWidth[] */ - int nAlign; /* Number of entries in aAlignment[] */ - short int *aWidth; /* Column widths */ - unsigned char *aAlign; /* Column alignments */ - char *zColumnSep; /* Alternative column separator */ - char *zRowSep; /* Alternative row separator */ - char *zTableName; /* Output table name */ - char *zNull; /* Rendering of NULL */ - char *(*xRender)(void*,sqlite3_value*); /* Render a value */ - int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ - void *pRenderArg; /* First argument to the xRender callback */ - void *pWriteArg; /* First argument to the xWrite callback */ - char **pzOutput; /* Storage location for output string */ - /* Additional fields may be added in the future */ -}; +/************************* End ../ext/misc/sqlite3_stdio.c ********************/ -/* -** Interfaces -*/ -int sqlite3_format_query_result( - sqlite3_stmt *pStmt, /* SQL statement to run */ - const sqlite3_qrf_spec *pSpec, /* Result format specification */ - char **pzErr /* OUT: Write error message here */ -); +/* Use console I/O package as a direct INCLUDE. */ +#define SQLITE_INTERNAL_LINKAGE static -/* -** Range of values for sqlite3_qrf_spec.aWidth[] entries and for -** sqlite3_qrf_spec.mxColWidth and .nScreenWidth -*/ -#define QRF_MAX_WIDTH 10000 -#define QRF_MIN_WIDTH 0 - -/* -** Output styles: -*/ -#define QRF_STYLE_Auto 0 /* Choose a style automatically */ -#define QRF_STYLE_Box 1 /* Unicode box-drawing characters */ -#define QRF_STYLE_Column 2 /* One record per line in neat columns */ -#define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ -#define QRF_STYLE_Csv 4 /* Comma-separated-value */ -#define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ -#define QRF_STYLE_Explain 6 /* EXPLAIN output */ -#define QRF_STYLE_Html 7 /* Generate an XHTML table */ -#define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ -#define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ -#define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ -#define QRF_STYLE_Line 11 /* One column per line. */ -#define QRF_STYLE_List 12 /* One record per line with a separator */ -#define QRF_STYLE_Markdown 13 /* Markdown formatting */ -#define QRF_STYLE_Off 14 /* No query output shown */ -#define QRF_STYLE_Quote 15 /* SQL-quoted, comma-separated */ -#define QRF_STYLE_Stats 16 /* EQP-like output but with performance stats */ -#define QRF_STYLE_StatsEst 17 /* EQP-like output with planner estimates */ -#define QRF_STYLE_StatsVm 18 /* EXPLAIN-like output with performance stats */ -#define QRF_STYLE_Table 19 /* MySQL-style table formatting */ - -/* -** Quoting styles for text. -** Allowed values for sqlite3_qrf_spec.eText -*/ -#define QRF_TEXT_Auto 0 /* Choose text encoding automatically */ -#define QRF_TEXT_Plain 1 /* Literal text */ -#define QRF_TEXT_Sql 2 /* Quote as an SQL literal */ -#define QRF_TEXT_Csv 3 /* CSV-style quoting */ -#define QRF_TEXT_Html 4 /* HTML-style quoting */ -#define QRF_TEXT_Tcl 5 /* C/Tcl quoting */ -#define QRF_TEXT_Json 6 /* JSON quoting */ -#define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */ - -/* -** Quoting styles for BLOBs -** Allowed values for sqlite3_qrf_spec.eBlob -*/ -#define QRF_BLOB_Auto 0 /* Determine BLOB quoting using eText */ -#define QRF_BLOB_Text 1 /* Display content exactly as it is */ -#define QRF_BLOB_Sql 2 /* Quote as an SQL literal */ -#define QRF_BLOB_Hex 3 /* Hexadecimal representation */ -#define QRF_BLOB_Tcl 4 /* "\000" notation */ -#define QRF_BLOB_Json 5 /* A JSON string */ -#define QRF_BLOB_Size 6 /* Display the blob size only */ - -/* -** Control-character escape modes. -** Allowed values for sqlite3_qrf_spec.eEsc -*/ -#define QRF_ESC_Auto 0 /* Choose the ctrl-char escape automatically */ -#define QRF_ESC_Off 1 /* Do not escape control characters */ -#define QRF_ESC_Ascii 2 /* Unix-style escapes. Ex: U+0007 shows ^G */ -#define QRF_ESC_Symbol 3 /* Unicode escapes. Ex: U+0007 shows U+2407 */ - -/* -** Allowed values for "boolean" fields, such as "bColumnNames", "bWordWrap", -** and "bTextJsonb". There is an extra "auto" variants so these are actually -** tri-state settings, not booleans. -*/ -#define QRF_SW_Auto 0 /* Let QRF choose the best value */ -#define QRF_SW_Off 1 /* This setting is forced off */ -#define QRF_SW_On 2 /* This setting is forced on */ -#define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ -#define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ -#define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ - -/* -** Possible alignment values alignment settings -** -** Horizontal Vertial -** ---------- -------- */ -#define QRF_ALIGN_Auto 0 /* auto auto */ -#define QRF_ALIGN_Left 1 /* left auto */ -#define QRF_ALIGN_Center 2 /* center auto */ -#define QRF_ALIGN_Right 3 /* right auto */ -#define QRF_ALIGN_Top 4 /* auto top */ -#define QRF_ALIGN_NW 5 /* left top */ -#define QRF_ALIGN_N 6 /* center top */ -#define QRF_ALIGN_NE 7 /* right top */ -#define QRF_ALIGN_Middle 8 /* auto middle */ -#define QRF_ALIGN_W 9 /* left middle */ -#define QRF_ALIGN_C 10 /* center middle */ -#define QRF_ALIGN_E 11 /* right middle */ -#define QRF_ALIGN_Bottom 12 /* auto bottom */ -#define QRF_ALIGN_SW 13 /* left bottom */ -#define QRF_ALIGN_S 14 /* center bottom */ -#define QRF_ALIGN_SE 15 /* right bottom */ -#define QRF_ALIGN_HMASK 3 /* Horizontal alignment mask */ -#define QRF_ALIGN_VMASK 12 /* Vertical alignment mask */ - -/* -** Auxiliary routines contined within this module that might be useful -** in other contexts, and which are therefore exported. -*/ -/* -** Return an estimate of the width, in columns, for the single Unicode -** character c. For normal characters, the answer is always 1. But the -** estimate might be 0 or 2 for zero-width and double-width characters. -** -** Different devices display unicode using different widths. So -** it is impossible to know that true display width with 100% accuracy. -** Inaccuracies in the width estimates might cause columns to be misaligned. -** Unfortunately, there is nothing we can do about that. -*/ -int sqlite3_qrf_wcwidth(int c); +#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 -/* -** Return an estimate of the number of display columns used by the -** string in the argument. The width of individual characters is -** determined as for sqlite3_qrf_wcwidth(). VT100 escape code sequences -** are assigned a width of zero. -*/ -size_t sqlite3_qrf_wcswidth(const char*); +#define eputz(z) sqlite3_fputs(z,stderr) +#define sputz(fp,z) sqlite3_fputs(z,fp) +/* True if the timer is enabled */ +static int enableTimer = 0; -#ifdef __cplusplus +/* 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); } -#endif -#endif /* !defined(SQLITE_QRF_H) */ -/************************* End ext/qrf/qrf.h ********************/ -/************************* Begin ext/qrf/qrf.c ******************/ -/* -** 2025-10-20 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Implementation of the Result-Format or "qrf" utility library for SQLite. -** See the qrf.md documentation for additional information. +/* Return the current wall-clock time in microseconds since the +** Unix epoch (1970-01-01T00:00:00Z) */ -#ifndef SQLITE_QRF_H -#include "qrf.h" +static sqlite3_int64 timeOfDay(void){ +#if defined(_WIN64) + sqlite3_uint64 t; + FILETIME tm; + GetSystemTimePreciseAsFileTime(&tm); + t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime; + t += 116444736000000000LL; + t /= 10; + return t; +#elif defined(_WIN32) + 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*1000; +#else + struct timeval sNow; + (void)gettimeofday(&sNow,0); + return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec; #endif -#include -#include -#include - -/* typedef sqlite3_int64 i64; */ - -/* A single line in the EQP output */ -typedef struct qrfEQPGraphRow qrfEQPGraphRow; -struct qrfEQPGraphRow { - int iEqpId; /* ID for this row */ - int iParentId; /* ID of the parent row */ - qrfEQPGraphRow *pNext; /* Next row in sequence */ - char zText[1]; /* Text to display for this row */ -}; +} -/* All EQP output is collected into an instance of the following */ -typedef struct qrfEQPGraph qrfEQPGraph; -struct qrfEQPGraph { - qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ - qrfEQPGraphRow *pLast; /* Last element of the pRow list */ - int nWidth; /* Width of the graph */ - char zPrefix[400]; /* Graph prefix */ -}; +#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) +#include +#include -/* -** Private state information. Subject to change from one release to the -** next. -*/ -typedef struct Qrf Qrf; -struct Qrf { - sqlite3_stmt *pStmt; /* The statement whose output is to be rendered */ - sqlite3 *db; /* The corresponding database connection */ - sqlite3_stmt *pJTrans; /* JSONB to JSON translator statement */ - char **pzErr; /* Write error message here, if not NULL */ - sqlite3_str *pOut; /* Accumulated output */ - int iErr; /* Error code */ - int nCol; /* Number of output columns */ - int expMode; /* Original sqlite3_stmt_isexplain() plus 1 */ - int mxWidth; /* Screen width */ - int mxHeight; /* nLineLimit */ - union { - struct { /* Content for QRF_STYLE_Line */ - int mxColWth; /* Maximum display width of any column */ - char **azCol; /* Names of output columns (MODE_Line) */ - } sLine; - qrfEQPGraph *pGraph; /* EQP graph (Eqp, Stats, and StatsEst) */ - struct { /* Content for QRF_STYLE_Explain */ - int nIndent; /* Slots allocated for aiIndent */ - int iIndent; /* Current slot */ - int *aiIndent; /* Indentation for each opcode */ - } sExpln; - } u; - sqlite3_int64 nRow; /* Number of rows handled so far */ - int *actualWidth; /* Actual width of each column */ - sqlite3_qrf_spec spec; /* Copy of the original spec */ +/* VxWorks does not support getrusage() as far as we can determine */ +#if defined(_WRS_KERNEL) || defined(__RTP__) +struct rusage { + struct timeval ru_utime; /* user CPU time used */ + struct timeval ru_stime; /* system CPU time used */ }; +#define getrusage(A,B) memset(B,0,sizeof(*B)) +#endif -/* -** Data for substitute ctype.h functions. Used for x-platform -** consistency and so that '_' is counted as an alphabetic -** character. -** -** 0x01 - space -** 0x02 - digit -** 0x04 - alphabetic, including '_' -*/ -static const char qrfCType[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, - 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4, - 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; -#define qrfSpace(x) ((qrfCType[(unsigned char)x]&1)!=0) -#define qrfDigit(x) ((qrfCType[(unsigned char)x]&2)!=0) -#define qrfAlpha(x) ((qrfCType[(unsigned char)x]&4)!=0) -#define qrfAlnum(x) ((qrfCType[(unsigned char)x]&6)!=0) -#ifndef deliberate_fall_through -/* Quiet some compilers about some of our intentional code. */ -# if defined(GCC_VERSION) && GCC_VERSION>=7000000 -# define deliberate_fall_through __attribute__((fallthrough)); -# else -# define deliberate_fall_through -# endif -#endif +/* 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 */ /* -** Set an error code and error message. +** Begin timing an operation */ -static void qrfError( - Qrf *p, /* Query result state */ - int iCode, /* Error code */ - const char *zFormat, /* Message format (or NULL) */ - ... -){ - p->iErr = iCode; - if( p->pzErr!=0 ){ - sqlite3_free(*p->pzErr); - *p->pzErr = 0; - if( zFormat ){ - va_list ap; - va_start(ap, zFormat); - *p->pzErr = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - } +static void beginTimer(void){ + if( enableTimer ){ + getrusage(RUSAGE_SELF, &sBegin); + iBegin = timeOfDay(); } } -/* -** Out-of-memory error. -*/ -static void qrfOom(Qrf *p){ - qrfError(p, SQLITE_NOMEM, "out of memory"); +/* Return the difference of two time_structs in seconds */ +static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + + (double)(pEnd->tv_sec - pStart->tv_sec); } /* -** Transfer any error in pStr over into p. +** Print the timing results. */ -static void qrfStrErr(Qrf *p, sqlite3_str *pStr){ - int rc = pStr ? sqlite3_str_errcode(pStr) : 0; - if( rc ){ - qrfError(p, rc, sqlite3_errstr(rc)); +static void endTimer(FILE *out){ + if( enableTimer ){ + sqlite3_int64 iEnd = timeOfDay(); + struct rusage sEnd; + getrusage(RUSAGE_SELF, &sEnd); + sqlite3_fprintf(out, "Run Time: real %.6f user %.6f sys %.6f\n", + (iEnd - iBegin)*0.000001, + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); } } +#define BEGIN_TIMER beginTimer() +#define END_TIMER(X) endTimer(X) +#define HAS_TIMER 1 + +#elif (defined(_WIN32) || defined(WIN32)) + +/* Saved resource information for the beginning of an operation */ +static HANDLE hProcess; +static FILETIME ftKernelBegin; +static FILETIME ftUserBegin; +static sqlite3_int64 ftWallBegin; +typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, + LPFILETIME, LPFILETIME); +static GETPROCTIMES getProcessTimesAddr = NULL; /* -** Add a new entry to the EXPLAIN QUERY PLAN data +** Check to see if we have timer support. Return 1 if necessary +** support found (or found previously). */ -static void qrfEqpAppend(Qrf *p, int iEqpId, int p2, const char *zText){ - qrfEQPGraphRow *pNew; - sqlite3_int64 nText; - if( zText==0 ) return; - if( p->u.pGraph==0 ){ - p->u.pGraph = sqlite3_malloc64( sizeof(qrfEQPGraph) ); - if( p->u.pGraph==0 ){ - qrfOom(p); - return; +static int hasTimer(void){ + if( getProcessTimesAddr ){ + return 1; + } else { +#if !SQLITE_OS_WINRT + /* GetProcessTimes() isn't supported in WIN95 and some other Windows + ** versions. See if the version we are running on has it, and if it + ** does, save off a pointer to it and the current process handle. + */ + hProcess = GetCurrentProcess(); + if( hProcess ){ + HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); + if( NULL != hinstLib ){ + getProcessTimesAddr = + (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); + if( NULL != getProcessTimesAddr ){ + return 1; + } + FreeLibrary(hinstLib); + } } - memset(p->u.pGraph, 0, sizeof(qrfEQPGraph) ); - } - nText = strlen(zText); - pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); - if( pNew==0 ){ - qrfOom(p); - return; - } - pNew->iEqpId = iEqpId; - pNew->iParentId = p2; - memcpy(pNew->zText, zText, nText+1); - pNew->pNext = 0; - if( p->u.pGraph->pLast ){ - p->u.pGraph->pLast->pNext = pNew; - }else{ - p->u.pGraph->pRow = pNew; +#endif } - p->u.pGraph->pLast = pNew; + return 0; } /* -** Free and reset the EXPLAIN QUERY PLAN data that has been collected -** in p->u.pGraph. +** Begin timing an operation */ -static void qrfEqpReset(Qrf *p){ - qrfEQPGraphRow *pRow, *pNext; - if( p->u.pGraph ){ - for(pRow = p->u.pGraph->pRow; pRow; pRow = pNext){ - pNext = pRow->pNext; - sqlite3_free(pRow); - } - sqlite3_free(p->u.pGraph); - p->u.pGraph = 0; +static void beginTimer(void){ + if( enableTimer && getProcessTimesAddr ){ + FILETIME ftCreation, ftExit; + getProcessTimesAddr(hProcess,&ftCreation,&ftExit, + &ftKernelBegin,&ftUserBegin); + ftWallBegin = timeOfDay(); } } -/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after -** pOld, or return the first such line if pOld is NULL -*/ -static qrfEQPGraphRow *qrfEqpNextRow(Qrf *p, int iEqpId, qrfEQPGraphRow *pOld){ - qrfEQPGraphRow *pRow = pOld ? pOld->pNext : p->u.pGraph->pRow; - while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; - return pRow; +/* Return the difference of two FILETIME structs in seconds */ +static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ + sqlite_int64 i64Start = *((sqlite_int64 *) pStart); + sqlite_int64 i64End = *((sqlite_int64 *) pEnd); + return (double) ((i64End - i64Start) / 10000000.0); } -/* Render a single level of the graph that has iEqpId as its parent. Called -** recursively to render sublevels. +/* +** Print the timing results. */ -static void qrfEqpRenderLevel(Qrf *p, int iEqpId){ - qrfEQPGraphRow *pRow, *pNext; - i64 n = strlen(p->u.pGraph->zPrefix); - char *z; - for(pRow = qrfEqpNextRow(p, iEqpId, 0); pRow; pRow = pNext){ - pNext = qrfEqpNextRow(p, iEqpId, pRow); - z = pRow->zText; - sqlite3_str_appendf(p->pOut, "%s%s%s\n", p->u.pGraph->zPrefix, - pNext ? "|--" : "`--", z); - if( n<(i64)sizeof(p->u.pGraph->zPrefix)-7 ){ - memcpy(&p->u.pGraph->zPrefix[n], pNext ? "| " : " ", 4); - qrfEqpRenderLevel(p, pRow->iEqpId); - p->u.pGraph->zPrefix[n] = 0; - } +static void endTimer(FILE *out){ + if( enableTimer && getProcessTimesAddr){ + FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; + sqlite3_int64 ftWallEnd = timeOfDay(); + getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); +#ifdef _WIN64 + /* microsecond precision on 64-bit windows */ + sqlite3_fprintf(out, "Run Time: real %.6f user %f sys %f\n", + (ftWallEnd - ftWallBegin)*0.000001, + timeDiff(&ftUserBegin, &ftUserEnd), + timeDiff(&ftKernelBegin, &ftKernelEnd)); +#else + /* millisecond precisino on 32-bit windows */ + sqlite3_fprintf(out, "Run Time: real %.3f user %.3f sys %.3f\n", + (ftWallEnd - ftWallBegin)*0.000001, + timeDiff(&ftUserBegin, &ftUserEnd), + timeDiff(&ftKernelBegin, &ftKernelEnd)); +#endif } } +#define BEGIN_TIMER beginTimer() +#define END_TIMER(X) endTimer(X) +#define HAS_TIMER hasTimer() + +#else +#define BEGIN_TIMER +#define END_TIMER(X) /*no-op*/ +#define HAS_TIMER 0 +#endif + /* -** Render the 64-bit value N in a more human-readable format into -** pOut. -** -** + Only show the first three significant digits. -** + Append suffixes K, M, G, T, P, and E for 1e3, 1e6, ... 1e18 +** Used to prevent warnings about unused parameters */ -static void qrfApproxInt64(sqlite3_str *pOut, i64 N){ - static const char aSuffix[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; - int i; - if( N<0 ){ - N = N==INT64_MIN ? INT64_MAX : -N; - sqlite3_str_append(pOut, "-", 1); - } - if( N<10000 ){ - sqlite3_str_appendf(pOut, "%4lld ", N); - return; - } - for(i=1; i<=18; i++){ - N = (N+5)/10; - if( N<10000 ){ - int n = (int)N; - switch( i%3 ){ - case 0: - sqlite3_str_appendf(pOut, "%d.%02d", n/1000, (n%1000)/10); - break; - case 1: - sqlite3_str_appendf(pOut, "%2d.%d", n/100, (n%100)/10); - break; - case 2: - sqlite3_str_appendf(pOut, "%4d", n/10); - break; - } - sqlite3_str_append(pOut, &aSuffix[i/3], 1); - break; - } - } -} +#define UNUSED_PARAMETER(x) (void)(x) /* -** Display and reset the EXPLAIN QUERY PLAN data +** Number of elements in an array */ -static void qrfEqpRender(Qrf *p, i64 nCycle){ - qrfEQPGraphRow *pRow; - if( p->u.pGraph!=0 && (pRow = p->u.pGraph->pRow)!=0 ){ - if( pRow->zText[0]=='-' ){ - if( pRow->pNext==0 ){ - qrfEqpReset(p); - return; - } - sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3); - p->u.pGraph->pRow = pRow->pNext; - sqlite3_free(pRow); - }else if( nCycle>0 ){ - int nSp = p->u.pGraph->nWidth - 2; - if( p->spec.eStyle==QRF_STYLE_StatsEst ){ - sqlite3_str_appendchar(p->pOut, nSp, ' '); - sqlite3_str_appendall(p->pOut, - "Cycles Loops (est) Rows (est)\n"); - sqlite3_str_appendchar(p->pOut, nSp, ' '); - sqlite3_str_appendall(p->pOut, - "---------- ------------ ------------\n"); - }else{ - sqlite3_str_appendchar(p->pOut, nSp, ' '); - sqlite3_str_appendall(p->pOut, - "Cycles Loops Rows \n"); - sqlite3_str_appendchar(p->pOut, nSp, ' '); - sqlite3_str_appendall(p->pOut, - "---------- ----- -----\n"); - } - sqlite3_str_appendall(p->pOut, "QUERY PLAN"); - sqlite3_str_appendchar(p->pOut, nSp - 10, ' '); - qrfApproxInt64(p->pOut, nCycle); - sqlite3_str_appendall(p->pOut, " 100%\n"); - }else{ - sqlite3_str_appendall(p->pOut, "QUERY PLAN\n"); - } - p->u.pGraph->zPrefix[0] = 0; - qrfEqpRenderLevel(p, 0); - qrfEqpReset(p); - } -} +#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* -** Helper function for qrfExpStats(). -** +** If the following flag is set, then command execution stops +** at an error if we are not interactive. */ -static int qrfStatsHeight(sqlite3_stmt *p, int iEntry){ - int iPid = 0; - int ret = 1; - sqlite3_stmt_scanstatus_v2(p, iEntry, - SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid - ); - while( iPid!=0 ){ - int ii; - for(ii=0; 1; ii++){ - int iId; - int res; - res = sqlite3_stmt_scanstatus_v2(p, ii, - SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iId - ); - if( res ) break; - if( iId==iPid ){ - sqlite3_stmt_scanstatus_v2(p, ii, - SQLITE_SCANSTAT_PARENTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid - ); - } - } - ret++; - } - return ret; -} -#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ +static int bail_on_error = 0; +/* +** Treat stdin as an interactive input if the following variable +** is true. Otherwise, assume stdin is connected to a file or pipe. +*/ +static int stdin_is_interactive = 1; /* -** Generate ".scanstatus est" style of EQP output. +** On Windows systems we need to know if standard output is a console +** in order to show that UTF-16 translation is done in the sign-on +** banner. The following variable is true if it is the console. */ -static void qrfEqpStats(Qrf *p){ -#ifndef SQLITE_ENABLE_STMT_SCANSTATUS - qrfError(p, SQLITE_ERROR, "not available in this build"); -#else - static const int f = SQLITE_SCANSTAT_COMPLEX; - sqlite3_stmt *pS = p->pStmt; - int i = 0; - i64 nTotal = 0; - int nWidth = 0; - int prevPid = -1; /* Previous iPid */ - double rEstCum = 1.0; /* Cumulative row estimate */ - sqlite3_str *pLine = sqlite3_str_new(p->db); - sqlite3_str *pStats = sqlite3_str_new(p->db); - qrfEqpReset(p); +static int stdout_is_console = 1; - for(i=0; 1; i++){ - const char *z = 0; - int n = 0; - if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){ - break; - } - n = (int)strlen(z) + qrfStatsHeight(pS,i)*3; - if( n>nWidth ) nWidth = n; - } - nWidth += 2; +/* +** The following is the open SQLite database. We make a pointer +** to this database a static variable so that it can be accessed +** by the SIGINT handler to interrupt database processing. +*/ +static sqlite3 *globalDb = 0; - sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); - for(i=0; 1; i++){ - i64 nLoop = 0; - i64 nRow = 0; - i64 nCycle = 0; - int iId = 0; - int iPid = 0; - const char *zo = 0; - const char *zName = 0; - double rEst = 0.0; +/* +** True if an interrupt (Control-C) has been received. +*/ +static volatile int seenInterrupt = 0; - if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ - break; - } - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); - if( iPid!=prevPid ){ - prevPid = iPid; - rEstCum = 1.0; - } - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst); - rEstCum *= rEst; - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName); +/* +** This is the name of our program. It is set in main(), used +** in a number of other places, mostly for error messages. +*/ +static char *Argv0; - if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ - int nSp = 0; - sqlite3_str_reset(pStats); - if( nCycle>=0 && nTotal>0 ){ - qrfApproxInt64(pStats, nCycle); - sqlite3_str_appendf(pStats, " %3d%%", - ((nCycle*100)+nTotal/2) / nTotal - ); - nSp = 2; - } - if( nLoop>=0 ){ - if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); - qrfApproxInt64(pStats, nLoop); - nSp = 2; - if( p->spec.eStyle==QRF_STYLE_StatsEst ){ - sqlite3_str_appendf(pStats, " "); - qrfApproxInt64(pStats, (i64)(rEstCum/rEst)); - } - } - if( nRow>=0 ){ - if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); - qrfApproxInt64(pStats, nRow); - nSp = 2; - if( p->spec.eStyle==QRF_STYLE_StatsEst ){ - sqlite3_str_appendf(pStats, " "); - qrfApproxInt64(pStats, (i64)rEstCum); - } - } - sqlite3_str_appendf(pLine, - "% *s %s", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo, - sqlite3_str_value(pStats) - ); - sqlite3_str_reset(pStats); - qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine)); - sqlite3_str_reset(pLine); - }else{ - qrfEqpAppend(p, iId, iPid, zo); - } - } - if( p->u.pGraph ) p->u.pGraph->nWidth = nWidth; - qrfStrErr(p, pLine); - sqlite3_free(sqlite3_str_finish(pLine)); - qrfStrErr(p, pStats); - sqlite3_free(sqlite3_str_finish(pStats)); -#endif -} +/* +** Prompt strings. Initialized in main. Settable with +** .prompt main continue +*/ +#define PROMPT_LEN_MAX 128 +/* First line prompt. default: "sqlite> " */ +static char mainPrompt[PROMPT_LEN_MAX]; +/* Continuation prompt. default: " ...> " */ +static char continuePrompt[PROMPT_LEN_MAX]; +/* This is variant of the standard-library strncpy() routine with the +** one change that the destination string is always zero-terminated, even +** if there is no zero-terminator in the first n-1 characters of the source +** string. +*/ +static char *shell_strncpy(char *dest, const char *src, size_t n){ + size_t i; + for(i=0; ipStmt); - if( rc!=SQLITE_OK && p->iErr==SQLITE_OK ){ - qrfError(p, rc, "%s", sqlite3_errmsg(p->db)); - } +static void shell_strcpy(char *dest, const char *src){ + while( (*(dest++) = *(src++))!=0 ){} } /* -** If xWrite is defined, send all content of pOut to xWrite and -** reset pOut. +** 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. +** This facility interacts with the scanner and process_input() where the +** below 5 macros are used. */ -static void qrfWrite(Qrf *p){ - int n; - if( p->spec.xWrite && (n = sqlite3_str_length(p->pOut))>0 ){ - int rc = p->spec.xWrite(p->spec.pWriteArg, - sqlite3_str_value(p->pOut), - (sqlite3_int64)n); - sqlite3_str_reset(p->pOut); - if( rc ){ - qrfError(p, rc, "Failed to write %d bytes of output", n); +#ifdef SQLITE_OMIT_DYNAPROMPT +# define CONTINUATION_PROMPT continuePrompt +# define CONTINUE_PROMPT_RESET +# define CONTINUE_PROMPT_AWAITS(p,s) +# define CONTINUE_PROMPT_AWAITC(p,c) +# define CONTINUE_PAREN_INCR(p,n) +# define CONTINUE_PROMPT_PSTATE 0 +typedef void *t_NoDynaPrompt; +# define SCAN_TRACKER_REFTYPE t_NoDynaPrompt +#else +# define CONTINUATION_PROMPT dynamicContinuePrompt() +# define CONTINUE_PROMPT_RESET \ + do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0) +# define CONTINUE_PROMPT_AWAITS(p,s) \ + if(p && stdin_is_interactive) setLexemeOpen(p, s, 0) +# define CONTINUE_PROMPT_AWAITC(p,c) \ + if(p && stdin_is_interactive) setLexemeOpen(p, 0, c) +# define CONTINUE_PAREN_INCR(p,n) \ + if(p && stdin_is_interactive) (trackParenLevel(p,n)) +# define CONTINUE_PROMPT_PSTATE (&dynPrompt) +typedef struct DynaPrompt *t_DynaPromptRef; +# define SCAN_TRACKER_REFTYPE t_DynaPromptRef + +static struct DynaPrompt { + char dynamicPrompt[PROMPT_LEN_MAX]; + char acAwait[2]; + int inParenLevel; + char *zScannerAwaits; +} dynPrompt = { {0}, {0}, 0, 0 }; + +/* Record parenthesis nesting level change, or force level to 0. */ +static void trackParenLevel(struct DynaPrompt *p, int ni){ + p->inParenLevel += ni; + if( ni==0 ) p->inParenLevel = 0; + p->zScannerAwaits = 0; +} + +/* Record that a lexeme is opened, or closed with args==0. */ +static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){ + if( s!=0 || c==0 ){ + p->zScannerAwaits = s; + p->acAwait[0] = 0; + }else{ + p->acAwait[0] = c; + p->zScannerAwaits = p->acAwait; + } +} + +/* Upon demand, derive the continuation prompt to display. */ +static char *dynamicContinuePrompt(void){ + if( continuePrompt[0]==0 + || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) ){ + return continuePrompt; + }else{ + if( dynPrompt.zScannerAwaits ){ + size_t ncp = strlen(continuePrompt); + size_t ndp = strlen(dynPrompt.zScannerAwaits); + if( ndp > ncp-3 ) return continuePrompt; + shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits); + while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' '; + shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, + PROMPT_LEN_MAX-4); + }else{ + if( dynPrompt.inParenLevel>9 ){ + shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4); + }else if( dynPrompt.inParenLevel<0 ){ + shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4); + }else{ + shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4); + dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel); + } + shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, + PROMPT_LEN_MAX-4); } } + return dynPrompt.dynamicPrompt; } +#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ -/* Lookup table to estimate the number of columns consumed by a Unicode -** character. +/* Indicate out-of-memory and exit. */ +static void shell_out_of_memory(void){ + eputz("Error: out of memory\n"); + exit(1); +} + +/* Check a pointer to see if it is NULL. If it is NULL, exit with an +** out-of-memory error. */ -static const struct { - unsigned char w; /* Width of the character in columns */ - int iFirst; /* First character in a span having this width */ -} aQrfUWidth[] = { - /* {1, 0x00000}, */ +static void shell_check_oom(const void *p){ + if( p==0 ) shell_out_of_memory(); +} + +/* +** Write I/O traces to the following stream. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static FILE *iotrace = 0; +#endif + +/* +** This routine works like printf in that its first argument is a +** format string and subsequent arguments are values to be substituted +** in place of % fields. The result of formatting this string +** is written to iotrace. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ + va_list ap; + char *z; + if( iotrace==0 ) return; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + 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}, @@ -1381,7 +1074,7 @@ static const struct { {1, 0x00f7f}, {0, 0x00f80}, {1, 0x00f85}, {0, 0x00f86}, {1, 0x00f88}, {0, 0x00f90}, {1, 0x00f98}, {0, 0x00f99}, {1, 0x00fbd}, {0, 0x00fc6}, {1, 0x00fc7}, {0, 0x0102d}, {1, 0x01031}, {0, 0x01032}, {1, 0x01033}, - {0, 0x01036}, {1, 0x0103b}, {0, 0x01058}, + {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}, @@ -1420,38 +1113,37 @@ static const struct { ** Inaccuracies in the width estimates might cause columns to be misaligned. ** Unfortunately, there is nothing we can do about that. */ -int sqlite3_qrf_wcwidth(int c){ +int cli_wcwidth(int c){ int iFirst, iLast; /* Fast path for common characters */ - if( c<0x300 ) return 1; + if( c<=0x300 ) return 1; /* The general case */ iFirst = 0; - iLast = sizeof(aQrfUWidth)/sizeof(aQrfUWidth[0]) - 1; + iLast = sizeof(aUWidth)/sizeof(aUWidth[0]) - 1; while( iFirst c ){ iLast = iMid - 1; }else{ - return aQrfUWidth[iMid].w; + return aUWidth[iMid].w; } } - if( aQrfUWidth[iLast].iFirst > c ) return aQrfUWidth[iFirst].w; - return aQrfUWidth[iLast].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. +** begins at z[0]. Return the length. Write the Unicode value into *pU. ** -** This routine only works for *multi-byte* UTF-8 characters. It does -** not attempt to detect illegal characters. +** This routine only works for *multi-byte* UTF-8 characters. */ -int sqlite3_qrf_decode_utf8(const unsigned char *z, int *pU){ +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; @@ -1471,6 +1163,36 @@ int sqlite3_qrf_decode_utf8(const unsigned char *z, int *pU){ 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 + /* ** Check to see if z[] is a valid VT100 escape. If it is, then ** return the number of bytes in the escape sequence. Return 0 if @@ -1478,7 +1200,7 @@ int sqlite3_qrf_decode_utf8(const unsigned char *z, int *pU){ ** ** This routine assumes that z[0] is \033 (ESC). */ -static int qrfIsVt100(const unsigned char *z){ +static int isVt100(const unsigned char *z){ int i; if( z[1]!='[' ) return 0; i = 2; @@ -1489,3150 +1211,1886 @@ static int qrfIsVt100(const unsigned char *z){ } /* -** Return the length of a string in display characters. +** 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. ** -** Most characters of the input string count as 1, including -** multi-byte UTF8 characters. However, zero-width unicode -** characters and VT100 escape sequences count as zero, and -** double-width characters count as two. +** 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. ** -** The definition of "zero-width" and "double-width" characters -** is not precise. It depends on the output device, to some extent, -** and it varies according to the Unicode version. This routine -** makes the best guess that it can. +** w should normally be a small number. A couple hundred at most. This +** routine caps w at 100 million to avoid integer overflow issues. */ -size_t sqlite3_qrf_wcswidth(const char *zIn){ - const unsigned char *z = (const unsigned char*)zIn; - size_t n = 0; - while( *z ){ - if( z[0]<' ' ){ - int k; - if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){ - z += k; - }else{ - z++; +static void utf8_width_print(FILE *out, int w, const char *zUtf){ + const unsigned char *a = (const unsigned char*)zUtf; + static const int mxW = 10000000; + unsigned char c; + int i = 0; + int n = 0; + int k; + int aw; + if( w<-mxW ){ + w = -mxW; + }else if( w>mxW ){ + w= mxW; + } + aw = w<0 ? -w : w; + if( zUtf==0 ) zUtf = ""; + 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; } - }else if( (0x80&z[0])==0 ){ - n++; - z++; + i += len; + n += x; + }else if( c==0x1b && (k = isVt100(&a[i]))>0 ){ + i += k; + }else if( n>=aw ){ + break; }else{ - int u = 0; - int len = sqlite3_qrf_decode_utf8(z, &u); - z += len; - n += sqlite3_qrf_wcwidth(u); + n++; + i++; } } - return n; + if( n>=aw ){ + sqlite3_fprintf(out, "%.*s", i, zUtf); + }else if( w<0 ){ + sqlite3_fprintf(out, "%*s%s", aw-n, "", zUtf); + }else{ + sqlite3_fprintf(out, "%s%*s", zUtf, aw-n, ""); + } +} + + +/* +** Determines if a string is a number of not. +*/ +static int isNumber(const char *z, int *realnum){ + if( *z=='-' || *z=='+' ) z++; + if( !IsDigit(*z) ){ + return 0; + } + z++; + if( realnum ) *realnum = 0; + while( IsDigit(*z) ){ z++; } + if( *z=='.' ){ + z++; + if( !IsDigit(*z) ) return 0; + while( IsDigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + if( *z=='e' || *z=='E' ){ + z++; + if( *z=='+' || *z=='-' ) z++; + if( !IsDigit(*z) ) return 0; + while( IsDigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + return *z==0; } /* -** Return the display width of the longest line of text -** in the (possibly) multi-line input string zIn[0..nByte]. -** zIn[] is not necessarily zero-terminated. Take -** into account tab characters, zero- and double-width -** characters, CR and NL, and VT100 escape codes. -** -** Write the number of newlines into *pnNL. So, *pnNL will -** return 0 if everything fits on one line, or positive it -** it will need to be split. +** Compute a string length that is limited to what can be stored in +** lower 30 bits of a 32-bit signed integer. +*/ +static int strlen30(const char *z){ + const char *z2 = z; + while( *z2 ){ z2++; } + return 0x3fffffff & (int)(z2 - z); +} + +/* +** Return the length of a string in characters. Multibyte UTF8 characters +** count as a single character for single-width characters, or as two +** characters for double-width characters. */ -static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){ - const unsigned char *z; - const unsigned char *zEnd; - int mx = 0; +static int strlenChar(const char *z){ int n = 0; - int nNL = 0; - if( zIn==0 ) zIn = ""; - z = (const unsigned char*)zIn; - zEnd = &z[nByte]; - while( z0 ){ - z += k; - }else{ - if( z[0]=='\t' ){ - n = (n+8)&~7; - }else if( z[0]=='\n' || z[0]=='\r' ){ - nNL++; - if( n>mx ) mx = n; - n = 0; - } - z++; - } - }else if( (0x80&z[0])==0 ){ + while( *z ){ + if( (0x80&z[0])==0 ){ n++; z++; }else{ int u = 0; - int len = sqlite3_qrf_decode_utf8(z, &u); + int len = decodeUtf8((const u8*)z, &u); z += len; - n += sqlite3_qrf_wcwidth(u); + n += cli_wcwidth(u); } } - if( mx>n ) n = mx; - if( pnNL ) *pnNL = nNL; return n; } /* -** Escape the input string if it is needed and in accordance with -** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol. -** -** Escaping is needed if the string contains any control characters -** other than \t, \n, and \r\n -** -** If no escaping is needed (the common case) then set *ppOut to NULL -** and return 0. If escaping is needed, write the escaped string into -** memory obtained from sqlite3_malloc64() and make *ppOut point to that -** memory and return 0. If an error occurs, return non-zero. -** -** The caller is responsible for freeing *ppFree if it is non-NULL in order -** to reclaim memory. +** Return open FILE * if zFile exists, can be opened for read +** and is an ordinary file or a character stream source. +** Otherwise return 0. */ -static void qrfEscape( - int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */ - sqlite3_str *pStr, /* String to be escaped */ - int iStart /* Begin escapding on this byte of pStr */ -){ - sqlite3_int64 i, j; /* Loop counters */ - sqlite3_int64 sz; /* Size of the string prior to escaping */ - sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */ - unsigned char *zIn; /* Text to be escaped */ - unsigned char c; /* A single character of the text */ - unsigned char *zOut; /* Where to write the results */ - - /* Find the text to be escaped */ - zIn = (unsigned char*)sqlite3_str_value(pStr); - if( zIn==0 ) return; - zIn += iStart; - - /* Count the control characters */ - for(i=0; (c = zIn[i])!=0; i++){ - if( c<=0x1f - && c!='\t' - && c!='\n' - && (c!='\r' || zIn[i+1]!='\n') - ){ - nCtrl++; - } +static FILE * openChrSource(const char *zFile){ +#if defined(_WIN32) || defined(WIN32) + struct __stat64 x = {0}; +# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0) + /* 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 = sqlite3_fopen(zFile, "rb"); + if( rv==0 ) return 0; + if( _fstat64(_fileno(rv), &x) != 0 + || !STAT_CHR_SRC(x.st_mode)){ + fclose(rv); + rv = 0; } - if( nCtrl==0 ) return; /* Early out if no control characters */ - - /* Make space to hold the escapes. Copy the original text to the end - ** of the available space. */ - sz = sqlite3_str_length(pStr) - iStart; - if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2; - sqlite3_str_appendchar(pStr, nCtrl, ' '); - zOut = (unsigned char*)sqlite3_str_value(pStr); - if( zOut==0 ) return; - zOut += iStart; - zIn = zOut + nCtrl; - memmove(zIn,zOut,sz); - - /* Convert the control characters */ - for(i=j=0; (c = zIn[i])!=0; i++){ - if( c>0x1f - || c=='\t' - || c=='\n' - || (c=='\r' && zIn[i+1]=='\n') - ){ - continue; - } - if( i>0 ){ - memmove(&zOut[j], zIn, i); - j += i; - } - zIn += i+1; - i = -1; - if( eEsc==QRF_ESC_Symbol ){ - zOut[j++] = 0xe2; - zOut[j++] = 0x90; - zOut[j++] = 0x80+c; - }else{ - zOut[j++] = '^'; - zOut[j++] = 0x40+c; - } + return rv; +#else + struct stat x = {0}; + int rc = stat(zFile, &x); +# 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 sqlite3_fopen(zFile, "rb"); + }else{ + return 0; } +#endif +#undef STAT_CHR_SRC } /* -** Determine if the string z[] can be shown as plain text. Return true -** if z[] is unambiguously text. Return false if z[] needs to be -** quoted. -** -** All of the following must be true in order for z[] to be relaxable: +** This routine reads a line of text from FILE in, stores +** the text in memory obtained from malloc() and returns a pointer +** to the text. NULL is returned at end of file, or if malloc() +** fails, or if the length of the line is longer than about a gigabyte. ** -** (1) z[] does not begin or end with ' or whitespace -** (2) z[] is not the same as the NULL rendering -** (3) z[] does not looks like a numeric literal -*/ -static int qrfRelaxable(Qrf *p, const char *z){ - size_t i, n; - if( z[0]=='\'' || qrfSpace(z[0]) ) return 0; - if( z[0]==0 ){ - return (p->spec.zNull!=0 && p->spec.zNull[0]!=0); - } - n = strlen(z); - if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0; - if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0; - i = (z[0]=='-' || z[0]=='+'); - if( strcmp(z+i,"Inf")==0 ) return 0; - if( !qrfDigit(z[i]) ) return 1; - i++; - while( qrfDigit(z[i]) ){ i++; } - if( z[i]==0 ) return 0; - if( z[i]=='.' ){ - i++; - while( qrfDigit(z[i]) ){ i++; } - if( z[i]==0 ) return 0; - } - if( z[i]=='e' || z[i]=='E' ){ - i++; - if( z[i]=='+' || z[i]=='-' ){ i++; } - if( !qrfDigit(z[i]) ) return 1; - i++; - while( qrfDigit(z[i]) ){ i++; } - } - return z[i]!=0; -} - -/* -** If a field contains any character identified by a 1 in the following -** array, then the string must be quoted for CSV. +** If zLine is not NULL then it is a malloced buffer returned from +** a previous call to this routine that may be reused. */ -static const char qrfCsvQuote[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -}; +static char *local_getline(char *zLine, FILE *in){ + int nLine = zLine==0 ? 0 : 100; + int n = 0; -/* -** Encode text appropriately and append it to pOut. -*/ -static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){ - int iStart = sqlite3_str_length(pOut); - switch( p->spec.eText ){ - case QRF_TEXT_Relaxed: - if( qrfRelaxable(p, zTxt) ){ - sqlite3_str_appendall(pOut, zTxt); - break; - } - deliberate_fall_through; /* FALLTHRU */ - case QRF_TEXT_Sql: { - if( p->spec.eEsc==QRF_ESC_Off ){ - sqlite3_str_appendf(pOut, "%Q", zTxt); - }else{ - sqlite3_str_appendf(pOut, "%#Q", zTxt); + while( 1 ){ + if( n+100>nLine ){ + if( nLine>=1073741773 ){ + free(zLine); + return 0; } - break; + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); + shell_check_oom(zLine); } - case QRF_TEXT_Csv: { - unsigned int i; - for(i=0; zTxt[i]; i++){ - if( qrfCsvQuote[((const unsigned char*)zTxt)[i]] ){ - i = 0; - break; - } - } - if( i==0 || strstr(zTxt, p->spec.zColumnSep)!=0 ){ - sqlite3_str_appendf(pOut, "\"%w\"", zTxt); - }else{ - sqlite3_str_appendall(pOut, zTxt); + if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ + free(zLine); + return 0; } + zLine[n] = 0; break; } - case QRF_TEXT_Html: { - const unsigned char *z = (const unsigned char*)zTxt; - while( *z ){ - unsigned int i = 0; - unsigned char c; - while( (c=z[i])>'>' - || (c && c!='<' && c!='>' && c!='&' && c!='\"' && c!='\'') - ){ - i++; - } - if( i>0 ){ - sqlite3_str_append(pOut, (const char*)z, i); - } - switch( z[i] ){ - case '>': sqlite3_str_append(pOut, "<", 4); break; - case '&': sqlite3_str_append(pOut, "&", 5); break; - case '<': sqlite3_str_append(pOut, "<", 4); break; - case '"': sqlite3_str_append(pOut, """, 6); break; - case '\'': sqlite3_str_append(pOut, "'", 5); break; - default: i--; - } - z += i + 1; - } - break; - } - case QRF_TEXT_Tcl: - case QRF_TEXT_Json: { - const unsigned char *z = (const unsigned char*)zTxt; - sqlite3_str_append(pOut, "\"", 1); - while( *z ){ - unsigned int i; - for(i=0; z[i]>=0x20 && z[i]!='\\' && z[i]!='"'; i++){} - if( i>0 ){ - sqlite3_str_append(pOut, (const char*)z, i); - } - if( z[i]==0 ) break; - switch( z[i] ){ - case '"': sqlite3_str_append(pOut, "\\\"", 2); break; - case '\\': sqlite3_str_append(pOut, "\\\\", 2); break; - case '\b': sqlite3_str_append(pOut, "\\b", 2); break; - case '\f': sqlite3_str_append(pOut, "\\f", 2); break; - case '\n': sqlite3_str_append(pOut, "\\n", 2); break; - case '\r': sqlite3_str_append(pOut, "\\r", 2); break; - case '\t': sqlite3_str_append(pOut, "\\t", 2); break; - default: { - if( p->spec.eText==QRF_TEXT_Json ){ - sqlite3_str_appendf(pOut, "\\u%04x", z[i]); - }else{ - sqlite3_str_appendf(pOut, "\\%03o", z[i]); - } - break; - } - } - z += i + 1; - } - sqlite3_str_append(pOut, "\"", 1); - break; - } - default: { - sqlite3_str_appendall(pOut, zTxt); + while( zLine[n] ) n++; + if( n>0 && zLine[n-1]=='\n' ){ + n--; + if( n>0 && zLine[n-1]=='\r' ) n--; + zLine[n] = 0; break; } } - if( p->spec.eEsc!=QRF_ESC_Off ){ - qrfEscape(p->spec.eEsc, pOut, iStart); - } + return zLine; } /* -** Do a quick sanity check to see aBlob[0..nBlob-1] is valid JSONB -** return true if it is and false if it is not. +** Retrieve a single line of input text. ** -** False positives are possible, but not false negatives. -*/ -static int qrfJsonbQuickCheck(unsigned char *aBlob, int nBlob){ - unsigned char x; /* Payload size half-byte */ - int i; /* Loop counter */ - int n; /* Bytes in the payload size integer */ - sqlite3_uint64 sz; /* value of the payload size integer */ - - if( nBlob==0 ) return 0; - x = aBlob[0]>>4; - if( x<=11 ) return nBlob==(1+x); - n = x<14 ? x-11 : 4*(x-13); - if( nBlob<1+n ) return 0; - sz = aBlob[1]; - for(i=1; ipStmt is known to be a BLOB. Check -** to see if that BLOB is really a JSONB blob. If it is, then translate -** it into a text JSON representation and return a pointer to that text JSON. -** If the BLOB is not JSONB, then return a NULL pointer. +** If in==0 then read from standard input and prompt before each line. +** If isContinuation is true, then a continuation prompt is appropriate. +** If isContinuation is zero, then the main prompt should be used. +** +** If zPrior is not NULL then it is a buffer from a prior call to this +** routine that can be reused. ** -** The memory used to hold the JSON text is managed internally by the -** "p" object and is overwritten and/or deallocated upon the next call -** to this routine (with the same p argument) or when the p object is -** finailized. +** The result is stored in space obtained from malloc() and must either +** be freed by the caller or else passed back into this routine via the +** zPrior argument for reuse. */ -static const char *qrfJsonbToJson(Qrf *p, int iCol){ - int nByte; - const void *pBlob; - int rc; - nByte = sqlite3_column_bytes(p->pStmt, iCol); - pBlob = sqlite3_column_blob(p->pStmt, iCol); - if( qrfJsonbQuickCheck((unsigned char*)pBlob, nByte)==0 ){ - return 0; - } - if( p->pJTrans==0 ){ - sqlite3 *db; - rc = sqlite3_open(":memory:",&db); - if( rc ){ - sqlite3_close(db); - return 0; - } - rc = sqlite3_prepare_v2(db, "SELECT json(?1)", -1, &p->pJTrans, 0); - if( rc ){ - sqlite3_finalize(p->pJTrans); - p->pJTrans = 0; - sqlite3_close(db); - return 0; - } - }else{ - sqlite3_reset(p->pJTrans); - } - sqlite3_bind_blob(p->pJTrans, 1, (void*)pBlob, nByte, SQLITE_STATIC); - rc = sqlite3_step(p->pJTrans); - if( rc==SQLITE_ROW ){ - return (const char*)sqlite3_column_text(p->pJTrans, 0); +#ifndef SQLITE_SHELL_FIDDLE +static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ + char *zPrompt; + char *zResult; + if( in!=0 ){ + zResult = local_getline(zPrior, in); }else{ - return 0; + zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt; +#if SHELL_USE_LOCAL_GETLINE + sputz(stdout, zPrompt); + fflush(stdout); + do{ + zResult = local_getline(zPrior, stdin); + zPrior = 0; + /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ + if( zResult==0 ) sqlite3_sleep(50); + }while( zResult==0 && seenInterrupt>0 ); +#else + free(zPrior); + zResult = shell_readline(zPrompt); + while( zResult==0 ){ + /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ + sqlite3_sleep(50); + if( seenInterrupt==0 ) break; + zResult = shell_readline(""); + } + if( zResult && *zResult ) shell_add_history(zResult); +#endif } + return zResult; } +#endif /* !SQLITE_SHELL_FIDDLE */ /* -** Adjust the input string zIn[] such that it is no more than N display -** characters wide. If it is wider than that, then truncate and add -** ellipsis. Or if zIn[] contains a \r or \n, truncate at that point, -** adding ellipsis. Embedded tabs in zIn[] are converted into ordinary -** spaces. -** -** Return this display width of the modified title string. +** Return the value of a hexadecimal digit. Return -1 if the input +** is not a hex digit. */ -static int qrfTitleLimit(char *zIn, int N){ - unsigned char *z = (unsigned char*)zIn; - int n = 0; - unsigned char *zEllipsis = 0; - while( 1 /*exit-by-break*/ ){ - if( z[0]<' ' ){ - int k; - if( z[0]==0 ){ - zEllipsis = 0; - break; - }else if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){ - z += k; - }else if( z[0]=='\t' ){ - z[0] = ' '; - }else if( z[0]=='\n' || z[0]=='\r' ){ - z[0] = ' '; - }else{ - z++; - } - }else if( (0x80&z[0])==0 ){ - if( n>=(N-3) && zEllipsis==0 ) zEllipsis = z; - if( n==N ){ z[0] = 0; break; } - n++; - z++; - }else{ - int u = 0; - int len = sqlite3_qrf_decode_utf8(z, &u); - if( n+len>(N-3) && zEllipsis==0 ) zEllipsis = z; - if( n+len>N ){ z[0] = 0; break; } - z += len; - n += sqlite3_qrf_wcwidth(u); - } - } - if( zEllipsis && N>=3 ) memcpy(zEllipsis,"...",4); - return n; +static int hexDigitValue(char c){ + if( c>='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; + return -1; } - /* -** Render value pVal into pOut +** Interpret zArg as an integer value, possibly with suffixes. +** +** If the value specified by zArg is outside the range of values that +** can be represented using a 64-bit twos-complement integer, then return +** the nearest representable value. */ -static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){ -#if SQLITE_VERSION_NUMBER>=3052000 - int iStartLen = sqlite3_str_length(pOut); -#endif - if( p->spec.xRender ){ - sqlite3_value *pVal; - char *z; - pVal = sqlite3_value_dup(sqlite3_column_value(p->pStmt,iCol)); - z = p->spec.xRender(p->spec.pRenderArg, pVal); - sqlite3_value_free(pVal); - if( z ){ - sqlite3_str_appendall(pOut, z); - sqlite3_free(z); - return; - } +static sqlite3_int64 integerValue(const char *zArg){ + sqlite3_uint64 v = 0; + static const struct { char *zSuffix; unsigned int iMult; } aMult[] = { + { "KiB", 1024 }, + { "MiB", 1024*1024 }, + { "GiB", 1024*1024*1024 }, + { "KB", 1000 }, + { "MB", 1000000 }, + { "GB", 1000000000 }, + { "K", 1000 }, + { "M", 1000000 }, + { "G", 1000000000 }, + }; + int i; + int isNeg = 0; + if( zArg[0]=='-' ){ + isNeg = 1; + zArg++; + }else if( zArg[0]=='+' ){ + zArg++; } - switch( sqlite3_column_type(p->pStmt,iCol) ){ - case SQLITE_INTEGER: { - sqlite3_str_appendf(pOut, "%lld", sqlite3_column_int64(p->pStmt,iCol)); - break; - } - case SQLITE_FLOAT: { - const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol); - sqlite3_str_appendall(pOut, zTxt); - break; + if( zArg[0]=='0' && zArg[1]=='x' ){ + int x; + zArg += 2; + while( (x = hexDigitValue(zArg[0]))>=0 ){ + if( v > 0x0fffffffffffffffULL ) goto integer_overflow; + v = (v<<4) + x; + zArg++; } - case SQLITE_BLOB: { - if( p->spec.bTextJsonb==QRF_Yes ){ - const char *zJson = qrfJsonbToJson(p, iCol); - if( zJson ){ - if( p->spec.eText==QRF_TEXT_Sql ){ - sqlite3_str_append(pOut,"jsonb(",6); - qrfEncodeText(p, pOut, zJson); - sqlite3_str_append(pOut,")",1); - }else{ - qrfEncodeText(p, pOut, zJson); - } - break; - } - } - switch( p->spec.eBlob ){ - case QRF_BLOB_Hex: - case QRF_BLOB_Sql: { - int iStart; - int nBlob = sqlite3_column_bytes(p->pStmt,iCol); - int i, j; - char *zVal; - const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol); - if( p->spec.eBlob==QRF_BLOB_Sql ){ - sqlite3_str_append(pOut, "x'", 2); - } - iStart = sqlite3_str_length(pOut); - sqlite3_str_appendchar(pOut, nBlob, ' '); - sqlite3_str_appendchar(pOut, nBlob, ' '); - if( p->spec.eBlob==QRF_BLOB_Sql ){ - sqlite3_str_appendchar(pOut, 1, '\''); - } - if( sqlite3_str_errcode(pOut) ) return; - zVal = sqlite3_str_value(pOut); - for(i=0, j=iStart; i>4)&0xf]; - zVal[j+1] = "0123456789abcdef"[(c)&0xf]; - } - break; - } - case QRF_BLOB_Tcl: - case QRF_BLOB_Json: { - int iStart; - int nBlob = sqlite3_column_bytes(p->pStmt,iCol); - int i, j; - char *zVal; - const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol); - int szC = p->spec.eBlob==QRF_BLOB_Json ? 6 : 4; - sqlite3_str_append(pOut, "\"", 1); - iStart = sqlite3_str_length(pOut); - for(i=szC; i>0; i--){ - sqlite3_str_appendchar(pOut, nBlob, ' '); - } - sqlite3_str_appendchar(pOut, 1, '"'); - if( sqlite3_str_errcode(pOut) ) return; - zVal = sqlite3_str_value(pOut); - for(i=0, j=iStart; i>6)&3); - zVal[j+2] = '0' + ((c>>3)&7); - zVal[j+3] = '0' + (c&7); - }else{ - zVal[j+1] = 'u'; - zVal[j+2] = '0'; - zVal[j+3] = '0'; - zVal[j+4] = "0123456789abcdef"[(c>>4)&0xf]; - zVal[j+5] = "0123456789abcdef"[(c)&0xf]; - } - } - break; - } - case QRF_BLOB_Size: { - int nBlob = sqlite3_column_bytes(p->pStmt,iCol); - sqlite3_str_appendf(pOut, "(%d-byte blob)", nBlob); - break; - } - default: { - const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol); - qrfEncodeText(p, pOut, zTxt); - } + }else{ + while( IsDigit(zArg[0]) ){ + if( v>=922337203685477580LL ){ + if( v>922337203685477580LL || zArg[0]>='8' ) goto integer_overflow; } - break; - } - case SQLITE_NULL: { - sqlite3_str_appendall(pOut, p->spec.zNull); - break; - } - case SQLITE_TEXT: { - const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol); - qrfEncodeText(p, pOut, zTxt); - break; + v = v*10 + (zArg[0] - '0'); + zArg++; } } -#if SQLITE_VERSION_NUMBER>=3052000 - if( p->spec.nCharLimit>0 - && (sqlite3_str_length(pOut) - iStartLen) > p->spec.nCharLimit - ){ - const unsigned char *z; - int ii = 0, w = 0, limit = p->spec.nCharLimit; - z = (const unsigned char*)sqlite3_str_value(pOut) + iStartLen; - if( limit<4 ) limit = 4; - while( 1 ){ - if( z[ii]<' ' ){ - int k; - if( z[ii]=='\033' && (k = qrfIsVt100(z+ii))>0 ){ - ii += k; - }else if( z[ii]==0 ){ - break; - }else{ - ii++; - } - }else if( (0x80&z[ii])==0 ){ - w++; - if( w>limit ) break; - ii++; - }else{ - int u = 0; - int len = sqlite3_qrf_decode_utf8(&z[ii], &u); - w += sqlite3_qrf_wcwidth(u); - if( w>limit ) break; - ii += len; - } - } - if( w>limit ){ - sqlite3_str_truncate(pOut, iStartLen+ii); - sqlite3_str_append(pOut, "...", 3); + for(i=0; i0x7fffffffffffffffULL ) goto integer_overflow; + return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v; +integer_overflow: + return isNeg ? (i64)0x8000000000000000LL : 0x7fffffffffffffffLL; } -/* Trim spaces of the end if pOut +/* +** A variable length string to which one can append text. */ -static void qrfRTrim(sqlite3_str *pOut){ -#if SQLITE_VERSION_NUMBER>=3052000 - int nByte = sqlite3_str_length(pOut); - const char *zOut = sqlite3_str_value(pOut); - while( nByte>0 && zOut[nByte-1]==' ' ){ nByte--; } - sqlite3_str_truncate(pOut, nByte); -#endif -} +typedef struct ShellText ShellText; +struct ShellText { + char *zTxt; /* The text */ + i64 n; /* Number of bytes of zTxt[] actually used */ + i64 nAlloc; /* Number of bytes allocated for zTxt[] */ +}; /* -** Store string zUtf to pOut as w characters. If w is negative, -** then right-justify the text. W is the width in display characters, not -** in bytes. Double-width unicode characters count as two characters. -** VT100 escape sequences count as zero. And so forth. +** Initialize and destroy a ShellText object */ -static void qrfWidthPrint(Qrf *p, sqlite3_str *pOut, int w, const char *zUtf){ - const unsigned char *a = (const unsigned char*)zUtf; - static const int mxW = 10000000; - unsigned char c; - int i = 0; - int n = 0; - int k; - int aw; - (void)p; - if( w<-mxW ){ - w = -mxW; - }else if( w>mxW ){ - w= mxW; - } - aw = w<0 ? -w : w; - if( a==0 ) a = (const unsigned char*)""; - while( (c = a[i])!=0 ){ - if( (c&0xc0)==0xc0 ){ - int u; - int len = sqlite3_qrf_decode_utf8(a+i, &u); - int x = sqlite3_qrf_wcwidth(u); - if( x+n>aw ){ - break; - } - i += len; - n += x; - }else if( c==0x1b && (k = qrfIsVt100(&a[i]))>0 ){ - i += k; - }else if( n>=aw ){ - break; - }else{ - n++; - i++; - } - } - if( n>=aw ){ - sqlite3_str_append(pOut, zUtf, i); - }else if( w<0 ){ - if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' '); - sqlite3_str_append(pOut, zUtf, i); - }else{ - sqlite3_str_append(pOut, zUtf, i); - if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' '); - } +static void initText(ShellText *p){ + memset(p, 0, sizeof(*p)); +} +static void freeText(ShellText *p){ + sqlite3_free(p->zTxt); + initText(p); } -/* -** (*pz)[] is a line of text that is to be displayed the box or table or -** similar tabular formats. z[] contain newlines or might be too wide -** to fit in the columns so will need to be split into multiple line. -** -** This routine determines: +/* zIn is either a pointer to a NULL-terminated string in memory obtained +** from malloc(), or a NULL pointer. The string pointed to by zAppend is +** added to zIn, and the result returned in memory obtained from malloc(). +** zIn, if it was not NULL, is freed. ** -** * How many bytes of z[] should be shown on the current line. -** * How many character positions those bytes will cover. -** * The byte offset to the start of the next line. +** If the third argument, quote, is not '\0', then it is used as a +** quote character for zAppend. */ -static void qrfWrapLine( - const char *zIn, /* Input text to be displayed */ - int w, /* Column width in characters (not bytes) */ - int bWrap, /* True if we should do word-wrapping */ - int *pnThis, /* OUT: How many bytes of z[] for the current line */ - int *pnWide, /* OUT: How wide is the text of this line */ - int *piNext /* OUT: Offset into z[] to start of the next line */ -){ - int i; /* Input bytes consumed */ - int k; /* Bytes in a VT100 code */ - int n; /* Output column number */ - const unsigned char *z = (const unsigned char*)zIn; - unsigned char c = 0; +static void appendText(ShellText *p, const char *zAppend, char quote){ + i64 len; + i64 i; + i64 nAppend = strlen30(zAppend); - if( z[0]==0 ){ - *pnThis = 0; - *pnWide = 0; - *piNext = 0; - return; - } - n = 0; - for(i=0; n<=w; i++){ - c = z[i]; - if( c>=0xc0 ){ - int u; - int len = sqlite3_qrf_decode_utf8(&z[i], &u); - int wcw = sqlite3_qrf_wcwidth(u); - if( wcw+n>w ) break; - i += len-1; - n += wcw; - continue; - } - if( c>=' ' ){ - if( n==w ) break; - n++; - continue; - } - if( c==0 || c=='\n' ) break; - if( c=='\r' && z[i+1]=='\n' ){ c = z[++i]; break; } - if( c=='\t' ){ - int wcw = 8 - (n&7); - if( n+wcw>w ) break; - n += wcw; - continue; - } - if( c==0x1b && (k = qrfIsVt100(&z[i]))>0 ){ - i += k-1; - }else if( n==w ){ - break; - }else{ - n++; + len = nAppend+p->n+1; + if( quote ){ + len += 2; + for(i=0; i=i/2; k--){ - if( qrfSpace(z[k]) ) break; - } - if( k=i/2; k--){ - if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break; - } - } - if( k>=i/2 ){ - i = k; - n = qrfDisplayWidth((const char*)z, k, 0); - } + if( p->zTxt==0 || p->n+len>=p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + len + 20; + p->zTxt = sqlite3_realloc64(p->zTxt, p->nAlloc); + shell_check_oom(p->zTxt); } - *pnThis = i; - *pnWide = n; - while( zIn[i]==' ' || zIn[i]=='\t' || zIn[i]=='\r' ){ i++; } - *piNext = i; -} -/* -** Append nVal bytes of text from zVal onto the end of pOut. -** Convert tab characters in zVal to the appropriate number of -** spaces. -*/ -static void qrfAppendWithTabs( - sqlite3_str *pOut, /* Append text here */ - const char *zVal, /* Text to append */ - int nVal /* Use only the first nVal bytes of zVal[] */ -){ - int i = 0; - unsigned int col = 0; - unsigned char *z = (unsigned char *)zVal; - while( i0 ){ - sqlite3_str_append(pOut, (const char*)z, k); - z += k; - nVal -= k; - }else if( c=='\t' ){ - k = 8 - (col&7); - sqlite3_str_appendchar(pOut, k, ' '); - col += k; - z++; - nVal--; - }else if( c=='\r' && nVal==1 ){ - z++; - nVal--; - }else{ - char zCtrlPik[4]; - col++; - zCtrlPik[0] = 0xe2; - zCtrlPik[1] = 0x90; - zCtrlPik[2] = 0x80+c; - sqlite3_str_append(pOut, zCtrlPik, 3); - z++; - nVal--; - } - }else if( (0x80&c)==0 ){ - i++; - col++; - }else{ - int u = 0; - int len = sqlite3_qrf_decode_utf8(&z[i], &u); - i += len; - col += sqlite3_qrf_wcwidth(u); + if( quote ){ + char *zCsr = p->zTxt+p->n; + *zCsr++ = quote; + for(i=0; iM - (char*)0)) -#endif - -/* -** Data for columnar layout, collected into a single object so -** that it can be more easily passed into subroutines. -*/ -typedef struct qrfColData qrfColData; -struct qrfColData { - Qrf *p; /* The QRF instance */ - int nCol; /* Number of columns in the table */ - unsigned char bMultiRow; /* One or more cells will span multiple lines */ - unsigned char nMargin; /* Width of column margins */ - sqlite3_int64 nRow; /* Number of rows */ - sqlite3_int64 nAlloc; /* Number of cells allocated */ - sqlite3_int64 n; /* Number of cells. nCol*nRow */ - char **az; /* Content of all cells */ - int *aiWth; /* Width of each cell */ - unsigned char *abNum; /* True for each numeric cell */ - struct qrfPerCol { /* Per-column data */ - char *z; /* Cache of text for current row */ - int w; /* Computed width of this column */ - int mxW; /* Maximum natural (unwrapped) width */ - unsigned char e; /* Alignment */ - unsigned char fx; /* Width is fixed */ - unsigned char bNum; /* True if is numeric */ - } *a; /* One per column */ -}; - -/* -** Output horizontally justified text into pOut. The text is the -** first nVal bytes of zVal. Include nWS bytes of whitespace, either -** split between both sides, or on the left, or on the right, depending -** on eAlign. -*/ -static void qrfPrintAligned( - sqlite3_str *pOut, /* Append text here */ - struct qrfPerCol *pCol, /* Information about the text to print */ - int nVal, /* Use only the first nVal bytes of zVal[] */ - int nWS /* Whitespace for horizonal alignment */ -){ - unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK; - if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right; - if( eAlign==QRF_ALIGN_Center ){ - /* Center the text */ - sqlite3_str_appendchar(pOut, nWS/2, ' '); - qrfAppendWithTabs(pOut, pCol->z, nVal); - sqlite3_str_appendchar(pOut, nWS - nWS/2, ' '); - }else if( eAlign==QRF_ALIGN_Right ){ - /* Right justify the text */ - sqlite3_str_appendchar(pOut, nWS, ' '); - qrfAppendWithTabs(pOut, pCol->z, nVal); + *zCsr++ = quote; + p->n = (i64)(zCsr - p->zTxt); + *zCsr = '\0'; }else{ - /* Left justify the text */ - qrfAppendWithTabs(pOut, pCol->z, nVal); - sqlite3_str_appendchar(pOut, nWS, ' '); - } -} - -/* -** Free all the memory allocates in the qrfColData object -*/ -static void qrfColDataFree(qrfColData *p){ - sqlite3_int64 i; - for(i=0; in; i++) sqlite3_free(p->az[i]); - sqlite3_free(p->az); - sqlite3_free(p->aiWth); - sqlite3_free(p->abNum); - sqlite3_free(p->a); - memset(p, 0, sizeof(*p)); -} - -/* -** Allocate space for more cells in the qrfColData object. -** Return non-zero if a memory allocation fails. -*/ -static int qrfColDataEnlarge(qrfColData *p){ - char **azData; - int *aiWth; - unsigned char *abNum; - p->nAlloc = 2*p->nAlloc + 10*p->nCol; - azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*)); - if( azData==0 ){ - qrfOom(p->p); - qrfColDataFree(p); - return 1; - } - p->az = azData; - aiWth = sqlite3_realloc64(p->aiWth, p->nAlloc*sizeof(int)); - if( aiWth==0 ){ - qrfOom(p->p); - qrfColDataFree(p); - return 1; - } - p->aiWth = aiWth; - abNum = sqlite3_realloc64(p->abNum, p->nAlloc); - if( abNum==0 ){ - qrfOom(p->p); - qrfColDataFree(p); - return 1; + memcpy(p->zTxt+p->n, zAppend, nAppend); + p->n += nAppend; + p->zTxt[p->n] = '\0'; } - p->abNum = abNum; - return 0; } /* -** Print a markdown or table-style row separator using ascii-art +** Attempt to determine if identifier zName needs to be quoted, either +** because it contains non-alphanumeric characters, or because it is an +** SQLite keyword. Be conservative in this estimate: When in doubt assume +** that quoting is required. +** +** Return '"' if quoting is required. Return 0 if no quoting is required. */ -static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){ +static char quoteChar(const char *zName){ int i; - if( p->nCol>0 ){ - int useBorder = p->p->spec.bBorder!=QRF_No; - if( useBorder ){ - sqlite3_str_append(pOut, &cSep, 1); - } - sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-'); - for(i=1; inCol; i++){ - sqlite3_str_append(pOut, &cSep, 1); - sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-'); - } - if( useBorder ){ - sqlite3_str_append(pOut, &cSep, 1); - } + if( zName==0 ) return '"'; + if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '"'; + for(i=0; zName[i]; i++){ + if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '"'; } - sqlite3_str_append(pOut, "\n", 1); + return sqlite3_keyword_check(zName, i) ? '"' : 0; } /* -** UTF8 box-drawing characters. Imagine box lines like this: -** -** 1 -** | -** 4 --+-- 2 -** | -** 3 +** Construct a fake object name and column list to describe the structure +** of the view, virtual table, or table valued function zSchema.zName. ** -** Each box characters has between 2 and 4 of the lines leading from -** the center. The characters are here identified by the numbers of -** their corresponding lines. +** The returned string comes from sqlite3_mprintf() and should be freed +** by the caller using sqlite3_free(). */ -#define BOX_24 "\342\224\200" /* U+2500 --- */ -#define BOX_13 "\342\224\202" /* U+2502 | */ -#define BOX_23 "\342\224\214" /* U+250c ,- */ -#define BOX_34 "\342\224\220" /* U+2510 -, */ -#define BOX_12 "\342\224\224" /* U+2514 '- */ -#define BOX_14 "\342\224\230" /* U+2518 -' */ -#define BOX_123 "\342\224\234" /* U+251c |- */ -#define BOX_134 "\342\224\244" /* U+2524 -| */ -#define BOX_234 "\342\224\254" /* U+252c -,- */ -#define BOX_124 "\342\224\264" /* U+2534 -'- */ -#define BOX_1234 "\342\224\274" /* U+253c -|- */ - -/* Rounded corners: */ -#define BOX_R12 "\342\225\260" /* U+2570 '- */ -#define BOX_R23 "\342\225\255" /* U+256d ,- */ -#define BOX_R34 "\342\225\256" /* U+256e -, */ -#define BOX_R14 "\342\225\257" /* U+256f -' */ - -/* Doubled horizontal lines: */ -#define DBL_24 "\342\225\220" /* U+2550 === */ -#define DBL_123 "\342\225\236" /* U+255e |= */ -#define DBL_134 "\342\225\241" /* U+2561 =| */ -#define DBL_1234 "\342\225\252" /* U+256a =|= */ +static char *shellFakeSchema( + sqlite3 *db, /* The database connection containing the vtab */ + const char *zSchema, /* Schema of the database holding the vtab */ + const char *zName /* The name of the virtual table */ +){ + sqlite3_stmt *pStmt = 0; + char *zSql; + ShellText s; + char cQuote; + char *zDiv = "("; + int nRow = 0; -/* Draw horizontal line N characters long using unicode box -** characters -*/ -static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){ - const char *azDash[2] = { - BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24, - DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 - };/* 0 1 2 3 4 5 6 7 8 9 */ - const int nDash = 30; - N *= 3; - while( N>nDash ){ - sqlite3_str_append(pOut, azDash[bDbl], nDash); - N -= nDash; + zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", + zSchema ? zSchema : "main", zName); + shell_check_oom(zSql); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + initText(&s); + if( zSchema ){ + cQuote = quoteChar(zSchema); + if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0; + appendText(&s, zSchema, cQuote); + appendText(&s, ".", 0); + } + cQuote = quoteChar(zName); + appendText(&s, zName, cQuote); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); + nRow++; + appendText(&s, zDiv, 0); + zDiv = ","; + if( zCol==0 ) zCol = ""; + cQuote = quoteChar(zCol); + appendText(&s, zCol, cQuote); } - sqlite3_str_append(pOut, azDash[bDbl], N); + appendText(&s, ")", 0); + sqlite3_finalize(pStmt); + if( nRow==0 ){ + freeText(&s); + s.zTxt = 0; + } + return s.zTxt; } /* -** Draw a horizontal separator for a QRF_STYLE_Box table. +** SQL function: strtod(X) +** +** Use the C-library strtod() function to convert string X into a double. +** Used for comparing the accuracy of SQLite's internal text-to-float conversion +** routines against the C-library. */ -static void qrfBoxSeparator( - sqlite3_str *pOut, - qrfColData *p, - const char *zSep1, - const char *zSep2, - const char *zSep3, - int bDbl +static void shellStrtod( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal ){ - int i; - if( p->nCol>0 ){ - int useBorder = p->p->spec.bBorder!=QRF_No; - if( useBorder ){ - sqlite3_str_appendall(pOut, zSep1); - } - qrfBoxLine(pOut, p->a[0].w+p->nMargin, bDbl); - for(i=1; inCol; i++){ - sqlite3_str_appendall(pOut, zSep2); - qrfBoxLine(pOut, p->a[i].w+p->nMargin, bDbl); - } - if( useBorder ){ - sqlite3_str_appendall(pOut, zSep3); - } - } - sqlite3_str_append(pOut, "\n", 1); + char *z = (char*)sqlite3_value_text(apVal[0]); + UNUSED_PARAMETER(nVal); + if( z==0 ) return; + sqlite3_result_double(pCtx, strtod(z,0)); } /* -** Load into pData the default alignment for the body of a table. +** SQL function: dtostr(X) +** +** Use the C-library printf() function to convert real value X into a string. +** Used for comparing the accuracy of SQLite's internal float-to-text conversion +** routines against the C-library. */ -static void qrfLoadAlignment(qrfColData *pData, Qrf *p){ - sqlite3_int64 i; - for(i=0; inCol; i++){ - pData->a[i].e = p->spec.eDfltAlign; - if( ispec.nAlign ){ - unsigned char ax = p->spec.aAlign[i]; - if( (ax & QRF_ALIGN_HMASK)!=0 ){ - pData->a[i].e = (ax & QRF_ALIGN_HMASK) | - (pData->a[i].e & QRF_ALIGN_VMASK); - } - }else if( ispec.nWidth ){ - if( p->spec.aWidth[i]<0 ){ - pData->a[i].e = QRF_ALIGN_Right | - (pData->a[i].e & QRF_ALIGN_VMASK); - } - } - } +static void shellDtostr( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + double r = sqlite3_value_double(apVal[0]); + int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26; + char z[400]; + if( n<1 ) n = 1; + if( n>350 ) n = 350; + sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r); + sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); } /* -** If the single column in pData->a[] with pData->n entries can be -** laid out as nCol columns with a 2-space gap between each such -** that all columns fit within nSW, then return a pointer to an array -** of integers which is the width of each column from left to right. +** SQL function: shell_add_schema(S,X) ** -** If the layout is not possible, return a NULL pointer. +** Add the schema name X to the CREATE statement in S and return the result. +** Examples: +** +** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x); +** +** Also works on +** +** CREATE INDEX +** CREATE UNIQUE INDEX +** CREATE VIEW +** CREATE TRIGGER +** CREATE VIRTUAL TABLE ** -** Space to hold the returned array is from sqlite_malloc64(). +** This UDF is used by the .schema command to insert the schema name of +** attached databases into the middle of the sqlite_schema.sql field. */ -static int *qrfValidLayout( - qrfColData *pData, /* Collected query results */ - Qrf *p, /* On which to report an OOM */ - int nCol, /* Attempt this many columns */ - int nSW /* Screen width */ +static void shellAddSchemaName( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal ){ - int i; /* Loop counter */ - int nr; /* Number of rows */ - int w = 0; /* Width of the current column */ - int t; /* Total width of all columns */ - int *aw; /* Array of individual column widths */ - - aw = sqlite3_malloc64( sizeof(int)*nCol ); - if( aw==0 ){ - qrfOom(p); - return 0; - } - nr = (pData->n + nCol - 1)/nCol; - for(i=0; in; i++){ - if( (i%nr)==0 ){ - if( i>0 ) aw[i/nr-1] = w; - w = pData->aiWth[i]; - }else if( pData->aiWth[i]>w ){ - w = pData->aiWth[i]; - } - } - aw[nCol-1] = w; - for(t=i=0; inSW ){ - sqlite3_free(aw); - return 0; - } - return aw; -} - -/* -** The output is single-column and the bSplitColumn flag is set. -** Check to see if the single-column output can be split into multiple -** columns that appear side-by-side. Adjust pData appropriately. -*/ -static void qrfSplitColumn(qrfColData *pData, Qrf *p){ - int nCol = 1; - int *aw = 0; - char **az = 0; - int *aiWth = 0; - unsigned char *abNum = 0; - int nColNext = 2; - int w; - struct qrfPerCol *a = 0; - sqlite3_int64 nRow = 1; - sqlite3_int64 i; - while( 1/*exit-by-break*/ ){ - int *awNew = qrfValidLayout(pData, p, nColNext, p->spec.nScreenWidth); - if( awNew==0 ) break; - sqlite3_free(aw); - aw = awNew; - nCol = nColNext; - nRow = (pData->n + nCol - 1)/nCol; - if( nRow==1 ) break; - nColNext++; - while( (pData->n + nColNext - 1)/nColNext == nRow ) nColNext++; - } - if( nCol==1 ){ - sqlite3_free(aw); - return; /* Cannot do better than 1 column */ - } - az = sqlite3_malloc64( nRow*nCol*sizeof(char*) ); - if( az==0 ){ - qrfOom(p); - return; - } - aiWth = sqlite3_malloc64( nRow*nCol*sizeof(int) ); - if( aiWth==0 ){ - sqlite3_free(az); - qrfOom(p); - return; - } - a = sqlite3_malloc64( nCol*sizeof(struct qrfPerCol) ); - if( a==0 ){ - sqlite3_free(az); - sqlite3_free(aiWth); - qrfOom(p); - return; - } - abNum = sqlite3_malloc64( nRow*nCol ); - if( abNum==0 ){ - sqlite3_free(az); - sqlite3_free(aiWth); - sqlite3_free(a); - qrfOom(p); - return; - } - for(i=0; in; i++){ - sqlite3_int64 j = (i%nRow)*nCol + (i/nRow); - az[j] = pData->az[i]; - abNum[j]= pData->abNum[i]; - pData->az[i] = 0; - aiWth[j] = pData->aiWth[i]; - } - while( ia[0].e; - } - sqlite3_free(pData->az); - sqlite3_free(pData->aiWth); - sqlite3_free(pData->a); - sqlite3_free(pData->abNum); - sqlite3_free(aw); - pData->az = az; - pData->aiWth = aiWth; - pData->a = a; - pData->abNum = abNum; - pData->nCol = nCol; - pData->n = pData->nAlloc = nRow*nCol; - for(i=w=0; inMargin = (p->spec.nScreenWidth - w)/(nCol - 1); - if( pData->nMargin>5 ) pData->nMargin = 5; -} - -/* -** Adjust the layout for the screen width restriction -*/ -static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){ - int sepW; /* Width of all box separators and margins */ - int sumW; /* Total width of data area over all columns */ - int targetW; /* Desired total data area */ - int i; /* Loop counters */ - int nCol; /* Number of columns */ - - pData->nMargin = 2; /* Default to normal margins */ - if( p->spec.nScreenWidth==0 ) return; - if( p->spec.eStyle==QRF_STYLE_Column ){ - sepW = pData->nCol*2 - 2; - }else{ - sepW = pData->nCol*3 + 1; - if( p->spec.bBorder==QRF_No ) sepW -= 2; - } - nCol = pData->nCol; - for(i=sumW=0; ia[i].w; - if( p->spec.nScreenWidth >= sumW+sepW ) return; - - /* First thing to do is reduce the separation between columns */ - pData->nMargin = 0; - if( p->spec.eStyle==QRF_STYLE_Column ){ - sepW = pData->nCol - 1; - }else{ - sepW = pData->nCol + 1; - if( p->spec.bBorder==QRF_No ) sepW -= 2; - } - targetW = p->spec.nScreenWidth - sepW; - -#define MIN_SQUOZE 8 -#define MIN_EX_SQUOZE 16 - /* Reduce the width of the widest eligible column. A column is - ** eligible for narrowing if: - ** - ** * It is not a fixed-width column (a[0].fx is false) - ** * The current width is more than MIN_SQUOZE - ** * Either: - ** + The current width is more then MIN_EX_SQUOZE, or - ** + The current width is more than half the max width (a[].mxW) - ** - ** Keep making reductions until either no more reductions are - ** possible or until the size target is reached. - */ - while( sumW > targetW ){ - int gain, w; - int ix = -1; - int mx = 0; - for(i=0; ia[i].fx==0 - && (w = pData->a[i].w)>mx - && w>MIN_SQUOZE - && (w>MIN_EX_SQUOZE || w*2>pData->a[i].mxW) - ){ - ix = i; - mx = w; - } - } - if( ix<0 ) break; - if( mx>=MIN_SQUOZE*2 ){ - gain = mx/2; - }else{ - gain = mx - MIN_SQUOZE; - } - if( sumW - gain < targetW ){ - gain = sumW - targetW; - } - sumW -= gain; - pData->a[ix].w -= gain; - pData->bMultiRow = 1; - } -} - -/* -** Columnar modes require that the entire query be evaluated first, with -** results written into memory, so that we can compute appropriate column -** widths. -*/ -static void qrfColumnar(Qrf *p){ - sqlite3_int64 i, j; /* Loop counters */ - const char *colSep = 0; /* Column separator text */ - const char *rowSep = 0; /* Row terminator text */ - const char *rowStart = 0; /* Row start text */ - int szColSep, szRowSep, szRowStart; /* Size in bytes of previous 3 */ - int rc; /* Result code */ - int nColumn = p->nCol; /* Number of columns */ - int bWW; /* True to do word-wrap */ - sqlite3_str *pStr; /* Temporary rendering */ - qrfColData data; /* Columnar layout data */ - int bRTrim; /* Trim trailing space */ - - rc = sqlite3_step(p->pStmt); - if( rc!=SQLITE_ROW || nColumn==0 ){ - return; /* No output */ - } - - /* Initialize the data container */ - memset(&data, 0, sizeof(data)); - data.nCol = p->nCol; - data.p = p; - data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) ); - if( data.a==0 ){ - qrfOom(p); - return; - } - memset(data.a, 0, nColumn*sizeof(struct qrfPerCol) ); - if( qrfColDataEnlarge(&data) ) return; - assert( data.az!=0 ); - - /* Load the column header names and all cell content into data */ - if( p->spec.bTitles==QRF_Yes ){ - unsigned char saved_eText = p->spec.eText; - p->spec.eText = p->spec.eTitle; - memset(data.abNum, 0, nColumn); - for(i=0; ipStmt,i); - int nNL = 0; - int n, w; - pStr = sqlite3_str_new(p->db); - qrfEncodeText(p, pStr, z ? z : ""); - n = sqlite3_str_length(pStr); - qrfStrErr(p, pStr); - z = data.az[data.n] = sqlite3_str_finish(pStr); - if( p->spec.nTitleLimit ){ - nNL = 0; - data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n], - p->spec.nTitleLimit ); - }else{ - data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL); - } - data.n++; - if( w>data.a[i].mxW ) data.a[i].mxW = w; - if( nNL ) data.bMultiRow = 1; - } - p->spec.eText = saved_eText; - p->nRow++; - } - do{ - if( data.n+nColumn > data.nAlloc ){ - if( qrfColDataEnlarge(&data) ) return; - } - for(i=0; ipStmt,i); - pStr = sqlite3_str_new(p->db); - qrfRenderValue(p, pStr, i); - n = sqlite3_str_length(pStr); - qrfStrErr(p, pStr); - z = data.az[data.n] = sqlite3_str_finish(pStr); - data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT; - data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL); - data.n++; - if( w>data.a[i].mxW ) data.a[i].mxW = w; - if( nNL ) data.bMultiRow = 1; - } - p->nRow++; - }while( sqlite3_step(p->pStmt)==SQLITE_ROW && p->iErr==SQLITE_OK ); - if( p->iErr ){ - qrfColDataFree(&data); - return; - } - - /* Compute the width and alignment of every column */ - if( p->spec.bTitles==QRF_No ){ - qrfLoadAlignment(&data, p); - }else{ - unsigned char e; - if( p->spec.eTitleAlign==QRF_Auto ){ - e = QRF_ALIGN_Center; - }else{ - e = p->spec.eTitleAlign; - } - for(i=0; ispec.nWidth ){ - w = p->spec.aWidth[i]; - if( w==(-32768) ){ - w = 0; - if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){ - data.a[i].e |= QRF_ALIGN_Right; - } - }else if( w<0 ){ - w = -w; - if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){ - data.a[i].e |= QRF_ALIGN_Right; - } - } - if( w ) data.a[i].fx = 1; - } - if( w==0 ){ - w = data.a[i].mxW; - if( p->spec.nWrap>0 && w>p->spec.nWrap ){ - w = p->spec.nWrap; - data.bMultiRow = 1; - } - }else if( (data.bMultiRow==0 || w==1) && data.a[i].mxW>w ){ - data.bMultiRow = 1; - if( w==1 ){ - /* If aiWth[j] is 2 or more, then there might be a double-wide - ** character somewhere. So make the column width at least 2. */ - w = 2; - } - } - data.a[i].w = w; - } - - if( nColumn==1 - && data.n>1 - && p->spec.bSplitColumn==QRF_Yes - && p->spec.eStyle==QRF_STYLE_Column - && p->spec.bTitles==QRF_No - && p->spec.nScreenWidth>data.a[0].w+3 - ){ - /* Attempt to convert single-column tables into multi-column by - ** verticle wrapping, if the screen is wide enough and if the - ** bSplitColumn flag is set. */ - qrfSplitColumn(&data, p); - nColumn = data.nCol; - }else{ - /* Adjust the column widths due to screen width restrictions */ - qrfRestrictScreenWidth(&data, p); - } - - /* Draw the line across the top of the table. Also initialize - ** the row boundary and column separator texts. */ - switch( p->spec.eStyle ){ - case QRF_STYLE_Box: - if( data.nMargin ){ - rowStart = BOX_13 " "; - colSep = " " BOX_13 " "; - rowSep = " " BOX_13 "\n"; - }else{ - rowStart = BOX_13; - colSep = BOX_13; - rowSep = BOX_13 "\n"; - } - if( p->spec.bBorder==QRF_No){ - rowStart += 3; - rowSep = "\n"; - }else{ - qrfBoxSeparator(p->pOut, &data, BOX_R23, BOX_234, BOX_R34, 0); - } - break; - case QRF_STYLE_Table: - if( data.nMargin ){ - rowStart = "| "; - colSep = " | "; - rowSep = " |\n"; - }else{ - rowStart = "|"; - colSep = "|"; - rowSep = "|\n"; - } - if( p->spec.bBorder==QRF_No ){ - rowStart += 1; - rowSep = "\n"; - }else{ - qrfRowSeparator(p->pOut, &data, '+'); - } - break; - case QRF_STYLE_Column: { - static const char zSpace[] = " "; - rowStart = ""; - if( data.nMargin<2 ){ - colSep = " "; - }else if( data.nMargin<=5 ){ - colSep = &zSpace[5-data.nMargin]; - }else{ - colSep = zSpace; - } - rowSep = "\n"; - break; - } - default: /*case QRF_STYLE_Markdown:*/ - if( data.nMargin ){ - rowStart = "| "; - colSep = " | "; - rowSep = " |\n"; - }else{ - rowStart = "|"; - colSep = "|"; - rowSep = "|\n"; - } - break; - } - szRowStart = (int)strlen(rowStart); - szRowSep = (int)strlen(rowSep); - szColSep = (int)strlen(colSep); - - bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow); - if( p->spec.eStyle==QRF_STYLE_Column - || (p->spec.bBorder==QRF_No - && (p->spec.eStyle==QRF_STYLE_Box || p->spec.eStyle==QRF_STYLE_Table) - ) - ){ - bRTrim = 1; - }else{ - bRTrim = 0; - } - for(i=0; ipOut)==SQLITE_OK; i+=nColumn){ - int bMore; - int nRow = 0; - - /* Draw a single row of the table. This might be the title line - ** (if there is a title line) or a row in the body of the table. - ** The column number will be j. The row number is i/nColumn. - */ - for(j=0; jpOut, rowStart, szRowStart); - bMore = 0; - for(j=0; jpOut, &data.a[j], nThis, nWS); - data.a[j].z += iNext; - if( data.a[j].z[0]!=0 ){ - bMore = 1; - } - if( jpOut, colSep, szColSep); - }else{ - if( bRTrim ) qrfRTrim(p->pOut); - sqlite3_str_append(p->pOut, rowSep, szRowSep); - } - } - }while( bMore && ++nRow < p->mxHeight ); - if( bMore ){ - /* This row was terminated by nLineLimit. Show ellipsis. */ - sqlite3_str_append(p->pOut, rowStart, szRowStart); - for(j=0; jpOut, data.a[j].w, ' '); - }else{ - int nE = 3; - if( nE>data.a[j].w ) nE = data.a[j].w; - data.a[j].z = "..."; - qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE); - } - if( jpOut, colSep, szColSep); - }else{ - if( bRTrim ) qrfRTrim(p->pOut); - sqlite3_str_append(p->pOut, rowSep, szRowSep); - } - } - } - - /* Draw either (1) the separator between the title line and the body - ** of the table, or (2) separators between individual rows of the table - ** body. isTitleDataSeparator will be true if we are doing (1). - */ - if( (i==0 || data.bMultiRow) && i+nColumnspec.bTitles==QRF_Yes); - if( isTitleDataSeparator ){ - qrfLoadAlignment(&data, p); - } - switch( p->spec.eStyle ){ - case QRF_STYLE_Table: { - if( isTitleDataSeparator || data.bMultiRow ){ - qrfRowSeparator(p->pOut, &data, '+'); - } - break; - } - case QRF_STYLE_Box: { - if( isTitleDataSeparator ){ - qrfBoxSeparator(p->pOut, &data, DBL_123, DBL_1234, DBL_134, 1); - }else if( data.bMultiRow ){ - qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134, 0); + static const char *aPrefix[] = { + "TABLE", + "INDEX", + "UNIQUE INDEX", + "VIEW", + "TRIGGER", + "VIRTUAL TABLE" + }; + int i = 0; + const char *zIn = (const char*)sqlite3_value_text(apVal[0]); + const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); + const char *zName = (const char*)sqlite3_value_text(apVal[2]); + sqlite3 *db = sqlite3_context_db_handle(pCtx); + UNUSED_PARAMETER(nVal); + if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){ + for(i=0; ipOut, &data, '|'); + if( zName + && aPrefix[i][0]=='V' + && (zFake = shellFakeSchema(db, zSchema, zName))!=0 + ){ + if( z==0 ){ + z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake); + }else{ + z = sqlite3_mprintf("%z\n/* %s */", z, zFake); } - break; + sqlite3_free(zFake); } - case QRF_STYLE_Column: { - if( isTitleDataSeparator ){ - for(j=0; jpOut, data.a[j].w, '-'); - if( jpOut, colSep, szColSep); - }else{ - qrfRTrim(p->pOut); - sqlite3_str_append(p->pOut, rowSep, szRowSep); - } - } - }else if( data.bMultiRow ){ - qrfRTrim(p->pOut); - sqlite3_str_append(p->pOut, "\n", 1); - } - break; + if( z ){ + sqlite3_result_text(pCtx, z, -1, sqlite3_free); + return; } } } } - - /* Draw the line across the bottom of the table */ - if( p->spec.bBorder!=QRF_No ){ - switch( p->spec.eStyle ){ - case QRF_STYLE_Box: - qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0); - break; - case QRF_STYLE_Table: - qrfRowSeparator(p->pOut, &data, '+'); - break; - } - } - qrfWrite(p); - - qrfColDataFree(&data); - return; + sqlite3_result_value(pCtx, apVal[0]); } /* -** Parameter azArray points to a zero-terminated array of strings. zStr -** points to a single nul-terminated string. Return non-zero if zStr -** is equal, according to strcmp(), to any of the strings in the array. -** Otherwise, return zero. +** The source code for several run-time loadable extensions is inserted +** below by the ../tool/mkshellc.tcl script. Before processing that included +** code, we need to override some macros to make the included program code +** work here in the middle of this regular program. */ -static int qrfStringInArray(const char *zStr, const char **azArray){ - int i; - if( zStr==0 ) return 0; - for(i=0; azArray[i]; i++){ - if( 0==strcmp(zStr, azArray[i]) ) return 1; - } - return 0; -} +#define SQLITE_EXTENSION_INIT1 +#define SQLITE_EXTENSION_INIT2(X) (void)(X) +/************************* Begin ../ext/misc/windirent.h ******************/ /* -** Print out an EXPLAIN with indentation. This is a two-pass algorithm. +** 2025-06-05 ** -** On the first pass, we compute aiIndent[iOp] which is the amount of -** indentation to apply to the iOp-th opcode. The output actually occurs -** on the second pass. +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: ** -** The indenting rules are: +** 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. ** -** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent -** all opcodes that occur between the p2 jump destination and the opcode -** itself by 2 spaces. +************************************************************************* ** -** * Do the previous for "Return" instructions for when P2 is positive. -** See tag-20220407a in wherecode.c and vdbe.c. +** An implementation of opendir(), readdir(), and closedir() for Windows, +** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs +** of Win32. ** -** * For each "Goto", if the jump destination is earlier in the program -** and ends on one of: -** Yield SeekGt SeekLt RowSetRead Rewind -** or if the P1 parameter is one instead of zero, -** then indent all opcodes between the earlier instruction -** and "Goto" by 2 spaces. +** #include this file inside any C-code module that needs to use +** opendir()/readdir()/closedir(). This file is a no-op on non-Windows +** machines. On Windows, static functions are defined that implement +** those standard interfaces. */ -static void qrfExplain(Qrf *p){ - int *abYield = 0; /* abYield[iOp] is rue if opcode iOp is an OP_Yield */ - int *aiIndent = 0; /* Indent the iOp-th opcode by aiIndent[iOp] */ - i64 nAlloc = 0; /* Allocated size of aiIndent[], abYield */ - int nIndent = 0; /* Number of entries in aiIndent[] */ - int iOp; /* Opcode number */ - int i; /* Column loop counter */ +#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H) +#define SQLITE_WINDIRENT_H - const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", - "Return", 0 }; - const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", - "Rewind", 0 }; - const char *azGoto[] = { "Goto", 0 }; +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef FILENAME_MAX +# define FILENAME_MAX (260) +#endif +#ifndef S_ISREG +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#ifndef S_ISLNK +#define S_ISLNK(m) (0) +#endif +typedef unsigned short mode_t; - /* The caller guarantees that the leftmost 4 columns of the statement - ** passed to this function are equivalent to the leftmost 4 columns - ** of EXPLAIN statement output. In practice the statement may be - ** an EXPLAIN, or it may be a query on the bytecode() virtual table. */ - assert( sqlite3_column_count(p->pStmt)>=4 ); - assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) ); - assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) ); - assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) ); - assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) ); - - for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){ - int iAddr = sqlite3_column_int(p->pStmt, 0); - const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1); - int p1 = sqlite3_column_int(p->pStmt, 2); - int p2 = sqlite3_column_int(p->pStmt, 3); +/* The dirent object for Windows is abbreviated. The only field really +** usable by applications is d_name[]. +*/ +struct dirent { + int d_ino; /* Inode number (synthesized) */ + unsigned d_attributes; /* File attributes */ + char d_name[FILENAME_MAX]; /* Null-terminated filename */ +}; - /* Assuming that p2 is an instruction address, set variable p2op to the - ** index of that instruction in the aiIndent[] array. p2 and p2op may be - ** different if the current instruction is part of a sub-program generated - ** by an SQL trigger or foreign key. */ - int p2op = (p2 + (iOp-iAddr)); +/* The internals of DIR are opaque according to standards. So it +** does not matter what we put here. */ +typedef struct DIR DIR; +struct DIR { + intptr_t d_handle; /* Handle for findfirst()/findnext() */ + struct dirent cur; /* Current entry */ +}; - /* Grow the aiIndent array as required */ - if( iOp>=nAlloc ){ - nAlloc += 100; - aiIndent = (int*)sqlite3_realloc64(aiIndent, nAlloc*sizeof(int)); - abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); - if( aiIndent==0 || abYield==0 ){ - qrfOom(p); - sqlite3_free(aiIndent); - sqlite3_free(abYield); - return; - } - } +/* Ignore hidden and system files */ +#define WindowsFileToIgnore(a) \ + ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) - abYield[iOp] = qrfStringInArray(zOp, azYield); - aiIndent[iOp] = 0; - nIndent = iOp+1; - if( qrfStringInArray(zOp, azNext) && p2op>0 ){ - for(i=p2op; id_handle!=0 && pDir->d_handle!=(-1) ){ + rc = _findclose(pDir->d_handle); + } + sqlite3_free(pDir); + return rc; +} - /* Second pass. Actually generate output */ - sqlite3_reset(p->pStmt); - if( p->iErr==SQLITE_OK ){ - static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13}; - static const int aExplainMap[] = {0, 1, 2, 3, 4, 5, 6, 7 }; - static const int aScanExpWidth[] = {4,15, 6, 13, 4, 4, 4, 13, 2, 13}; - static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 }; - const int *aWidth = aExplainWidth; - const int *aMap = aExplainMap; - int nWidth = sizeof(aExplainWidth)/sizeof(int); - int iIndent = 1; - int nArg = p->nCol; - if( p->spec.eStyle==QRF_STYLE_StatsVm ){ - aWidth = aScanExpWidth; - aMap = aScanExpMap; - nWidth = sizeof(aScanExpWidth)/sizeof(int); - iIndent = 3; - } - if( nArg>nWidth ) nArg = nWidth; - - for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){ - /* If this is the first row seen, print out the headers */ - if( iOp==0 ){ - for(i=0; ipStmt, aMap[i]); - qrfWidthPrint(p,p->pOut, aWidth[i], zCol); - if( i==nArg-1 ){ - sqlite3_str_append(p->pOut, "\n", 1); - }else{ - sqlite3_str_append(p->pOut, " ", 2); - } - } - for(i=0; ipOut, "%.*c", aWidth[i], '-'); - if( i==nArg-1 ){ - sqlite3_str_append(p->pOut, "\n", 1); - }else{ - sqlite3_str_append(p->pOut, " ", 2); - } - } - } - - for(i=0; ipStmt, aMap[i]); - int len; - if( i==nArg-1 ) w = 0; - if( zVal==0 ) zVal = ""; - len = (int)sqlite3_qrf_wcswidth(zVal); - if( len>w ){ - w = len; - zSep = " "; - } - if( i==iIndent && aiIndent && iOppOut, aiIndent[iOp], ' '); - } - qrfWidthPrint(p, p->pOut, w, zVal); - if( i==nArg-1 ){ - sqlite3_str_append(p->pOut, "\n", 1); - }else{ - sqlite3_str_appendall(p->pOut, zSep); - } - } - p->nRow++; +/* +** Open a new directory. The directory name should be UTF-8 encoded. +** appropriate translations happen automatically. +*/ +static DIR *opendir(const char *zDirName){ + DIR *pDir; + wchar_t *b1; + sqlite3_int64 sz; + struct _wfinddata_t data; + + pDir = sqlite3_malloc64( sizeof(DIR) ); + if( pDir==0 ) return 0; + memset(pDir, 0, sizeof(DIR)); + memset(&data, 0, sizeof(data)); + sz = strlen(zDirName); + b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) ); + if( b1==0 ){ + closedir(pDir); + return NULL; + } + sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz); + b1[sz++] = '\\'; + b1[sz++] = '*'; + b1[sz] = 0; + if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){ + closedir(pDir); + sqlite3_free(b1); + return NULL; + } + memcpy(data.name, b1, (sz+1)*sizeof(b1[0])); + sqlite3_free(b1); + pDir->d_handle = _wfindfirst(data.name, &data); + if( pDir->d_handle<0 ){ + closedir(pDir); + return NULL; + } + while( WindowsFileToIgnore(data) ){ + memset(&data, 0, sizeof(data)); + if( _wfindnext(pDir->d_handle, &data)==-1 ){ + closedir(pDir); + return NULL; } - qrfWrite(p); } - sqlite3_free(aiIndent); + pDir->cur.d_ino = 0; + pDir->cur.d_attributes = data.attrib; + WideCharToMultiByte(CP_UTF8, 0, data.name, -1, + pDir->cur.d_name, FILENAME_MAX, 0, 0); + return pDir; } /* -** Do a "scanstatus vm" style EXPLAIN listing on p->pStmt. +** Read the next entry from a directory. ** -** p->pStmt is probably not an EXPLAIN query. Instead, construct a -** new query that is a bytecode() rendering of p->pStmt with extra -** columns for the "scanstatus vm" outputs, and run the results of -** that new query through the normal EXPLAIN formatting. +** The returned struct-dirent object is managed by DIR. It is only +** valid until the next readdir() or closedir() call. Only the +** d_name[] field is meaningful. The d_name[] value has been +** translated into UTF8. */ -static void qrfScanStatusVm(Qrf *p){ - sqlite3_stmt *pOrigStmt = p->pStmt; - sqlite3_stmt *pExplain; - int rc; - static const char *zSql = - " SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec," - " format('% 6s (%.2f%%)'," - " CASE WHEN ncycle<100_000 THEN ncycle || ' '" - " WHEN ncycle<100_000_000 THEN (ncycle/1_000) || 'K'" - " WHEN ncycle<100_000_000_000 THEN (ncycle/1_000_000) || 'M'" - " ELSE (ncycle/1000_000_000) || 'G' END," - " ncycle*100.0/(sum(ncycle) OVER ())" - " ) AS cycles" - " FROM bytecode(?1)"; - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pExplain, 0); - if( rc ){ - qrfError(p, rc, "%s", sqlite3_errmsg(p->db)); - sqlite3_finalize(pExplain); - return; +static struct dirent *readdir(DIR *pDir){ + struct _wfinddata_t data; + if( pDir==0 ) return 0; + if( (pDir->cur.d_ino++)==0 ){ + return &pDir->cur; } - sqlite3_bind_pointer(pExplain, 1, pOrigStmt, "stmt-pointer", 0); - p->pStmt = pExplain; - p->nCol = 10; - qrfExplain(p); - sqlite3_finalize(pExplain); - p->pStmt = pOrigStmt; + do{ + memset(&data, 0, sizeof(data)); + if( _wfindnext(pDir->d_handle, &data)==-1 ){ + return NULL; + } + }while( WindowsFileToIgnore(data) ); + pDir->cur.d_attributes = data.attrib; + WideCharToMultiByte(CP_UTF8, 0, data.name, -1, + pDir->cur.d_name, FILENAME_MAX, 0, 0); + return &pDir->cur; } +#endif /* defined(_WIN32) && defined(_MSC_VER) */ + +/************************* End ../ext/misc/windirent.h ********************/ +/************************* Begin ../ext/misc/memtrace.c ******************/ /* -** Attempt to determine if identifier zName needs to be quoted, either -** because it contains non-alphanumeric characters, or because it is an -** SQLite keyword. Be conservative in this estimate: When in doubt assume -** that quoting is required. +** 2019-01-21 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements an extension that uses the SQLITE_CONFIG_MALLOC +** mechanism to add a tracing layer on top of SQLite. If this extension +** is registered prior to sqlite3_initialize(), it will cause all memory +** allocation activities to be logged on standard output, or to some other +** FILE specified by the initializer. +** +** This file needs to be compiled into the application that uses it. ** -** Return 1 if quoting is required. Return 0 if no quoting is required. +** This extension is used to implement the --memtrace option of the +** command-line shell. */ +#include +#include +#include -static int qrf_need_quote(const char *zName){ - int i; - const unsigned char *z = (const unsigned char*)zName; - if( z==0 ) return 1; - if( !qrfAlpha(z[0]) ) return 1; - for(i=0; z[i]; i++){ - if( !qrfAlnum(z[i]) ) return 1; +/* The original memory allocation routines */ +static sqlite3_mem_methods memtraceBase; +static FILE *memtraceOut; + +/* Methods that trace memory allocations */ +static void *memtraceMalloc(int n){ + if( memtraceOut ){ + fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", + memtraceBase.xRoundup(n)); + } + return memtraceBase.xMalloc(n); +} +static void memtraceFree(void *p){ + if( p==0 ) return; + if( memtraceOut ){ + fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p)); } - return sqlite3_keyword_check(zName, i)!=0; + memtraceBase.xFree(p); } - -/* -** Helper function for QRF_STYLE_Json and QRF_STYLE_JObject. -** The initial "{" for a JSON object that will contain row content -** has been output. Now output all the content. -*/ -static void qrfOneJsonRow(Qrf *p){ - int i, nItem; - for(nItem=i=0; inCol; i++){ - const char *zCName; - zCName = sqlite3_column_name(p->pStmt, i); - if( nItem>0 ) sqlite3_str_append(p->pOut, ",", 1); - nItem++; - qrfEncodeText(p, p->pOut, zCName); - sqlite3_str_append(p->pOut, ":", 1); - qrfRenderValue(p, p->pOut, i); +static void *memtraceRealloc(void *p, int n){ + if( p==0 ) return memtraceMalloc(n); + if( n==0 ){ + memtraceFree(p); + return 0; + } + if( memtraceOut ){ + fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n", + memtraceBase.xSize(p), memtraceBase.xRoundup(n)); } - qrfWrite(p); + return memtraceBase.xRealloc(p, n); +} +static int memtraceSize(void *p){ + return memtraceBase.xSize(p); +} +static int memtraceRoundup(int n){ + return memtraceBase.xRoundup(n); +} +static int memtraceInit(void *p){ + return memtraceBase.xInit(p); +} +static void memtraceShutdown(void *p){ + memtraceBase.xShutdown(p); } -/* -** Render a single row of output for non-columnar styles - any -** style that lets us render row by row as the content is received -** from the query. -*/ -static void qrfOneSimpleRow(Qrf *p){ - int i; - switch( p->spec.eStyle ){ - case QRF_STYLE_Off: - case QRF_STYLE_Count: { - /* No-op */ - break; - } - case QRF_STYLE_Json: { - if( p->nRow==0 ){ - sqlite3_str_append(p->pOut, "[{", 2); - }else{ - sqlite3_str_append(p->pOut, "},\n{", 4); - } - qrfOneJsonRow(p); - break; - } - case QRF_STYLE_JObject: { - if( p->nRow==0 ){ - sqlite3_str_append(p->pOut, "{", 1); - }else{ - sqlite3_str_append(p->pOut, "}\n{", 3); - } - qrfOneJsonRow(p); - break; - } - case QRF_STYLE_Html: { - if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){ - sqlite3_str_append(p->pOut, "", 4); - for(i=0; inCol; i++){ - const char *zCName = sqlite3_column_name(p->pStmt, i); - sqlite3_str_append(p->pOut, "\n", 5); - qrfEncodeText(p, p->pOut, zCName); - } - sqlite3_str_append(p->pOut, "\n\n", 7); - } - sqlite3_str_append(p->pOut, "", 4); - for(i=0; inCol; i++){ - sqlite3_str_append(p->pOut, "\n", 5); - qrfRenderValue(p, p->pOut, i); - } - sqlite3_str_append(p->pOut, "\n\n", 7); - qrfWrite(p); - break; - } - case QRF_STYLE_Insert: { - if( qrf_need_quote(p->spec.zTableName) ){ - sqlite3_str_appendf(p->pOut,"INSERT INTO \"%w\"",p->spec.zTableName); - }else{ - sqlite3_str_appendf(p->pOut,"INSERT INTO %s",p->spec.zTableName); - } - if( p->spec.bTitles==QRF_Yes ){ - for(i=0; inCol; i++){ - const char *zCName = sqlite3_column_name(p->pStmt, i); - if( qrf_need_quote(zCName) ){ - sqlite3_str_appendf(p->pOut, "%c\"%w\"", - i==0 ? '(' : ',', zCName); - }else{ - sqlite3_str_appendf(p->pOut, "%c%s", - i==0 ? '(' : ',', zCName); - } - } - sqlite3_str_append(p->pOut, ")", 1); - } - sqlite3_str_append(p->pOut," VALUES(", 8); - for(i=0; inCol; i++){ - if( i>0 ) sqlite3_str_append(p->pOut, ",", 1); - qrfRenderValue(p, p->pOut, i); - } - sqlite3_str_append(p->pOut, ");\n", 3); - qrfWrite(p); - break; - } - case QRF_STYLE_Line: { - sqlite3_str *pVal; - int mxW; - int bWW; - int nSep; - if( p->u.sLine.azCol==0 ){ - p->u.sLine.azCol = sqlite3_malloc64( p->nCol*sizeof(char*) ); - if( p->u.sLine.azCol==0 ){ - qrfOom(p); - break; - } - p->u.sLine.mxColWth = 0; - for(i=0; inCol; i++){ - int sz; - const char *zCName = sqlite3_column_name(p->pStmt, i); - if( zCName==0 ) zCName = "unknown"; - p->u.sLine.azCol[i] = sqlite3_mprintf("%s", zCName); - if( p->spec.nTitleLimit>0 ){ - (void)qrfTitleLimit(p->u.sLine.azCol[i], p->spec.nTitleLimit); - } - sz = (int)sqlite3_qrf_wcswidth(p->u.sLine.azCol[i]); - if( sz > p->u.sLine.mxColWth ) p->u.sLine.mxColWth = sz; - } - } - if( p->nRow ) sqlite3_str_append(p->pOut, "\n", 1); - pVal = sqlite3_str_new(p->db); - nSep = (int)strlen(p->spec.zColumnSep); - mxW = p->mxWidth - (nSep + p->u.sLine.mxColWth); - bWW = p->spec.bWordWrap==QRF_Yes; - for(i=0; inCol; i++){ - const char *zVal; - int cnt = 0; - qrfWidthPrint(p, p->pOut, -p->u.sLine.mxColWth, p->u.sLine.azCol[i]); - sqlite3_str_append(p->pOut, p->spec.zColumnSep, nSep); - qrfRenderValue(p, pVal, i); - zVal = sqlite3_str_value(pVal); - if( zVal==0 ) zVal = ""; - do{ - int nThis, nWide, iNext; - qrfWrapLine(zVal, mxW, bWW, &nThis, &nWide, &iNext); - if( cnt ) sqlite3_str_appendchar(p->pOut,p->u.sLine.mxColWth+2,' '); - cnt++; - if( cnt>p->mxHeight ){ - zVal = "..."; - nThis = iNext = 3; - } - sqlite3_str_append(p->pOut, zVal, nThis); - sqlite3_str_append(p->pOut, "\n", 1); - zVal += iNext; - }while( zVal[0] ); - sqlite3_str_reset(pVal); - } - qrfStrErr(p, pVal); - sqlite3_free(sqlite3_str_finish(pVal)); - qrfWrite(p); - break; - } - case QRF_STYLE_Eqp: { - const char *zEqpLine = (const char*)sqlite3_column_text(p->pStmt,3); - int iEqpId = sqlite3_column_int(p->pStmt, 0); - int iParentId = sqlite3_column_int(p->pStmt, 1); - if( zEqpLine==0 ) zEqpLine = ""; - if( zEqpLine[0]=='-' ) qrfEqpRender(p, 0); - qrfEqpAppend(p, iEqpId, iParentId, zEqpLine); - break; - } - default: { /* QRF_STYLE_List */ - if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){ - int saved_eText = p->spec.eText; - p->spec.eText = p->spec.eTitle; - for(i=0; inCol; i++){ - const char *zCName = sqlite3_column_name(p->pStmt, i); - if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); - qrfEncodeText(p, p->pOut, zCName); - } - sqlite3_str_appendall(p->pOut, p->spec.zRowSep); - qrfWrite(p); - p->spec.eText = saved_eText; - } - for(i=0; inCol; i++){ - if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); - qrfRenderValue(p, p->pOut, i); - } - sqlite3_str_appendall(p->pOut, p->spec.zRowSep); - qrfWrite(p); - break; +/* The substitute memory allocator */ +static sqlite3_mem_methods ersaztMethods = { + memtraceMalloc, + memtraceFree, + memtraceRealloc, + memtraceSize, + memtraceRoundup, + memtraceInit, + memtraceShutdown, + 0 +}; + +/* Begin tracing memory allocations to out. */ +int sqlite3MemTraceActivate(FILE *out){ + int rc = SQLITE_OK; + if( memtraceBase.xMalloc==0 ){ + rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase); + if( rc==SQLITE_OK ){ + rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods); } } - p->nRow++; + memtraceOut = out; + return rc; } -/* -** Initialize the internal Qrf object. -*/ -static void qrfInitialize( - Qrf *p, /* State object to be initialized */ - sqlite3_stmt *pStmt, /* Query whose output to be formatted */ - const sqlite3_qrf_spec *pSpec, /* Format specification */ - char **pzErr /* Write errors here */ -){ - size_t sz; /* Size of pSpec[], based on pSpec->iVersion */ - memset(p, 0, sizeof(*p)); - p->pzErr = pzErr; - if( pSpec->iVersion!=1 ){ - qrfError(p, SQLITE_ERROR, - "unusable sqlite3_qrf_spec.iVersion (%d)", - pSpec->iVersion); - return; - } - p->pStmt = pStmt; - p->db = sqlite3_db_handle(pStmt); - p->pOut = sqlite3_str_new(p->db); - if( p->pOut==0 ){ - qrfOom(p); - return; - } - p->iErr = SQLITE_OK; - p->nCol = sqlite3_column_count(p->pStmt); - p->nRow = 0; - sz = sizeof(sqlite3_qrf_spec); - memcpy(&p->spec, pSpec, sz); - if( p->spec.zNull==0 ) p->spec.zNull = ""; - p->mxWidth = p->spec.nScreenWidth; - if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH; - p->mxHeight = p->spec.nLineLimit; - if( p->mxHeight<=0 ) p->mxHeight = 2147483647; - if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto; - if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto; - if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto; - if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto; - if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto; -qrf_reinit: - switch( p->spec.eStyle ){ - case QRF_Auto: { - switch( sqlite3_stmt_isexplain(pStmt) ){ - case 0: p->spec.eStyle = QRF_STYLE_Box; break; - case 1: p->spec.eStyle = QRF_STYLE_Explain; break; - default: p->spec.eStyle = QRF_STYLE_Eqp; break; - } - goto qrf_reinit; - } - case QRF_STYLE_List: { - if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = "|"; - if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n"; - break; - } - case QRF_STYLE_JObject: - case QRF_STYLE_Json: { - p->spec.eText = QRF_TEXT_Json; - p->spec.zNull = "null"; - break; - } - case QRF_STYLE_Html: { - p->spec.eText = QRF_TEXT_Html; - p->spec.zNull = "null"; - break; - } - case QRF_STYLE_Insert: { - p->spec.eText = QRF_TEXT_Sql; - p->spec.zNull = "NULL"; - if( p->spec.zTableName==0 || p->spec.zTableName[0]==0 ){ - p->spec.zTableName = "tab"; - } - break; - } - case QRF_STYLE_Line: { - if( p->spec.zColumnSep==0 ){ - p->spec.zColumnSep = ": "; - } - break; - } - case QRF_STYLE_Csv: { - p->spec.eStyle = QRF_STYLE_List; - p->spec.eText = QRF_TEXT_Csv; - p->spec.zColumnSep = ","; - p->spec.zRowSep = "\r\n"; - p->spec.zNull = ""; - break; - } - case QRF_STYLE_Quote: { - p->spec.eText = QRF_TEXT_Sql; - p->spec.zNull = "NULL"; - p->spec.zColumnSep = ","; - p->spec.zRowSep = "\n"; - break; - } - case QRF_STYLE_Eqp: { - int expMode = sqlite3_stmt_isexplain(p->pStmt); - if( expMode!=2 ){ - sqlite3_stmt_explain(p->pStmt, 2); - p->expMode = expMode+1; - } - break; - } - case QRF_STYLE_Explain: { - int expMode = sqlite3_stmt_isexplain(p->pStmt); - if( expMode!=1 ){ - sqlite3_stmt_explain(p->pStmt, 1); - p->expMode = expMode+1; - } - break; +/* Deactivate memory tracing */ +int sqlite3MemTraceDeactivate(void){ + int rc = SQLITE_OK; + if( memtraceBase.xMalloc!=0 ){ + rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase); + if( rc==SQLITE_OK ){ + memset(&memtraceBase, 0, sizeof(memtraceBase)); } } - if( p->spec.eEsc==QRF_Auto ){ - p->spec.eEsc = QRF_ESC_Ascii; - } - if( p->spec.eText==QRF_Auto ){ - p->spec.eText = QRF_TEXT_Plain; - } - if( p->spec.eTitle==QRF_Auto ){ - switch( p->spec.eStyle ){ - case QRF_STYLE_Box: - case QRF_STYLE_Column: - case QRF_STYLE_Table: - p->spec.eTitle = QRF_TEXT_Plain; - break; - default: - p->spec.eTitle = p->spec.eText; - break; - } + memtraceOut = 0; + return rc; +} + +/************************* End ../ext/misc/memtrace.c ********************/ +/************************* Begin ../ext/misc/pcachetrace.c ******************/ +/* +** 2023-06-21 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements an extension that uses the SQLITE_CONFIG_PCACHE2 +** mechanism to add a tracing layer on top of pluggable page cache of +** SQLite. If this extension is registered prior to sqlite3_initialize(), +** it will cause all page cache activities to be logged on standard output, +** or to some other FILE specified by the initializer. +** +** This file needs to be compiled into the application that uses it. +** +** This extension is used to implement the --pcachetrace option of the +** command-line shell. +*/ +#include +#include +#include + +/* The original page cache routines */ +static sqlite3_pcache_methods2 pcacheBase; +static FILE *pcachetraceOut; + +/* Methods that trace pcache activity */ +static int pcachetraceInit(void *pArg){ + int nRes; + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p)\n", pArg); } - if( p->spec.eBlob==QRF_Auto ){ - switch( p->spec.eText ){ - case QRF_TEXT_Sql: p->spec.eBlob = QRF_BLOB_Sql; break; - case QRF_TEXT_Csv: p->spec.eBlob = QRF_BLOB_Tcl; break; - case QRF_TEXT_Tcl: p->spec.eBlob = QRF_BLOB_Tcl; break; - case QRF_TEXT_Json: p->spec.eBlob = QRF_BLOB_Json; break; - default: p->spec.eBlob = QRF_BLOB_Text; break; - } + nRes = pcacheBase.xInit(pArg); + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p) -> %d\n", pArg, nRes); } - if( p->spec.bTitles==QRF_Auto ){ - switch( p->spec.eStyle ){ - case QRF_STYLE_Box: - case QRF_STYLE_Csv: - case QRF_STYLE_Column: - case QRF_STYLE_Table: - case QRF_STYLE_Markdown: - p->spec.bTitles = QRF_Yes; - break; - default: - p->spec.bTitles = QRF_No; - break; - } + return nRes; +} +static void pcachetraceShutdown(void *pArg){ + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xShutdown(%p)\n", pArg); } - if( p->spec.bWordWrap==QRF_Auto ){ - p->spec.bWordWrap = QRF_Yes; + pcacheBase.xShutdown(pArg); +} +static sqlite3_pcache *pcachetraceCreate(int szPage, int szExtra, int bPurge){ + sqlite3_pcache *pRes; + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d)\n", + szPage, szExtra, bPurge); } - if( p->spec.bTextJsonb==QRF_Auto ){ - p->spec.bTextJsonb = QRF_No; + pRes = pcacheBase.xCreate(szPage, szExtra, bPurge); + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d) -> %p\n", + szPage, szExtra, bPurge, pRes); } - if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = ","; - if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n"; + return pRes; } - -/* -** Finish rendering the results -*/ -static void qrfFinalize(Qrf *p){ - switch( p->spec.eStyle ){ - case QRF_STYLE_Count: { - sqlite3_str_appendf(p->pOut, "%lld\n", p->nRow); - qrfWrite(p); - break; - } - case QRF_STYLE_Json: { - if( p->nRow>0 ){ - sqlite3_str_append(p->pOut, "}]\n", 3); - qrfWrite(p); - } - break; - } - case QRF_STYLE_JObject: { - if( p->nRow>0 ){ - sqlite3_str_append(p->pOut, "}\n", 2); - qrfWrite(p); - } - break; - } - case QRF_STYLE_Line: { - if( p->u.sLine.azCol ){ - int i; - for(i=0; inCol; i++) sqlite3_free(p->u.sLine.azCol[i]); - sqlite3_free(p->u.sLine.azCol); - } - break; - } - case QRF_STYLE_Stats: - case QRF_STYLE_StatsEst: { - i64 nCycle = 0; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - sqlite3_stmt_scanstatus_v2(p->pStmt, -1, SQLITE_SCANSTAT_NCYCLE, - SQLITE_SCANSTAT_COMPLEX, (void*)&nCycle); -#endif - qrfEqpRender(p, nCycle); - qrfWrite(p); - break; - } - case QRF_STYLE_Eqp: { - qrfEqpRender(p, 0); - qrfWrite(p); - break; - } +static void pcachetraceCachesize(sqlite3_pcache *p, int nCachesize){ + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xCachesize(%p, %d)\n", p, nCachesize); } - qrfStrErr(p, p->pOut); - if( p->spec.pzOutput ){ - if( p->spec.pzOutput[0] ){ - sqlite3_int64 n, sz; - char *zCombined; - sz = strlen(p->spec.pzOutput[0]); - n = sqlite3_str_length(p->pOut); - zCombined = sqlite3_realloc64(p->spec.pzOutput[0], sz+n+1); - if( zCombined==0 ){ - sqlite3_free(p->spec.pzOutput[0]); - p->spec.pzOutput[0] = 0; - qrfOom(p); - }else{ - p->spec.pzOutput[0] = zCombined; - memcpy(zCombined+sz, sqlite3_str_value(p->pOut), n+1); - } - sqlite3_free(sqlite3_str_finish(p->pOut)); - }else{ - p->spec.pzOutput[0] = sqlite3_str_finish(p->pOut); - } - }else if( p->pOut ){ - sqlite3_free(sqlite3_str_finish(p->pOut)); + pcacheBase.xCachesize(p, nCachesize); +} +static int pcachetracePagecount(sqlite3_pcache *p){ + int nRes; + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p)\n", p); } - if( p->expMode>0 ){ - sqlite3_stmt_explain(p->pStmt, p->expMode-1); + nRes = pcacheBase.xPagecount(p); + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p) -> %d\n", p, nRes); } - if( p->actualWidth ){ - sqlite3_free(p->actualWidth); + return nRes; +} +static sqlite3_pcache_page *pcachetraceFetch( + sqlite3_pcache *p, + unsigned key, + int crFg +){ + sqlite3_pcache_page *pRes; + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d)\n", p, key, crFg); } - if( p->pJTrans ){ - sqlite3 *db = sqlite3_db_handle(p->pJTrans); - sqlite3_finalize(p->pJTrans); - sqlite3_close(db); + pRes = pcacheBase.xFetch(p, key, crFg); + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d) -> %p\n", + p, key, crFg, pRes); } + return pRes; } - -/* -** Run the prepared statement pStmt and format the results according -** to the specification provided in pSpec. Return an error code. -** If pzErr is not NULL and if an error occurs, write an error message -** into *pzErr. -*/ -int sqlite3_format_query_result( - sqlite3_stmt *pStmt, /* Statement to evaluate */ - const sqlite3_qrf_spec *pSpec, /* Format specification */ - char **pzErr /* Write error message here */ +static void pcachetraceUnpin( + sqlite3_pcache *p, + sqlite3_pcache_page *pPg, + int bDiscard ){ - Qrf qrf; /* The new Qrf being created */ - - if( pStmt==0 ) return SQLITE_OK; /* No-op */ - if( pSpec==0 ) return SQLITE_MISUSE; - qrfInitialize(&qrf, pStmt, pSpec, pzErr); - switch( qrf.spec.eStyle ){ - case QRF_STYLE_Box: - case QRF_STYLE_Column: - case QRF_STYLE_Markdown: - case QRF_STYLE_Table: { - /* Columnar modes require that the entire query be evaluated and the - ** results stored in memory, so that we can compute column widths */ - qrfColumnar(&qrf); - break; - } - case QRF_STYLE_Explain: { - qrfExplain(&qrf); - break; - } - case QRF_STYLE_StatsVm: { - qrfScanStatusVm(&qrf); - break; - } - case QRF_STYLE_Stats: - case QRF_STYLE_StatsEst: { - qrfEqpStats(&qrf); - break; - } - default: { - /* Non-columnar modes where the output can occur after each row - ** of result is received */ - while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - qrfOneSimpleRow(&qrf); - } - break; - } + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xUnpin(%p, %p, %d)\n", + p, pPg, bDiscard); } - qrfResetStmt(&qrf); - qrfFinalize(&qrf); - return qrf.iErr; + pcacheBase.xUnpin(p, pPg, bDiscard); } - -/************************* End ext/qrf/qrf.c ********************/ - -/* Use console I/O package as a direct INCLUDE. */ -#define SQLITE_INTERNAL_LINKAGE static - -#ifdef SQLITE_SHELL_FIDDLE -/* Deselect most features from the console I/O package for Fiddle. */ -# define SQLITE_CIO_NO_REDIRECT -# define SQLITE_CIO_NO_CLASSIFY -# define SQLITE_CIO_NO_TRANSLATE -# define SQLITE_CIO_NO_SETMODE -# define SQLITE_CIO_NO_FLUSH -#endif - -/* -** Output routines that are able to redirect to memory rather than -** doing actually I/O. -** Works like. -** -------------- -** cli_printf(FILE*, const char*, ...); fprintf() -** cli_puts(const char*, FILE*); fputs() -** cli_vprintf(FILE*, const char*, va_list); vfprintf() -** -** These are just thin wrappers with the following added semantics: -** If the file-scope variable cli_output_capture is not NULL, and -** if the FILE* argument is stdout or stderr, then rather than -** writing to stdout/stdout, append the text to the cli_output_capture -** variable. -** -** The cli_exit(int) routine works like exit() except that it -** first dumps any capture output to stdout. -*/ -static sqlite3_str *cli_output_capture = 0; -static int cli_printf(FILE *out, const char *zFormat, ...){ - va_list ap; - int rc; - va_start(ap,zFormat); - if( cli_output_capture && (out==stdout || out==stderr) ){ - sqlite3_str_vappendf(cli_output_capture, zFormat, ap); - rc = 1; - }else{ - rc = sqlite3_vfprintf(out, zFormat, ap); +static void pcachetraceRekey( + sqlite3_pcache *p, + sqlite3_pcache_page *pPg, + unsigned oldKey, + unsigned newKey +){ + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xRekey(%p, %p, %u, %u)\n", + p, pPg, oldKey, newKey); } - va_end(ap); - return rc; + pcacheBase.xRekey(p, pPg, oldKey, newKey); } -static int cli_puts(const char *zText, FILE *out){ - if( cli_output_capture && (out==stdout || out==stderr) ){ - sqlite3_str_appendall(cli_output_capture, zText); - return 1; +static void pcachetraceTruncate(sqlite3_pcache *p, unsigned n){ + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xTruncate(%p, %u)\n", p, n); } - return sqlite3_fputs(zText, out); + pcacheBase.xTruncate(p, n); } -#if 0 /* Not currently used - available if we need it later */ -static int cli_vprintf(FILE *out, const char *zFormat, va_list ap){ - if( cli_output_capture && (out==stdout || out==stderr) ){ - sqlite3_str_vappendf(cli_output_capture, zFormat, ap); - return 1; - }else{ - return sqlite3_vfprintf(out, zFormat, ap); +static void pcachetraceDestroy(sqlite3_pcache *p){ + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xDestroy(%p)\n", p); } + pcacheBase.xDestroy(p); } -#endif -static void cli_exit(int rc){ - if( cli_output_capture ){ - char *z = sqlite3_str_finish(cli_output_capture); - sqlite3_fputs(z, stdout); - fflush(stdout); +static void pcachetraceShrink(sqlite3_pcache *p){ + if( pcachetraceOut ){ + fprintf(pcachetraceOut, "PCACHETRACE: xShrink(%p)\n", p); } - exit(rc); + pcacheBase.xShrink(p); } +/* The substitute pcache methods */ +static sqlite3_pcache_methods2 ersaztPcacheMethods = { + 0, + 0, + pcachetraceInit, + pcachetraceShutdown, + pcachetraceCreate, + pcachetraceCachesize, + pcachetracePagecount, + pcachetraceFetch, + pcachetraceUnpin, + pcachetraceRekey, + pcachetraceTruncate, + pcachetraceDestroy, + pcachetraceShrink +}; -#define eputz(z) cli_puts(z,stderr) -#define sputz(fp,z) cli_puts(z,fp) - -/* 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); +/* Begin tracing memory allocations to out. */ +int sqlite3PcacheTraceActivate(FILE *out){ + int rc = SQLITE_OK; + if( pcacheBase.xFetch==0 ){ + rc = sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &pcacheBase); + if( rc==SQLITE_OK ){ + rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &ersaztPcacheMethods); + } + } + pcachetraceOut = out; + return rc; } -/* Return the current wall-clock time in microseconds since the -** Unix epoch (1970-01-01T00:00:00Z) -*/ -static sqlite3_int64 timeOfDay(void){ -#if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8 - sqlite3_uint64 t; - FILETIME tm; - GetSystemTimePreciseAsFileTime(&tm); - t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime; - t += 116444736000000000LL; - t /= 10; - return t; -#elif defined(_WIN32) - 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); +/* Deactivate memory tracing */ +int sqlite3PcacheTraceDeactivate(void){ + int rc = SQLITE_OK; + if( pcacheBase.xFetch!=0 ){ + rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcacheBase); + if( rc==SQLITE_OK ){ + memset(&pcacheBase, 0, sizeof(pcacheBase)); + } } - return t*1000; -#else - struct timeval sNow; - (void)gettimeofday(&sNow,0); - return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec; -#endif + pcachetraceOut = 0; + return rc; } - -/* -** Used to prevent warnings about unused parameters -*/ -#define UNUSED_PARAMETER(x) (void)(x) - -/* -** Number of elements in an array -*/ -#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) - -/* -** If the following flag is set, then command execution stops -** at an error if we are not interactive. -*/ -static int bail_on_error = 0; - -/* -** Treat stdin as an interactive input if the following variable -** is true. Otherwise, assume stdin is connected to a file or pipe. -*/ -static int stdin_is_interactive = 1; - +/************************* End ../ext/misc/pcachetrace.c ********************/ +/************************* Begin ../ext/misc/shathree.c ******************/ /* -** Treat stdout like a TTY if true. +** 2017-03-08 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This SQLite extension implements functions that compute SHA3 hashes +** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard. +** Three SQL functions are implemented: +** +** sha3(X,SIZE) +** sha3_agg(Y,SIZE) +** sha3_query(Z,SIZE) +** +** The sha3(X) function computes the SHA3 hash of the input X, or NULL if +** X is NULL. If inputs X is text, the UTF-8 rendering of that text is +** used to compute the hash. If X is a BLOB, then the binary data of the +** blob is used to compute the hash. If X is an integer or real number, +** then that number if converted into UTF-8 text and the hash is computed +** over the text. +** +** The sha3_agg(Y) function computes the SHA3 hash of all Y inputs. Since +** order is important for the hash, it is recommended that the Y expression +** by followed by an ORDER BY clause to guarantee that the inputs occur +** in the desired order. +** +** The sha3_query(Y) function evaluates all queries in the SQL statements of Y +** and returns a hash of their results. +** +** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm +** is used. If SIZE is included it must be one of the integers 224, 256, +** 384, or 512, to determine SHA3 hash variant that is computed. +** +** Because the sha3_agg() and sha3_query() functions compute a hash over +** multiple values, the values are encode to use include type information. +** +** In sha3_agg(), the sequence of bytes that gets hashed for each input +** Y depends on the datatype of Y: +** +** typeof(Y)='null' A single "N" is hashed. (One byte) +** +** typeof(Y)='integer' The data hash is the character "I" followed +** by an 8-byte big-endian binary of the +** 64-bit signed integer. (Nine bytes total.) +** +** typeof(Y)='real' The character "F" followed by an 8-byte +** big-ending binary of the double. (Nine +** bytes total.) +** +** typeof(Y)='text' The hash is over prefix "Tnnn:" followed +** by the UTF8 encoding of the text. The "nnn" +** in the prefix is the minimum-length decimal +** representation of the octet_length of the text. +** Notice the ":" at the end of the prefix, which +** is needed to separate the prefix from the +** content in cases where the content starts +** with a digit. +** +** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed +** by the binary content of the blob. The "nnn" +** in the prefix is the minimum-length decimal +** representation of the byte-length of the blob. +** +** According to the rules above, all of the following SELECT statements +** should return TRUE: +** +** SELECT sha3(1) = sha3('1'); +** +** SELECT sha3('hello') = sha3(x'68656c6c6f'); +** +** WITH a(x) AS (VALUES('xyzzy')) +** SELECT sha3_agg(x) = sha3('T5:xyzzy') FROM a; +** +** WITH a(x) AS (VALUES(x'010203')) +** SELECT sha3_agg(x) = sha3(x'42333a010203') FROM a; +** +** WITH a(x) AS (VALUES(0x123456)) +** SELECT sha3_agg(x) = sha3(x'490000000000123456') FROM a; +** +** WITH a(x) AS (VALUES(100.015625)) +** SELECT sha3_agg(x) = sha3(x'464059010000000000') FROM a; +** +** WITH a(x) AS (VALUES(NULL)) +** SELECT sha3_agg(x) = sha3('N') FROM a; +** +** +** In sha3_query(), individual column values are encoded as with +** sha3_agg(), but with the addition that a single "R" character is +** inserted at the start of each row. +** +** Note that sha3_agg() hashes rows for which Y is NULL. Add a FILTER +** clause if NULL rows should be excluded: +** +** SELECT sha3_agg(x ORDER BY rowid) FILTER(WHERE x NOT NULL) FROM t1; */ -static int stdout_is_console = 1; +/* #include "sqlite3ext.h" */ +SQLITE_EXTENSION_INIT1 +#include +#include +#include -/* -** Use this value as the width of the output device. Or, figure it -** out at runtime if the value is negative. Or use a default width -** if this value is zero. -*/ -static int stdout_tty_width = -1; +#ifndef SQLITE_AMALGAMATION +/* typedef sqlite3_uint64 u64; */ +#endif /* SQLITE_AMALGAMATION */ -/* -** The following is the open SQLite database. We make a pointer -** to this database a static variable so that it can be accessed -** by the SIGINT handler to interrupt database processing. +/****************************************************************************** +** The Hash Engine */ -static sqlite3 *globalDb = 0; - /* -** True if an interrupt (Control-C) has been received. +** Macros to determine whether the machine is big or little endian, +** and whether or not that determination is run-time or compile-time. +** +** For best performance, an attempt is made to guess at the byte-order +** using C-preprocessor macros. If that is unsuccessful, or if +** -DSHA3_BYTEORDER=0 is set, then byte-order is determined +** at run-time. */ -static volatile int seenInterrupt = 0; +#ifndef SHA3_BYTEORDER +# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ + defined(__arm__) +# define SHA3_BYTEORDER 1234 +# elif defined(sparc) || defined(__ppc__) +# define SHA3_BYTEORDER 4321 +# else +# define SHA3_BYTEORDER 0 +# endif +#endif -/* -** This is the name of our program. It is set in main(), used -** in a number of other places, mostly for error messages. -*/ -static char *Argv0; /* -** Prompt strings. Initialized in main. Settable with -** .prompt main continue +** State structure for a SHA3 hash in progress */ -#define PROMPT_LEN_MAX 128 -/* First line prompt. default: "sqlite> " */ -static char mainPrompt[PROMPT_LEN_MAX]; -/* Continuation prompt. default: " ...> " */ -static char continuePrompt[PROMPT_LEN_MAX]; +typedef struct SHA3Context SHA3Context; +struct SHA3Context { + union { + u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ + unsigned char x[1600]; /* ... or 1600 bytes */ + } u; + unsigned nRate; /* Bytes of input accepted per Keccak iteration */ + unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ + unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ + unsigned iSize; /* 224, 256, 358, or 512 */ +}; /* -** Write I/O traces to the following stream. -*/ -#ifdef SQLITE_ENABLE_IOTRACE -static FILE *iotrace = 0; -#endif - - -/* This is variant of the standard-library strncpy() routine with the -** one change that the destination string is always zero-terminated, even -** if there is no zero-terminator in the first n-1 characters of the source -** string. +** A single step of the Keccak mixing function for a 1600-bit state */ -static char *shell_strncpy(char *dest, const char *src, size_t n){ - size_t i; - for(i=0; iu.s[0]) +# define a01 (p->u.s[1]) +# define a02 (p->u.s[2]) +# define a03 (p->u.s[3]) +# define a04 (p->u.s[4]) +# define a10 (p->u.s[5]) +# define a11 (p->u.s[6]) +# define a12 (p->u.s[7]) +# define a13 (p->u.s[8]) +# define a14 (p->u.s[9]) +# define a20 (p->u.s[10]) +# define a21 (p->u.s[11]) +# define a22 (p->u.s[12]) +# define a23 (p->u.s[13]) +# define a24 (p->u.s[14]) +# define a30 (p->u.s[15]) +# define a31 (p->u.s[16]) +# define a32 (p->u.s[17]) +# define a33 (p->u.s[18]) +# define a34 (p->u.s[19]) +# define a40 (p->u.s[20]) +# define a41 (p->u.s[21]) +# define a42 (p->u.s[22]) +# define a43 (p->u.s[23]) +# define a44 (p->u.s[24]) +# define ROL64(a,x) ((a<>(64-x))) -/* -** strcpy() workalike to squelch an unwarranted link-time warning -** from OpenBSD. -*/ -static void shell_strcpy(char *dest, const char *src){ - while( (*(dest++) = *(src++))!=0 ){} -} + for(i=0; i<24; i+=4){ + c0 = a00^a10^a20^a30^a40; + c1 = a01^a11^a21^a31^a41; + c2 = a02^a12^a22^a32^a42; + c3 = a03^a13^a23^a33^a43; + c4 = a04^a14^a24^a34^a44; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); -/* -** 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. -** This facility interacts with the scanner and process_input() where the -** below 5 macros are used. -*/ -#ifdef SQLITE_OMIT_DYNAPROMPT -# define CONTINUATION_PROMPT continuePrompt -# define CONTINUE_PROMPT_RESET -# define CONTINUE_PROMPT_AWAITS(p,s) -# define CONTINUE_PROMPT_AWAITC(p,c) -# define CONTINUE_PAREN_INCR(p,n) -# define CONTINUE_PROMPT_PSTATE 0 -typedef void *t_NoDynaPrompt; -# define SCAN_TRACKER_REFTYPE t_NoDynaPrompt -#else -# define CONTINUATION_PROMPT dynamicContinuePrompt() -# define CONTINUE_PROMPT_RESET \ - do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0) -# define CONTINUE_PROMPT_AWAITS(p,s) \ - if(p && stdin_is_interactive) setLexemeOpen(p, s, 0) -# define CONTINUE_PROMPT_AWAITC(p,c) \ - if(p && stdin_is_interactive) setLexemeOpen(p, 0, c) -# define CONTINUE_PAREN_INCR(p,n) \ - if(p && stdin_is_interactive) (trackParenLevel(p,n)) -# define CONTINUE_PROMPT_PSTATE (&dynPrompt) -typedef struct DynaPrompt *t_DynaPromptRef; -# define SCAN_TRACKER_REFTYPE t_DynaPromptRef + b0 = (a00^d0); + b1 = ROL64((a11^d1), 44); + b2 = ROL64((a22^d2), 43); + b3 = ROL64((a33^d3), 21); + b4 = ROL64((a44^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i]; + a11 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); -static struct DynaPrompt { - char dynamicPrompt[PROMPT_LEN_MAX]; - char acAwait[2]; - int inParenLevel; - char *zScannerAwaits; -} dynPrompt = { {0}, {0}, 0, 0 }; + b2 = ROL64((a20^d0), 3); + b3 = ROL64((a31^d1), 45); + b4 = ROL64((a42^d2), 61); + b0 = ROL64((a03^d3), 28); + b1 = ROL64((a14^d4), 20); + a20 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); -/* Record parenthesis nesting level change, or force level to 0. */ -static void trackParenLevel(struct DynaPrompt *p, int ni){ - p->inParenLevel += ni; - if( ni==0 ) p->inParenLevel = 0; - p->zScannerAwaits = 0; -} + b4 = ROL64((a40^d0), 18); + b0 = ROL64((a01^d1), 1); + b1 = ROL64((a12^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a34^d4), 8); + a40 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); -/* Record that a lexeme is opened, or closed with args==0. */ -static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){ - if( s!=0 || c==0 ){ - p->zScannerAwaits = s; - p->acAwait[0] = 0; - }else{ - p->acAwait[0] = c; - p->zScannerAwaits = p->acAwait; - } -} + b1 = ROL64((a10^d0), 36); + b2 = ROL64((a21^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a43^d3), 56); + b0 = ROL64((a04^d4), 27); + a10 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); -/* Upon demand, derive the continuation prompt to display. */ -static char *dynamicContinuePrompt(void){ - if( continuePrompt[0]==0 - || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) ){ - return continuePrompt; - }else{ - if( dynPrompt.zScannerAwaits ){ - size_t ncp = strlen(continuePrompt); - size_t ndp = strlen(dynPrompt.zScannerAwaits); - if( ndp > ncp-3 ) return continuePrompt; - shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits); - while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' '; - shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, - PROMPT_LEN_MAX-4); - }else{ - if( dynPrompt.inParenLevel>9 ){ - shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4); - }else if( dynPrompt.inParenLevel<0 ){ - shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4); - }else{ - shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4); - dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel); - } - shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, - PROMPT_LEN_MAX-4); - } - } - return dynPrompt.dynamicPrompt; -} -#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ + b3 = ROL64((a30^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a02^d2), 62); + b1 = ROL64((a13^d3), 55); + b2 = ROL64((a24^d4), 39); + a30 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); -/* Indicate out-of-memory and exit. */ -static void shell_out_of_memory(void){ - eputz("Error: out of memory\n"); - cli_exit(1); -} + c0 = a00^a20^a40^a10^a30; + c1 = a11^a31^a01^a21^a41; + c2 = a22^a42^a12^a32^a02; + c3 = a33^a03^a23^a43^a13; + c4 = a44^a14^a34^a04^a24; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); -/* Check a pointer to see if it is NULL. If it is NULL, exit with an -** out-of-memory error. -*/ -static void shell_check_oom(const void *p){ - if( p==0 ) shell_out_of_memory(); -} + b0 = (a00^d0); + b1 = ROL64((a31^d1), 44); + b2 = ROL64((a12^d2), 43); + b3 = ROL64((a43^d3), 21); + b4 = ROL64((a24^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+1]; + a31 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); -/* -** This routine works like printf in that its first argument is a -** format string and subsequent arguments are values to be substituted -** in place of % fields. The result of formatting this string -** is written to iotrace. -*/ -#ifdef SQLITE_ENABLE_IOTRACE -static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ - va_list ap; - char *z; - if( iotrace==0 ) return; - va_start(ap, zFormat); - z = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - cli_printf(iotrace, "%s", z); - sqlite3_free(z); -} -#endif + b2 = ROL64((a40^d0), 3); + b3 = ROL64((a21^d1), 45); + b4 = ROL64((a02^d2), 61); + b0 = ROL64((a33^d3), 28); + b1 = ROL64((a14^d4), 20); + a40 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); -/* -** Compute a string length that is limited to what can be stored in -** lower 30 bits of a 32-bit signed integer. -*/ -static int strlen30(const char *z){ - size_t n; - if( z==0 ) return 0; - n = strlen(z); - return n>0x3fffffff ? 0x3fffffff : (int)n; + b4 = ROL64((a30^d0), 18); + b0 = ROL64((a11^d1), 1); + b1 = ROL64((a42^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a04^d4), 8); + a30 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a20^d0), 36); + b2 = ROL64((a01^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a13^d3), 56); + b0 = ROL64((a44^d4), 27); + a20 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a10^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a22^d2), 62); + b1 = ROL64((a03^d3), 55); + b2 = ROL64((a34^d4), 39); + a10 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + c0 = a00^a40^a30^a20^a10; + c1 = a31^a21^a11^a01^a41; + c2 = a12^a02^a42^a32^a22; + c3 = a43^a33^a23^a13^a03; + c4 = a24^a14^a04^a44^a34; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a21^d1), 44); + b2 = ROL64((a42^d2), 43); + b3 = ROL64((a13^d3), 21); + b4 = ROL64((a34^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+2]; + a21 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a30^d0), 3); + b3 = ROL64((a01^d1), 45); + b4 = ROL64((a22^d2), 61); + b0 = ROL64((a43^d3), 28); + b1 = ROL64((a14^d4), 20); + a30 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a10^d0), 18); + b0 = ROL64((a31^d1), 1); + b1 = ROL64((a02^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a44^d4), 8); + a10 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a40^d0), 36); + b2 = ROL64((a11^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a03^d3), 56); + b0 = ROL64((a24^d4), 27); + a40 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a20^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a12^d2), 62); + b1 = ROL64((a33^d3), 55); + b2 = ROL64((a04^d4), 39); + a20 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + c0 = a00^a30^a10^a40^a20; + c1 = a21^a01^a31^a11^a41; + c2 = a42^a22^a02^a32^a12; + c3 = a13^a43^a23^a03^a33; + c4 = a34^a14^a44^a24^a04; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a01^d1), 44); + b2 = ROL64((a02^d2), 43); + b3 = ROL64((a03^d3), 21); + b4 = ROL64((a04^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+3]; + a01 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a10^d0), 3); + b3 = ROL64((a11^d1), 45); + b4 = ROL64((a12^d2), 61); + b0 = ROL64((a13^d3), 28); + b1 = ROL64((a14^d4), 20); + a10 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a20^d0), 18); + b0 = ROL64((a21^d1), 1); + b1 = ROL64((a22^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a24^d4), 8); + a20 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a30^d0), 36); + b2 = ROL64((a31^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a33^d3), 56); + b0 = ROL64((a34^d4), 27); + a30 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a40^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a42^d2), 62); + b1 = ROL64((a43^d3), 55); + b2 = ROL64((a44^d4), 39); + a40 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + } } /* -** Return open FILE * if zFile exists, can be opened for read -** and is an ordinary file or a character stream source. -** Otherwise return 0. +** Initialize a new hash. iSize determines the size of the hash +** in bits and should be one of 224, 256, 384, or 512. Or iSize +** can be zero to use the default hash size of 256 bits. */ -static FILE * openChrSource(const char *zFile){ -#if defined(_WIN32) || defined(WIN32) - struct __stat64 x = {0}; -# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0) - /* 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 = sqlite3_fopen(zFile, "rb"); - if( rv==0 ) return 0; - if( _fstat64(_fileno(rv), &x) != 0 - || !STAT_CHR_SRC(x.st_mode)){ - fclose(rv); - rv = 0; +static void SHA3Init(SHA3Context *p, int iSize){ + memset(p, 0, sizeof(*p)); + p->iSize = iSize; + if( iSize>=128 && iSize<=512 ){ + p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; + }else{ + p->nRate = (1600 - 2*256)/8; } - return rv; +#if SHA3_BYTEORDER==1234 + /* Known to be little-endian at compile-time. No-op */ +#elif SHA3_BYTEORDER==4321 + p->ixMask = 7; /* Big-endian */ #else - struct stat x = {0}; - int rc = stat(zFile, &x); -# 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 sqlite3_fopen(zFile, "rb"); - }else{ - return 0; + { + static unsigned int one = 1; + if( 1==*(unsigned char*)&one ){ + /* Little endian. No byte swapping. */ + p->ixMask = 0; + }else{ + /* Big endian. Byte swap. */ + p->ixMask = 7; + } } #endif -#undef STAT_CHR_SRC } /* -** This routine reads a line of text from FILE in, stores -** the text in memory obtained from malloc() and returns a pointer -** to the text. NULL is returned at end of file, or if malloc() -** fails, or if the length of the line is longer than about a gigabyte. -** -** If zLine is not NULL then it is a malloced buffer returned from -** a previous call to this routine that may be reused. +** Make consecutive calls to the SHA3Update function to add new content +** to the hash */ -static char *local_getline(char *zLine, FILE *in){ - int nLine = zLine==0 ? 0 : 100; - int n = 0; - - while( 1 ){ - if( n+100>nLine ){ - if( nLine>=1073741773 ){ - free(zLine); - return 0; +static void SHA3Update( + SHA3Context *p, + const unsigned char *aData, + unsigned int nData +){ + unsigned int i = 0; + if( aData==0 ) return; +#if SHA3_BYTEORDER==1234 + if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ + for(; i+7u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; + p->nLoaded += 8; + if( p->nLoaded>=p->nRate ){ + KeccakF1600Step(p); + p->nLoaded = 0; } - nLine = nLine*2 + 100; - zLine = realloc(zLine, nLine); - shell_check_oom(zLine); } - if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){ - if( n==0 ){ - free(zLine); - return 0; - } - zLine[n] = 0; - break; - } - while( zLine[n] ) n++; - if( n>0 && zLine[n-1]=='\n' ){ - n--; - if( n>0 && zLine[n-1]=='\r' ) n--; - zLine[n] = 0; - break; + } +#endif + for(; iu.x[p->nLoaded] ^= aData[i]; +#elif SHA3_BYTEORDER==4321 + p->u.x[p->nLoaded^0x07] ^= aData[i]; +#else + p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; +#endif + p->nLoaded++; + if( p->nLoaded==p->nRate ){ + KeccakF1600Step(p); + p->nLoaded = 0; } } - return zLine; } /* -** Retrieve a single line of input text. -** -** If in==0 then read from standard input and prompt before each line. -** If isContinuation is true, then a continuation prompt is appropriate. -** If isContinuation is zero, then the main prompt should be used. -** -** If zPrior is not NULL then it is a buffer from a prior call to this -** routine that can be reused. +** After all content has been added, invoke SHA3Final() to compute +** the final hash. The function returns a pointer to the binary +** hash value. +*/ +static unsigned char *SHA3Final(SHA3Context *p){ + unsigned int i; + if( p->nLoaded==p->nRate-1 ){ + const unsigned char c1 = 0x86; + SHA3Update(p, &c1, 1); + }else{ + const unsigned char c2 = 0x06; + const unsigned char c3 = 0x80; + SHA3Update(p, &c2, 1); + p->nLoaded = p->nRate - 1; + SHA3Update(p, &c3, 1); + } + for(i=0; inRate; i++){ + p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; + } + return &p->u.x[p->nRate]; +} +/* End of the hashing logic +*****************************************************************************/ + +/* +** Implementation of the sha3(X,SIZE) function. ** -** The result is stored in space obtained from malloc() and must either -** be freed by the caller or else passed back into this routine via the -** zPrior argument for reuse. +** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default +** size is 256. If X is a BLOB, it is hashed as is. +** For all other non-NULL types of input, X is converted into a UTF-8 string +** and the string is hashed without the trailing 0x00 terminator. The hash +** of a NULL value is NULL. */ -#ifndef SQLITE_SHELL_FIDDLE -static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ - char *zPrompt; - char *zResult; - if( in!=0 ){ - zResult = local_getline(zPrior, in); +static void sha3Func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + SHA3Context cx; + int eType = sqlite3_value_type(argv[0]); + int nByte = sqlite3_value_bytes(argv[0]); + int iSize; + if( argc==1 ){ + iSize = 256; }else{ - zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt; -#if SHELL_USE_LOCAL_GETLINE - sputz(stdout, zPrompt); - fflush(stdout); - do{ - zResult = local_getline(zPrior, stdin); - zPrior = 0; - /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ - if( zResult==0 ) sqlite3_sleep(50); - }while( zResult==0 && seenInterrupt>0 ); -#else - free(zPrior); - zResult = shell_readline(zPrompt); - while( zResult==0 ){ - /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ - sqlite3_sleep(50); - if( seenInterrupt==0 ) break; - zResult = shell_readline(""); + iSize = sqlite3_value_int(argv[1]); + if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ + sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " + "384 512", -1); + return; } - if( zResult && *zResult ) shell_add_history(zResult); -#endif } - return zResult; + if( eType==SQLITE_NULL ) return; + SHA3Init(&cx, iSize); + if( eType==SQLITE_BLOB ){ + SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); + }else{ + SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); + } + sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); } -#endif /* !SQLITE_SHELL_FIDDLE */ -/* -** Return the value of a hexadecimal digit. Return -1 if the input -** is not a hex digit. +/* Compute a string using sqlite3_vsnprintf() with a maximum length +** of 50 bytes and add it to the hash. */ -static int hexDigitValue(char c){ - if( c>='0' && c<='9' ) return c - '0'; - if( c>='a' && c<='f' ) return c - 'a' + 10; - if( c>='A' && c<='F' ) return c - 'A' + 10; - return -1; +static void sha3_step_vformat( + SHA3Context *p, /* Add content to this context */ + const char *zFormat, + ... +){ + va_list ap; + int n; + char zBuf[50]; + va_start(ap, zFormat); + sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); + va_end(ap); + n = (int)strlen(zBuf); + SHA3Update(p, (unsigned char*)zBuf, n); } /* -** Interpret zArg as an integer value, possibly with suffixes. -** -** If the value specified by zArg is outside the range of values that -** can be represented using a 64-bit twos-complement integer, then return -** the nearest representable value. +** Update a SHA3Context using a single sqlite3_value. */ -static sqlite3_int64 integerValue(const char *zArg){ - sqlite3_uint64 v = 0; - static const struct { char *zSuffix; unsigned int iMult; } aMult[] = { - { "KiB", 1024 }, - { "MiB", 1024*1024 }, - { "GiB", 1024*1024*1024 }, - { "KB", 1000 }, - { "MB", 1000000 }, - { "GB", 1000000000 }, - { "K", 1000 }, - { "M", 1000000 }, - { "G", 1000000000 }, - }; - int i; - int isNeg = 0; - if( zArg[0]=='-' ){ - isNeg = 1; - zArg++; - }else if( zArg[0]=='+' ){ - zArg++; - } - if( zArg[0]=='0' && zArg[1]=='x' ){ - int x; - zArg += 2; - while( (x = hexDigitValue(zArg[0]))>=0 ){ - if( v > 0x0fffffffffffffffULL ) goto integer_overflow; - v = (v<<4) + x; - zArg++; +static void sha3UpdateFromValue(SHA3Context *p, sqlite3_value *pVal){ + switch( sqlite3_value_type(pVal) ){ + case SQLITE_NULL: { + SHA3Update(p, (const unsigned char*)"N",1); + break; } - }else{ - while( IsDigit(zArg[0]) ){ - if( v>=922337203685477580LL ){ - if( v>922337203685477580LL || zArg[0]>='8' ) goto integer_overflow; + 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; } - v = v*10 + (zArg[0] - '0'); - zArg++; + x[0] = 'I'; + SHA3Update(p, x, 9); + break; } - } - for(i=0; i=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; } } - if( isNeg && v>0x7fffffffffffffffULL ) goto integer_overflow; - return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v; -integer_overflow: - return isNeg ? (i64)0x8000000000000000LL : 0x7fffffffffffffffLL; } /* -** A variable length string to which one can append text. -*/ -typedef struct ShellText ShellText; -struct ShellText { - char *zTxt; /* The text */ - i64 n; /* Number of bytes of zTxt[] actually used */ - i64 nAlloc; /* Number of bytes allocated for zTxt[] */ -}; - -/* -** Initialize and destroy a ShellText object -*/ -static void initText(ShellText *p){ - memset(p, 0, sizeof(*p)); -} -static void freeText(ShellText *p){ - sqlite3_free(p->zTxt); - initText(p); -} - -/* zIn is either a pointer to a NULL-terminated string in memory obtained -** from malloc(), or a NULL pointer. The string pointed to by zAppend is -** added to zIn, and the result returned in memory obtained from malloc(). -** zIn, if it was not NULL, is freed. +** Implementation of the sha3_query(SQL,SIZE) function. ** -** If the third argument, quote, is not '\0', then it is used as a -** quote character for zAppend. +** This function compiles and runs the SQL statement(s) given in the +** argument. The results are hashed using a SIZE-bit SHA3. The default +** size is 256. +** +** The format of the byte stream that is hashed is summarized as follows: +** +** S: +** R +** N +** I +** F +** B: +** T: +** +** is the original SQL text for each statement run and is +** the size of that text. The SQL text is UTF-8. A single R character +** occurs before the start of each row. N means a NULL value. +** I mean an 8-byte little-endian integer . F is a floating point +** number with an 8-byte little-endian IEEE floating point value . +** B means blobs of bytes. T means text rendered as +** bytes of UTF-8. The and values are expressed as an ASCII +** text integers. +** +** For each SQL statement in the X input, there is one S segment. Each +** S segment is followed by zero or more R segments, one for each row in the +** result set. After each R, there are one or more N, I, F, B, or T segments, +** one for each column in the result set. Segments are concatentated directly +** with no delimiters of any kind. */ -static void appendText(ShellText *p, const char *zAppend, char quote){ - i64 len; - i64 i; - i64 nAppend = strlen30(zAppend); +static void sha3QueryFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_context_db_handle(context); + const char *zSql = (const char*)sqlite3_value_text(argv[0]); + sqlite3_stmt *pStmt = 0; + int nCol; /* Number of columns in the result set */ + int i; /* Loop counter */ + int rc; + int n; + const char *z; + SHA3Context cx; + int iSize; - len = nAppend+p->n+1; - if( quote ){ - len += 2; - for(i=0; izTxt==0 || p->n+len>=p->nAlloc ){ - p->nAlloc = p->nAlloc*2 + len + 20; - p->zTxt = sqlite3_realloc64(p->zTxt, p->nAlloc); - shell_check_oom(p->zTxt); - } - - if( quote ){ - char *zCsr = p->zTxt+p->n; - *zCsr++ = quote; - for(i=0; in = (i64)(zCsr - p->zTxt); - *zCsr = '\0'; - }else{ - memcpy(p->zTxt+p->n, zAppend, nAppend); - p->n += nAppend; - p->zTxt[p->n] = '\0'; + sqlite3_finalize(pStmt); } + sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); } /* -** Attempt to determine if identifier zName needs to be quoted, either -** because it contains non-alphanumeric characters, or because it is an -** SQLite keyword. Be conservative in this estimate: When in doubt assume -** that quoting is required. -** -** Return '"' if quoting is required. Return 0 if no quoting is required. +** xStep function for sha3_agg(). */ -static char quoteChar(const char *zName){ - int i; - if( zName==0 ) return '"'; - if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '"'; - for(i=0; zName[i]; i++){ - if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '"'; +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); } - return sqlite3_keyword_check(zName, i) ? '"' : 0; + sha3UpdateFromValue(p, argv[0]); } + /* -** Construct a fake object name and column list to describe the structure -** of the view, virtual table, or table valued function zSchema.zName. -** -** The returned string comes from sqlite3_mprintf() and should be freed -** by the caller using sqlite3_free(). +** xFinal function for sha3_agg(). */ -static char *shellFakeSchema( - sqlite3 *db, /* The database connection containing the vtab */ - const char *zSchema, /* Schema of the database holding the vtab */ - const char *zName /* The name of the virtual table */ -){ - sqlite3_stmt *pStmt = 0; - char *zSql; - ShellText s; - char cQuote; - char *zDiv = "("; - int nRow = 0; +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); + } +} - zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", - zSchema ? zSchema : "main", zName); - shell_check_oom(zSql); - sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - initText(&s); - if( zSchema ){ - cQuote = quoteChar(zSchema); - if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0; - appendText(&s, zSchema, cQuote); - appendText(&s, ".", 0); + + +#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); } - cQuote = quoteChar(zName); - appendText(&s, zName, cQuote); - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); - nRow++; - appendText(&s, zDiv, 0); - zDiv = ","; - if( zCol==0 ) zCol = ""; - cQuote = quoteChar(zCol); - appendText(&s, zCol, cQuote); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_agg", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, 0, sha3AggStep, sha3AggFinal); } - appendText(&s, ")", 0); - sqlite3_finalize(pStmt); - if( nRow==0 ){ - freeText(&s); - s.zTxt = 0; + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_agg", 2, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, 0, sha3AggStep, sha3AggFinal); } - return s.zTxt; + 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 ******************/ /* -** SQL function: strtod(X) -** -** Use the C-library strtod() function to convert string X into a double. -** Used for comparing the accuracy of SQLite's internal text-to-float conversion -** routines against the C-library. -*/ -static void shellStrtod( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - char *z = (char*)sqlite3_value_text(apVal[0]); - UNUSED_PARAMETER(nVal); - if( z==0 ) return; - sqlite3_result_double(pCtx, strtod(z,0)); -} - -/* -** SQL function: dtostr(X) -** -** Use the C-library printf() function to convert real value X into a string. -** Used for comparing the accuracy of SQLite's internal float-to-text conversion -** routines against the C-library. -*/ -static void shellDtostr( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - double r = sqlite3_value_double(apVal[0]); - int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26; - char z[400]; - if( n<1 ) n = 1; - if( n>350 ) n = 350; - sprintf(z, "%#+.*e", n, r); - sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); -} - -/* -** SQL function: shell_add_schema(S,X) -** -** Add the schema name X to the CREATE statement in S and return the result. -** Examples: -** -** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x); -** -** Also works on -** -** CREATE INDEX -** CREATE UNIQUE INDEX -** CREATE VIEW -** CREATE TRIGGER -** CREATE VIRTUAL TABLE -** -** This UDF is used by the .schema command to insert the schema name of -** attached databases into the middle of the sqlite_schema.sql field. -*/ -static void shellAddSchemaName( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - static const char *aPrefix[] = { - "TABLE", - "INDEX", - "UNIQUE INDEX", - "VIEW", - "TRIGGER", - "VIRTUAL TABLE" - }; - int i = 0; - const char *zIn = (const char*)sqlite3_value_text(apVal[0]); - const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); - const char *zName = (const char*)sqlite3_value_text(apVal[2]); - sqlite3 *db = sqlite3_context_db_handle(pCtx); - UNUSED_PARAMETER(nVal); - if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){ - for(i=0; i -#include -#include -#include -#include -#include -#include -#include +/* #include "sqlite3ext.h" */ +SQLITE_EXTENSION_INIT1 +#include #include -#ifndef FILENAME_MAX -# define FILENAME_MAX (260) -#endif -#ifndef S_ISREG -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif -#ifndef S_ISDIR -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif -#ifndef S_ISLNK -#define S_ISLNK(m) (0) -#endif -typedef unsigned short mode_t; +#include -/* The dirent object for Windows is abbreviated. The only field really -** usable by applications is d_name[]. +/****************************************************************************** +** The Hash Engine */ -struct dirent { - int d_ino; /* Inode number (synthesized) */ - unsigned d_attributes; /* File attributes */ - char d_name[FILENAME_MAX]; /* Null-terminated filename */ +/* Context for the SHA1 hash */ +typedef struct SHA1Context SHA1Context; +struct SHA1Context { + unsigned int state[5]; + unsigned int count[2]; + unsigned char buffer[64]; }; -/* The internals of DIR are opaque according to standards. So it -** does not matter what we put here. */ -typedef struct DIR DIR; -struct DIR { - intptr_t d_handle; /* Handle for findfirst()/findnext() */ - struct dirent cur; /* Current entry */ -}; +#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) -/* Ignore hidden and system files */ -#define WindowsFileToIgnore(a) \ - ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) +#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)) /* -** Close a previously opened directory -*/ -static int closedir(DIR *pDir){ - int rc = 0; - if( pDir==0 ){ - return EINVAL; - } - if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){ - rc = _findclose(pDir->d_handle); - } - sqlite3_free(pDir); - return rc; -} + * (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); /* -** Open a new directory. The directory name should be UTF-8 encoded. -** appropriate translations happen automatically. -*/ -static DIR *opendir(const char *zDirName){ - DIR *pDir; - wchar_t *b1; - sqlite3_int64 sz; - struct _wfinddata_t data; + * 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)); - pDir = sqlite3_malloc64( sizeof(DIR) ); - if( pDir==0 ) return 0; - memset(pDir, 0, sizeof(DIR)); - memset(&data, 0, sizeof(data)); - sz = strlen(zDirName); - b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) ); - if( b1==0 ){ - closedir(pDir); - return NULL; - } - sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz); - b1[sz++] = '\\'; - b1[sz++] = '*'; - b1[sz] = 0; - if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){ - closedir(pDir); - sqlite3_free(b1); - return NULL; +#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); } - memcpy(data.name, b1, (sz+1)*sizeof(b1[0])); - sqlite3_free(b1); - pDir->d_handle = _wfindfirst(data.name, &data); - if( pDir->d_handle<0 ){ - closedir(pDir); - return NULL; + 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; } - while( WindowsFileToIgnore(data) ){ - memset(&data, 0, sizeof(data)); - if( _wfindnext(pDir->d_handle, &data)==-1 ){ - closedir(pDir); - return NULL; + 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; } - pDir->cur.d_ino = 0; - pDir->cur.d_attributes = data.attrib; - WideCharToMultiByte(CP_UTF8, 0, data.name, -1, - pDir->cur.d_name, FILENAME_MAX, 0, 0); - return pDir; } +/* End of the hashing logic +*****************************************************************************/ /* -** Read the next entry from a directory. +** Implementation of the sha1(X) function. ** -** The returned struct-dirent object is managed by DIR. It is only -** valid until the next readdir() or closedir() call. Only the -** d_name[] field is meaningful. The d_name[] value has been -** translated into UTF8. +** 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 struct dirent *readdir(DIR *pDir){ - struct _wfinddata_t data; - if( pDir==0 ) return 0; - if( (pDir->cur.d_ino++)==0 ){ - return &pDir->cur; +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); } - do{ - memset(&data, 0, sizeof(data)); - if( _wfindnext(pDir->d_handle, &data)==-1 ){ - return NULL; - } - }while( WindowsFileToIgnore(data) ); - pDir->cur.d_attributes = data.attrib; - WideCharToMultiByte(CP_UTF8, 0, data.name, -1, - pDir->cur.d_name, FILENAME_MAX, 0, 0); - return &pDir->cur; } -#endif /* defined(_WIN32) && defined(_MSC_VER) */ - -/************************* End ext/misc/windirent.h ********************/ -/************************* Begin ext/misc/memtrace.c ******************/ /* -** 2019-01-21 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* +** Implementation of the sha1_query(SQL) function. ** -** This file implements an extension that uses the SQLITE_CONFIG_MALLOC -** mechanism to add a tracing layer on top of SQLite. If this extension -** is registered prior to sqlite3_initialize(), it will cause all memory -** allocation activities to be logged on standard output, or to some other -** FILE specified by the initializer. +** This function compiles and runs the SQL statement(s) given in the +** argument. The results are hashed using SHA1 and that hash is returned. ** -** This file needs to be compiled into the application that uses it. +** The original SQL text is included as part of the hash. ** -** This extension is used to implement the --memtrace option of the -** command-line shell. +** 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. */ -#include -#include -#include +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]; -/* The original memory allocation routines */ -static sqlite3_mem_methods memtraceBase; -static FILE *memtraceOut; + 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); -/* Methods that trace memory allocations */ -static void *memtraceMalloc(int n){ - if( memtraceOut ){ - fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", - memtraceBase.xRoundup(n)); - } - return memtraceBase.xMalloc(n); -} -static void memtraceFree(void *p){ - if( p==0 ) return; - if( memtraceOut ){ - fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p)); - } - memtraceBase.xFree(p); -} -static void *memtraceRealloc(void *p, int n){ - if( p==0 ) return memtraceMalloc(n); - if( n==0 ){ - memtraceFree(p); - return 0; - } - if( memtraceOut ){ - fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n", - memtraceBase.xSize(p), memtraceBase.xRoundup(n)); + /* 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=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'I'; + hash_step(&cx, x, 9); + break; + } + case SQLITE_FLOAT: { + sqlite3_uint64 u; + int j; + unsigned char x[9]; + double r = sqlite3_column_double(pStmt,i); + memcpy(&u, &r, 8); + for(j=8; j>=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'F'; + hash_step(&cx,x,9); + break; + } + case SQLITE_TEXT: { + int n2 = sqlite3_column_bytes(pStmt, i); + const unsigned char *z2 = sqlite3_column_text(pStmt, i); + hash_step_vformat(&cx,"T%d:",n2); + hash_step(&cx, z2, n2); + break; + } + case SQLITE_BLOB: { + int n2 = sqlite3_column_bytes(pStmt, i); + const unsigned char *z2 = sqlite3_column_blob(pStmt, i); + hash_step_vformat(&cx,"B%d:",n2); + hash_step(&cx, z2, n2); + break; + } + } + } + } + sqlite3_finalize(pStmt); } - return memtraceBase.xRealloc(p, n); -} -static int memtraceSize(void *p){ - return memtraceBase.xSize(p); -} -static int memtraceRoundup(int n){ - return memtraceBase.xRoundup(n); -} -static int memtraceInit(void *p){ - return memtraceBase.xInit(p); -} -static void memtraceShutdown(void *p){ - memtraceBase.xShutdown(p); + hash_finish(&cx, zOut, 0); + sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT); } -/* The substitute memory allocator */ -static sqlite3_mem_methods ersaztMethods = { - memtraceMalloc, - memtraceFree, - memtraceRealloc, - memtraceSize, - memtraceRoundup, - memtraceInit, - memtraceShutdown, - 0 -}; -/* Begin tracing memory allocations to out. */ -int sqlite3MemTraceActivate(FILE *out){ - int rc = SQLITE_OK; - if( memtraceBase.xMalloc==0 ){ - rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase); - if( rc==SQLITE_OK ){ - rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods); - } - } - memtraceOut = out; - return rc; -} +#ifdef _WIN32 -/* Deactivate memory tracing */ -int sqlite3MemTraceDeactivate(void){ +#endif +int sqlite3_sha_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ int rc = SQLITE_OK; - if( memtraceBase.xMalloc!=0 ){ - rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase); - if( rc==SQLITE_OK ){ - memset(&memtraceBase, 0, sizeof(memtraceBase)); - } + static int one = 1; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + rc = sqlite3_create_function(db, "sha1", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, sha1Func, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha1b", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + (void*)&one, sha1Func, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha1_query", 1, + SQLITE_UTF8|SQLITE_DIRECTONLY, 0, + sha1QueryFunc, 0, 0); } - memtraceOut = 0; return rc; } -/************************* End ext/misc/memtrace.c ********************/ -/************************* Begin ext/misc/pcachetrace.c ******************/ +/************************* End ../ext/misc/sha1.c ********************/ +/************************* Begin ../ext/misc/uint.c ******************/ /* -** 2023-06-21 +** 2020-04-14 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -4918,180 +3511,93 @@ int sqlite3MemTraceDeactivate(void){ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** -************************************************************************* +****************************************************************************** ** -** This file implements an extension that uses the SQLITE_CONFIG_PCACHE2 -** mechanism to add a tracing layer on top of pluggable page cache of -** SQLite. If this extension is registered prior to sqlite3_initialize(), -** it will cause all page cache activities to be logged on standard output, -** or to some other FILE specified by the initializer. +** This SQLite extension implements the UINT collating sequence. ** -** This file needs to be compiled into the application that uses it. +** UINT works like BINARY for text, except that embedded strings +** of digits compare in numeric order. ** -** This extension is used to implement the --pcachetrace option of the -** command-line shell. +** * Leading zeros are handled properly, in the sense that +** they do not mess of the magnitude comparison of embedded +** strings of digits. "x00123y" is equal to "x123y". +** +** * Only unsigned integers are recognized. Plus and minus +** signs are ignored. Decimal points and exponential notation +** are ignored. +** +** * Embedded integers can be of arbitrary length. Comparison +** is *not* limited integers that can be expressed as a +** 64-bit machine integer. */ +/* #include "sqlite3ext.h" */ +SQLITE_EXTENSION_INIT1 #include #include -#include - -/* The original page cache routines */ -static sqlite3_pcache_methods2 pcacheBase; -static FILE *pcachetraceOut; +#include -/* Methods that trace pcache activity */ -static int pcachetraceInit(void *pArg){ - int nRes; - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p)\n", pArg); - } - nRes = pcacheBase.xInit(pArg); - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p) -> %d\n", pArg, nRes); +/* +** Compare text in lexicographic order, except strings of digits +** compare in numeric order. +*/ +static int uintCollFunc( + void *notUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + const unsigned char *zA = (const unsigned char*)pKey1; + const unsigned char *zB = (const unsigned char*)pKey2; + int i=0, j=0, x; + (void)notUsed; + while( i %p\n", - szPage, szExtra, bPurge, pRes); - } - return pRes; -} -static void pcachetraceCachesize(sqlite3_pcache *p, int nCachesize){ - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xCachesize(%p, %d)\n", p, nCachesize); - } - pcacheBase.xCachesize(p, nCachesize); -} -static int pcachetracePagecount(sqlite3_pcache *p){ - int nRes; - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p)\n", p); - } - nRes = pcacheBase.xPagecount(p); - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p) -> %d\n", p, nRes); - } - return nRes; -} -static sqlite3_pcache_page *pcachetraceFetch( - sqlite3_pcache *p, - unsigned key, - int crFg -){ - sqlite3_pcache_page *pRes; - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d)\n", p, key, crFg); - } - pRes = pcacheBase.xFetch(p, key, crFg); - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d) -> %p\n", - p, key, crFg, pRes); - } - return pRes; -} -static void pcachetraceUnpin( - sqlite3_pcache *p, - sqlite3_pcache_page *pPg, - int bDiscard -){ - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xUnpin(%p, %p, %d)\n", - p, pPg, bDiscard); - } - pcacheBase.xUnpin(p, pPg, bDiscard); -} -static void pcachetraceRekey( - sqlite3_pcache *p, - sqlite3_pcache_page *pPg, - unsigned oldKey, - unsigned newKey -){ - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xRekey(%p, %p, %u, %u)\n", - p, pPg, oldKey, newKey); - } - pcacheBase.xRekey(p, pPg, oldKey, newKey); -} -static void pcachetraceTruncate(sqlite3_pcache *p, unsigned n){ - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xTruncate(%p, %u)\n", p, n); - } - pcacheBase.xTruncate(p, n); -} -static void pcachetraceDestroy(sqlite3_pcache *p){ - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xDestroy(%p)\n", p); - } - pcacheBase.xDestroy(p); -} -static void pcachetraceShrink(sqlite3_pcache *p){ - if( pcachetraceOut ){ - fprintf(pcachetraceOut, "PCACHETRACE: xShrink(%p)\n", p); - } - pcacheBase.xShrink(p); + return (nKey1 - i) - (nKey2 - j); } -/* The substitute pcache methods */ -static sqlite3_pcache_methods2 ersaztPcacheMethods = { - 0, - 0, - pcachetraceInit, - pcachetraceShutdown, - pcachetraceCreate, - pcachetraceCachesize, - pcachetracePagecount, - pcachetraceFetch, - pcachetraceUnpin, - pcachetraceRekey, - pcachetraceTruncate, - pcachetraceDestroy, - pcachetraceShrink -}; - -/* Begin tracing memory allocations to out. */ -int sqlite3PcacheTraceActivate(FILE *out){ - int rc = SQLITE_OK; - if( pcacheBase.xFetch==0 ){ - rc = sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &pcacheBase); - if( rc==SQLITE_OK ){ - rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &ersaztPcacheMethods); - } - } - pcachetraceOut = out; - return rc; -} +#ifdef _WIN32 -/* Deactivate memory tracing */ -int sqlite3PcacheTraceDeactivate(void){ - int rc = SQLITE_OK; - if( pcacheBase.xFetch!=0 ){ - rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcacheBase); - if( rc==SQLITE_OK ){ - memset(&pcacheBase, 0, sizeof(pcacheBase)); - } - } - pcachetraceOut = 0; - return rc; +#endif +int sqlite3_uint_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc); } -/************************* End ext/misc/pcachetrace.c ********************/ -/************************* Begin ext/misc/shathree.c ******************/ +/************************* End ../ext/misc/uint.c ********************/ +/************************* Begin ../ext/misc/decimal.c ******************/ /* -** 2017-03-08 +** 2020-06-22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -5102,1270 +3608,903 @@ int sqlite3PcacheTraceDeactivate(void){ ** ****************************************************************************** ** -** This SQLite extension implements functions that compute SHA3 hashes -** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard. -** Three SQL functions are implemented: -** -** sha3(X,SIZE) -** sha3_agg(Y,SIZE) -** sha3_query(Z,SIZE) -** -** The sha3(X) function computes the SHA3 hash of the input X, or NULL if -** X is NULL. If inputs X is text, the UTF-8 rendering of that text is -** used to compute the hash. If X is a BLOB, then the binary data of the -** blob is used to compute the hash. If X is an integer or real number, -** then that number if converted into UTF-8 text and the hash is computed -** over the text. -** -** The sha3_agg(Y) function computes the SHA3 hash of all Y inputs. Since -** order is important for the hash, it is recommended that the Y expression -** by followed by an ORDER BY clause to guarantee that the inputs occur -** in the desired order. -** -** The sha3_query(Y) function evaluates all queries in the SQL statements of Y -** and returns a hash of their results. -** -** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm -** is used. If SIZE is included it must be one of the integers 224, 256, -** 384, or 512, to determine SHA3 hash variant that is computed. -** -** Because the sha3_agg() and sha3_query() functions compute a hash over -** multiple values, the values are encode to use include type information. -** -** In sha3_agg(), the sequence of bytes that gets hashed for each input -** Y depends on the datatype of Y: -** -** typeof(Y)='null' A single "N" is hashed. (One byte) -** -** typeof(Y)='integer' The data hash is the character "I" followed -** by an 8-byte big-endian binary of the -** 64-bit signed integer. (Nine bytes total.) -** -** typeof(Y)='real' The character "F" followed by an 8-byte -** big-ending binary of the double. (Nine -** bytes total.) -** -** typeof(Y)='text' The hash is over prefix "Tnnn:" followed -** by the UTF8 encoding of the text. The "nnn" -** in the prefix is the minimum-length decimal -** representation of the octet_length of the text. -** Notice the ":" at the end of the prefix, which -** is needed to separate the prefix from the -** content in cases where the content starts -** with a digit. -** -** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed -** by the binary content of the blob. The "nnn" -** in the prefix is the minimum-length decimal -** representation of the byte-length of the blob. -** -** According to the rules above, all of the following SELECT statements -** should return TRUE: -** -** SELECT sha3(1) = sha3('1'); -** -** SELECT sha3('hello') = sha3(x'68656c6c6f'); -** -** WITH a(x) AS (VALUES('xyzzy')) -** SELECT sha3_agg(x) = sha3('T5:xyzzy') FROM a; -** -** WITH a(x) AS (VALUES(x'010203')) -** SELECT sha3_agg(x) = sha3(x'42333a010203') FROM a; -** -** WITH a(x) AS (VALUES(0x123456)) -** SELECT sha3_agg(x) = sha3(x'490000000000123456') FROM a; -** -** WITH a(x) AS (VALUES(100.015625)) -** SELECT sha3_agg(x) = sha3(x'464059010000000000') FROM a; -** -** WITH a(x) AS (VALUES(NULL)) -** SELECT sha3_agg(x) = sha3('N') FROM a; -** -** -** In sha3_query(), individual column values are encoded as with -** sha3_agg(), but with the addition that a single "R" character is -** inserted at the start of each row. -** -** Note that sha3_agg() hashes rows for which Y is NULL. Add a FILTER -** clause if NULL rows should be excluded: +** Routines to implement arbitrary-precision decimal math. ** -** SELECT sha3_agg(x ORDER BY rowid) FILTER(WHERE x NOT NULL) FROM t1; +** The focus here is on simplicity and correctness, not performance. */ /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #include #include -#include +#include +#include -#ifndef SQLITE_AMALGAMATION -/* typedef sqlite3_uint64 u64; */ -#endif /* SQLITE_AMALGAMATION */ +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAMETER +# define UNUSED_PARAMETER(X) (void)(X) +#endif -/****************************************************************************** -** The Hash Engine -*/ -/* -** Macros to determine whether the machine is big or little endian, -** and whether or not that determination is run-time or compile-time. -** -** For best performance, an attempt is made to guess at the byte-order -** using C-preprocessor macros. If that is unsuccessful, or if -** -DSHA3_BYTEORDER=0 is set, then byte-order is determined -** at run-time. -*/ -#ifndef SHA3_BYTEORDER -# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__arm__) -# define SHA3_BYTEORDER 1234 -# elif defined(sparc) || defined(__ppc__) -# define SHA3_BYTEORDER 4321 -# else -# define SHA3_BYTEORDER 0 -# endif +#ifndef IsSpace +#define IsSpace(X) isspace((unsigned char)X) #endif +/* A decimal object */ +typedef struct Decimal Decimal; +struct Decimal { + char sign; /* 0 for positive, 1 for negative */ + char oom; /* True if an OOM is encountered */ + char isNull; /* True if holds a NULL rather than a number */ + char isInit; /* True upon initialization */ + int nDigit; /* Total number of digits */ + int nFrac; /* Number of digits to the right of the decimal point */ + signed char *a; /* Array of digits. Most significant first. */ +}; /* -** State structure for a SHA3 hash in progress +** Release memory held by a Decimal, but do not free the object itself. */ -typedef struct SHA3Context SHA3Context; -struct SHA3Context { - union { - u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ - unsigned char x[1600]; /* ... or 1600 bytes */ - } u; - unsigned nRate; /* Bytes of input accepted per Keccak iteration */ - unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ - unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ - unsigned iSize; /* 224, 256, 358, or 512 */ -}; +static void decimal_clear(Decimal *p){ + sqlite3_free(p->a); +} /* -** A single step of the Keccak mixing function for a 1600-bit state +** Destroy a Decimal object */ -static void KeccakF1600Step(SHA3Context *p){ - int i; - u64 b0, b1, b2, b3, b4; - u64 c0, c1, c2, c3, c4; - u64 d0, d1, d2, d3, d4; - static const u64 RC[] = { - 0x0000000000000001ULL, 0x0000000000008082ULL, - 0x800000000000808aULL, 0x8000000080008000ULL, - 0x000000000000808bULL, 0x0000000080000001ULL, - 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x000000000000008aULL, 0x0000000000000088ULL, - 0x0000000080008009ULL, 0x000000008000000aULL, - 0x000000008000808bULL, 0x800000000000008bULL, - 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, - 0x000000000000800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, - 0x0000000080000001ULL, 0x8000000080008008ULL - }; -# define a00 (p->u.s[0]) -# define a01 (p->u.s[1]) -# define a02 (p->u.s[2]) -# define a03 (p->u.s[3]) -# define a04 (p->u.s[4]) -# define a10 (p->u.s[5]) -# define a11 (p->u.s[6]) -# define a12 (p->u.s[7]) -# define a13 (p->u.s[8]) -# define a14 (p->u.s[9]) -# define a20 (p->u.s[10]) -# define a21 (p->u.s[11]) -# define a22 (p->u.s[12]) -# define a23 (p->u.s[13]) -# define a24 (p->u.s[14]) -# define a30 (p->u.s[15]) -# define a31 (p->u.s[16]) -# define a32 (p->u.s[17]) -# define a33 (p->u.s[18]) -# define a34 (p->u.s[19]) -# define a40 (p->u.s[20]) -# define a41 (p->u.s[21]) -# define a42 (p->u.s[22]) -# define a43 (p->u.s[23]) -# define a44 (p->u.s[24]) -# define ROL64(a,x) ((a<>(64-x))) +static void decimal_free(Decimal *p){ + if( p ){ + decimal_clear(p); + sqlite3_free(p); + } +} - for(i=0; i<24; i+=4){ - c0 = a00^a10^a20^a30^a40; - c1 = a01^a11^a21^a31^a41; - c2 = a02^a12^a22^a32^a42; - c3 = a03^a13^a23^a33^a43; - c4 = a04^a14^a24^a34^a44; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); +/* +** Allocate a new Decimal object initialized to the text in zIn[]. +** Return NULL if any kind of error occurs. +*/ +static Decimal *decimalNewFromText(const char *zIn, int n){ + Decimal *p = 0; + int i; + int iExp = 0; - b0 = (a00^d0); - b1 = ROL64((a11^d1), 44); - b2 = ROL64((a22^d2), 43); - b3 = ROL64((a33^d3), 21); - b4 = ROL64((a44^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i]; - a11 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a33 = b3 ^((~b4)& b0 ); - a44 = b4 ^((~b0)& b1 ); + p = sqlite3_malloc( sizeof(*p) ); + if( p==0 ) goto new_from_text_failed; + p->sign = 0; + p->oom = 0; + p->isInit = 1; + p->isNull = 0; + p->nDigit = 0; + p->nFrac = 0; + p->a = sqlite3_malloc64( n+1 ); + if( p->a==0 ) goto new_from_text_failed; + for(i=0; IsSpace(zIn[i]); i++){} + if( zIn[i]=='-' ){ + p->sign = 1; + i++; + }else if( zIn[i]=='+' ){ + i++; + } + while( i='0' && c<='9' ){ + p->a[p->nDigit++] = c - '0'; + }else if( c=='.' ){ + p->nFrac = p->nDigit + 1; + }else if( c=='e' || c=='E' ){ + int j = i+1; + int neg = 0; + if( j>=n ) break; + if( zIn[j]=='-' ){ + neg = 1; + j++; + }else if( zIn[j]=='+' ){ + j++; + } + while( j='0' && zIn[j]<='9' ){ + iExp = iExp*10 + zIn[j] - '0'; + } + j++; + } + if( neg ) iExp = -iExp; + break; + } + i++; + } + if( p->nFrac ){ + p->nFrac = p->nDigit - (p->nFrac - 1); + } + if( iExp>0 ){ + if( p->nFrac>0 ){ + if( iExp<=p->nFrac ){ + p->nFrac -= iExp; + iExp = 0; + }else{ + iExp -= p->nFrac; + p->nFrac = 0; + } + } + if( iExp>0 ){ + p->a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit + + (sqlite3_int64)iExp + 1 ); + if( p->a==0 ) goto new_from_text_failed; + memset(p->a+p->nDigit, 0, iExp); + p->nDigit += iExp; + } + }else if( iExp<0 ){ + int nExtra; + iExp = -iExp; + nExtra = p->nDigit - p->nFrac - 1; + if( nExtra ){ + if( nExtra>=iExp ){ + p->nFrac += iExp; + iExp = 0; + }else{ + iExp -= nExtra; + p->nFrac = p->nDigit - 1; + } + } + if( iExp>0 ){ + p->a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit + + (sqlite3_int64)iExp + 1 ); + if( p->a==0 ) goto new_from_text_failed; + memmove(p->a+iExp, p->a, p->nDigit); + memset(p->a, 0, iExp); + p->nDigit += iExp; + p->nFrac += iExp; + } + } + if( p->sign ){ + for(i=0; inDigit && p->a[i]==0; i++){} + if( i>=p->nDigit ) p->sign = 0; + } + return p; - b2 = ROL64((a20^d0), 3); - b3 = ROL64((a31^d1), 45); - b4 = ROL64((a42^d2), 61); - b0 = ROL64((a03^d3), 28); - b1 = ROL64((a14^d4), 20); - a20 = b0 ^((~b1)& b2 ); - a31 = b1 ^((~b2)& b3 ); - a42 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a14 = b4 ^((~b0)& b1 ); +new_from_text_failed: + if( p ){ + if( p->a ) sqlite3_free(p->a); + sqlite3_free(p); + } + return 0; +} - b4 = ROL64((a40^d0), 18); - b0 = ROL64((a01^d1), 1); - b1 = ROL64((a12^d2), 6); - b2 = ROL64((a23^d3), 25); - b3 = ROL64((a34^d4), 8); - a40 = b0 ^((~b1)& b2 ); - a01 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a23 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); +/* Forward reference */ +static Decimal *decimalFromDouble(double); - b1 = ROL64((a10^d0), 36); - b2 = ROL64((a21^d1), 10); - b3 = ROL64((a32^d2), 15); - b4 = ROL64((a43^d3), 56); - b0 = ROL64((a04^d4), 27); - a10 = b0 ^((~b1)& b2 ); - a21 = b1 ^((~b2)& b3 ); - a32 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a04 = b4 ^((~b0)& b1 ); +/* +** Allocate a new Decimal object from an sqlite3_value. Return a pointer +** to the new object, or NULL if there is an error. If the pCtx argument +** is not NULL, then errors are reported on it as well. +** +** If the pIn argument is SQLITE_TEXT or SQLITE_INTEGER, it is converted +** directly into a Decimal. For SQLITE_FLOAT or for SQLITE_BLOB of length +** 8 bytes, the resulting double value is expanded into its decimal equivalent. +** If pIn is NULL or if it is a BLOB that is not exactly 8 bytes in length, +** then NULL is returned. +*/ +static Decimal *decimal_new( + sqlite3_context *pCtx, /* Report error here, if not null */ + sqlite3_value *pIn, /* Construct the decimal object from this */ + int bTextOnly /* Always interpret pIn as text if true */ +){ + Decimal *p = 0; + int eType = sqlite3_value_type(pIn); + if( bTextOnly && (eType==SQLITE_FLOAT || eType==SQLITE_BLOB) ){ + eType = SQLITE_TEXT; + } + switch( eType ){ + case SQLITE_TEXT: + case SQLITE_INTEGER: { + const char *zIn = (const char*)sqlite3_value_text(pIn); + int n = sqlite3_value_bytes(pIn); + p = decimalNewFromText(zIn, n); + if( p==0 ) goto new_failed; + break; + } - b3 = ROL64((a30^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a02^d2), 62); - b1 = ROL64((a13^d3), 55); - b2 = ROL64((a24^d4), 39); - a30 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a02 = b2 ^((~b3)& b4 ); - a13 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); + case SQLITE_FLOAT: { + p = decimalFromDouble(sqlite3_value_double(pIn)); + break; + } - c0 = a00^a20^a40^a10^a30; - c1 = a11^a31^a01^a21^a41; - c2 = a22^a42^a12^a32^a02; - c3 = a33^a03^a23^a43^a13; - c4 = a44^a14^a34^a04^a24; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); + case SQLITE_BLOB: { + const unsigned char *x; + unsigned int i; + sqlite3_uint64 v = 0; + double r; - b0 = (a00^d0); - b1 = ROL64((a31^d1), 44); - b2 = ROL64((a12^d2), 43); - b3 = ROL64((a43^d3), 21); - b4 = ROL64((a24^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i+1]; - a31 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); + if( sqlite3_value_bytes(pIn)!=sizeof(r) ) break; + x = sqlite3_value_blob(pIn); + for(i=0; ioom ){ + sqlite3_result_error_nomem(pCtx); + return; + } + if( p->isNull ){ + sqlite3_result_null(pCtx); + return; + } + z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 ); + if( z==0 ){ + sqlite3_result_error_nomem(pCtx); + return; + } + i = 0; + if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){ + p->sign = 0; + } + if( p->sign ){ + z[0] = '-'; + i = 1; + } + n = p->nDigit - p->nFrac; + if( n<=0 ){ + z[i++] = '0'; + } + j = 0; + while( n>1 && p->a[j]==0 ){ + j++; + n--; + } + while( n>0 ){ + z[i++] = p->a[j] + '0'; + j++; + n--; + } + if( p->nFrac ){ + z[i++] = '.'; + do{ + z[i++] = p->a[j] + '0'; + j++; + }while( jnDigit ); + } + z[i] = 0; + sqlite3_result_text(pCtx, z, i, sqlite3_free); +} - b3 = ROL64((a10^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a22^d2), 62); - b1 = ROL64((a03^d3), 55); - b2 = ROL64((a34^d4), 39); - a10 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); +/* +** Make the given Decimal the result in an format similar to '%+#e'. +** In other words, show exponential notation with leading and trailing +** zeros omitted. +*/ +static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){ + char *z; /* The output buffer */ + int i; /* Loop counter */ + int nZero; /* Number of leading zeros */ + int nDigit; /* Number of digits not counting trailing zeros */ + int nFrac; /* Digits to the right of the decimal point */ + int exp; /* Exponent value */ + signed char zero; /* Zero value */ + signed char *a; /* Array of digits */ - c0 = a00^a40^a30^a20^a10; - c1 = a31^a21^a11^a01^a41; - c2 = a12^a02^a42^a32^a22; - c3 = a43^a33^a23^a13^a03; - c4 = a24^a14^a04^a44^a34; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); - - b0 = (a00^d0); - b1 = ROL64((a21^d1), 44); - b2 = ROL64((a42^d2), 43); - b3 = ROL64((a13^d3), 21); - b4 = ROL64((a34^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i+2]; - a21 = b1 ^((~b2)& b3 ); - a42 = b2 ^((~b3)& b4 ); - a13 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); - - b2 = ROL64((a30^d0), 3); - b3 = ROL64((a01^d1), 45); - b4 = ROL64((a22^d2), 61); - b0 = ROL64((a43^d3), 28); - b1 = ROL64((a14^d4), 20); - a30 = b0 ^((~b1)& b2 ); - a01 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a14 = b4 ^((~b0)& b1 ); - - b4 = ROL64((a10^d0), 18); - b0 = ROL64((a31^d1), 1); - b1 = ROL64((a02^d2), 6); - b2 = ROL64((a23^d3), 25); - b3 = ROL64((a44^d4), 8); - a10 = b0 ^((~b1)& b2 ); - a31 = b1 ^((~b2)& b3 ); - a02 = b2 ^((~b3)& b4 ); - a23 = b3 ^((~b4)& b0 ); - a44 = b4 ^((~b0)& b1 ); - - b1 = ROL64((a40^d0), 36); - b2 = ROL64((a11^d1), 10); - b3 = ROL64((a32^d2), 15); - b4 = ROL64((a03^d3), 56); - b0 = ROL64((a24^d4), 27); - a40 = b0 ^((~b1)& b2 ); - a11 = b1 ^((~b2)& b3 ); - a32 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); - - b3 = ROL64((a20^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a12^d2), 62); - b1 = ROL64((a33^d3), 55); - b2 = ROL64((a04^d4), 39); - a20 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a33 = b3 ^((~b4)& b0 ); - a04 = b4 ^((~b0)& b1 ); - - c0 = a00^a30^a10^a40^a20; - c1 = a21^a01^a31^a11^a41; - c2 = a42^a22^a02^a32^a12; - c3 = a13^a43^a23^a03^a33; - c4 = a34^a14^a44^a24^a04; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); - - b0 = (a00^d0); - b1 = ROL64((a01^d1), 44); - b2 = ROL64((a02^d2), 43); - b3 = ROL64((a03^d3), 21); - b4 = ROL64((a04^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i+3]; - a01 = b1 ^((~b2)& b3 ); - a02 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a04 = b4 ^((~b0)& b1 ); - - b2 = ROL64((a10^d0), 3); - b3 = ROL64((a11^d1), 45); - b4 = ROL64((a12^d2), 61); - b0 = ROL64((a13^d3), 28); - b1 = ROL64((a14^d4), 20); - a10 = b0 ^((~b1)& b2 ); - a11 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a13 = b3 ^((~b4)& b0 ); - a14 = b4 ^((~b0)& b1 ); - - b4 = ROL64((a20^d0), 18); - b0 = ROL64((a21^d1), 1); - b1 = ROL64((a22^d2), 6); - b2 = ROL64((a23^d3), 25); - b3 = ROL64((a24^d4), 8); - a20 = b0 ^((~b1)& b2 ); - a21 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a23 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); - - b1 = ROL64((a30^d0), 36); - b2 = ROL64((a31^d1), 10); - b3 = ROL64((a32^d2), 15); - b4 = ROL64((a33^d3), 56); - b0 = ROL64((a34^d4), 27); - a30 = b0 ^((~b1)& b2 ); - a31 = b1 ^((~b2)& b3 ); - a32 = b2 ^((~b3)& b4 ); - a33 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); - - b3 = ROL64((a40^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a42^d2), 62); - b1 = ROL64((a43^d3), 55); - b2 = ROL64((a44^d4), 39); - a40 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a42 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a44 = b4 ^((~b0)& b1 ); - } -} + if( p==0 || p->oom ){ + sqlite3_result_error_nomem(pCtx); + return; + } + if( p->isNull ){ + sqlite3_result_null(pCtx); + return; + } + for(nDigit=p->nDigit; nDigit>0 && p->a[nDigit-1]==0; nDigit--){} + for(nZero=0; nZeroa[nZero]==0; nZero++){} + nFrac = p->nFrac + (nDigit - p->nDigit); + nDigit -= nZero; + z = sqlite3_malloc64( (sqlite3_int64)nDigit+20 ); + if( z==0 ){ + sqlite3_result_error_nomem(pCtx); + return; + } + if( nDigit==0 ){ + zero = 0; + a = &zero; + nDigit = 1; + nFrac = 0; + }else{ + a = &p->a[nZero]; + } + if( p->sign && nDigit>0 ){ + z[0] = '-'; + }else{ + z[0] = '+'; + } + z[1] = a[0]+'0'; + z[2] = '.'; + if( nDigit==1 ){ + z[3] = '0'; + i = 4; + }else{ + for(i=1; iisNull==0 +** pB!=0 +** pB->isNull==0 */ -static void SHA3Init(SHA3Context *p, int iSize){ - memset(p, 0, sizeof(*p)); - p->iSize = iSize; - if( iSize>=128 && iSize<=512 ){ - p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; - }else{ - p->nRate = (1600 - 2*256)/8; +static int decimal_cmp(Decimal *pA, Decimal *pB){ + int nASig, nBSig, rc, n; + while( pA->nFrac>0 && pA->a[pA->nDigit-1]==0 ){ + pA->nDigit--; + pA->nFrac--; } -#if SHA3_BYTEORDER==1234 - /* Known to be little-endian at compile-time. No-op */ -#elif SHA3_BYTEORDER==4321 - p->ixMask = 7; /* Big-endian */ -#else - { - static unsigned int one = 1; - if( 1==*(unsigned char*)&one ){ - /* Little endian. No byte swapping. */ - p->ixMask = 0; - }else{ - /* Big endian. Byte swap. */ - p->ixMask = 7; - } + while( pB->nFrac>0 && pB->a[pB->nDigit-1]==0 ){ + pB->nDigit--; + pB->nFrac--; } -#endif -} - -/* -** Make consecutive calls to the SHA3Update function to add new content -** to the hash -*/ -static void SHA3Update( - SHA3Context *p, - const unsigned char *aData, - unsigned int nData -){ - unsigned int i = 0; - if( aData==0 ) return; -#if SHA3_BYTEORDER==1234 - if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ - for(; i+7u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; - p->nLoaded += 8; - if( p->nLoaded>=p->nRate ){ - KeccakF1600Step(p); - p->nLoaded = 0; - } - } + if( pA->sign!=pB->sign ){ + return pA->sign ? -1 : +1; } -#endif - for(; iu.x[p->nLoaded] ^= aData[i]; -#elif SHA3_BYTEORDER==4321 - p->u.x[p->nLoaded^0x07] ^= aData[i]; -#else - p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; -#endif - p->nLoaded++; - if( p->nLoaded==p->nRate ){ - KeccakF1600Step(p); - p->nLoaded = 0; - } + if( pA->sign ){ + Decimal *pTemp = pA; + pA = pB; + pB = pTemp; } -} - -/* -** After all content has been added, invoke SHA3Final() to compute -** the final hash. The function returns a pointer to the binary -** hash value. -*/ -static unsigned char *SHA3Final(SHA3Context *p){ - unsigned int i; - if( p->nLoaded==p->nRate-1 ){ - const unsigned char c1 = 0x86; - SHA3Update(p, &c1, 1); - }else{ - const unsigned char c2 = 0x06; - const unsigned char c3 = 0x80; - SHA3Update(p, &c2, 1); - p->nLoaded = p->nRate - 1; - SHA3Update(p, &c3, 1); + nASig = pA->nDigit - pA->nFrac; + nBSig = pB->nDigit - pB->nFrac; + if( nASig!=nBSig ){ + return nASig - nBSig; } - for(i=0; inRate; i++){ - p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; + n = pA->nDigit; + if( n>pB->nDigit ) n = pB->nDigit; + rc = memcmp(pA->a, pB->a, n); + if( rc==0 ){ + rc = pA->nDigit - pB->nDigit; } - return &p->u.x[p->nRate]; + return rc; } -/* End of the hashing logic -*****************************************************************************/ /* -** Implementation of the sha3(X,SIZE) function. +** SQL Function: decimal_cmp(X, Y) ** -** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default -** size is 256. If X is a BLOB, it is hashed as is. -** For all other non-NULL types of input, X is converted into a UTF-8 string -** and the string is hashed without the trailing 0x00 terminator. The hash -** of a NULL value is NULL. +** Return negative, zero, or positive if X is less then, equal to, or +** greater than Y. */ -static void sha3Func( +static void decimalCmpFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ - SHA3Context cx; - int eType = sqlite3_value_type(argv[0]); - int nByte = sqlite3_value_bytes(argv[0]); - int iSize; - if( argc==1 ){ - iSize = 256; - }else{ - iSize = sqlite3_value_int(argv[1]); - if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ - sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " - "384 512", -1); - return; - } - } - if( eType==SQLITE_NULL ) return; - SHA3Init(&cx, iSize); - if( eType==SQLITE_BLOB ){ - SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); - }else{ - SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); - } - sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); + Decimal *pA = 0, *pB = 0; + int rc; + + UNUSED_PARAMETER(argc); + pA = decimal_new(context, argv[0], 1); + if( pA==0 || pA->isNull ) goto cmp_done; + pB = decimal_new(context, argv[1], 1); + if( pB==0 || pB->isNull ) goto cmp_done; + rc = decimal_cmp(pA, pB); + if( rc<0 ) rc = -1; + else if( rc>0 ) rc = +1; + sqlite3_result_int(context, rc); +cmp_done: + decimal_free(pA); + decimal_free(pB); } -/* Compute a string using sqlite3_vsnprintf() with a maximum length -** of 50 bytes and add it to the hash. +/* +** Expand the Decimal so that it has a least nDigit digits and nFrac +** digits to the right of the decimal point. */ -static void sha3_step_vformat( - SHA3Context *p, /* Add content to this context */ - const char *zFormat, - ... -){ - va_list ap; - int n; - char zBuf[50]; - va_start(ap, zFormat); - sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); - va_end(ap); - n = (int)strlen(zBuf); - SHA3Update(p, (unsigned char*)zBuf, n); +static void decimal_expand(Decimal *p, int nDigit, int nFrac){ + int nAddSig; + int nAddFrac; + if( p==0 ) return; + nAddFrac = nFrac - p->nFrac; + nAddSig = (nDigit - p->nDigit) - nAddFrac; + if( nAddFrac==0 && nAddSig==0 ) return; + p->a = sqlite3_realloc64(p->a, nDigit+1); + if( p->a==0 ){ + p->oom = 1; + return; + } + if( nAddSig ){ + memmove(p->a+nAddSig, p->a, p->nDigit); + memset(p->a, 0, nAddSig); + p->nDigit += nAddSig; + } + if( nAddFrac ){ + memset(p->a+p->nDigit, 0, nAddFrac); + p->nDigit += nAddFrac; + p->nFrac += nAddFrac; + } } /* -** Update a SHA3Context using a single sqlite3_value. +** Add the value pB into pA. A := A + B. +** +** Both pA and pB might become denormalized by this routine. */ -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; +static void decimal_add(Decimal *pA, Decimal *pB){ + int nSig, nFrac, nDigit; + int i, rc; + if( pA==0 ){ + return; + } + if( pA->oom || pB==0 || pB->oom ){ + pA->oom = 1; + return; + } + if( pA->isNull || pB->isNull ){ + pA->isNull = 1; + return; + } + nSig = pA->nDigit - pA->nFrac; + if( nSig && pA->a[0]==0 ) nSig--; + if( nSignDigit-pB->nFrac ){ + nSig = pB->nDigit - pB->nFrac; + } + nFrac = pA->nFrac; + if( nFracnFrac ) nFrac = pB->nFrac; + nDigit = nSig + nFrac + 1; + decimal_expand(pA, nDigit, nFrac); + decimal_expand(pB, nDigit, nFrac); + if( pA->oom || pB->oom ){ + pA->oom = 1; + }else{ + if( pA->sign==pB->sign ){ + int carry = 0; + for(i=nDigit-1; i>=0; i--){ + int x = pA->a[i] + pB->a[i] + carry; + if( x>=10 ){ + carry = 1; + pA->a[i] = x - 10; + }else{ + carry = 0; + pA->a[i] = x; + } } - 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; + }else{ + signed char *aA, *aB; + int borrow = 0; + rc = memcmp(pA->a, pB->a, nDigit); + if( rc<0 ){ + aA = pB->a; + aB = pA->a; + pA->sign = !pA->sign; + }else{ + aA = pA->a; + aB = pB->a; + } + for(i=nDigit-1; i>=0; i--){ + int x = aA[i] - aB[i] - borrow; + if( x<0 ){ + pA->a[i] = x+10; + borrow = 1; + }else{ + pA->a[i] = x; + borrow = 0; + } } - x[0] = 'F'; - SHA3Update(p,x,9); - break; - } - case SQLITE_TEXT: { - int n2 = sqlite3_value_bytes(pVal); - const unsigned char *z2 = sqlite3_value_text(pVal); - sha3_step_vformat(p,"T%d:",n2); - SHA3Update(p, z2, n2); - break; - } - case SQLITE_BLOB: { - int n2 = sqlite3_value_bytes(pVal); - const unsigned char *z2 = sqlite3_value_blob(pVal); - sha3_step_vformat(p,"B%d:",n2); - SHA3Update(p, z2, n2); - break; } } } /* -** Implementation of the sha3_query(SQL,SIZE) function. -** -** This function compiles and runs the SQL statement(s) given in the -** argument. The results are hashed using a SIZE-bit SHA3. The default -** size is 256. -** -** The format of the byte stream that is hashed is summarized as follows: -** -** S: -** R -** N -** I -** F -** B: -** T: -** -** is the original SQL text for each statement run and is -** the size of that text. The SQL text is UTF-8. A single R character -** occurs before the start of each row. N means a NULL value. -** I mean an 8-byte little-endian integer . F is a floating point -** number with an 8-byte little-endian IEEE floating point value . -** B means blobs of bytes. T means text rendered as -** bytes of UTF-8. The and values are expressed as an ASCII -** text integers. +** Multiply A by B. A := A * B ** -** For each SQL statement in the X input, there is one S segment. Each -** S segment is followed by zero or more R segments, one for each row in the -** result set. After each R, there are one or more N, I, F, B, or T segments, -** one for each column in the result set. Segments are concatentated directly -** with no delimiters of any kind. +** All significant digits after the decimal point are retained. +** Trailing zeros after the decimal point are omitted as long as +** the number of digits after the decimal point is no less than +** either the number of digits in either input. */ -static void sha3QueryFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - const char *zSql = (const char*)sqlite3_value_text(argv[0]); - sqlite3_stmt *pStmt = 0; - int nCol; /* Number of columns in the result set */ - int i; /* Loop counter */ - int rc; - int n; - const char *z; - SHA3Context cx; - int iSize; +static void decimalMul(Decimal *pA, Decimal *pB){ + signed char *acc = 0; + int i, j, k; + int minFrac; - if( argc==1 ){ - iSize = 256; - }else{ - iSize = sqlite3_value_int(argv[1]); - if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ - sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " - "384 512", -1); - return; - } + if( pA==0 || pA->oom || pA->isNull + || pB==0 || pB->oom || pB->isNull + ){ + goto mul_end; } - if( zSql==0 ) return; - SHA3Init(&cx, iSize); - while( zSql[0] ){ - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); - if( rc ){ - char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", - zSql, sqlite3_errmsg(db)); - sqlite3_finalize(pStmt); - sqlite3_result_error(context, zMsg, -1); - sqlite3_free(zMsg); - return; - } - if( !sqlite3_stmt_readonly(pStmt) ){ - char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); - sqlite3_finalize(pStmt); - sqlite3_result_error(context, zMsg, -1); - sqlite3_free(zMsg); - return; + acc = sqlite3_malloc64( (sqlite3_int64)pA->nDigit + + (sqlite3_int64)pB->nDigit + 2 ); + if( acc==0 ){ + pA->oom = 1; + goto mul_end; + } + memset(acc, 0, pA->nDigit + pB->nDigit + 2); + minFrac = pA->nFrac; + if( pB->nFracnFrac; + for(i=pA->nDigit-1; i>=0; i--){ + signed char f = pA->a[i]; + int carry = 0, x; + for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){ + x = acc[k] + f*pB->a[j] + carry; + acc[k] = x%10; + carry = x/10; } - nCol = sqlite3_column_count(pStmt); - z = sqlite3_sql(pStmt); - if( z ){ - n = (int)strlen(z); - sha3_step_vformat(&cx,"S%d:",n); - SHA3Update(&cx,(unsigned char*)z,n); + x = acc[k] + carry; + acc[k] = x%10; + acc[k-1] += x/10; + } + sqlite3_free(pA->a); + pA->a = acc; + acc = 0; + pA->nDigit += pB->nDigit + 2; + pA->nFrac += pB->nFrac; + pA->sign ^= pB->sign; + while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){ + pA->nFrac--; + pA->nDigit--; + } + +mul_end: + sqlite3_free(acc); +} + +/* +** Create a new Decimal object that contains an integer power of 2. +*/ +static Decimal *decimalPow2(int N){ + Decimal *pA = 0; /* The result to be returned */ + Decimal *pX = 0; /* Multiplier */ + if( N<-20000 || N>20000 ) goto pow2_fault; + pA = decimalNewFromText("1.0", 3); + if( pA==0 || pA->oom ) goto pow2_fault; + if( N==0 ) return pA; + if( N>0 ){ + pX = decimalNewFromText("2.0", 3); + }else{ + N = -N; + pX = decimalNewFromText("0.5", 3); + } + if( pX==0 || pX->oom ) goto pow2_fault; + while( 1 /* Exit by break */ ){ + if( N & 1 ){ + decimalMul(pA, pX); + if( pA->oom ) goto pow2_fault; } + N >>= 1; + if( N==0 ) break; + decimalMul(pX, pX); + } + decimal_free(pX); + return pA; - /* Compute a hash over the result of the query */ - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - SHA3Update(&cx,(const unsigned char*)"R",1); - for(i=0; i>52; + m = a & ((((sqlite3_int64)1)<<52)-1); + if( e==0 ){ + m <<= 1; + }else{ + m |= ((sqlite3_int64)1)<<52; + } + while( e<1075 && m>0 && (m&1)==0 ){ + m >>= 1; + e++; + } + if( isNeg ) m = -m; + e = e - 1075; + if( e>971 ){ + return 0; /* A NaN or an Infinity */ } - sqlite3_finalize(pStmt); } - sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); + + /* At this point m is the integer significand and e is the exponent */ + sqlite3_snprintf(sizeof(zNum), zNum, "%lld", m); + pA = decimalNewFromText(zNum, (int)strlen(zNum)); + pX = decimalPow2(e); + decimalMul(pA, pX); + decimal_free(pX); + return pA; } /* -** xStep function for sha3_agg(). +** SQL Function: decimal(X) +** OR: decimal_exp(X) +** +** Convert input X into decimal and then back into text. +** +** If X is originally a float, then a full decimal expansion of that floating +** point value is done. Or if X is an 8-byte blob, it is interpreted +** as a float and similarly expanded. +** +** The decimal_exp(X) function returns the result in exponential notation. +** decimal(X) returns a complete decimal, without the e+NNN at the end. */ -static void sha3AggStep( +static void decimalFunc( 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; - } + Decimal *p = decimal_new(context, argv[0], 0); + UNUSED_PARAMETER(argc); + if( p ){ + if( sqlite3_user_data(context)!=0 ){ + decimal_result_sci(context, p); + }else{ + decimal_result(context, p); } - SHA3Init(p, sz); + decimal_free(p); } - sha3UpdateFromValue(p, argv[0]); } - /* -** xFinal function for sha3_agg(). +** Compare text in decimal order. */ -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 +static int decimalCollFunc( + void *notUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 ){ - 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); + const unsigned char *zA = (const unsigned char*)pKey1; + const unsigned char *zB = (const unsigned char*)pKey2; + Decimal *pA = decimalNewFromText((const char*)zA, nKey1); + Decimal *pB = decimalNewFromText((const char*)zB, nKey2); + int rc; + UNUSED_PARAMETER(notUsed); + if( pA==0 || pB==0 ){ + rc = 0; + }else{ + rc = decimal_cmp(pA, pB); } + decimal_free(pA); + decimal_free(pB); return rc; } -/************************* 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. +** SQL Function: decimal_add(X, Y) +** decimal_sub(X, Y) ** -** The sha1_query(Y) function evalutes all queries in the SQL statements of Y -** and returns a hash of their results. +** Return the sum or difference of X and Y. */ -/* #include "sqlite3ext.h" */ -SQLITE_EXTENSION_INIT1 -#include -#include -#include - -/****************************************************************************** -** 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, - ... +static void decimalAddFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - 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); + Decimal *pA = decimal_new(context, argv[0], 1); + Decimal *pB = decimal_new(context, argv[1], 1); + UNUSED_PARAMETER(argc); + decimal_add(pA, pB); + decimal_result(context, pA); + decimal_free(pA); + decimal_free(pB); } - - -/* 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 */ +static void decimalSubFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - 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; + Decimal *pA = decimal_new(context, argv[0], 1); + Decimal *pB = decimal_new(context, argv[1], 1); + UNUSED_PARAMETER(argc); + if( pB ){ + pB->sign = !pB->sign; + decimal_add(pA, pB); + decimal_result(context, pA); } + decimal_free(pA); + decimal_free(pB); } -/* End of the hashing logic -*****************************************************************************/ -/* -** Two SQL functions: sha1(X) and sha1b(X). -** -** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash -** of the argument X. If X is a BLOB, it is hashed as is. For all other -** types of input, X is converted into a UTF-8 string and the string -** is hashed without the trailing 0x00 terminator. The hash of a NULL -** value is NULL. +/* Aggregate function: decimal_sum(X) ** -** sha1b(X) is the same except that it returns a 20-byte BLOB containing -** the binary hash instead of a hexadecimal string. +** Works like sum() except that it uses decimal arithmetic for unlimited +** precision. */ -static void sha1Func( +static void decimalSumStep( 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 ){ - /* sha1b() - binary result */ - hash_finish(&cx, zOut, 1); - sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT); - }else{ - /* sha1() - hexadecimal text result */ - hash_finish(&cx, zOut, 0); - sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT); - } -} - -/* -** Implementation of the sha1_query(SQL) function. -** -** This function compiles and runs the SQL statement(s) given in the -** argument. The results are hashed using SHA1 and that hash is returned. -** -** The original SQL text is included as part of the hash. + Decimal *p; + Decimal *pArg; + UNUSED_PARAMETER(argc); + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( !p->isInit ){ + p->isInit = 1; + p->a = sqlite3_malloc(2); + if( p->a==0 ){ + p->oom = 1; + }else{ + p->a[0] = 0; + } + p->nDigit = 1; + p->nFrac = 0; + } + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pArg = decimal_new(context, argv[0], 1); + decimal_add(p, pArg); + decimal_free(pArg); +} +static void decimalSumInverse( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + Decimal *p; + Decimal *pArg; + UNUSED_PARAMETER(argc); + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pArg = decimal_new(context, argv[0], 1); + if( pArg ) pArg->sign = !pArg->sign; + decimal_add(p, pArg); + decimal_free(pArg); +} +static void decimalSumValue(sqlite3_context *context){ + Decimal *p = sqlite3_aggregate_context(context, 0); + if( p==0 ) return; + decimal_result(context, p); +} +static void decimalSumFinalize(sqlite3_context *context){ + Decimal *p = sqlite3_aggregate_context(context, 0); + if( p==0 ) return; + decimal_result(context, p); + decimal_clear(p); +} + +/* +** SQL Function: decimal_mul(X, Y) ** -** 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. +** Return the product of X and Y. */ -static void sha1QueryFunc( +static void decimalMulFunc( 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]; + Decimal *pA = decimal_new(context, argv[0], 1); + Decimal *pB = decimal_new(context, argv[1], 1); + UNUSED_PARAMETER(argc); + if( pA==0 || pA->oom || pA->isNull + || pB==0 || pB->oom || pB->isNull + ){ + goto mul_end; + } + decimalMul(pA, pB); + if( pA->oom ){ + goto mul_end; + } + decimal_result(context, pA); - 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); +mul_end: + decimal_free(pA); + decimal_free(pB); +} - /* 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=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'I'; - hash_step(&cx, x, 9); - break; - } - case SQLITE_FLOAT: { - sqlite3_uint64 u; - int j; - unsigned char x[9]; - double r = sqlite3_column_double(pStmt,i); - memcpy(&u, &r, 8); - for(j=8; j>=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'F'; - hash_step(&cx,x,9); - break; - } - case SQLITE_TEXT: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_text(pStmt, i); - hash_step_vformat(&cx,"T%d:",n2); - hash_step(&cx, z2, n2); - break; - } - case SQLITE_BLOB: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_blob(pStmt, i); - hash_step_vformat(&cx,"B%d:",n2); - hash_step(&cx, z2, n2); - break; - } - } - } - } - sqlite3_finalize(pStmt); +/* +** SQL Function: decimal_pow2(N) +** +** Return the N-th power of 2. N must be an integer. +*/ +static void decimalPow2Func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + UNUSED_PARAMETER(argc); + if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){ + Decimal *pA = decimalPow2(sqlite3_value_int(argv[0])); + decimal_result_sci(context, pA); + decimal_free(pA); } - hash_finish(&cx, zOut, 0); - sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT); } - #ifdef _WIN32 #endif -int sqlite3_sha_init( - sqlite3 *db, - char **pzErrMsg, +int sqlite3_decimal_init( + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; - static int one = 1; - SQLITE_EXTENSION_INIT2(pApi); + static const struct { + const char *zFuncName; + int nArg; + int iArg; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFunc[] = { + { "decimal", 1, 0, decimalFunc }, + { "decimal_exp", 1, 1, decimalFunc }, + { "decimal_cmp", 2, 0, decimalCmpFunc }, + { "decimal_add", 2, 0, decimalAddFunc }, + { "decimal_sub", 2, 0, decimalSubFunc }, + { "decimal_mul", 2, 0, decimalMulFunc }, + { "decimal_pow2", 1, 0, decimalPow2Func }, + }; + unsigned int i; (void)pzErrMsg; /* Unused parameter */ - rc = sqlite3_create_function(db, "sha1", 1, - SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, - 0, sha1Func, 0, 0); + + SQLITE_EXTENSION_INIT2(pApi); + + for(i=0; i<(int)(sizeof(aFunc)/sizeof(aFunc[0])) && rc==SQLITE_OK; i++){ + rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg, + SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, + aFunc[i].iArg ? db : 0, aFunc[i].xFunc, 0, 0); + } if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "sha1b", 1, - SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, - (void*)&one, sha1Func, 0, 0); + rc = sqlite3_create_window_function(db, "decimal_sum", 1, + SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0, + decimalSumStep, decimalSumFinalize, + decimalSumValue, decimalSumInverse, 0); } if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "sha1_query", 1, - SQLITE_UTF8|SQLITE_DIRECTONLY, 0, - sha1QueryFunc, 0, 0); + rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8, + 0, decimalCollFunc); } return rc; } -/************************* End ext/misc/sha1.c ********************/ -/************************* Begin ext/misc/uint.c ******************/ +/************************* End ../ext/misc/decimal.c ********************/ +#undef sqlite3_base_init +#define sqlite3_base_init sqlite3_base64_init +/************************* Begin ../ext/misc/base64.c ******************/ /* -** 2020-04-14 +** 2022-11-18 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -6374,1033 +4513,758 @@ int sqlite3_sha_init( ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** -****************************************************************************** -** -** This SQLite extension implements the UINT collating sequence. +************************************************************************* ** -** UINT works like BINARY for text, except that embedded strings -** of digits compare in numeric order. +** 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. ** -** * Leading zeros are handled properly, in the sense that -** they do not mess of the magnitude comparison of embedded -** strings of digits. "x00123y" is equal to "x123y". +** 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. ** -** * Only unsigned integers are recognized. Plus and minus -** signs are ignored. Decimal points and exponential notation -** are ignored. -** -** * Embedded integers can be of arbitrary length. Comparison -** is *not* limited integers that can be expressed as a -** 64-bit machine integer. -*/ -/* #include "sqlite3ext.h" */ -SQLITE_EXTENSION_INIT1 -#include -#include -#include - -/* -** Compare text in lexicographic order, except strings of digits -** compare in numeric order. -*/ -static int uintCollFunc( - void *notUsed, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 -){ - const unsigned char *zA = (const unsigned char*)pKey1; - const unsigned char *zB = (const unsigned char*)pKey2; - int i=0, j=0, x; - (void)notUsed; - while( i +** *Nix: gcc -O2 -shared -I$SQDIR -fPIC -o base64.so base64.c +** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR -o base64.dylib base64.c +** Win32: gcc -O2 -shared -I%SQDIR% -o base64.dll base64.c +** Win32: cl /Os -I%SQDIR% base64.c -link -dll -out:base64.dll */ -/* #include "sqlite3ext.h" */ -SQLITE_EXTENSION_INIT1 + #include -#include -#include -#include -/* Mark a function parameter as unused, to suppress nuisance compiler -** warnings. */ -#ifndef UNUSED_PARAMETER -# define UNUSED_PARAMETER(X) (void)(X) +/* #include "sqlite3ext.h" */ + +#ifndef deliberate_fall_through +/* Quiet some compilers about some of our intentional code. */ +# if GCC_VERSION>=7000000 +# define deliberate_fall_through __attribute__((fallthrough)); +# else +# define deliberate_fall_through +# endif #endif -#ifndef IsSpace -#define IsSpace(X) isspace((unsigned char)X) +SQLITE_EXTENSION_INIT1; + +#define PC 0x80 /* pad character */ +#define WS 0x81 /* whitespace */ +#define ND 0x82 /* Not above or digit-value */ +#define PAD_CHAR '=' + +#ifndef U8_TYPEDEF +/* typedef unsigned char u8; */ +#define U8_TYPEDEF #endif -/* A decimal object */ -typedef struct Decimal Decimal; -struct Decimal { - char sign; /* 0 for positive, 1 for negative */ - char oom; /* True if an OOM is encountered */ - char isNull; /* True if holds a NULL rather than a number */ - char isInit; /* True upon initialization */ - int nDigit; /* Total number of digits */ - int nFrac; /* Number of digits to the right of the decimal point */ - signed char *a; /* Array of digits. Most significant first. */ +/* Decoding table, ASCII (7-bit) value to base 64 digit value or other */ +static const u8 b64DigitValues[128] = { + /* HT LF VT FF CR */ + ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND, + /* US */ + ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, + /*sp + / */ + WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63, + /* 0 1 5 9 = */ + 52,53,54,55, 56,57,58,59, 60,61,ND,ND, ND,PC,ND,ND, + /* A O */ + ND, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + /* P Z */ + 15,16,17,18, 19,20,21,22, 23,24,25,ND, ND,ND,ND,ND, + /* a o */ + ND,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + /* p z */ + 41,42,43,44, 45,46,47,48, 49,50,51,ND, ND,ND,ND,ND }; -/* -** Release memory held by a Decimal, but do not free the object itself. -*/ -static void decimal_clear(Decimal *p){ - sqlite3_free(p->a); -} +static const char b64Numerals[64+1] += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -/* -** Destroy a Decimal object +#define BX_DV_PROTO(c) \ + ((((u8)(c))<0x80)? (u8)(b64DigitValues[(u8)(c)]) : 0x80) +#define IS_BX_DIGIT(bdp) (((u8)(bdp))<0x80) +#define IS_BX_WS(bdp) ((bdp)==WS) +#define IS_BX_PAD(bdp) ((bdp)==PC) +#define BX_NUMERAL(dv) (b64Numerals[(u8)(dv)]) +/* Width of base64 lines. Should be an integer multiple of 4. */ +#define B64_DARK_MAX 72 + +/* Encode a byte buffer into base64 text with linefeeds appended to limit +** encoded group lengths to B64_DARK_MAX or to terminate the last group. */ -static void decimal_free(Decimal *p){ - if( p ){ - decimal_clear(p); - sqlite3_free(p); +static char* toBase64( u8 *pIn, int nbIn, char *pOut ){ + int nCol = 0; + while( nbIn >= 3 ){ + /* Do the bit-shuffle, exploiting unsigned input to avoid masking. */ + pOut[0] = BX_NUMERAL(pIn[0]>>2); + pOut[1] = BX_NUMERAL(((pIn[0]<<4)|(pIn[1]>>4))&0x3f); + pOut[2] = BX_NUMERAL(((pIn[1]&0xf)<<2)|(pIn[2]>>6)); + pOut[3] = BX_NUMERAL(pIn[2]&0x3f); + pOut += 4; + nbIn -= 3; + pIn += 3; + if( (nCol += 4)>=B64_DARK_MAX || nbIn<=0 ){ + *pOut++ = '\n'; + nCol = 0; + } + } + if( nbIn > 0 ){ + signed char nco = nbIn+1; + int nbe; + unsigned long qv = *pIn++; + for( nbe=1; nbe<3; ++nbe ){ + qv <<= 8; + if( nbe=0; --nbe ){ + char ce = (nbe>= 6; + pOut[nbe] = ce; + } + pOut += 4; + *pOut++ = '\n'; } + *pOut = 0; + return pOut; } -/* -** Allocate a new Decimal object initialized to the text in zIn[]. -** Return NULL if any kind of error occurs. -*/ -static Decimal *decimalNewFromText(const char *zIn, int n){ - Decimal *p = 0; - int i; - int iExp = 0; +/* Skip over text which is not base64 numeral(s). */ +static char * skipNonB64( char *s, int nc ){ + char c; + while( nc-- > 0 && (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s; + return s; +} - p = sqlite3_malloc( sizeof(*p) ); - if( p==0 ) goto new_from_text_failed; - p->sign = 0; - p->oom = 0; - p->isInit = 1; - p->isNull = 0; - p->nDigit = 0; - p->nFrac = 0; - p->a = sqlite3_malloc64( n+1 ); - if( p->a==0 ) goto new_from_text_failed; - for(i=0; IsSpace(zIn[i]); i++){} - if( zIn[i]=='-' ){ - p->sign = 1; - i++; - }else if( zIn[i]=='+' ){ - i++; - } - while( i='0' && c<='9' ){ - p->a[p->nDigit++] = c - '0'; - }else if( c=='.' ){ - p->nFrac = p->nDigit + 1; - }else if( c=='e' || c=='E' ){ - int j = i+1; - int neg = 0; - if( j>=n ) break; - if( zIn[j]=='-' ){ - neg = 1; - j++; - }else if( zIn[j]=='+' ){ - j++; - } - while( j='0' && zIn[j]<='9' ){ - iExp = iExp*10 + zIn[j] - '0'; - } - j++; +/* Decode base64 text into a byte buffer. */ +static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){ + if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn; + while( ncIn>0 && *pIn!=PAD_CHAR ){ + static signed char nboi[] = { 0, 0, 1, 2, 3 }; + char *pUse = skipNonB64(pIn, ncIn); + unsigned long qv = 0L; + int nti, nbo, nac; + ncIn -= (pUse - pIn); + pIn = pUse; + nti = (ncIn>4)? 4 : ncIn; + ncIn -= nti; + nbo = nboi[nti]; + if( nbo==0 ) break; + for( nac=0; nac<4; ++nac ){ + char c = (nac>8) & 0xff; + deliberate_fall_through; /* FALLTHRU */ + case 1: + pOut[0] = (qv>>16) & 0xff; break; } - i++; - } - if( p->nFrac ){ - p->nFrac = p->nDigit - (p->nFrac - 1); + pOut += nbo; } - if( iExp>0 ){ - if( p->nFrac>0 ){ - if( iExp<=p->nFrac ){ - p->nFrac -= iExp; - iExp = 0; - }else{ - iExp -= p->nFrac; - p->nFrac = 0; + return pOut; +} + +/* This function does the work for the SQLite base64(x) UDF. */ +static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){ + sqlite3_int64 nb; + sqlite3_int64 nv = sqlite3_value_bytes(av[0]); + sqlite3_int64 nc; + int nvMax = sqlite3_limit(sqlite3_context_db_handle(context), + SQLITE_LIMIT_LENGTH, -1); + char *cBuf; + u8 *bBuf; + assert(na==1); + switch( sqlite3_value_type(av[0]) ){ + case SQLITE_BLOB: + nb = nv; + nc = 4*((nv+2)/3); /* quads needed */ + nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */ + if( nvMax < nc ){ + sqlite3_result_error(context, "blob expanded to base64 too big", -1); + return; + } + bBuf = (u8*)sqlite3_value_blob(av[0]); + if( !bBuf ){ + if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ + goto memFail; } + sqlite3_result_text(context,"",-1,SQLITE_STATIC); + break; } - if( iExp>0 ){ - p->a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit - + (sqlite3_int64)iExp + 1 ); - if( p->a==0 ) goto new_from_text_failed; - memset(p->a+p->nDigit, 0, iExp); - p->nDigit += iExp; + cBuf = sqlite3_malloc(nc); + if( !cBuf ) goto memFail; + nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf); + sqlite3_result_text(context, cBuf, nc, sqlite3_free); + break; + case SQLITE_TEXT: + nc = nv; + nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */ + if( nvMax < nb ){ + sqlite3_result_error(context, "blob from base64 may be too big", -1); + return; + }else if( nb<1 ){ + nb = 1; } - }else if( iExp<0 ){ - int nExtra; - iExp = -iExp; - nExtra = p->nDigit - p->nFrac - 1; - if( nExtra ){ - if( nExtra>=iExp ){ - p->nFrac += iExp; - iExp = 0; - }else{ - iExp -= nExtra; - p->nFrac = p->nDigit - 1; + cBuf = (char *)sqlite3_value_text(av[0]); + if( !cBuf ){ + if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ + goto memFail; } + sqlite3_result_zeroblob(context, 0); + break; } - if( iExp>0 ){ - p->a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit - + (sqlite3_int64)iExp + 1 ); - if( p->a==0 ) goto new_from_text_failed; - memmove(p->a+iExp, p->a, p->nDigit); - memset(p->a, 0, iExp); - p->nDigit += iExp; - p->nFrac += iExp; - } - } - if( p->sign ){ - for(i=0; inDigit && p->a[i]==0; i++){} - if( i>=p->nDigit ) p->sign = 0; - } - return p; - -new_from_text_failed: - if( p ){ - if( p->a ) sqlite3_free(p->a); - sqlite3_free(p); + bBuf = sqlite3_malloc(nb); + if( !bBuf ) goto memFail; + nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf); + sqlite3_result_blob(context, bBuf, nb, sqlite3_free); + break; + default: + sqlite3_result_error(context, "base64 accepts only blob or text", -1); + return; } - return 0; + return; + memFail: + sqlite3_result_error(context, "base64 OOM", -1); } -/* Forward reference */ -static Decimal *decimalFromDouble(double); - /* -** Allocate a new Decimal object from an sqlite3_value. Return a pointer -** to the new object, or NULL if there is an error. If the pCtx argument -** is not NULL, then errors are reported on it as well. -** -** If the pIn argument is SQLITE_TEXT or SQLITE_INTEGER, it is converted -** directly into a Decimal. For SQLITE_FLOAT or for SQLITE_BLOB of length -** 8 bytes, the resulting double value is expanded into its decimal equivalent. -** If pIn is NULL or if it is a BLOB that is not exactly 8 bytes in length, -** then NULL is returned. +** Establish linkage to running SQLite library. */ -static Decimal *decimal_new( - sqlite3_context *pCtx, /* Report error here, if not null */ - sqlite3_value *pIn, /* Construct the decimal object from this */ - int bTextOnly /* Always interpret pIn as text if true */ -){ - Decimal *p = 0; - int eType = sqlite3_value_type(pIn); - if( bTextOnly && (eType==SQLITE_FLOAT || eType==SQLITE_BLOB) ){ - eType = SQLITE_TEXT; - } - switch( eType ){ - case SQLITE_TEXT: - case SQLITE_INTEGER: { - const char *zIn = (const char*)sqlite3_value_text(pIn); - int n = sqlite3_value_bytes(pIn); - p = decimalNewFromText(zIn, n); - if( p==0 ) goto new_failed; - break; - } - - case SQLITE_FLOAT: { - p = decimalFromDouble(sqlite3_value_double(pIn)); - break; - } - - case SQLITE_BLOB: { - const unsigned char *x; - unsigned int i; - sqlite3_uint64 v = 0; - double r; - - if( sqlite3_value_bytes(pIn)!=sizeof(r) ) break; - x = sqlite3_value_blob(pIn); - for(i=0; ioom ){ - sqlite3_result_error_nomem(pCtx); - return; - } - if( p->isNull ){ - sqlite3_result_null(pCtx); - return; - } - z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 ); - if( z==0 ){ - sqlite3_result_error_nomem(pCtx); - return; - } - i = 0; - if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){ - p->sign = 0; - } - if( p->sign ){ - z[0] = '-'; - i = 1; - } - n = p->nDigit - p->nFrac; - if( n<=0 ){ - z[i++] = '0'; - } - j = 0; - while( n>1 && p->a[j]==0 ){ - j++; - n--; - } - while( n>0 ){ - z[i++] = p->a[j] + '0'; - j++; - n--; - } - if( p->nFrac ){ - z[i++] = '.'; - do{ - z[i++] = p->a[j] + '0'; - j++; - }while( jnDigit ); - } - z[i] = 0; - sqlite3_result_text(pCtx, z, i, sqlite3_free); -} - -/* -** Round a decimal value to N significant digits. N must be positive. -*/ -static void decimal_round(Decimal *p, int N){ - int i; - int nZero; - if( N<1 ) return; - for(nZero=0; nZeronDigit && p->a[nZero]==0; nZero++){} - N += nZero; - if( p->nDigit<=N ) return; - if( p->a[N]>4 ){ - p->a[N-1]++; - for(i=N-1; i>0 && p->a[i]>9; i--){ - p->a[i] = 0; - p->a[i-1]++; - } - if( p->a[0]>9 ){ - p->a[0] = 1; - p->nFrac--; - } - } - memset(&p->a[N], 0, p->nDigit - N); -} - -/* -** Make the given Decimal the result in an format similar to '%+#e'. -** In other words, show exponential notation with leading and trailing -** zeros omitted. -*/ -static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p, int N){ - char *z; /* The output buffer */ - int i; /* Loop counter */ - int nZero; /* Number of leading zeros */ - int nDigit; /* Number of digits not counting trailing zeros */ - int nFrac; /* Digits to the right of the decimal point */ - int exp; /* Exponent value */ - signed char zero; /* Zero value */ - signed char *a; /* Array of digits */ - - if( p==0 || p->oom ){ - sqlite3_result_error_nomem(pCtx); - return; - } - if( p->isNull ){ - sqlite3_result_null(pCtx); - return; - } - if( N<1 ) N = 0; - for(nDigit=p->nDigit; nDigit>N && p->a[nDigit-1]==0; nDigit--){} - for(nZero=0; nZeroa[nZero]==0; nZero++){} - nFrac = p->nFrac + (nDigit - p->nDigit); - nDigit -= nZero; - z = sqlite3_malloc64( (sqlite3_int64)nDigit+20 ); - if( z==0 ){ - sqlite3_result_error_nomem(pCtx); - return; - } - if( nDigit==0 ){ - zero = 0; - a = &zero; - nDigit = 1; - nFrac = 0; - }else{ - a = &p->a[nZero]; - } - if( p->sign && nDigit>0 ){ - z[0] = '-'; - }else{ - z[0] = '+'; - } - z[1] = a[0]+'0'; - z[2] = '.'; - if( nDigit==1 ){ - z[3] = '0'; - i = 4; - }else{ - for(i=1; iisNull==0 -** pB!=0 -** pB->isNull==0 -*/ -static int decimal_cmp(Decimal *pA, Decimal *pB){ - int nASig, nBSig, rc, n; - while( pA->nFrac>0 && pA->a[pA->nDigit-1]==0 ){ - pA->nDigit--; - pA->nFrac--; - } - while( pB->nFrac>0 && pB->a[pB->nDigit-1]==0 ){ - pB->nDigit--; - pB->nFrac--; - } - if( pA->sign!=pB->sign ){ - return pA->sign ? -1 : +1; - } - if( pA->sign ){ - Decimal *pTemp = pA; - pA = pB; - pB = pTemp; - } - nASig = pA->nDigit - pA->nFrac; - nBSig = pB->nDigit - pB->nFrac; - if( nASig!=nBSig ){ - return nASig - nBSig; - } - n = pA->nDigit; - if( n>pB->nDigit ) n = pB->nDigit; - rc = memcmp(pA->a, pB->a, n); - if( rc==0 ){ - rc = pA->nDigit - pB->nDigit; - } - return rc; -} +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This is a utility for converting binary to base85 or vice-versa. +** It can be built as a standalone program or an SQLite3 extension. +** +** Much like base64 representations, base85 can be sent through a +** sane USASCII channel unmolested. It also plays nicely in CSV or +** written as TCL brace-enclosed literals or SQL string literals. +** It is not suited for unmodified use in XML-like documents. +** +** The encoding used resembles Ascii85, but was devised by the author +** (Larry Brasfield) before Mozilla, Adobe, ZMODEM or other Ascii85 +** variant sources existed, in the 1984 timeframe on a VAX mainframe. +** Further, this is an independent implementation of a base85 system. +** Hence, the author has rightfully put this into the public domain. +** +** Base85 numerals are taken from the set of 7-bit USASCII codes, +** excluding control characters and Space ! " ' ( ) { | } ~ Del +** in code order representing digit values 0 to 84 (base 10.) +** +** Groups of 4 bytes, interpreted as big-endian 32-bit values, +** are represented as 5-digit base85 numbers with MS to LS digit +** order. Groups of 1-3 bytes are represented with 2-4 digits, +** still big-endian but 8-24 bit values. (Using big-endian yields +** the simplest transition to byte groups smaller than 4 bytes. +** These byte groups can also be considered base-256 numbers.) +** Groups of 0 bytes are represented with 0 digits and vice-versa. +** No pad characters are used; Encoded base85 numeral sequence +** (aka "group") length maps 1-to-1 to the decoded binary length. +** +** Any character not in the base85 numeral set delimits groups. +** When base85 is streamed or stored in containers of indefinite +** size, newline is used to separate it into sub-sequences of no +** more than 80 digits so that fgets() can be used to read it. +** +** Length limitations are not imposed except that the runtime +** SQLite string or blob length limits are respected. Otherwise, +** any length binary sequence can be represented and recovered. +** Base85 sequences can be concatenated by separating them with +** a non-base85 character; the conversion to binary will then +** be the concatenation of the represented binary sequences. -/* -** SQL Function: decimal_cmp(X, Y) +** The standalone program either converts base85 on stdin to create +** a binary file or converts a binary file to base85 on stdout. +** Read or make it blurt its help for invocation details. ** -** Return negative, zero, or positive if X is less then, equal to, or -** greater than Y. +** The SQLite3 extension creates a function, base85(x), which will +** either convert text base85 to a blob or a blob to text base85 +** and return the result (or throw an error for other types.) +** Unless built with OMIT_BASE85_CHECKER defined, it also creates a +** function, is_base85(t), which returns 1 iff the text t contains +** nothing other than base85 numerals and whitespace, or 0 otherwise. +** +** To build the extension: +** Set shell variable SQDIR= +** and variable OPTS to -DOMIT_BASE85_CHECKER if is_base85() unwanted. +** *Nix: gcc -O2 -shared -I$SQDIR $OPTS -fPIC -o base85.so base85.c +** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR $OPTS -o base85.dylib base85.c +** Win32: gcc -O2 -shared -I%SQDIR% %OPTS% -o base85.dll base85.c +** Win32: cl /Os -I%SQDIR% %OPTS% base85.c -link -dll -out:base85.dll +** +** To build the standalone program, define PP symbol BASE85_STANDALONE. Eg. +** *Nix or OSX: gcc -O2 -DBASE85_STANDALONE base85.c -o base85 +** Win32: gcc -O2 -DBASE85_STANDALONE -o base85.exe base85.c +** Win32: cl /Os /MD -DBASE85_STANDALONE base85.c */ -static void decimalCmpFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Decimal *pA = 0, *pB = 0; - int rc; - - UNUSED_PARAMETER(argc); - pA = decimal_new(context, argv[0], 1); - if( pA==0 || pA->isNull ) goto cmp_done; - pB = decimal_new(context, argv[1], 1); - if( pB==0 || pB->isNull ) goto cmp_done; - rc = decimal_cmp(pA, pB); - if( rc<0 ) rc = -1; - else if( rc>0 ) rc = +1; - sqlite3_result_int(context, rc); -cmp_done: - decimal_free(pA); - decimal_free(pB); -} -/* -** Expand the Decimal so that it has a least nDigit digits and nFrac -** digits to the right of the decimal point. -*/ -static void decimal_expand(Decimal *p, int nDigit, int nFrac){ - int nAddSig; - int nAddFrac; - if( p==0 ) return; - nAddFrac = nFrac - p->nFrac; - nAddSig = (nDigit - p->nDigit) - nAddFrac; - if( nAddFrac==0 && nAddSig==0 ) return; - p->a = sqlite3_realloc64(p->a, nDigit+1); - if( p->a==0 ){ - p->oom = 1; - return; - } - if( nAddSig ){ - memmove(p->a+nAddSig, p->a, p->nDigit); - memset(p->a, 0, nAddSig); - p->nDigit += nAddSig; - } - if( nAddFrac ){ - memset(p->a+p->nDigit, 0, nAddFrac); - p->nDigit += nAddFrac; - p->nFrac += nAddFrac; - } +#include +#include +#include +#include +#ifndef OMIT_BASE85_CHECKER +# include +#endif + +#ifndef BASE85_STANDALONE + +/* # include "sqlite3ext.h" */ + +SQLITE_EXTENSION_INIT1; + +#else + +# ifdef _WIN32 +# include +# include +# else +# define setmode(fd,m) +# endif + +static char *zHelp = + "Usage: base85 \n" + " is either -r to read or -w to write ,\n" + " content to be converted to/from base85 on stdout/stdin.\n" + " names a binary file to be rendered or created.\n" + " Or, the name '-' refers to the stdin or stdout stream.\n" + ; + +static void sayHelp(){ + printf("%s", zHelp); } +#endif -/* -** Add the value pB into pA. A := A + B. -** -** Both pA and pB might become denormalized by this routine. -*/ -static void decimal_add(Decimal *pA, Decimal *pB){ - int nSig, nFrac, nDigit; - int i, rc; - if( pA==0 ){ - return; - } - if( pA->oom || pB==0 || pB->oom ){ - pA->oom = 1; - return; - } - if( pA->isNull || pB->isNull ){ - pA->isNull = 1; - return; - } - nSig = pA->nDigit - pA->nFrac; - if( nSig && pA->a[0]==0 ) nSig--; - if( nSignDigit-pB->nFrac ){ - nSig = pB->nDigit - pB->nFrac; - } - nFrac = pA->nFrac; - if( nFracnFrac ) nFrac = pB->nFrac; - nDigit = nSig + nFrac + 1; - decimal_expand(pA, nDigit, nFrac); - decimal_expand(pB, nDigit, nFrac); - if( pA->oom || pB->oom ){ - pA->oom = 1; - }else{ - if( pA->sign==pB->sign ){ - int carry = 0; - for(i=nDigit-1; i>=0; i--){ - int x = pA->a[i] + pB->a[i] + carry; - if( x>=10 ){ - carry = 1; - pA->a[i] = x - 10; - }else{ - carry = 0; - pA->a[i] = x; - } - } - }else{ - signed char *aA, *aB; - int borrow = 0; - rc = memcmp(pA->a, pB->a, nDigit); - if( rc<0 ){ - aA = pB->a; - aB = pA->a; - pA->sign = !pA->sign; - }else{ - aA = pA->a; - aB = pB->a; - } - for(i=nDigit-1; i>=0; i--){ - int x = aA[i] - aB[i] - borrow; - if( x<0 ){ - pA->a[i] = x+10; - borrow = 1; - }else{ - pA->a[i] = x; - borrow = 0; - } - } - } - } +#ifndef U8_TYPEDEF +/* typedef unsigned char u8; */ +#define U8_TYPEDEF +#endif + +/* Classify c according to interval within USASCII set w.r.t. base85 + * Values of 1 and 3 are base85 numerals. Values of 0, 2, or 4 are not. + */ +#define B85_CLASS( c ) (((c)>='#')+((c)>'&')+((c)>='*')+((c)>'z')) + +/* Provide digitValue to b85Numeral offset as a function of above class. */ +static u8 b85_cOffset[] = { 0, '#', 0, '*'-4, 0 }; +#define B85_DNOS( c ) b85_cOffset[B85_CLASS(c)] + +/* Say whether c is a base85 numeral. */ +#define IS_B85( c ) (B85_CLASS(c) & 1) + +#if 0 /* Not used, */ +static u8 base85DigitValue( char c ){ + u8 dv = (u8)(c - '#'); + if( dv>87 ) return 0xff; + return (dv > 3)? dv-3 : dv; } +#endif -/* -** Multiply A by B. A := A * B -** -** All significant digits after the decimal point are retained. -** Trailing zeros after the decimal point are omitted as long as -** the number of digits after the decimal point is no less than -** either the number of digits in either input. -*/ -static void decimalMul(Decimal *pA, Decimal *pB){ - signed char *acc = 0; - int i, j, k; - int minFrac; +/* Width of base64 lines. Should be an integer multiple of 5. */ +#define B85_DARK_MAX 80 - if( pA==0 || pA->oom || pA->isNull - || pB==0 || pB->oom || pB->isNull - ){ - goto mul_end; - } - acc = sqlite3_malloc64( (sqlite3_int64)pA->nDigit + - (sqlite3_int64)pB->nDigit + 2 ); - if( acc==0 ){ - pA->oom = 1; - goto mul_end; - } - memset(acc, 0, pA->nDigit + pB->nDigit + 2); - minFrac = pA->nFrac; - if( pB->nFracnFrac; - for(i=pA->nDigit-1; i>=0; i--){ - signed char f = pA->a[i]; - int carry = 0, x; - for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){ - x = acc[k] + f*pB->a[j] + carry; - acc[k] = x%10; - carry = x/10; - } - x = acc[k] + carry; - acc[k] = x%10; - acc[k-1] += x/10; - } - sqlite3_free(pA->a); - pA->a = acc; - acc = 0; - pA->nDigit += pB->nDigit + 2; - pA->nFrac += pB->nFrac; - pA->sign ^= pB->sign; - while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){ - pA->nFrac--; - pA->nDigit--; - } -mul_end: - sqlite3_free(acc); +static char * skipNonB85( char *s, int nc ){ + char c; + while( nc-- > 0 && (c = *s) && !IS_B85(c) ) ++s; + return s; } -/* -** Create a new Decimal object that contains an integer power of 2. -*/ -static Decimal *decimalPow2(int N){ - Decimal *pA = 0; /* The result to be returned */ - Decimal *pX = 0; /* Multiplier */ - if( N<-20000 || N>20000 ) goto pow2_fault; - pA = decimalNewFromText("1.0", 3); - if( pA==0 || pA->oom ) goto pow2_fault; - if( N==0 ) return pA; - if( N>0 ){ - pX = decimalNewFromText("2.0", 3); - }else{ - N = -N; - pX = decimalNewFromText("0.5", 3); - } - if( pX==0 || pX->oom ) goto pow2_fault; - while( 1 /* Exit by break */ ){ - if( N & 1 ){ - decimalMul(pA, pX); - if( pA->oom ) goto pow2_fault; - } - N >>= 1; - if( N==0 ) break; - decimalMul(pX, pX); - } - decimal_free(pX); - return pA; +/* Convert small integer, known to be in 0..84 inclusive, to base85 numeral. + * Do not use the macro form with argument expression having a side-effect.*/ +#if 0 +static char base85Numeral( u8 b ){ + return (b < 4)? (char)(b + '#') : (char)(b - 4 + '*'); +} +#else +# define base85Numeral( dn )\ + ((char)(((dn) < 4)? (char)((dn) + '#') : (char)((dn) - 4 + '*'))) +#endif -pow2_fault: - decimal_free(pA); - decimal_free(pX); - return 0; +static char *putcs(char *pc, char *s){ + char c; + while( (c = *s++)!=0 ) *pc++ = c; + return pc; } -/* -** Use an IEEE754 binary64 ("double") to generate a new Decimal object. +/* Encode a byte buffer into base85 text. If pSep!=0, it's a C string +** to be appended to encoded groups to limit their length to B85_DARK_MAX +** or to terminate the last group (to aid concatenation.) */ -static Decimal *decimalFromDouble(double r){ - sqlite3_int64 m, a; - int e; - int isNeg; - Decimal *pA; - Decimal *pX; - char zNum[100]; - if( r<0.0 ){ - isNeg = 1; - r = -r; - }else{ - isNeg = 0; - } - memcpy(&a,&r,sizeof(a)); - if( a==0 || a==(sqlite3_int64)0x8000000000000000LL){ - e = 0; - m = 0; - }else{ - e = a>>52; - m = a & ((((sqlite3_int64)1)<<52)-1); - if( e==0 ){ - m <<= 1; - }else{ - m |= ((sqlite3_int64)1)<<52; +static char* toBase85( u8 *pIn, int nbIn, char *pOut, char *pSep ){ + int nCol = 0; + while( nbIn >= 4 ){ + int nco = 5; + unsigned long qbv = (((unsigned long)pIn[0])<<24) | + (pIn[1]<<16) | (pIn[2]<<8) | pIn[3]; + while( nco > 0 ){ + unsigned nqv = (unsigned)(qbv/85UL); + unsigned char dv = qbv - 85UL*nqv; + qbv = nqv; + pOut[--nco] = base85Numeral(dv); } - while( e<1075 && m>0 && (m&1)==0 ){ - m >>= 1; - e++; + nbIn -= 4; + pIn += 4; + pOut += 5; + if( pSep && (nCol += 5)>=B85_DARK_MAX ){ + pOut = putcs(pOut, pSep); + nCol = 0; } - if( isNeg ) m = -m; - e = e - 1075; - if( e>971 ){ - return 0; /* A NaN or an Infinity */ + } + if( nbIn > 0 ){ + int nco = nbIn + 1; + unsigned long qv = *pIn++; + int nbe = 1; + while( nbe++ < nbIn ){ + qv = (qv<<8) | *pIn++; + } + nCol += nco; + while( nco > 0 ){ + u8 dv = (u8)(qv % 85); + qv /= 85; + pOut[--nco] = base85Numeral(dv); } + pOut += (nbIn+1); } - - /* At this point m is the integer significand and e is the exponent */ - sqlite3_snprintf(sizeof(zNum), zNum, "%lld", m); - pA = decimalNewFromText(zNum, (int)strlen(zNum)); - pX = decimalPow2(e); - decimalMul(pA, pX); - decimal_free(pX); - return pA; + if( pSep && nCol>0 ) pOut = putcs(pOut, pSep); + *pOut = 0; + return pOut; } -/* -** SQL Function: decimal(X) -** OR: decimal_exp(X) -** -** Convert input X into decimal and then back into text. -** -** If X is originally a float, then a full decimal expansion of that floating -** point value is done. Or if X is an 8-byte blob, it is interpreted -** as a float and similarly expanded. -** -** The decimal_exp(X) function returns the result in exponential notation. -** decimal(X) returns a complete decimal, without the e+NNN at the end. -*/ -static void decimalFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Decimal *p = decimal_new(context, argv[0], 0); - int N; - if( argc==2 ){ - N = sqlite3_value_int(argv[1]); - if( N>0 ) decimal_round(p, N); - }else{ - N = 0; - } - if( p ){ - if( sqlite3_user_data(context)!=0 ){ - decimal_result_sci(context, p, N); - }else{ - decimal_result(context, p); +/* Decode base85 text into a byte buffer. */ +static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){ + if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn; + while( ncIn>0 ){ + static signed char nboi[] = { 0, 0, 1, 2, 3, 4 }; + char *pUse = skipNonB85(pIn, ncIn); + unsigned long qv = 0L; + int nti, nbo; + ncIn -= (pUse - pIn); + pIn = pUse; + nti = (ncIn>5)? 5 : ncIn; + nbo = nboi[nti]; + if( nbo==0 ) break; + while( nti>0 ){ + char c = *pIn++; + u8 cdo = B85_DNOS(c); + --ncIn; + if( cdo==0 ) break; + qv = 85 * qv + (c - cdo); + --nti; + } + nbo -= nti; /* Adjust for early (non-digit) end of group. */ + switch( nbo ){ + case 4: + *pOut++ = (qv >> 24)&0xff; + /* FALLTHRU */ + case 3: + *pOut++ = (qv >> 16)&0xff; + /* FALLTHRU */ + case 2: + *pOut++ = (qv >> 8)&0xff; + /* FALLTHRU */ + case 1: + *pOut++ = qv&0xff; + /* FALLTHRU */ + case 0: + break; } - decimal_free(p); } + return pOut; } -/* -** Compare text in decimal order. -*/ -static int decimalCollFunc( - void *notUsed, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 -){ - const unsigned char *zA = (const unsigned char*)pKey1; - const unsigned char *zB = (const unsigned char*)pKey2; - Decimal *pA = decimalNewFromText((const char*)zA, nKey1); - Decimal *pB = decimalNewFromText((const char*)zB, nKey2); - int rc; - UNUSED_PARAMETER(notUsed); - if( pA==0 || pB==0 ){ - rc = 0; - }else{ - rc = decimal_cmp(pA, pB); +#ifndef OMIT_BASE85_CHECKER +/* Say whether input char sequence is all (base85 and/or whitespace).*/ +static int allBase85( char *p, int len ){ + char c; + while( len-- > 0 && (c = *p++) != 0 ){ + if( !IS_B85(c) && !isspace(c) ) return 0; } - decimal_free(pA); - decimal_free(pB); - return rc; + return 1; } +#endif +#ifndef BASE85_STANDALONE -/* -** SQL Function: decimal_add(X, Y) -** decimal_sub(X, Y) -** -** Return the sum or difference of X and Y. -*/ -static void decimalAddFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Decimal *pA = decimal_new(context, argv[0], 1); - Decimal *pB = decimal_new(context, argv[1], 1); - UNUSED_PARAMETER(argc); - decimal_add(pA, pB); - decimal_result(context, pA); - decimal_free(pA); - decimal_free(pB); -} -static void decimalSubFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Decimal *pA = decimal_new(context, argv[0], 1); - Decimal *pB = decimal_new(context, argv[1], 1); - UNUSED_PARAMETER(argc); - if( pB ){ - pB->sign = !pB->sign; - decimal_add(pA, pB); - decimal_result(context, pA); - } - decimal_free(pA); - decimal_free(pB); -} - -/* Aggregate function: decimal_sum(X) -** -** Works like sum() except that it uses decimal arithmetic for unlimited -** precision. -*/ -static void decimalSumStep( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Decimal *p; - Decimal *pArg; - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - if( p==0 ) return; - if( !p->isInit ){ - p->isInit = 1; - p->a = sqlite3_malloc(2); - if( p->a==0 ){ - p->oom = 1; - }else{ - p->a[0] = 0; +# ifndef OMIT_BASE85_CHECKER +/* This function does the work for the SQLite is_base85(t) UDF. */ +static void is_base85(sqlite3_context *context, int na, sqlite3_value *av[]){ + assert(na==1); + switch( sqlite3_value_type(av[0]) ){ + case SQLITE_TEXT: + { + int rv = allBase85( (char *)sqlite3_value_text(av[0]), + sqlite3_value_bytes(av[0]) ); + sqlite3_result_int(context, rv); } - p->nDigit = 1; - p->nFrac = 0; + break; + case SQLITE_NULL: + sqlite3_result_null(context); + break; + default: + sqlite3_result_error(context, "is_base85 accepts only text or NULL", -1); + return; } - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pArg = decimal_new(context, argv[0], 1); - decimal_add(p, pArg); - decimal_free(pArg); -} -static void decimalSumInverse( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Decimal *p; - Decimal *pArg; - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - if( p==0 ) return; - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pArg = decimal_new(context, argv[0], 1); - if( pArg ) pArg->sign = !pArg->sign; - decimal_add(p, pArg); - decimal_free(pArg); -} -static void decimalSumValue(sqlite3_context *context){ - Decimal *p = sqlite3_aggregate_context(context, 0); - if( p==0 ) return; - decimal_result(context, p); -} -static void decimalSumFinalize(sqlite3_context *context){ - Decimal *p = sqlite3_aggregate_context(context, 0); - if( p==0 ) return; - decimal_result(context, p); - decimal_clear(p); } +# endif -/* -** SQL Function: decimal_mul(X, Y) -** -** Return the product of X and Y. -*/ -static void decimalMulFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Decimal *pA = decimal_new(context, argv[0], 1); - Decimal *pB = decimal_new(context, argv[1], 1); - UNUSED_PARAMETER(argc); - if( pA==0 || pA->oom || pA->isNull - || pB==0 || pB->oom || pB->isNull - ){ - goto mul_end; - } - decimalMul(pA, pB); - if( pA->oom ){ - goto mul_end; +/* This function does the work for the SQLite base85(x) UDF. */ +static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){ + sqlite3_int64 nb, nc, nv = sqlite3_value_bytes(av[0]); + int nvMax = sqlite3_limit(sqlite3_context_db_handle(context), + SQLITE_LIMIT_LENGTH, -1); + char *cBuf; + u8 *bBuf; + assert(na==1); + switch( sqlite3_value_type(av[0]) ){ + case SQLITE_BLOB: + nb = nv; + /* ulongs tail newlines tailenc+nul*/ + nc = 5*(nv/4) + nv%4 + nv/64+1 + 2; + if( nvMax < nc ){ + sqlite3_result_error(context, "blob expanded to base85 too big", -1); + return; + } + bBuf = (u8*)sqlite3_value_blob(av[0]); + if( !bBuf ){ + if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ + goto memFail; + } + sqlite3_result_text(context,"",-1,SQLITE_STATIC); + break; + } + cBuf = sqlite3_malloc(nc); + if( !cBuf ) goto memFail; + nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf); + sqlite3_result_text(context, cBuf, nc, sqlite3_free); + break; + case SQLITE_TEXT: + nc = nv; + nb = 4*(nv/5) + nv%5; /* may overestimate */ + if( nvMax < nb ){ + sqlite3_result_error(context, "blob from base85 may be too big", -1); + return; + }else if( nb<1 ){ + nb = 1; + } + cBuf = (char *)sqlite3_value_text(av[0]); + if( !cBuf ){ + if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ + goto memFail; + } + sqlite3_result_zeroblob(context, 0); + break; + } + bBuf = sqlite3_malloc(nb); + if( !bBuf ) goto memFail; + nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf); + sqlite3_result_blob(context, bBuf, nb, sqlite3_free); + break; + default: + sqlite3_result_error(context, "base85 accepts only blob or text.", -1); + return; } - decimal_result(context, pA); - -mul_end: - decimal_free(pA); - decimal_free(pB); + return; + memFail: + sqlite3_result_error(context, "base85 OOM", -1); } /* -** SQL Function: decimal_pow2(N) -** -** Return the N-th power of 2. N must be an integer. +** Establish linkage to running SQLite library. */ -static void decimalPow2Func( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){ - Decimal *pA = decimalPow2(sqlite3_value_int(argv[0])); - decimal_result_sci(context, pA, 0); - decimal_free(pA); - } -} - +#ifndef SQLITE_SHELL_EXTFUNCS #ifdef _WIN32 #endif -int sqlite3_decimal_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - int rc = SQLITE_OK; - static const struct { - const char *zFuncName; - int nArg; - int iArg; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aFunc[] = { - { "decimal", 1, 0, decimalFunc }, - { "decimal", 2, 0, decimalFunc }, - { "decimal_exp", 1, 1, decimalFunc }, - { "decimal_exp", 2, 1, decimalFunc }, - { "decimal_cmp", 2, 0, decimalCmpFunc }, - { "decimal_add", 2, 0, decimalAddFunc }, - { "decimal_sub", 2, 0, decimalSubFunc }, - { "decimal_mul", 2, 0, decimalMulFunc }, - { "decimal_pow2", 1, 0, decimalPow2Func }, - }; - unsigned int i; - (void)pzErrMsg; /* Unused parameter */ - +int sqlite3_base_init +#else +static int sqlite3_base85_init +#endif +(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){ SQLITE_EXTENSION_INIT2(pApi); + (void)pzErr; +# ifndef OMIT_BASE85_CHECKER + { + int rc = sqlite3_create_function + (db, "is_base85", 1, + SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_UTF8, + 0, is_base85, 0, 0); + if( rc!=SQLITE_OK ) return rc; + } +# endif + return sqlite3_create_function + (db, "base85", 1, + SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8, + 0, base85, 0, 0); +} - for(i=0; i<(int)(sizeof(aFunc)/sizeof(aFunc[0])) && rc==SQLITE_OK; i++){ - rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg, - SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, - aFunc[i].iArg ? db : 0, aFunc[i].xFunc, 0, 0); +/* +** Define some macros to allow this extension to be built into the shell +** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This +** allows shell.c, as distributed, to have this extension built in. +*/ +# define BASE85_INIT(db) sqlite3_base85_init(db, 0, 0) +# define BASE85_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */ + +#else /* standalone program */ + +int main(int na, char *av[]){ + int cin; + int rc = 0; + u8 bBuf[4*(B85_DARK_MAX/5)]; + char cBuf[5*(sizeof(bBuf)/4)+2]; + size_t nio; +# ifndef OMIT_BASE85_CHECKER + int b85Clean = 1; +# endif + char rw; + FILE *fb = 0, *foc = 0; + char fmode[3] = "xb"; + if( na < 3 || av[1][0]!='-' || (rw = av[1][1])==0 || (rw!='r' && rw!='w') ){ + sayHelp(); + return 0; } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_window_function(db, "decimal_sum", 1, - SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0, - decimalSumStep, decimalSumFinalize, - decimalSumValue, decimalSumInverse, 0); + fmode[0] = rw; + if( av[2][0]=='-' && av[2][1]==0 ){ + switch( rw ){ + case 'r': + fb = stdin; + setmode(fileno(stdin), O_BINARY); + break; + case 'w': + fb = stdout; + setmode(fileno(stdout), O_BINARY); + break; + } + }else{ + fb = fopen(av[2], fmode); + foc = fb; } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8, - 0, decimalCollFunc); + if( !fb ){ + fprintf(stderr, "Cannot open %s for %c\n", av[2], rw); + rc = 1; + }else{ + switch( rw ){ + case 'r': + while( (nio = fread( bBuf, 1, sizeof(bBuf), fb))>0 ){ + toBase85( bBuf, (int)nio, cBuf, 0 ); + fprintf(stdout, "%s\n", cBuf); + } + break; + case 'w': + while( 0 != fgets(cBuf, sizeof(cBuf), stdin) ){ + int nc = strlen(cBuf); + size_t nbo = fromBase85( cBuf, nc, bBuf ) - bBuf; + if( 1 != fwrite(bBuf, nbo, 1, fb) ) rc = 1; +# ifndef OMIT_BASE85_CHECKER + b85Clean &= allBase85( cBuf, nc ); +# endif + } + break; + default: + sayHelp(); + rc = 1; + } + if( foc ) fclose(foc); + } +# ifndef OMIT_BASE85_CHECKER + if( !b85Clean ){ + fprintf(stderr, "Base85 input had non-base85 dark or control content.\n"); } +# endif return rc; } -/************************* End ext/misc/decimal.c ********************/ -#undef sqlite3_base_init -#define sqlite3_base_init sqlite3_base64_init -/************************* Begin ext/misc/base64.c ******************/ +#endif + +/************************* End ../ext/misc/base85.c ********************/ +/************************* Begin ../ext/misc/ieee754.c ******************/ /* -** 2022-11-18 +** 2013-04-17 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -7409,758 +5273,328 @@ 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 SQLite extension implements functions for the exact display +** and input of IEEE754 Binary64 floating-point numbers. ** -** 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. +** ieee754(X) +** ieee754(Y,Z) ** -** 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. +** In the first form, the value X should be a floating-point number. +** The function will return a string of the form 'ieee754(Y,Z)' where +** Y and Z are integers such that X==Y*pow(2,Z). ** -** 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. +** In the second form, Y and Z are integers which are the mantissa and +** base-2 exponent of a new floating point number. The function returns +** a floating-point value equal to Y*pow(2,Z). ** -** 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. +** Examples: ** -** This code relies on UTF-8 encoding only with respect to the -** meaning of the first 128 (7-bit) codes matching that of USASCII. -** It will fail miserably if somehow made to try to convert EBCDIC. -** Because it is table-driven, it could be enhanced to handle that, -** but the world and SQLite have moved on from that anachronism. +** ieee754(2.0) -> 'ieee754(2,0)' +** ieee754(45.25) -> 'ieee754(181,-2)' +** ieee754(2, 0) -> 2.0 +** ieee754(181, -2) -> 45.25 +** +** Two additional functions break apart the one-argument ieee754() +** result into separate integer values: +** +** ieee754_mantissa(45.25) -> 181 +** ieee754_exponent(45.25) -> -2 +** +** These functions convert binary64 numbers into blobs and back again. +** +** ieee754_from_blob(x'3ff0000000000000') -> 1.0 +** ieee754_to_blob(1.0) -> x'3ff0000000000000' +** +** In all single-argument functions, if the argument is an 8-byte blob +** then that blob is interpreted as a big-endian binary64 value. +** +** +** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES +** ----------------------------------------------- +** +** This extension in combination with the separate 'decimal' extension +** can be used to compute the exact decimal representation of binary64 +** values. To begin, first compute a table of exponent values: +** +** CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT); +** WITH RECURSIVE c(x,v) AS ( +** VALUES(0,'1') +** UNION ALL +** SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971 +** ) INSERT INTO pow2(x,v) SELECT x, v FROM c; +** WITH RECURSIVE c(x,v) AS ( +** VALUES(-1,'0.5') +** UNION ALL +** SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075 +** ) INSERT INTO pow2(x,v) SELECT x, v FROM c; +** +** Then, to compute the exact decimal representation of a floating +** point value (the value 47.49 is used in the example) do: +** +** WITH c(n) AS (VALUES(47.49)) +** ---------------^^^^^---- Replace with whatever you want +** SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v) +** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n); +** +** Here is a query to show various boundry values for the binary64 +** number format: +** +** WITH c(name,bin) AS (VALUES +** ('minimum positive value', x'0000000000000001'), +** ('maximum subnormal value', x'000fffffffffffff'), +** ('minimum positive normal value', x'0010000000000000'), +** ('maximum value', x'7fefffffffffffff')) +** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v) +** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin); ** -** To build the extension: -** Set shell variable SQDIR= -** *Nix: gcc -O2 -shared -I$SQDIR -fPIC -o base64.so base64.c -** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR -o base64.dylib base64.c -** Win32: gcc -O2 -shared -I%SQDIR% -o base64.dll base64.c -** Win32: cl /Os -I%SQDIR% base64.c -link -dll -out:base64.dll */ - -#include - /* #include "sqlite3ext.h" */ +SQLITE_EXTENSION_INIT1 +#include +#include -#ifndef deliberate_fall_through -/* Quiet some compilers about some of our intentional code. */ -# if GCC_VERSION>=7000000 -# define deliberate_fall_through __attribute__((fallthrough)); -# else -# define deliberate_fall_through -# endif -#endif - -SQLITE_EXTENSION_INIT1; - -#define PC 0x80 /* pad character */ -#define WS 0x81 /* whitespace */ -#define ND 0x82 /* Not above or digit-value */ -#define PAD_CHAR '=' - -#ifndef U8_TYPEDEF -/* typedef unsigned char u8; */ -#define U8_TYPEDEF +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAMETER +# define UNUSED_PARAMETER(X) (void)(X) #endif -/* Decoding table, ASCII (7-bit) value to base 64 digit value or other */ -static const u8 b64DigitValues[128] = { - /* HT LF VT FF CR */ - ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND, - /* US */ - ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, - /*sp + / */ - WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63, - /* 0 1 5 9 = */ - 52,53,54,55, 56,57,58,59, 60,61,ND,ND, ND,PC,ND,ND, - /* A O */ - ND, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, - /* P Z */ - 15,16,17,18, 19,20,21,22, 23,24,25,ND, ND,ND,ND,ND, - /* a o */ - ND,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, - /* p z */ - 41,42,43,44, 45,46,47,48, 49,50,51,ND, ND,ND,ND,ND -}; - -static const char b64Numerals[64+1] -= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -#define BX_DV_PROTO(c) \ - ((((u8)(c))<0x80)? (u8)(b64DigitValues[(u8)(c)]) : 0x80) -#define IS_BX_DIGIT(bdp) (((u8)(bdp))<0x80) -#define IS_BX_WS(bdp) ((bdp)==WS) -#define IS_BX_PAD(bdp) ((bdp)==PC) -#define BX_NUMERAL(dv) (b64Numerals[(u8)(dv)]) -/* Width of base64 lines. Should be an integer multiple of 4. */ -#define B64_DARK_MAX 72 - -/* Encode a byte buffer into base64 text with linefeeds appended to limit -** encoded group lengths to B64_DARK_MAX or to terminate the last group. +/* +** Implementation of the ieee754() function */ -static char* toBase64( u8 *pIn, int nbIn, char *pOut ){ - int nCol = 0; - while( nbIn >= 3 ){ - /* Do the bit-shuffle, exploiting unsigned input to avoid masking. */ - pOut[0] = BX_NUMERAL(pIn[0]>>2); - pOut[1] = BX_NUMERAL(((pIn[0]<<4)|(pIn[1]>>4))&0x3f); - pOut[2] = BX_NUMERAL(((pIn[1]&0xf)<<2)|(pIn[2]>>6)); - pOut[3] = BX_NUMERAL(pIn[2]&0x3f); - pOut += 4; - nbIn -= 3; - pIn += 3; - if( (nCol += 4)>=B64_DARK_MAX || nbIn<=0 ){ - *pOut++ = '\n'; - nCol = 0; +static void ieee754func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + if( argc==1 ){ + sqlite3_int64 m, a; + double r; + int e; + int isNeg; + char zResult[100]; + assert( sizeof(m)==sizeof(r) ); + if( sqlite3_value_type(argv[0])==SQLITE_BLOB + && sqlite3_value_bytes(argv[0])==sizeof(r) + ){ + const unsigned char *x = sqlite3_value_blob(argv[0]); + unsigned int i; + sqlite3_uint64 v = 0; + for(i=0; i 0 ){ - signed char nco = nbIn+1; - int nbe; - unsigned long qv = *pIn++; - for( nbe=1; nbe<3; ++nbe ){ - qv <<= 8; - if( nbe=0; --nbe ){ - char ce = (nbe>= 6; - pOut[nbe] = ce; + memcpy(&a,&r,sizeof(a)); + if( a==0 ){ + e = 0; + m = 0; + }else if( a==(sqlite3_int64)0x8000000000000000LL ){ + e = -1996; + m = -1; + }else{ + e = a>>52; + m = a & ((((sqlite3_int64)1)<<52)-1); + if( e==0 ){ + m <<= 1; + }else{ + m |= ((sqlite3_int64)1)<<52; + } + while( e<1075 && m>0 && (m&1)==0 ){ + m >>= 1; + e++; + } + if( isNeg ) m = -m; } - pOut += 4; - *pOut++ = '\n'; - } - *pOut = 0; - return pOut; -} - -/* Skip over text which is not base64 numeral(s). */ -static char * skipNonB64( char *s, int nc ){ - char c; - while( nc-- > 0 && (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s; - return s; -} - -/* Decode base64 text into a byte buffer. */ -static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){ - if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn; - while( ncIn>0 && *pIn!=PAD_CHAR ){ - static signed char nboi[] = { 0, 0, 1, 2, 3 }; - char *pUse = skipNonB64(pIn, ncIn); - unsigned long qv = 0L; - int nti, nbo, nac; - ncIn -= (pUse - pIn); - pIn = pUse; - nti = (ncIn>4)? 4 : ncIn; - ncIn -= nti; - nbo = nboi[nti]; - if( nbo==0 ) break; - for( nac=0; nac<4; ++nac ){ - char c = (nac>8) & 0xff; - deliberate_fall_through; /* FALLTHRU */ - case 1: - pOut[0] = (qv>>16) & 0xff; - break; + }else{ + sqlite3_int64 m, e, a; + double r; + int isNeg = 0; + m = sqlite3_value_int64(argv[0]); + e = sqlite3_value_int64(argv[1]); + + /* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */ + if( e>10000 ){ + e = 10000; + }else if( e<-10000 ){ + e = -10000; } - pOut += nbo; - } - return pOut; -} -/* This function does the work for the SQLite base64(x) UDF. */ -static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){ - sqlite3_int64 nb; - sqlite3_int64 nv = sqlite3_value_bytes(av[0]); - sqlite3_int64 nc; - int nvMax = sqlite3_limit(sqlite3_context_db_handle(context), - SQLITE_LIMIT_LENGTH, -1); - char *cBuf; - u8 *bBuf; - assert(na==1); - switch( sqlite3_value_type(av[0]) ){ - case SQLITE_BLOB: - nb = nv; - nc = 4*((nv+2)/3); /* quads needed */ - nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */ - if( nvMax < nc ){ - sqlite3_result_error(context, "blob expanded to base64 too big", -1); + if( m<0 ){ + isNeg = 1; + m = -m; + if( m<0 ) return; + }else if( m==0 && e>-1000 && e<1000 ){ + sqlite3_result_double(context, 0.0); return; } - bBuf = (u8*)sqlite3_value_blob(av[0]); - if( !bBuf ){ - if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ - goto memFail; - } - sqlite3_result_text(context,"",-1,SQLITE_STATIC); - break; + while( (m>>32)&0xffe00000 ){ + m >>= 1; + e++; } - cBuf = sqlite3_malloc(nc); - if( !cBuf ) goto memFail; - nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf); - sqlite3_result_text(context, cBuf, nc, sqlite3_free); - break; - case SQLITE_TEXT: - nc = nv; - nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */ - if( nvMax < nb ){ - sqlite3_result_error(context, "blob from base64 may be too big", -1); - return; - }else if( nb<1 ){ - nb = 1; + while( m!=0 && ((m>>32)&0xfff00000)==0 ){ + m <<= 1; + e--; } - cBuf = (char *)sqlite3_value_text(av[0]); - if( !cBuf ){ - if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ - goto memFail; + e += 1075; + if( e<=0 ){ + /* Subnormal */ + if( 1-e >= 64 ){ + m = 0; + }else{ + m >>= 1-e; } - sqlite3_result_zeroblob(context, 0); - break; + e = 0; + }else if( e>0x7ff ){ + e = 0x7ff; } - bBuf = sqlite3_malloc(nb); - if( !bBuf ) goto memFail; - nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf); - sqlite3_result_blob(context, bBuf, nb, sqlite3_free); - break; - default: - sqlite3_result_error(context, "base64 accepts only blob or text", -1); - return; + a = m & ((((sqlite3_int64)1)<<52)-1); + a |= e<<52; + if( isNeg ) a |= ((sqlite3_uint64)1)<<63; + memcpy(&r, &a, sizeof(r)); + sqlite3_result_double(context, r); } - return; - memFail: - sqlite3_result_error(context, "base64 OOM", -1); } /* -** Establish linkage to running SQLite library. +** Functions to convert between blobs and floats. */ -#ifndef SQLITE_SHELL_EXTFUNCS -#ifdef _WIN32 - -#endif -int sqlite3_base_init -#else -static int sqlite3_base64_init -#endif -(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){ - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErr; - return sqlite3_create_function - (db, "base64", 1, - SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8, - 0, base64, 0, 0); +static void ieee754func_from_blob( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + UNUSED_PARAMETER(argc); + if( sqlite3_value_type(argv[0])==SQLITE_BLOB + && sqlite3_value_bytes(argv[0])==sizeof(double) + ){ + double r; + const unsigned char *x = sqlite3_value_blob(argv[0]); + unsigned int i; + sqlite3_uint64 v = 0; + for(i=0; i>= 8; + } + sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT); + } } /* -** Define some macros to allow this extension to be built into the shell -** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This -** allows shell.c, as distributed, to have this extension built in. -*/ -#define BASE64_INIT(db) sqlite3_base64_init(db, 0, 0) -#define BASE64_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */ - -/************************* End ext/misc/base64.c ********************/ -#undef sqlite3_base_init -#define sqlite3_base_init sqlite3_base85_init -#define OMIT_BASE85_CHECKER -/************************* Begin ext/misc/base85.c ******************/ -/* -** 2022-11-16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This is a utility for converting binary to base85 or vice-versa. -** It can be built as a standalone program or an SQLite3 extension. +** SQL Function: ieee754_inc(r,N) ** -** Much like base64 representations, base85 can be sent through a -** sane USASCII channel unmolested. It also plays nicely in CSV or -** written as TCL brace-enclosed literals or SQL string literals. -** It is not suited for unmodified use in XML-like documents. +** Move the floating point value r by N quantums and return the new +** values. ** -** The encoding used resembles Ascii85, but was devised by the author -** (Larry Brasfield) before Mozilla, Adobe, ZMODEM or other Ascii85 -** variant sources existed, in the 1984 timeframe on a VAX mainframe. -** Further, this is an independent implementation of a base85 system. -** Hence, the author has rightfully put this into the public domain. +** Behind the scenes: this routine merely casts r into a 64-bit unsigned +** integer, adds N, then casts the value back into float. ** -** Base85 numerals are taken from the set of 7-bit USASCII codes, -** excluding control characters and Space ! " ' ( ) { | } ~ Del -** in code order representing digit values 0 to 84 (base 10.) +** Example: To find the smallest positive number: ** -** Groups of 4 bytes, interpreted as big-endian 32-bit values, -** are represented as 5-digit base85 numbers with MS to LS digit -** order. Groups of 1-3 bytes are represented with 2-4 digits, -** still big-endian but 8-24 bit values. (Using big-endian yields -** the simplest transition to byte groups smaller than 4 bytes. -** These byte groups can also be considered base-256 numbers.) -** Groups of 0 bytes are represented with 0 digits and vice-versa. -** No pad characters are used; Encoded base85 numeral sequence -** (aka "group") length maps 1-to-1 to the decoded binary length. -** -** Any character not in the base85 numeral set delimits groups. -** When base85 is streamed or stored in containers of indefinite -** size, newline is used to separate it into sub-sequences of no -** more than 80 digits so that fgets() can be used to read it. -** -** Length limitations are not imposed except that the runtime -** SQLite string or blob length limits are respected. Otherwise, -** any length binary sequence can be represented and recovered. -** Base85 sequences can be concatenated by separating them with -** a non-base85 character; the conversion to binary will then -** be the concatenation of the represented binary sequences. - -** The standalone program either converts base85 on stdin to create -** a binary file or converts a binary file to base85 on stdout. -** Read or make it blurt its help for invocation details. -** -** The SQLite3 extension creates a function, base85(x), which will -** either convert text base85 to a blob or a blob to text base85 -** and return the result (or throw an error for other types.) -** Unless built with OMIT_BASE85_CHECKER defined, it also creates a -** function, is_base85(t), which returns 1 iff the text t contains -** nothing other than base85 numerals and whitespace, or 0 otherwise. -** -** To build the extension: -** Set shell variable SQDIR= -** and variable OPTS to -DOMIT_BASE85_CHECKER if is_base85() unwanted. -** *Nix: gcc -O2 -shared -I$SQDIR $OPTS -fPIC -o base85.so base85.c -** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR $OPTS -o base85.dylib base85.c -** Win32: gcc -O2 -shared -I%SQDIR% %OPTS% -o base85.dll base85.c -** Win32: cl /Os -I%SQDIR% %OPTS% base85.c -link -dll -out:base85.dll -** -** To build the standalone program, define PP symbol BASE85_STANDALONE. Eg. -** *Nix or OSX: gcc -O2 -DBASE85_STANDALONE base85.c -o base85 -** Win32: gcc -O2 -DBASE85_STANDALONE -o base85.exe base85.c -** Win32: cl /Os /MD -DBASE85_STANDALONE base85.c +** SELECT ieee754_inc(0.0,+1); */ - -#include -#include -#include -#include -#ifndef OMIT_BASE85_CHECKER -# include -#endif - -#ifndef BASE85_STANDALONE - -/* # include "sqlite3ext.h" */ - -SQLITE_EXTENSION_INIT1; - -#else - -# ifdef _WIN32 -# include -# include -# else -# define setmode(fd,m) -# endif - -static char *zHelp = - "Usage: base85 \n" - " is either -r to read or -w to write ,\n" - " content to be converted to/from base85 on stdout/stdin.\n" - " names a binary file to be rendered or created.\n" - " Or, the name '-' refers to the stdin or stdout stream.\n" - ; - -static void sayHelp(){ - printf("%s", zHelp); -} -#endif - -#ifndef U8_TYPEDEF -/* typedef unsigned char u8; */ -#define U8_TYPEDEF -#endif - -/* Classify c according to interval within USASCII set w.r.t. base85 - * Values of 1 and 3 are base85 numerals. Values of 0, 2, or 4 are not. - */ -#define B85_CLASS( c ) (((c)>='#')+((c)>'&')+((c)>='*')+((c)>'z')) - -/* Provide digitValue to b85Numeral offset as a function of above class. */ -static u8 b85_cOffset[] = { 0, '#', 0, '*'-4, 0 }; -#define B85_DNOS( c ) b85_cOffset[B85_CLASS(c)] - -/* Say whether c is a base85 numeral. */ -#define IS_B85( c ) (B85_CLASS(c) & 1) - -#if 0 /* Not used, */ -static u8 base85DigitValue( char c ){ - u8 dv = (u8)(c - '#'); - if( dv>87 ) return 0xff; - return (dv > 3)? dv-3 : dv; +static void ieee754inc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + double r; + sqlite3_int64 N; + sqlite3_uint64 m1, m2; + double r2; + UNUSED_PARAMETER(argc); + r = sqlite3_value_double(argv[0]); + N = sqlite3_value_int64(argv[1]); + memcpy(&m1, &r, 8); + m2 = m1 + N; + memcpy(&r2, &m2, 8); + sqlite3_result_double(context, r2); } -#endif - -/* Width of base64 lines. Should be an integer multiple of 5. */ -#define B85_DARK_MAX 80 -static char * skipNonB85( char *s, int nc ){ - char c; - while( nc-- > 0 && (c = *s) && !IS_B85(c) ) ++s; - return s; -} +#ifdef _WIN32 -/* Convert small integer, known to be in 0..84 inclusive, to base85 numeral. - * Do not use the macro form with argument expression having a side-effect.*/ -#if 0 -static char base85Numeral( u8 b ){ - return (b < 4)? (char)(b + '#') : (char)(b - 4 + '*'); -} -#else -# define base85Numeral( dn )\ - ((char)(((dn) < 4)? (char)((dn) + '#') : (char)((dn) - 4 + '*'))) #endif - -static char *putcs(char *pc, char *s){ - char c; - while( (c = *s++)!=0 ) *pc++ = c; - return pc; -} - -/* Encode a byte buffer into base85 text. If pSep!=0, it's a C string -** to be appended to encoded groups to limit their length to B85_DARK_MAX -** or to terminate the last group (to aid concatenation.) -*/ -static char* toBase85( u8 *pIn, int nbIn, char *pOut, char *pSep ){ - int nCol = 0; - while( nbIn >= 4 ){ - int nco = 5; - unsigned long qbv = (((unsigned long)pIn[0])<<24) | - (pIn[1]<<16) | (pIn[2]<<8) | pIn[3]; - while( nco > 0 ){ - unsigned nqv = (unsigned)(qbv/85UL); - unsigned char dv = qbv - 85UL*nqv; - qbv = nqv; - pOut[--nco] = base85Numeral(dv); - } - nbIn -= 4; - pIn += 4; - pOut += 5; - if( pSep && (nCol += 5)>=B85_DARK_MAX ){ - pOut = putcs(pOut, pSep); - nCol = 0; - } - } - if( nbIn > 0 ){ - int nco = nbIn + 1; - unsigned long qv = *pIn++; - int nbe = 1; - while( nbe++ < nbIn ){ - qv = (qv<<8) | *pIn++; - } - nCol += nco; - while( nco > 0 ){ - u8 dv = (u8)(qv % 85); - qv /= 85; - pOut[--nco] = base85Numeral(dv); - } - pOut += (nbIn+1); - } - if( pSep && nCol>0 ) pOut = putcs(pOut, pSep); - *pOut = 0; - return pOut; -} - -/* Decode base85 text into a byte buffer. */ -static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){ - if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn; - while( ncIn>0 ){ - static signed char nboi[] = { 0, 0, 1, 2, 3, 4 }; - char *pUse = skipNonB85(pIn, ncIn); - unsigned long qv = 0L; - int nti, nbo; - ncIn -= (pUse - pIn); - pIn = pUse; - nti = (ncIn>5)? 5 : ncIn; - nbo = nboi[nti]; - if( nbo==0 ) break; - while( nti>0 ){ - char c = *pIn++; - u8 cdo = B85_DNOS(c); - --ncIn; - if( cdo==0 ) break; - qv = 85 * qv + (c - cdo); - --nti; - } - nbo -= nti; /* Adjust for early (non-digit) end of group. */ - switch( nbo ){ - case 4: - *pOut++ = (qv >> 24)&0xff; - /* FALLTHRU */ - case 3: - *pOut++ = (qv >> 16)&0xff; - /* FALLTHRU */ - case 2: - *pOut++ = (qv >> 8)&0xff; - /* FALLTHRU */ - case 1: - *pOut++ = qv&0xff; - /* FALLTHRU */ - case 0: - break; - } +int sqlite3_ieee_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + static const struct { + char *zFName; + int nArg; + int iAux; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFunc[] = { + { "ieee754", 1, 0, ieee754func }, + { "ieee754", 2, 0, ieee754func }, + { "ieee754_mantissa", 1, 1, ieee754func }, + { "ieee754_exponent", 1, 2, ieee754func }, + { "ieee754_to_blob", 1, 0, ieee754func_to_blob }, + { "ieee754_from_blob", 1, 0, ieee754func_from_blob }, + { "ieee754_inc", 2, 0, ieee754inc }, + }; + unsigned int i; + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + for(i=0; i 0 && (c = *p++) != 0 ){ - if( !IS_B85(c) && !isspace(c) ) return 0; - } - return 1; -} -#endif - -#ifndef BASE85_STANDALONE - -# ifndef OMIT_BASE85_CHECKER -/* This function does the work for the SQLite is_base85(t) UDF. */ -static void is_base85(sqlite3_context *context, int na, sqlite3_value *av[]){ - assert(na==1); - switch( sqlite3_value_type(av[0]) ){ - case SQLITE_TEXT: - { - int rv = allBase85( (char *)sqlite3_value_text(av[0]), - sqlite3_value_bytes(av[0]) ); - sqlite3_result_int(context, rv); - } - break; - case SQLITE_NULL: - sqlite3_result_null(context); - break; - default: - sqlite3_result_error(context, "is_base85 accepts only text or NULL", -1); - return; - } -} -# endif - -/* This function does the work for the SQLite base85(x) UDF. */ -static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){ - sqlite3_int64 nb, nc, nv = sqlite3_value_bytes(av[0]); - int nvMax = sqlite3_limit(sqlite3_context_db_handle(context), - SQLITE_LIMIT_LENGTH, -1); - char *cBuf; - u8 *bBuf; - assert(na==1); - switch( sqlite3_value_type(av[0]) ){ - case SQLITE_BLOB: - nb = nv; - /* ulongs tail newlines tailenc+nul*/ - nc = 5*(nv/4) + nv%4 + nv/64+1 + 2; - if( nvMax < nc ){ - sqlite3_result_error(context, "blob expanded to base85 too big", -1); - return; - } - bBuf = (u8*)sqlite3_value_blob(av[0]); - if( !bBuf ){ - if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ - goto memFail; - } - sqlite3_result_text(context,"",-1,SQLITE_STATIC); - break; - } - cBuf = sqlite3_malloc(nc); - if( !cBuf ) goto memFail; - nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf); - sqlite3_result_text(context, cBuf, nc, sqlite3_free); - break; - case SQLITE_TEXT: - nc = nv; - nb = 4*(nv/5) + nv%5; /* may overestimate */ - if( nvMax < nb ){ - sqlite3_result_error(context, "blob from base85 may be too big", -1); - return; - }else if( nb<1 ){ - nb = 1; - } - cBuf = (char *)sqlite3_value_text(av[0]); - if( !cBuf ){ - if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){ - goto memFail; - } - sqlite3_result_zeroblob(context, 0); - break; - } - bBuf = sqlite3_malloc(nb); - if( !bBuf ) goto memFail; - nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf); - sqlite3_result_blob(context, bBuf, nb, sqlite3_free); - break; - default: - sqlite3_result_error(context, "base85 accepts only blob or text.", -1); - return; - } - return; - memFail: - sqlite3_result_error(context, "base85 OOM", -1); -} - -/* -** Establish linkage to running SQLite library. -*/ -#ifndef SQLITE_SHELL_EXTFUNCS -#ifdef _WIN32 - -#endif -int sqlite3_base_init -#else -static int sqlite3_base85_init -#endif -(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){ - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErr; -# ifndef OMIT_BASE85_CHECKER - { - int rc = sqlite3_create_function - (db, "is_base85", 1, - SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_UTF8, - 0, is_base85, 0, 0); - if( rc!=SQLITE_OK ) return rc; - } -# endif - return sqlite3_create_function - (db, "base85", 1, - SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8, - 0, base85, 0, 0); -} - -/* -** Define some macros to allow this extension to be built into the shell -** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This -** allows shell.c, as distributed, to have this extension built in. -*/ -# define BASE85_INIT(db) sqlite3_base85_init(db, 0, 0) -# define BASE85_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */ - -#else /* standalone program */ - -int main(int na, char *av[]){ - int cin; - int rc = 0; - u8 bBuf[4*(B85_DARK_MAX/5)]; - char cBuf[5*(sizeof(bBuf)/4)+2]; - size_t nio; -# ifndef OMIT_BASE85_CHECKER - int b85Clean = 1; -# endif - char rw; - FILE *fb = 0, *foc = 0; - char fmode[3] = "xb"; - if( na < 3 || av[1][0]!='-' || (rw = av[1][1])==0 || (rw!='r' && rw!='w') ){ - sayHelp(); - return 0; - } - fmode[0] = rw; - if( av[2][0]=='-' && av[2][1]==0 ){ - switch( rw ){ - case 'r': - fb = stdin; - setmode(fileno(stdin), O_BINARY); - break; - case 'w': - fb = stdout; - setmode(fileno(stdout), O_BINARY); - break; - } - }else{ - fb = fopen(av[2], fmode); - foc = fb; - } - if( !fb ){ - fprintf(stderr, "Cannot open %s for %c\n", av[2], rw); - rc = 1; - }else{ - switch( rw ){ - case 'r': - while( (nio = fread( bBuf, 1, sizeof(bBuf), fb))>0 ){ - toBase85( bBuf, (int)nio, cBuf, 0 ); - fprintf(stdout, "%s\n", cBuf); - } - break; - case 'w': - while( 0 != fgets(cBuf, sizeof(cBuf), stdin) ){ - int nc = strlen(cBuf); - size_t nbo = fromBase85( cBuf, nc, bBuf ) - bBuf; - if( 1 != fwrite(bBuf, nbo, 1, fb) ) rc = 1; -# ifndef OMIT_BASE85_CHECKER - b85Clean &= allBase85( cBuf, nc ); -# endif - } - break; - default: - sayHelp(); - rc = 1; - } - if( foc ) fclose(foc); - } -# ifndef OMIT_BASE85_CHECKER - if( !b85Clean ){ - fprintf(stderr, "Base85 input had non-base85 dark or control content.\n"); - } -# endif - return rc; -} - -#endif - -/************************* End ext/misc/base85.c ********************/ -/************************* Begin ext/misc/ieee754.c ******************/ +/************************* End ../ext/misc/ieee754.c ********************/ +/************************* Begin ../ext/misc/series.c ******************/ /* -** 2013-04-17 +** 2015-08-18, 2023-04-28 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -8169,771 +5603,407 @@ int main(int na, char *av[]){ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** -****************************************************************************** -** -** This SQLite extension implements functions for the exact display -** and input of IEEE754 Binary64 floating-point numbers. +************************************************************************* ** -** ieee754(X) -** ieee754(Y,Z) +** This file demonstrates how to create a table-valued-function using +** a virtual table. This demo implements the generate_series() function +** which gives the same results as the eponymous function in PostgreSQL, +** within the limitation that its arguments are signed 64-bit integers. ** -** In the first form, the value X should be a floating-point number. -** The function will return a string of the form 'ieee754(Y,Z)' where -** Y and Z are integers such that X==Y*pow(2,Z). +** Considering its equivalents to generate_series(start,stop,step): A +** value V[n] sequence is produced for integer n ascending from 0 where +** ( V[n] == start + n * step && sgn(V[n] - stop) * sgn(step) >= 0 ) +** for each produced value (independent of production time ordering.) ** -** In the second form, Y and Z are integers which are the mantissa and -** base-2 exponent of a new floating point number. The function returns -** a floating-point value equal to Y*pow(2,Z). +** All parameters must be either integer or convertable to integer. +** The start parameter is required. +** The stop parameter defaults to (1<<32)-1 (aka 4294967295 or 0xffffffff) +** The step parameter defaults to 1 and 0 is treated as 1. ** ** Examples: ** -** ieee754(2.0) -> 'ieee754(2,0)' -** ieee754(45.25) -> 'ieee754(181,-2)' -** ieee754(2, 0) -> 2.0 -** ieee754(181, -2) -> 45.25 +** SELECT * FROM generate_series(0,100,5); ** -** Two additional functions break apart the one-argument ieee754() -** result into separate integer values: +** The query above returns integers from 0 through 100 counting by steps +** of 5. In other words, 0, 5, 10, 15, ..., 90, 95, 100. There are a total +** of 21 rows. ** -** ieee754_mantissa(45.25) -> 181 -** ieee754_exponent(45.25) -> -2 +** SELECT * FROM generate_series(0,100); ** -** These functions convert binary64 numbers into blobs and back again. +** Integers from 0 through 100 with a step size of 1. 101 rows. ** -** ieee754_from_blob(x'3ff0000000000000') -> 1.0 -** ieee754_to_blob(1.0) -> x'3ff0000000000000' +** SELECT * FROM generate_series(20) LIMIT 10; ** -** In all single-argument functions, if the argument is an 8-byte blob -** then that blob is interpreted as a big-endian binary64 value. +** Integers 20 through 29. 10 rows. ** +** SELECT * FROM generate_series(0,-100,-5); ** -** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES -** ----------------------------------------------- +** Integers 0 -5 -10 ... -100. 21 rows. ** -** This extension in combination with the separate 'decimal' extension -** can be used to compute the exact decimal representation of binary64 -** values. To begin, first compute a table of exponent values: +** SELECT * FROM generate_series(0,-1); ** -** CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT); -** WITH RECURSIVE c(x,v) AS ( -** VALUES(0,'1') -** UNION ALL -** SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971 -** ) INSERT INTO pow2(x,v) SELECT x, v FROM c; -** WITH RECURSIVE c(x,v) AS ( -** VALUES(-1,'0.5') -** UNION ALL -** SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075 -** ) INSERT INTO pow2(x,v) SELECT x, v FROM c; +** Empty sequence. ** -** Then, to compute the exact decimal representation of a floating -** point value (the value 47.49 is used in the example) do: +** HOW IT WORKS ** -** WITH c(n) AS (VALUES(47.49)) -** ---------------^^^^^---- Replace with whatever you want -** SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v) -** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n); +** The generate_series "function" is really a virtual table with the +** following schema: ** -** Here is a query to show various boundry values for the binary64 -** number format: +** CREATE TABLE generate_series( +** value, +** start HIDDEN, +** stop HIDDEN, +** step HIDDEN +** ); ** -** WITH c(name,bin) AS (VALUES -** ('minimum positive value', x'0000000000000001'), -** ('maximum subnormal value', x'000fffffffffffff'), -** ('minimum positive normal value', x'0010000000000000'), -** ('maximum value', x'7fefffffffffffff')) -** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v) -** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin); +** The virtual table also has a rowid which is an alias for the value. +** +** Function arguments in queries against this virtual table are translated +** into equality constraints against successive hidden columns. In other +** words, the following pairs of queries are equivalent to each other: +** +** SELECT * FROM generate_series(0,100,5); +** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5; +** +** SELECT * FROM generate_series(0,100); +** SELECT * FROM generate_series WHERE start=0 AND stop=100; +** +** SELECT * FROM generate_series(20) LIMIT 10; +** SELECT * FROM generate_series WHERE start=20 LIMIT 10; +** +** The generate_series virtual table implementation leaves the xCreate method +** set to NULL. This means that it is not possible to do a CREATE VIRTUAL +** TABLE command with "generate_series" as the USING argument. Instead, there +** is a single generate_series virtual table that is always available without +** having to be created first. +** +** The xBestIndex method looks for equality constraints against the hidden +** start, stop, and step columns, and if present, it uses those constraints +** to bound the sequence of generated values. If the equality constraints +** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step. +** xBestIndex returns a small cost when both start and stop are available, +** and a very large cost if either start or stop are unavailable. This +** encourages the query planner to order joins such that the bounds of the +** series are well-defined. +** +** Update on 2024-08-22: +** xBestIndex now also looks for equality and inequality constraints against +** the value column and uses those constraints as additional bounds against +** the sequence range. Thus, a query like this: +** +** SELECT value FROM generate_series($SA,$EA) +** WHERE value BETWEEN $SB AND $EB; +** +** Is logically the same as: +** +** SELECT value FROM generate_series(max($SA,$SB),min($EA,$EB)); +** +** Constraints on the value column can server as substitutes for constraints +** on the hidden start and stop columns. So, the following two queries +** are equivalent: +** +** SELECT value FROM generate_series($S,$E); +** SELECT value FROM generate_series WHERE value BETWEEN $S and $E; ** */ /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #include #include +#include +#include -/* Mark a function parameter as unused, to suppress nuisance compiler -** warnings. */ -#ifndef UNUSED_PARAMETER -# define UNUSED_PARAMETER(X) (void)(X) -#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* series_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result. +** +** iOBase, iOTerm, and iOStep are the original values of the +** start=, stop=, and step= constraints on the query. These are +** the values reported by the start, stop, and step columns of the +** virtual table. +** +** iBase, iTerm, iStep, and bDescp are the actual values used to generate +** the sequence. These might be different from the iOxxxx values. +** For example in +** +** SELECT value FROM generate_series(1,11,2) +** WHERE value BETWEEN 4 AND 8; +** +** The iOBase is 1, but the iBase is 5. iOTerm is 11 but iTerm is 7. +** Another example: +** +** SELECT value FROM generate_series(1,15,3) ORDER BY value DESC; +** +** The cursor initialization for the above query is: +** +** iOBase = 1 iBase = 13 +** iOTerm = 15 iTerm = 1 +** iOStep = 3 iStep = 3 bDesc = 1 +** +** The actual step size is unsigned so that can have a value of +** +9223372036854775808 which is needed for querys like this: +** +** SELECT value +** FROM generate_series(9223372036854775807, +** -9223372036854775808, +** -9223372036854775808) +** ORDER BY value ASC; +** +** The setup for the previous query will be: +** +** iOBase = 9223372036854775807 iBase = -1 +** iOTerm = -9223372036854775808 iTerm = 9223372036854775807 +** iOStep = -9223372036854775808 iStep = 9223372036854775808 bDesc = 0 +*/ +/* typedef unsigned char u8; */ +typedef struct series_cursor series_cursor; +struct series_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3_int64 iOBase; /* Original starting value ("start") */ + sqlite3_int64 iOTerm; /* Original terminal value ("stop") */ + sqlite3_int64 iOStep; /* Original step value */ + sqlite3_int64 iBase; /* Starting value to actually use */ + sqlite3_int64 iTerm; /* Terminal value to actually use */ + sqlite3_uint64 iStep; /* The step size */ + sqlite3_int64 iValue; /* Current value */ + u8 bDesc; /* iStep is really negative */ + u8 bDone; /* True if stepped past last element */ +}; /* -** Implementation of the ieee754() function +** Computed the difference between two 64-bit signed integers using a +** convoluted computation designed to work around the silly restriction +** against signed integer overflow in C. */ -static void ieee754func( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - if( argc==1 ){ - sqlite3_int64 m, a; - double r; - int e; - int isNeg; - char zResult[100]; - assert( sizeof(m)==sizeof(r) ); - if( sqlite3_value_type(argv[0])==SQLITE_BLOB - && sqlite3_value_bytes(argv[0])==sizeof(r) - ){ - const unsigned char *x = sqlite3_value_blob(argv[0]); - unsigned int i; - sqlite3_uint64 v = 0; - for(i=0; i>52; - m = a & ((((sqlite3_int64)1)<<52)-1); - if( e==0 ){ - m <<= 1; - }else{ - m |= ((sqlite3_int64)1)<<52; - } - while( e<1075 && m>0 && (m&1)==0 ){ - m >>= 1; - e++; - } - if( isNeg ) m = -m; - } - switch( *(int*)sqlite3_user_data(context) ){ - case 0: - sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)", - m, e-1075); - sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); - break; - case 1: - sqlite3_result_int64(context, m); - break; - case 2: - sqlite3_result_int(context, e-1075); - break; - } - }else{ - sqlite3_int64 m, e, a; - double r; - int isNeg = 0; - m = sqlite3_value_int64(argv[0]); - e = sqlite3_value_int64(argv[1]); +static sqlite3_uint64 span64(sqlite3_int64 a, sqlite3_int64 b){ + assert( a>=b ); + return (*(sqlite3_uint64*)&a) - (*(sqlite3_uint64*)&b); +} - /* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */ - if( e>10000 ){ - e = 10000; - }else if( e<-10000 ){ - e = -10000; - } +/* +** Add or substract an unsigned 64-bit integer from a signed 64-bit integer +** and return the new signed 64-bit integer. +*/ +static sqlite3_int64 add64(sqlite3_int64 a, sqlite3_uint64 b){ + sqlite3_uint64 x = *(sqlite3_uint64*)&a; + x += b; + return *(sqlite3_int64*)&x; +} +static sqlite3_int64 sub64(sqlite3_int64 a, sqlite3_uint64 b){ + sqlite3_uint64 x = *(sqlite3_uint64*)&a; + x -= b; + return *(sqlite3_int64*)&x; +} - if( m<0 ){ - if( m<(-9223372036854775807LL) ) return; - isNeg = 1; - m = -m; - }else if( m==0 && e>-1000 && e<1000 ){ - sqlite3_result_double(context, 0.0); - return; - } - while( (m>>32)&0xffe00000 ){ - m >>= 1; - e++; - } - while( m!=0 && ((m>>32)&0xfff00000)==0 ){ - m <<= 1; - e--; - } - e += 1075; - if( e<=0 ){ - /* Subnormal */ - if( 1-e >= 64 ){ - m = 0; - }else{ - m >>= 1-e; - } - e = 0; - }else if( e>0x7ff ){ - e = 0x7ff; - } - a = m & ((((sqlite3_int64)1)<<52)-1); - a |= e<<52; - if( isNeg ) a |= ((sqlite3_uint64)1)<<63; - memcpy(&r, &a, sizeof(r)); - sqlite3_result_double(context, r); +/* +** The seriesConnect() method is invoked to create a new +** series_vtab that describes the generate_series virtual table. +** +** Think of this routine as the constructor for series_vtab objects. +** +** All this routine needs to do is: +** +** (1) Allocate the series_vtab object and initialize all fields. +** +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the +** result set of queries against generate_series will look like. +*/ +static int seriesConnect( + sqlite3 *db, + void *pUnused, + int argcUnused, const char *const*argvUnused, + sqlite3_vtab **ppVtab, + char **pzErrUnused +){ + sqlite3_vtab *pNew; + int rc; + +/* Column numbers */ +#define SERIES_COLUMN_ROWID (-1) +#define SERIES_COLUMN_VALUE 0 +#define SERIES_COLUMN_START 1 +#define SERIES_COLUMN_STOP 2 +#define SERIES_COLUMN_STEP 3 + + (void)pUnused; + (void)argcUnused; + (void)argvUnused; + (void)pzErrUnused; + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(value,start hidden,stop hidden,step hidden)"); + if( rc==SQLITE_OK ){ + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); } + return rc; } /* -** Functions to convert between blobs and floats. +** This method is the destructor for series_cursor objects. */ -static void ieee754func_from_blob( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_BLOB - && sqlite3_value_bytes(argv[0])==sizeof(double) - ){ - double r; - const unsigned char *x = sqlite3_value_blob(argv[0]); - unsigned int i; - sqlite3_uint64 v = 0; - for(i=0; i>= 8; - } - sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT); - } + +/* +** Constructor for a new series_cursor object. +*/ +static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){ + series_cursor *pCur; + (void)pUnused; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; } /* -** Functions to convert between 64-bit integers and floats. -** -** The bit patterns are copied. The numeric values are different. +** Destructor for a series_cursor. */ -static void ieee754func_from_int( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){ - double r; - sqlite3_int64 v = sqlite3_value_int64(argv[0]); - memcpy(&r, &v, sizeof(r)); - sqlite3_result_double(context, r); - } +static int seriesClose(sqlite3_vtab_cursor *cur){ + sqlite3_free(cur); + return SQLITE_OK; } -static void ieee754func_to_int( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_FLOAT ){ - double r = sqlite3_value_double(argv[0]); - sqlite3_uint64 v; - memcpy(&v, &r, sizeof(v)); - sqlite3_result_int64(context, v); + + +/* +** Advance a series_cursor to its next row of output. +*/ +static int seriesNext(sqlite3_vtab_cursor *cur){ + series_cursor *pCur = (series_cursor*)cur; + if( pCur->iValue==pCur->iTerm ){ + pCur->bDone = 1; + }else if( pCur->bDesc ){ + pCur->iValue = sub64(pCur->iValue, pCur->iStep); + assert( pCur->iValue>=pCur->iTerm ); + }else{ + pCur->iValue = add64(pCur->iValue, pCur->iStep); + assert( pCur->iValue<=pCur->iTerm ); } + return SQLITE_OK; } /* -** SQL Function: ieee754_inc(r,N) -** -** Move the floating point value r by N quantums and return the new -** values. -** -** Behind the scenes: this routine merely casts r into a 64-bit unsigned -** integer, adds N, then casts the value back into float. -** -** Example: To find the smallest positive number: -** -** SELECT ieee754_inc(0.0,+1); +** Return values of columns for the row at which the series_cursor +** is currently pointing. */ -static void ieee754inc( - sqlite3_context *context, - int argc, - sqlite3_value **argv +static int seriesColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ ){ - double r; - sqlite3_int64 N; - sqlite3_uint64 m1, m2; - double r2; - UNUSED_PARAMETER(argc); - r = sqlite3_value_double(argv[0]); - N = sqlite3_value_int64(argv[1]); - memcpy(&m1, &r, 8); - m2 = m1 + N; - memcpy(&r2, &m2, 8); - sqlite3_result_double(context, r2); + series_cursor *pCur = (series_cursor*)cur; + sqlite3_int64 x = 0; + switch( i ){ + case SERIES_COLUMN_START: x = pCur->iOBase; break; + case SERIES_COLUMN_STOP: x = pCur->iOTerm; break; + case SERIES_COLUMN_STEP: x = pCur->iOStep; break; + default: x = pCur->iValue; break; + } + sqlite3_result_int64(ctx, x); + return SQLITE_OK; } - -#ifdef _WIN32 - +#ifndef LARGEST_UINT64 +#define LARGEST_INT64 ((sqlite3_int64)0x7fffffffffffffffLL) +#define LARGEST_UINT64 ((sqlite3_uint64)0xffffffffffffffffULL) +#define SMALLEST_INT64 ((sqlite3_int64)0x8000000000000000LL) #endif -int sqlite3_ieee_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - static const struct { - char *zFName; - int nArg; - int iAux; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aFunc[] = { - { "ieee754", 1, 0, ieee754func }, - { "ieee754", 2, 0, ieee754func }, - { "ieee754_mantissa", 1, 1, ieee754func }, - { "ieee754_exponent", 1, 2, ieee754func }, - { "ieee754_to_blob", 1, 0, ieee754func_to_blob }, - { "ieee754_from_blob", 1, 0, ieee754func_from_blob }, - { "ieee754_to_int", 1, 0, ieee754func_to_int }, - { "ieee754_from_int", 1, 0, ieee754func_from_int }, - { "ieee754_inc", 2, 0, ieee754inc }, - }; - unsigned int i; - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ - for(i=0; iiValue; + return SQLITE_OK; } -/************************* End ext/misc/ieee754.c ********************/ -/************************* Begin ext/misc/series.c ******************/ /* -** 2015-08-18, 2023-04-28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file demonstrates how to create a table-valued-function using -** a virtual table. This demo implements the generate_series() function -** which gives the same results as the eponymous function in PostgreSQL, -** within the limitation that its arguments are signed 64-bit integers. -** -** Considering its equivalents to generate_series(start,stop,step): A -** value V[n] sequence is produced for integer n ascending from 0 where -** ( V[n] == start + n * step && sgn(V[n] - stop) * sgn(step) >= 0 ) -** for each produced value (independent of production time ordering.) -** -** All parameters must be either integer or convertable to integer. -** The start parameter is required. -** The stop parameter defaults to (1<<32)-1 (aka 4294967295 or 0xffffffff) -** The step parameter defaults to 1 and 0 is treated as 1. -** -** Examples: -** -** SELECT * FROM generate_series(0,100,5); -** -** The query above returns integers from 0 through 100 counting by steps -** of 5. In other words, 0, 5, 10, 15, ..., 90, 95, 100. There are a total -** of 21 rows. -** -** SELECT * FROM generate_series(0,100); -** -** Integers from 0 through 100 with a step size of 1. 101 rows. -** -** SELECT * FROM generate_series(20) LIMIT 10; -** -** Integers 20 through 29. 10 rows. -** -** SELECT * FROM generate_series(0,-100,-5); -** -** Integers 0 -5 -10 ... -100. 21 rows. -** -** SELECT * FROM generate_series(0,-1); -** -** Empty sequence. -** -** HOW IT WORKS -** -** The generate_series "function" is really a virtual table with the -** following schema: -** -** CREATE TABLE generate_series( -** value, -** start HIDDEN, -** stop HIDDEN, -** step HIDDEN -** ); -** -** The virtual table also has a rowid which is an alias for the value. -** -** Function arguments in queries against this virtual table are translated -** into equality constraints against successive hidden columns. In other -** words, the following pairs of queries are equivalent to each other: -** -** SELECT * FROM generate_series(0,100,5); -** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5; -** -** SELECT * FROM generate_series(0,100); -** SELECT * FROM generate_series WHERE start=0 AND stop=100; -** -** SELECT * FROM generate_series(20) LIMIT 10; -** SELECT * FROM generate_series WHERE start=20 LIMIT 10; -** -** The generate_series virtual table implementation leaves the xCreate method -** set to NULL. This means that it is not possible to do a CREATE VIRTUAL -** TABLE command with "generate_series" as the USING argument. Instead, there -** is a single generate_series virtual table that is always available without -** having to be created first. -** -** The xBestIndex method looks for equality constraints against the hidden -** start, stop, and step columns, and if present, it uses those constraints -** to bound the sequence of generated values. If the equality constraints -** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step. -** xBestIndex returns a small cost when both start and stop are available, -** and a very large cost if either start or stop are unavailable. This -** encourages the query planner to order joins such that the bounds of the -** series are well-defined. -** -** Update on 2024-08-22: -** xBestIndex now also looks for equality and inequality constraints against -** the value column and uses those constraints as additional bounds against -** the sequence range. Thus, a query like this: -** -** SELECT value FROM generate_series($SA,$EA) -** WHERE value BETWEEN $SB AND $EB; -** -** Is logically the same as: -** -** SELECT value FROM generate_series(max($SA,$SB),min($EA,$EB)); -** -** Constraints on the value column can server as substitutes for constraints -** on the hidden start and stop columns. So, the following two queries -** are equivalent: -** -** SELECT value FROM generate_series($S,$E); -** SELECT value FROM generate_series WHERE value BETWEEN $S and $E; -** +** Return TRUE if the cursor has been moved off of the last +** row of output. */ -/* #include "sqlite3ext.h" */ -SQLITE_EXTENSION_INIT1 -#include -#include -#include -#include - -#ifndef SQLITE_OMIT_VIRTUALTABLE +static int seriesEof(sqlite3_vtab_cursor *cur){ + series_cursor *pCur = (series_cursor*)cur; + return pCur->bDone; +} -/* series_cursor is a subclass of sqlite3_vtab_cursor which will -** serve as the underlying representation of a cursor that scans -** over rows of the result. -** -** iOBase, iOTerm, and iOStep are the original values of the -** start=, stop=, and step= constraints on the query. These are -** the values reported by the start, stop, and step columns of the -** virtual table. -** -** iBase, iTerm, iStep, and bDescp are the actual values used to generate -** the sequence. These might be different from the iOxxxx values. -** For example in -** -** SELECT value FROM generate_series(1,11,2) -** WHERE value BETWEEN 4 AND 8; -** -** The iOBase is 1, but the iBase is 5. iOTerm is 11 but iTerm is 7. -** Another example: -** -** SELECT value FROM generate_series(1,15,3) ORDER BY value DESC; -** -** The cursor initialization for the above query is: -** -** iOBase = 1 iBase = 13 -** iOTerm = 15 iTerm = 1 -** iOStep = 3 iStep = 3 bDesc = 1 -** -** The actual step size is unsigned so that can have a value of -** +9223372036854775808 which is needed for querys like this: -** -** SELECT value -** FROM generate_series(9223372036854775807, -** -9223372036854775808, -** -9223372036854775808) -** ORDER BY value ASC; -** -** The setup for the previous query will be: -** -** iOBase = 9223372036854775807 iBase = -1 -** iOTerm = -9223372036854775808 iTerm = 9223372036854775807 -** iOStep = -9223372036854775808 iStep = 9223372036854775808 bDesc = 0 +/* True to cause run-time checking of the start=, stop=, and/or step= +** parameters. The only reason to do this is for testing the +** constraint checking logic for virtual tables in the SQLite core. */ -/* typedef unsigned char u8; */ -typedef struct series_cursor series_cursor; -struct series_cursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ - sqlite3_int64 iOBase; /* Original starting value ("start") */ - sqlite3_int64 iOTerm; /* Original terminal value ("stop") */ - sqlite3_int64 iOStep; /* Original step value */ - sqlite3_int64 iBase; /* Starting value to actually use */ - sqlite3_int64 iTerm; /* Terminal value to actually use */ - sqlite3_uint64 iStep; /* The step size */ - sqlite3_int64 iValue; /* Current value */ - u8 bDesc; /* iStep is really negative */ - u8 bDone; /* True if stepped past last element */ -}; +#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY +# define SQLITE_SERIES_CONSTRAINT_VERIFY 0 +#endif /* -** Computed the difference between two 64-bit signed integers using a -** convoluted computation designed to work around the silly restriction -** against signed integer overflow in C. +** Return the number of steps between pCur->iBase and pCur->iTerm if +** the step width is pCur->iStep. */ -static sqlite3_uint64 span64(sqlite3_int64 a, sqlite3_int64 b){ - assert( a>=b ); - return (*(sqlite3_uint64*)&a) - (*(sqlite3_uint64*)&b); -} +static sqlite3_uint64 seriesSteps(series_cursor *pCur){ + if( pCur->bDesc ){ + assert( pCur->iBase >= pCur->iTerm ); + return span64(pCur->iBase, pCur->iTerm)/pCur->iStep; + }else{ + assert( pCur->iBase <= pCur->iTerm ); + return span64(pCur->iTerm, pCur->iBase)/pCur->iStep; + } +} +#if defined(SQLITE_ENABLE_MATH_FUNCTIONS) || defined(_WIN32) /* -** Add or substract an unsigned 64-bit integer from a signed 64-bit integer -** and return the new signed 64-bit integer. +** Case 1 (the most common case): +** The standard math library is available so use ceil() and floor() from there. */ -static sqlite3_int64 add64(sqlite3_int64 a, sqlite3_uint64 b){ - sqlite3_uint64 x = *(sqlite3_uint64*)&a; - x += b; - return *(sqlite3_int64*)&x; +static double seriesCeil(double r){ return ceil(r); } +static double seriesFloor(double r){ return floor(r); } +#elif defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) +/* +** Case 2 (2nd most common): Use GCC/Clang builtins +*/ +static double seriesCeil(double r){ return __builtin_ceil(r); } +static double seriesFloor(double r){ return __builtin_floor(r); } +#else +/* +** Case 3 (rarely happens): Use home-grown ceil() and floor() routines. +*/ +static double seriesCeil(double r){ + sqlite3_int64 x; + if( r!=r ) return r; + if( r<=(-4503599627370496.0) ) return r; + if( r>=(+4503599627370496.0) ) return r; + x = (sqlite3_int64)r; + if( r==(double)x ) return r; + if( r>(double)x ) x++; + return (double)x; } -static sqlite3_int64 sub64(sqlite3_int64 a, sqlite3_uint64 b){ - sqlite3_uint64 x = *(sqlite3_uint64*)&a; - x -= b; - return *(sqlite3_int64*)&x; +static double seriesFloor(double r){ + sqlite3_int64 x; + if( r!=r ) return r; + if( r<=(-4503599627370496.0) ) return r; + if( r>=(+4503599627370496.0) ) return r; + x = (sqlite3_int64)r; + if( r==(double)x ) return r; + if( r<(double)x ) x--; + return (double)x; } +#endif /* -** The seriesConnect() method is invoked to create a new -** series_vtab that describes the generate_series virtual table. -** -** Think of this routine as the constructor for series_vtab objects. -** -** All this routine needs to do is: +** This method is called to "rewind" the series_cursor object back +** to the first row of output. This method is always called at least +** once prior to any call to seriesColumn() or seriesRowid() or +** seriesEof(). ** -** (1) Allocate the series_vtab object and initialize all fields. -** -** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the -** result set of queries against generate_series will look like. -*/ -static int seriesConnect( - sqlite3 *db, - void *pUnused, - int argcUnused, const char *const*argvUnused, - sqlite3_vtab **ppVtab, - char **pzErrUnused -){ - sqlite3_vtab *pNew; - int rc; - -/* Column numbers */ -#define SERIES_COLUMN_ROWID (-1) -#define SERIES_COLUMN_VALUE 0 -#define SERIES_COLUMN_START 1 -#define SERIES_COLUMN_STOP 2 -#define SERIES_COLUMN_STEP 3 - - (void)pUnused; - (void)argcUnused; - (void)argvUnused; - (void)pzErrUnused; - rc = sqlite3_declare_vtab(db, - "CREATE TABLE x(value,start hidden,stop hidden,step hidden)"); - if( rc==SQLITE_OK ){ - pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(*pNew)); - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - } - return rc; -} - -/* -** This method is the destructor for series_cursor objects. -*/ -static int seriesDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; -} - -/* -** Constructor for a new series_cursor object. -*/ -static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){ - series_cursor *pCur; - (void)pUnused; - pCur = sqlite3_malloc( sizeof(*pCur) ); - if( pCur==0 ) return SQLITE_NOMEM; - memset(pCur, 0, sizeof(*pCur)); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* -** Destructor for a series_cursor. -*/ -static int seriesClose(sqlite3_vtab_cursor *cur){ - sqlite3_free(cur); - return SQLITE_OK; -} - - -/* -** Advance a series_cursor to its next row of output. -*/ -static int seriesNext(sqlite3_vtab_cursor *cur){ - series_cursor *pCur = (series_cursor*)cur; - if( pCur->iValue==pCur->iTerm ){ - pCur->bDone = 1; - }else if( pCur->bDesc ){ - pCur->iValue = sub64(pCur->iValue, pCur->iStep); - assert( pCur->iValue>=pCur->iTerm ); - }else{ - pCur->iValue = add64(pCur->iValue, pCur->iStep); - assert( pCur->iValue<=pCur->iTerm ); - } - return SQLITE_OK; -} - -/* -** Return values of columns for the row at which the series_cursor -** is currently pointing. -*/ -static int seriesColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ -){ - series_cursor *pCur = (series_cursor*)cur; - sqlite3_int64 x = 0; - switch( i ){ - case SERIES_COLUMN_START: x = pCur->iOBase; break; - case SERIES_COLUMN_STOP: x = pCur->iOTerm; break; - case SERIES_COLUMN_STEP: x = pCur->iOStep; break; - default: x = pCur->iValue; break; - } - sqlite3_result_int64(ctx, x); - return SQLITE_OK; -} - -#ifndef LARGEST_UINT64 -#define LARGEST_INT64 ((sqlite3_int64)0x7fffffffffffffffLL) -#define LARGEST_UINT64 ((sqlite3_uint64)0xffffffffffffffffULL) -#define SMALLEST_INT64 ((sqlite3_int64)0x8000000000000000LL) -#endif - -/* -** The rowid is the same as the value. -*/ -static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - series_cursor *pCur = (series_cursor*)cur; - *pRowid = pCur->iValue; - return SQLITE_OK; -} - -/* -** Return TRUE if the cursor has been moved off of the last -** row of output. -*/ -static int seriesEof(sqlite3_vtab_cursor *cur){ - series_cursor *pCur = (series_cursor*)cur; - return pCur->bDone; -} - -/* True to cause run-time checking of the start=, stop=, and/or step= -** parameters. The only reason to do this is for testing the -** constraint checking logic for virtual tables in the SQLite core. -*/ -#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY -# define SQLITE_SERIES_CONSTRAINT_VERIFY 0 -#endif - -/* -** Return the number of steps between pCur->iBase and pCur->iTerm if -** the step width is pCur->iStep. -*/ -static sqlite3_uint64 seriesSteps(series_cursor *pCur){ - if( pCur->bDesc ){ - assert( pCur->iBase >= pCur->iTerm ); - return span64(pCur->iBase, pCur->iTerm)/pCur->iStep; - }else{ - assert( pCur->iBase <= pCur->iTerm ); - return span64(pCur->iTerm, pCur->iBase)/pCur->iStep; - } -} - -#if defined(SQLITE_ENABLE_MATH_FUNCTIONS) || defined(_WIN32) -/* -** Case 1 (the most common case): -** The standard math library is available so use ceil() and floor() from there. -*/ -static double seriesCeil(double r){ return ceil(r); } -static double seriesFloor(double r){ return floor(r); } -#elif defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) -/* -** Case 2 (2nd most common): Use GCC/Clang builtins -*/ -static double seriesCeil(double r){ return __builtin_ceil(r); } -static double seriesFloor(double r){ return __builtin_floor(r); } -#else -/* -** Case 3 (rarely happens): Use home-grown ceil() and floor() routines. -*/ -static double seriesCeil(double r){ - sqlite3_int64 x; - if( r!=r ) return r; - if( r<=(-4503599627370496.0) ) return r; - if( r>=(+4503599627370496.0) ) return r; - x = (sqlite3_int64)r; - if( r==(double)x ) return r; - if( r>(double)x ) x++; - return (double)x; -} -static double seriesFloor(double r){ - sqlite3_int64 x; - if( r!=r ) return r; - if( r<=(-4503599627370496.0) ) return r; - if( r>=(+4503599627370496.0) ) return r; - x = (sqlite3_int64)r; - if( r==(double)x ) return r; - if( r<(double)x ) x--; - return (double)x; -} -#endif - -/* -** This method is called to "rewind" the series_cursor object back -** to the first row of output. This method is always called at least -** once prior to any call to seriesColumn() or seriesRowid() or -** seriesEof(). -** -** The query plan selected by seriesBestIndex is passed in the idxNum -** parameter. (idxStr is not used in this implementation.) idxNum -** is a bitmask showing which constraints are available: +** The query plan selected by seriesBestIndex is passed in the idxNum +** parameter. (idxStr is not used in this implementation.) idxNum +** is a bitmask showing which constraints are available: ** ** 0x0001: start=VALUE ** 0x0002: stop=VALUE @@ -9461,8 +6531,8 @@ int sqlite3_series_init( return rc; } -/************************* End ext/misc/series.c ********************/ -/************************* Begin ext/misc/regexp.c ******************/ +/************************* End ../ext/misc/series.c ********************/ +/************************* Begin ../ext/misc/regexp.c ******************/ /* ** 2012-11-13 ** @@ -9497,7 +6567,7 @@ int sqlite3_series_init( ** ^X X occurring at the beginning of the string ** X$ X occurring at the end of the string ** . Match any single character -** \c Character c where c is one of \{}()[]|*+?-. +** \c Character c where c is one of \{}()[]|*+?. ** \c C-language escapes for c in afnrtv. ex: \t or \n ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX ** \xXX Where XX is exactly 2 hex digits, unicode value XX @@ -9882,7 +6952,7 @@ static int re_hex(int c, int *pV){ ** return its interpretation. */ static unsigned re_esc_char(ReCompiled *p){ - static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-"; + static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]"; static const char zTrans[] = "\a\f\n\r\t\v"; int i, v = 0; char c; @@ -10205,18 +7275,11 @@ static const char *re_compile( } /* -** The value of LIMIT_MAX_PATTERN_LENGTH. +** Compute a reasonable limit on the length of the REGEXP NFA. */ static int re_maxlen(sqlite3_context *context){ sqlite3 *db = sqlite3_context_db_handle(context); - return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1); -} - -/* -** Maximum NFA size given a maximum pattern length. -*/ -static int re_maxnfa(int mxlen){ - return 75+mxlen/2; + return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2; } /* @@ -10242,17 +7305,10 @@ static void re_sql_func( (void)argc; /* Unused */ pRe = sqlite3_get_auxdata(context, 0); if( pRe==0 ){ - int mxLen = re_maxlen(context); - int nPattern; zPattern = (const char*)sqlite3_value_text(argv[0]); if( zPattern==0 ) return; - nPattern = sqlite3_value_bytes(argv[0]); - if( nPattern>mxLen ){ - zErr = "REGEXP pattern too big"; - }else{ - zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen), - sqlite3_user_data(context)!=0); - } + zErr = re_compile(&pRe, zPattern, re_maxlen(context), + sqlite3_user_data(context)!=0); if( zErr ){ re_free(pRe); sqlite3_result_error(context, zErr, -1); @@ -10318,7 +7374,7 @@ static void re_bytecode_func( zPattern = (const char*)sqlite3_value_text(argv[0]); if( zPattern==0 ) return; - zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)), + zErr = re_compile(&pRe, zPattern, re_maxlen(context), sqlite3_user_data(context)!=0); if( zErr ){ re_free(pRe); @@ -10392,9 +7448,9 @@ int sqlite3_regexp_init( return rc; } -/************************* End ext/misc/regexp.c ********************/ +/************************* End ../ext/misc/regexp.c ********************/ #ifndef SQLITE_SHELL_FIDDLE -/************************* Begin ext/misc/fileio.c ******************/ +/************************* Begin ../ext/misc/fileio.c ******************/ /* ** 2014-06-13 ** @@ -10491,16 +7547,12 @@ SQLITE_EXTENSION_INIT1 # include # include # define STRUCT_STAT struct stat -# include -# include #else /* # include "windirent.h" */ # include # define STRUCT_STAT struct _stat # define chmod(path,mode) fileio_chmod(path,mode) # define mkdir(path,mode) fileio_mkdir(path) - extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); - extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); #endif #include #include @@ -10532,9 +7584,12 @@ SQLITE_EXTENSION_INIT1 */ #if defined(_WIN32) || defined(WIN32) static int fileio_chmod(const char *zPath, int pmode){ + sqlite3_int64 sz = strlen(zPath); + wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); int rc; - wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath); if( b1==0 ) return -1; + sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); + b1[sz] = 0; rc = _wchmod(b1, pmode); sqlite3_free(b1); return rc; @@ -10546,9 +7601,12 @@ static int fileio_chmod(const char *zPath, int pmode){ */ #if defined(_WIN32) || defined(WIN32) static int fileio_mkdir(const char *zPath){ + sqlite3_int64 sz = strlen(zPath); + wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); int rc; - wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath); if( b1==0 ) return -1; + sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); + b1[sz] = 0; rc = _wmkdir(b1); sqlite3_free(b1); return rc; @@ -10661,34 +7719,69 @@ static sqlite3_uint64 fileTimeToUnixTime( return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000; } -#endif /* _WIN32 */ + + +#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32)) +# /* To allow a standalone DLL, use this next replacement function: */ +# undef sqlite3_win32_utf8_to_unicode +# define sqlite3_win32_utf8_to_unicode utf8_to_utf16 +# +LPWSTR utf8_to_utf16(const char *z){ + int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0); + LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR)); + if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) ) + return rv; + sqlite3_free(rv); + return 0; +} +#endif /* -** This function is used in place of stat(). On Windows, special handling -** is required in order for the included time to be returned as UTC. On all -** other systems, this function simply calls stat(). +** This function attempts to normalize the time values found in the stat() +** buffer to UTC. This is necessary on Win32, where the runtime library +** appears to return these values as local times. */ -static int fileStat( +static void statTimesToUtc( const char *zPath, STRUCT_STAT *pStatBuf ){ -#if defined(_WIN32) - int rc; - wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath); - if( b1==0 ) return 1; - rc = _wstat(b1, pStatBuf); - if( rc==0 ){ - HANDLE hFindFile; - WIN32_FIND_DATAW fd; + HANDLE hFindFile; + WIN32_FIND_DATAW fd; + LPWSTR zUnicodeName; + extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); + zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); + if( zUnicodeName ){ memset(&fd, 0, sizeof(WIN32_FIND_DATAW)); - hFindFile = FindFirstFileW(b1, &fd); + hFindFile = FindFirstFileW(zUnicodeName, &fd); if( hFindFile!=NULL ){ pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime); pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime); pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime); FindClose(hFindFile); } + sqlite3_free(zUnicodeName); } +} +#endif + +/* +** This function is used in place of stat(). On Windows, special handling +** is required in order for the included time to be returned as UTC. On all +** other systems, this function simply calls stat(). +*/ +static int fileStat( + const char *zPath, + STRUCT_STAT *pStatBuf +){ +#if defined(_WIN32) + sqlite3_int64 sz = strlen(zPath); + wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); + int rc; + if( b1==0 ) return 1; + sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); + b1[sz] = 0; + rc = _wstat(b1, pStatBuf); + if( rc==0 ) statTimesToUtc(zPath, pStatBuf); sqlite3_free(b1); return rc; #else @@ -10820,6 +7913,7 @@ static int writeFile( if( mtime>=0 ){ #if defined(_WIN32) +#if !SQLITE_OS_WINRT /* Windows */ FILETIME lastAccess; FILETIME lastWrite; @@ -10850,6 +7944,7 @@ static int writeFile( }else{ return 1; } +#endif #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */ /* Recent unix */ struct timespec times[2]; @@ -11453,172 +8548,24 @@ static int fsdirRegister(sqlite3 *db){ # define fsdirRegister(x) SQLITE_OK #endif -/* -** This version of realpath() works on any system. The string -** returned is held in memory allocated using sqlite3_malloc64(). -** The caller is responsible for calling sqlite3_free(). -*/ -static char *portable_realpath(const char *zPath){ -#if !defined(_WIN32) /* BEGIN unix */ +#ifdef _WIN32 - char *zOut = 0; /* Result */ - char *z; /* Temporary buffer */ -#if defined(PATH_MAX) - char zBuf[PATH_MAX+1]; /* Space for the temporary buffer */ #endif - - if( zPath==0 ) return 0; -#if defined(PATH_MAX) - z = realpath(zPath, zBuf); - if( z ){ - zOut = sqlite3_mprintf("%s", zBuf); - } -#endif /* defined(PATH_MAX) */ - if( zOut==0 ){ - /* Try POSIX.1-2008 malloc behavior */ - z = realpath(zPath, NULL); - if( z ){ - zOut = sqlite3_mprintf("%s", z); - free(z); - } - } - return zOut; - -#else /* End UNIX, Begin WINDOWS */ - - wchar_t *zPath16; /* UTF16 translation of zPath */ - char *zOut = 0; /* Result */ - wchar_t *z = 0; /* Temporary buffer */ - - if( zPath==0 ) return 0; - - zPath16 = sqlite3_win32_utf8_to_unicode(zPath); - if( zPath16==0 ) return 0; - z = _wfullpath(NULL, zPath16, 0); - sqlite3_free(zPath16); - if( z ){ - zOut = sqlite3_win32_unicode_to_utf8(z); - free(z); - } - return zOut; - -#endif /* End WINDOWS, Begin common code */ -} - -/* -** SQL function: realpath(X) -** -** Try to convert file or pathname X into its real, absolute pathname. -** Return NULL if unable. -** -** The file or directory X is not required to exist. The answer is formed -** by calling system realpath() on the prefix of X that does exist and -** appending the tail of X that does not (yet) exist. -*/ -static void realpathFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *zPath; /* Original input path */ - char *zCopy; /* An editable copy of zPath */ - char *zOut; /* The result */ - char cSep = 0; /* Separator turned into \000 */ - size_t len; /* Prefix length before cSep */ -#ifdef _WIN32 - const int isWin = 1; -#else - const int isWin = 0; -#endif - - (void)argc; - zPath = (const char*)sqlite3_value_text(argv[0]); - if( zPath==0 ) return; - if( zPath[0]==0 ) zPath = "."; - zCopy = sqlite3_mprintf("%s",zPath); - len = strlen(zCopy); - while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){ - len--; - } - zCopy[len] = 0; - while( 1 /*exit-by-break*/ ){ - zOut = portable_realpath(zCopy); - zCopy[len] = cSep; - if( zOut ){ - if( cSep ){ - zOut = sqlite3_mprintf("%z%s",zOut,&zCopy[len]); - } - break; - }else{ - size_t i = len-1; - while( i>0 ){ - if( zCopy[i]=='/' || (isWin && zCopy[i]=='\\') ) break; - i--; - } - if( i<=0 ){ - if( zCopy[0]=='/' ){ - zOut = zCopy; - zCopy = 0; - }else if( (zOut = portable_realpath("."))!=0 ){ - zOut = sqlite3_mprintf("%z/%s", zOut, zCopy); - } - break; - } - cSep = zCopy[i]; - zCopy[i] = 0; - len = i; - } - } - sqlite3_free(zCopy); - if( zOut ){ - /* Simplify any "/./" or "/../" that might have snuck into the - ** pathname due to appending of zCopy. We only have to consider - ** unix "/" separators, because the _wfilepath() system call on - ** Windows will have already done this simplification for us. */ - size_t i, j, n; - n = strlen(zOut); - for(i=j=0; i0 && zOut[j-1]!='/' ){ j--; } - if( j>0 ){ j--; } - i += 2; - continue; - } - } - zOut[j++] = zOut[i]; - } - zOut[j] = 0; - - /* Return the result */ - sqlite3_result_text(context, zOut, -1, sqlite3_free); - } -} - - -#ifdef _WIN32 - -#endif -int sqlite3_fileio_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ - rc = sqlite3_create_function(db, "readfile", 1, - SQLITE_UTF8|SQLITE_DIRECTONLY, 0, - readfileFunc, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "writefile", -1, - SQLITE_UTF8|SQLITE_DIRECTONLY, 0, - writefileFunc, 0, 0); +int sqlite3_fileio_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + rc = sqlite3_create_function(db, "readfile", 1, + SQLITE_UTF8|SQLITE_DIRECTONLY, 0, + readfileFunc, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "writefile", -1, + SQLITE_UTF8|SQLITE_DIRECTONLY, 0, + writefileFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, @@ -11627,16 +8574,19 @@ int sqlite3_fileio_init( if( rc==SQLITE_OK ){ rc = fsdirRegister(db); } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "realpath", 1, - SQLITE_UTF8, 0, - realpathFunc, 0, 0); - } return rc; } -/************************* End ext/misc/fileio.c ********************/ -/************************* Begin ext/misc/completion.c ******************/ +#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32)) +/* To allow a standalone DLL, make test_windirent.c use the same + * redefined SQLite API calls as the above extension code does. + * Just pull in this .c to accomplish this. As a beneficial side + * effect, this extension becomes a single translation unit. */ +# include "test_windirent.c" +#endif + +/************************* End ../ext/misc/fileio.c ********************/ +/************************* Begin ../ext/misc/completion.c ******************/ /* ** 2017-07-10 ** @@ -12148,8 +9098,8 @@ int sqlite3_completion_init( return rc; } -/************************* End ext/misc/completion.c ********************/ -/************************* Begin ext/misc/appendvfs.c ******************/ +/************************* End ../ext/misc/completion.c ********************/ +/************************* Begin ../ext/misc/appendvfs.c ******************/ /* ** 2017-10-20 ** @@ -12823,10 +9773,10 @@ int sqlite3_appendvfs_init( return rc; } -/************************* End ext/misc/appendvfs.c ********************/ +/************************* End ../ext/misc/appendvfs.c ********************/ #endif #ifdef SQLITE_HAVE_ZLIB -/************************* Begin ext/misc/zipfile.c ******************/ +/************************* Begin ../ext/misc/zipfile.c ******************/ /* ** 2017-12-26 ** @@ -13222,7 +10172,7 @@ static int zipfileConnect( rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); if( rc==SQLITE_OK ){ - pNew = (ZipfileTab*)sqlite3_malloc64((i64)nByte+nFile); + pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile); if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, nByte+nFile); pNew->db = db; @@ -13368,15 +10318,14 @@ static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){ static int zipfileReadData( FILE *pFile, /* Read from this file */ u8 *aRead, /* Read into this buffer */ - i64 nRead, /* Number of bytes to read */ + int nRead, /* Number of bytes to read */ i64 iOff, /* Offset to read from */ char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ ){ size_t n; fseek(pFile, (long)iOff, SEEK_SET); - n = fread(aRead, 1, (long)nRead, pFile); - if( n!=(size_t)nRead ){ - sqlite3_free(*pzErrmsg); + n = fread(aRead, 1, nRead, pFile); + if( (int)n!=nRead ){ *pzErrmsg = sqlite3_mprintf("error in fread()"); return SQLITE_ERROR; } @@ -13393,7 +10342,7 @@ static int zipfileAppendData( fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); if( (int)n!=nWrite ){ - zipfileTableErr(pTab,"error in fwrite()"); + pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()"); return SQLITE_ERROR; } pTab->szCurrent += nWrite; @@ -13534,12 +10483,7 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){ u8 *p = aExtra; u8 *pEnd = &aExtra[nExtra]; - /* Stop when there are less than 9 bytes left to scan in the buffer. This - ** is because the timestamp field requires exactly 9 bytes - 4 bytes of - ** header fields and 5 bytes of data. If there are less than 9 bytes - ** remaining, either it is some other field or else the extra data - ** is corrupt. Either way, do not process it. */ - while( p+(2*sizeof(u16) + 1 + sizeof(u32))<=pEnd ){ + while( pcds); if( rc!=SQLITE_OK ){ - zipfileTableErr(pTab, "failed to read CDS at offset %lld", iOff); + *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff); }else if( aBlob==0 ){ rc = zipfileReadData( pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr @@ -13736,15 +10679,14 @@ static int zipfileGetEntry( rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); }else{ aRead = (u8*)&aBlob[pNew->cds.iOffset]; - if( ((i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){ + if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){ rc = zipfileCorrupt(pzErr); } } - memset(&lfh, 0, sizeof(lfh)); if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh); if( rc==SQLITE_OK ){ - pNew->iDataOff = (i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; + pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; pNew->iDataOff += lfh.nFile + lfh.nExtra; if( aBlob && pNew->cds.szCompressed ){ if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){ @@ -13755,7 +10697,7 @@ static int zipfileGetEntry( } } }else{ - zipfileTableErr(pTab, "failed to read LFH at offset %d", + *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", (int)pNew->cds.iOffset ); } @@ -13779,7 +10721,7 @@ static int zipfileNext(sqlite3_vtab_cursor *cur){ int rc = SQLITE_OK; if( pCsr->pFile ){ - i64 iEof = (i64)pCsr->eocd.iOffset + (i64)pCsr->eocd.nSize; + i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize; zipfileEntryFree(pCsr->pCurrent); pCsr->pCurrent = 0; if( pCsr->iNextOff>=iEof ){ @@ -13845,7 +10787,7 @@ static void zipfileInflate( if( err!=Z_STREAM_END ){ zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err); }else{ - sqlite3_result_blob(pCtx, aRes, (int)str.total_out, zipfileFree); + sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree); aRes = 0; } } @@ -14017,12 +10959,12 @@ static int zipfileEof(sqlite3_vtab_cursor *cur){ static int zipfileReadEOCD( ZipfileTab *pTab, /* Return errors here */ const u8 *aBlob, /* Pointer to in-memory file image */ - i64 nBlob, /* Size of aBlob[] in bytes */ + int nBlob, /* Size of aBlob[] in bytes */ FILE *pFile, /* Read from this file if aBlob==0 */ ZipfileEOCD *pEOCD /* Object to populate */ ){ u8 *aRead = pTab->aBuffer; /* Temporary buffer */ - i64 nRead; /* Bytes to read from file */ + int nRead; /* Bytes to read from file */ int rc = SQLITE_OK; memset(pEOCD, 0, sizeof(ZipfileEOCD)); @@ -14043,7 +10985,7 @@ static int zipfileReadEOCD( } if( rc==SQLITE_OK ){ - i64 i; + int i; /* Scan backwards looking for the signature bytes */ for(i=nRead-20; i>=0; i--){ @@ -14054,7 +10996,9 @@ static int zipfileReadEOCD( } } if( i<0 ){ - zipfileTableErr(pTab, "cannot find end of central directory record"); + pTab->base.zErrMsg = sqlite3_mprintf( + "cannot find end of central directory record" + ); return SQLITE_ERROR; } @@ -14099,7 +11043,7 @@ static void zipfileAddEntry( } } -static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, i64 nBlob){ +static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){ ZipfileEOCD eocd; int rc; int i; @@ -14147,7 +11091,7 @@ static int zipfileFilter( }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ static const u8 aEmptyBlob = 0; const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); - i64 nBlob = sqlite3_value_bytes(argv[0]); + int nBlob = sqlite3_value_bytes(argv[0]); assert( pTab->pFirstEntry==0 ); if( aBlob==0 ){ aBlob = &aEmptyBlob; @@ -14345,7 +11289,7 @@ static int zipfileBegin(sqlite3_vtab *pVtab){ assert( pTab->pWriteFd==0 ); if( pTab->zFile==0 || pTab->zFile[0]==0 ){ - zipfileTableErr(pTab, "zipfile: missing filename"); + pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename"); return SQLITE_ERROR; } @@ -14355,9 +11299,9 @@ static int zipfileBegin(sqlite3_vtab *pVtab){ ** in main-memory until the transaction is committed. */ pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+"); if( pTab->pWriteFd==0 ){ - zipfileTableErr(pTab, - "zipfile: failed to open file %s for writing", pTab->zFile - ); + pTab->base.zErrMsg = sqlite3_mprintf( + "zipfile: failed to open file %s for writing", pTab->zFile + ); rc = SQLITE_ERROR; }else{ fseek(pTab->pWriteFd, 0, SEEK_END); @@ -14822,7 +11766,7 @@ struct ZipfileCtx { ZipfileBuffer cds; }; -static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){ +static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ if( pBuf->n+nByte>pBuf->nAlloc ){ u8 *aNew; sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512; @@ -14871,7 +11815,7 @@ static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ char *zName = 0; /* Path (name) of new entry */ int nName = 0; /* Size of zName in bytes */ char *zFree = 0; /* Free this before returning */ - i64 nByte; + int nByte; memset(&e, 0, sizeof(e)); p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); @@ -15121,8 +12065,8 @@ int sqlite3_zipfile_init( return zipfileRegister(db); } -/************************* End ext/misc/zipfile.c ********************/ -/************************* Begin ext/misc/sqlar.c ******************/ +/************************* End ../ext/misc/zipfile.c ********************/ +/************************* Begin ../ext/misc/sqlar.c ******************/ /* ** 2017-12-17 ** @@ -15250,10 +12194,10 @@ int sqlite3_sqlar_init( return rc; } -/************************* End ext/misc/sqlar.c ********************/ +/************************* End ../ext/misc/sqlar.c ********************/ #endif #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION) -/************************* Begin ext/expert/sqlite3expert.h ******************/ +/************************* Begin ../ext/expert/sqlite3expert.h ******************/ /* ** 2017 April 07 ** @@ -15423,8 +12367,8 @@ void sqlite3_expert_destroy(sqlite3expert*); #endif /* !defined(SQLITEEXPERT_H) */ -/************************* End ext/expert/sqlite3expert.h ********************/ -/************************* Begin ext/expert/sqlite3expert.c ******************/ +/************************* End ../ext/expert/sqlite3expert.h ********************/ +/************************* Begin ../ext/expert/sqlite3expert.c ******************/ /* ** 2017 April 09 ** @@ -17662,9 +14606,9 @@ void sqlite3_expert_destroy(sqlite3expert *p){ #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ -/************************* End ext/expert/sqlite3expert.c ********************/ +/************************* End ../ext/expert/sqlite3expert.c ********************/ #endif -/************************* Begin ext/intck/sqlite3intck.h ******************/ +/************************* Begin ../ext/intck/sqlite3intck.h ******************/ /* ** 2024-02-08 ** @@ -17837,8 +14781,8 @@ const char *sqlite3_intck_test_sql(sqlite3_intck *pCk, const char *zObj); #endif /* ifndef _SQLITE_INTCK_H */ -/************************* End ext/intck/sqlite3intck.h ********************/ -/************************* Begin ext/intck/sqlite3intck.c ******************/ +/************************* End ../ext/intck/sqlite3intck.h ********************/ +/************************* Begin ../ext/intck/sqlite3intck.c ******************/ /* ** 2024-02-08 ** @@ -18160,7 +15104,7 @@ static int intckGetToken(const char *z){ char c = z[0]; int iRet = 1; if( c=='\'' || c=='"' || c=='`' ){ - while( z[iRet] ){ + while( 1 ){ if( z[iRet]==c ){ iRet++; if( z[iRet]!=c ) break; @@ -18781,8 +15725,8 @@ const char *sqlite3_intck_test_sql(sqlite3_intck *p, const char *zObj){ return p->zTestSql; } -/************************* End ext/intck/sqlite3intck.c ********************/ -/************************* Begin ext/misc/stmtrand.c ******************/ +/************************* End ../ext/intck/sqlite3intck.c ********************/ +/************************* Begin ../ext/misc/stmtrand.c ******************/ /* ** 2024-05-24 ** @@ -18881,8 +15825,8 @@ int sqlite3_stmtrand_init( return rc; } -/************************* End ext/misc/stmtrand.c ********************/ -/************************* Begin ext/misc/vfstrace.c ******************/ +/************************* End ../ext/misc/stmtrand.c ********************/ +/************************* Begin ../ext/misc/vfstrace.c ******************/ /* ** 2011 March 16 ** @@ -20095,7 +17039,7 @@ void vfstrace_unregister(const char *zTraceName){ sqlite3_free(pVfs); } -/************************* End ext/misc/vfstrace.c ********************/ +/************************* End ../ext/misc/vfstrace.c ********************/ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) #define SQLITE_SHELL_HAVE_RECOVER 1 @@ -20103,7 +17047,7 @@ void vfstrace_unregister(const char *zTraceName){ #define SQLITE_SHELL_HAVE_RECOVER 0 #endif #if SQLITE_SHELL_HAVE_RECOVER -/************************* Begin ext/recover/sqlite3recover.h ******************/ +/************************* Begin ../ext/recover/sqlite3recover.h ******************/ /* ** 2022-08-27 ** @@ -20354,9 +17298,9 @@ int sqlite3_recover_finish(sqlite3_recover*); #endif /* ifndef _SQLITE_RECOVER_H */ -/************************* End ext/recover/sqlite3recover.h ********************/ +/************************* End ../ext/recover/sqlite3recover.h ********************/ # ifndef SQLITE_HAVE_SQLITE3R -/************************* Begin ext/recover/dbdata.c ******************/ +/************************* Begin ../ext/recover/dbdata.c ******************/ /* ** 2019-04-17 ** @@ -21381,8 +18325,8 @@ int sqlite3_dbdata_init( #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ -/************************* End ext/recover/dbdata.c ********************/ -/************************* Begin ext/recover/sqlite3recover.c ******************/ +/************************* End ../ext/recover/dbdata.c ********************/ +/************************* Begin ../ext/recover/sqlite3recover.c ******************/ /* ** 2022-08-27 ** @@ -24285,7 +21229,7 @@ int sqlite3_recover_finish(sqlite3_recover *p){ #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ -/************************* End ext/recover/sqlite3recover.c ********************/ +/************************* End ../ext/recover/sqlite3recover.c ********************/ # endif /* SQLITE_HAVE_SQLITE3R */ #endif #ifdef SQLITE_SHELL_EXTSRC @@ -24313,24 +21257,31 @@ struct ExpertInfo { }; #endif -/* All the parameters that determine how to render query results. -*/ -typedef struct Mode { - u8 autoExplain; /* Automatically turn on .explain mode */ - u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */ - u8 autoEQPtrace; /* autoEQP is in trace mode */ - u8 scanstatsOn; /* True to display scan stats before each finalize */ - u8 bAutoScreenWidth; /* Using the TTY to determine screen width */ - u8 mFlags; /* MFLG_ECHO, MFLG_CRLF, etc. */ - u8 eMode; /* One of the MODE_ values */ - sqlite3_qrf_spec spec; /* Spec to be passed into QRF */ -} Mode; +/* A single line in the EQP output */ +typedef struct EQPGraphRow EQPGraphRow; +struct EQPGraphRow { + int iEqpId; /* ID for this row */ + int iParentId; /* ID of the parent row */ + EQPGraphRow *pNext; /* Next row in sequence */ + char zText[1]; /* Text to display for this row */ +}; -/* Flags for Mode.mFlags */ -#define MFLG_ECHO 0x01 /* Echo inputs to output */ -#define MFLG_CRLF 0x02 /* Use CR/LF output line endings */ -#define MFLG_HDR 0x04 /* .header used to change headers on/off */ +/* All EQP output is collected into an instance of the following */ +typedef struct EQPGraph EQPGraph; +struct EQPGraph { + EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ + EQPGraphRow *pLast; /* Last element of the pRow list */ + char zPrefix[100]; /* Graph prefix */ +}; +/* Parameters affecting columnar mode result display (defaulting together) */ +typedef struct ColModeOpts { + int iWrap; /* In columnar modes, wrap lines reaching this limit */ + u8 bQuote; /* Quote results for .mode box and table */ + u8 bWordWrap; /* In columnar modes, wrap at word boundaries */ +} ColModeOpts; +#define ColModeOpts_default { 60, 0, 0 } +#define ColModeOpts_default_qbox { 60, 1, 0 } /* ** State information about the database connection is contained in an @@ -24339,6 +21290,11 @@ typedef struct Mode { typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ + u8 autoExplain; /* Automatically turn on .explain mode */ + u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */ + u8 autoEQPtest; /* autoEQP is in test mode */ + u8 autoEQPtrace; /* autoEQP is in trace mode */ + u8 scanstatsOn; /* True to display scan stats before each finalize */ u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ u8 nEqpLevel; /* Depth of the EQP output graph */ @@ -24346,44 +21302,48 @@ 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) */ + u8 eEscMode; /* Escape mode for text output */ + 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 */ - u8 nPopOutput; /* Revert .output settings when reaching zero */ - u8 nPopMode; /* Revert .mode settings when reaching zero */ - u8 enableTimer; /* Enable the timer. 2: permanently 1: only once */ int inputNesting; /* Track nesting level of .read and other redirects */ - double prevTimer; /* Last reported timer value */ - double tmProgress; /* --timeout option for .progress */ + int outCount; /* Revert to stdout when reaching zero */ + int cnt; /* Number of records displayed so far */ i64 lineno; /* Line number of last line read from in */ - const char *zInFile; /* Name of the input file */ int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ FILE *in; /* Read commands from this stream */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ + int mode; /* An output mode setting */ + int modePrior; /* Saved mode */ + int cMode; /* temporary output mode for the current query */ + int normalMode; /* Output mode before ".explain on" */ int writableSchema; /* True if PRAGMA writable_schema=ON */ + int showHeader; /* True to show column names in List or Column mode */ int nCheck; /* Number of ".check" commands run */ unsigned nProgress; /* Number of progress callbacks encountered */ unsigned mxProgress; /* Maximum progress callbacks before failing */ unsigned flgProgress; /* Flags for the progress callback */ unsigned shellFlgs; /* Various flags */ - unsigned nTestRun; /* Number of test cases run */ - unsigned nTestErr; /* Number of test cases that failed */ + unsigned priorShFlgs; /* Saved copy of flags */ sqlite3_int64 szMax; /* --maxsize argument to .open */ char *zDestTable; /* Name of destination table when MODE_Insert */ char *zTempFile; /* Temporary file that might need deleting */ - char *zErrPrefix; /* Alternative error message prefix */ char zTestcase[30]; /* Name of current test case */ + char colSeparator[20]; /* Column separator character for several modes */ + char rowSeparator[20]; /* Row separator character for MODE_Ascii */ + char colSepPrior[20]; /* Saved column separator */ + char rowSepPrior[20]; /* Saved row separator */ + int *colWidth; /* Requested width of each column in columnar modes */ + int *actualWidth; /* Actual width of each column */ + int nWidth; /* Number of slots in colWidth[] and actualWidth[] */ + char nullValue[20]; /* The text to print when a NULL comes back from + ** the database */ char outfile[FILENAME_MAX]; /* Filename for *out */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ - Mode mode; /* Current display mode */ - Mode modePrior; /* Backup */ - struct SavedMode { /* Ability to define custom mode configurations */ - char *zTag; /* Name of this saved mode */ - Mode mode; /* The saved mode */ - } *aSavedModes; /* Array of saved .mode settings. system malloc() */ - int nSavedModes; /* Number of saved .mode settings */ struct AuxDb { /* Storage space for auxiliary database connections */ sqlite3 *db; /* Connection pointer */ const char *zDbFilename; /* Filename used to open the connection */ @@ -24394,19 +21354,14 @@ struct ShellState { #endif } aAuxDb[5], /* Array of all database connections */ *pAuxDb; /* Currently active database connection */ + int *aiIndent; /* Array of indents used in MODE_Explain */ + int nIndent; /* Size of array aiIndent[] */ + int iIndent; /* Index of current op in aiIndent[] */ char *zNonce; /* Nonce for temporary safe-mode escapes */ + EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION) ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */ #endif - struct DotCmdLine { /* Info about arguments to a dot-command */ - const char *zOrig; /* Original text of the dot-command */ - char *zCopy; /* Copy of zOrig, from malloc() */ - int nAlloc; /* Size of allocates for arrays below */ - int nArg; /* Number of argument slots actually used */ - char **azArg; /* Pointer to each argument, dequoted */ - int *aiOfst; /* Offset into zOrig[] for start of each arg */ - char *abQuot; /* True if the argment was originally quoted */ - } dot; #ifdef SQLITE_SHELL_FIDDLE struct { const char * zInput; /* Input string from wasm/JS proxy */ @@ -24421,7 +21376,7 @@ static ShellState shellState; #endif -/* Allowed values for ShellState.mode.autoEQP +/* Allowed values for ShellState.autoEQP */ #define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */ #define AUTOEQP_on 1 /* Automatic EQP is on */ @@ -24449,13 +21404,15 @@ static ShellState shellState; ** callback limit is reached, and for each ** top-level SQL statement */ #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */ -#define SHELL_PROGRESS_TMOUT 0x08 /* Stop after tmProgress seconds */ -/* Names of values for Mode.spec.eEsc and Mode.spec.eText +/* Allowed values for ShellState.eEscMode. The default value should +** be 0, so to change the default, reorder the names. */ -static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" }; -static const char *qrfQuoteNames[] = - { "off","off","sql","hex","csv","tcl","json","relaxed"}; +#define SHELL_ESC_ASCII 0 /* Substitute ^Y for X where Y=X+0x40 */ +#define SHELL_ESC_SYMBOL 1 /* Substitute U+2400 graphics */ +#define SHELL_ESC_OFF 2 /* Send characters verbatim */ + +static const char *shell_EscModeNames[] = { "ascii", "symbol", "off" }; /* ** These are the allowed shellFlgs values @@ -24464,8 +21421,10 @@ static const char *qrfQuoteNames[] = #define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */ #define SHFLG_Backslash 0x00000004 /* The --backslash option is used */ #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */ -#define SHFLG_NoErrLineno 0x00000010 /* Omit line numbers from error msgs */ +#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */ #define SHFLG_CountChanges 0x00000020 /* .changes setting */ +#define SHFLG_Echo 0x00000040 /* .echo on/off, or --echo setting */ +#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */ #define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */ #define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */ #define SHFLG_TestingMode 0x00000400 /* allow unsafe testing features */ @@ -24478,107 +21437,54 @@ static const char *qrfQuoteNames[] = #define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X))) /* -** These are the allowed values for Mode.eMode. There is a lot of overlap -** between these values and the Mode.spec.eStyle values, but they are not -** one-to-one, and thus need to be tracked separately. -*/ -#define MODE_Ascii 0 /* Use ASCII unit and record separators (0x1F/0x1E) */ -#define MODE_Box 1 /* Unicode box-drawing characters */ -#define MODE_C 2 /* Comma-separated list of C-strings */ -#define MODE_Column 3 /* One record per line in neat columns */ -#define MODE_Count 4 /* Output only a count of the rows of output */ -#define MODE_Csv 5 /* Quote strings, numbers are plain */ -#define MODE_Html 6 /* Generate an XHTML table */ -#define MODE_Insert 7 /* Generate SQL "insert" statements */ -#define MODE_JAtom 8 /* Comma-separated list of JSON atoms */ -#define MODE_JObject 9 /* One JSON object per row */ -#define MODE_Json 10 /* Output JSON */ -#define MODE_Line 11 /* One column per line. Blank line between records */ -#define MODE_List 12 /* One record per line with a separator */ -#define MODE_Markdown 13 /* Markdown formatting */ -#define MODE_Off 14 /* No query output shown */ -#define MODE_Psql 15 /* Similar to psql */ -#define MODE_QBox 16 /* BOX with SQL-quoted content */ -#define MODE_Quote 17 /* Quote values as for SQL */ -#define MODE_Split 18 /* Split-column mode */ -#define MODE_Table 19 /* MySQL-style table formatting */ -#define MODE_Tabs 20 /* Tab-separated values */ -#define MODE_Tcl 21 /* Space-separated list of TCL strings */ -#define MODE_Www 22 /* Full web-page output */ - -#define MODE_BUILTIN 22 /* Maximum built-in mode */ -#define MODE_BATCH 50 /* Default mode for batch processing */ -#define MODE_TTY 51 /* Default mode for interactive processing */ -#define MODE_USER 75 /* First user-defined mode */ -#define MODE_N_USER 25 /* Maximum number of user-defined modes */ - -/* -** Information about built-in display modes -*/ -typedef struct ModeInfo ModeInfo; -struct ModeInfo { - char zName[9]; /* Symbolic name of the mode */ - unsigned char eCSep; /* Column separator */ - unsigned char eRSep; /* Row separator */ - unsigned char eNull; /* Null representation */ - unsigned char eText; /* Default text encoding */ - unsigned char eHdr; /* Default header encoding. */ - unsigned char eBlob; /* Default blob encoding. */ - unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */ - unsigned char eStyle; /* Underlying QRF style */ - unsigned char eCx; /* 0: other, 1: line, 2: columnar */ - unsigned char mFlg; /* Flags. 1=border-off 2=split-column */ +** These are the allowed modes. +*/ +#define MODE_Line 0 /* One column per line. Blank line between records */ +#define MODE_Column 1 /* One record per line in neat columns */ +#define MODE_List 2 /* One record per line with a separator */ +#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ +#define MODE_Html 4 /* Generate an XHTML table */ +#define MODE_Insert 5 /* Generate SQL "insert" statements */ +#define MODE_Quote 6 /* Quote values as for SQL */ +#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ +#define MODE_Csv 8 /* Quote strings, numbers are plain */ +#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ +#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ +#define MODE_Pretty 11 /* Pretty-print schemas */ +#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */ +#define MODE_Json 13 /* Output JSON */ +#define MODE_Markdown 14 /* Markdown formatting */ +#define MODE_Table 15 /* MySQL-style table formatting */ +#define MODE_Box 16 /* Unicode box-drawing characters */ +#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", + "column", + "list", + "semi", + "html", + "insert", + "quote", + "tcl", + "csv", + "explain", + "ascii", + "prettyprint", + "eqp", + "json", + "markdown", + "table", + "box", + "count", + "off", + "scanexp", + "www", }; -/* String constants used by built-in modes */ -static const char *aModeStr[] = - /* 0 1 2 3 4 5 6 7 8 */ - { 0, "\n", "|", " ", ",", "\r\n", "\036", "\037", "\t", - "", "NULL", "null", "\"\"", ": ", }; - /* 9 10 11 12 13 */ - -static const ModeInfo aModeInfo[] = { -/* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */ - { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 }, - { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2, 0 }, - { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 }, - { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2, 0 }, - { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, - { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 }, - { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 }, - { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 }, - { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 }, - { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 }, - { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 }, - { "line", 13, 1, 9, 1, 1, 0, 0, 11, 1, 0 }, - { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 }, - { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2, 0 }, - { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 }, - { "psql", 0, 0, 9, 1, 1, 0, 2, 19, 2, 1 }, - { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2, 0 }, - { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 }, - { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 }, - { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2, 0 }, - { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 }, - { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 }, - { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 } -}; /* | / / | / / | | \ - ** | / / | / / | | \_ 2: columnar - ** Index into aModeStr[] | / / | | 1: line - ** | / / | | 0: other - ** | / / | \ - ** text encoding |/ | show | \ - ** v-------------------' | hdrs? | The QRF style - ** 0: n/a blob | v-----' - ** 1: plain v_---------' 0: n/a - ** 2: sql 0: auto 1: no - ** 3: csv 1: as-text 2: yes - ** 4: html 2: sql - ** 5: c 3: hex - ** 6: json 4: c - ** 5: json - ** 6: size - ******************************************************************/ /* ** These are the column/row/line separators used by the various ** import/export modes. @@ -24592,513 +21498,92 @@ static const ModeInfo aModeInfo[] = { #define SEP_Unit "\x1F" #define SEP_Record "\x1E" -/* -** Default values for the various QRF limits -*/ -#ifndef DFLT_CHAR_LIMIT -# define DFLT_CHAR_LIMIT 300 -#endif -#ifndef DFLT_LINE_LIMIT -# define DFLT_LINE_LIMIT 5 -#endif -#ifndef DFLT_TITLE_LIMIT -# define DFLT_TITLE_LIMIT 20 -#endif - /* ** Limit input nesting via .read or any other input redirect. ** It's not too expensive, so a generous allowance can be made. */ #define MAX_INPUT_NESTING 25 -/************************* BEGIN PERFORMANCE TIMER *****************************/ -#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) -#include -#include -/* VxWorks does not support getrusage() as far as we can determine */ -#if defined(_WRS_KERNEL) || defined(__RTP__) -struct rusage { - struct timeval ru_utime; /* user CPU time used */ - struct timeval ru_stime; /* system CPU time used */ -}; -#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 */ - /* -** Begin timing an operation +** A callback for the sqlite3_log() interface. */ -static void beginTimer(ShellState *p){ - if( p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 ){ - getrusage(RUSAGE_SELF, &sBegin); - iBegin = timeOfDay(); - } -} - -/* Return the difference of two time_structs in seconds */ -static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ - return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + - (double)(pEnd->tv_sec - pStart->tv_sec); -} - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK -/* Return the time since the start of the timer in -** seconds. */ -static double elapseTime(ShellState *NotUsed){ - (void)NotUsed; - if( iBegin==0 ) return 0.0; - return (timeOfDay() - iBegin)*0.000001; +static void shellLog(void *pArg, int iErrCode, const char *zMsg){ + ShellState *p = (ShellState*)pArg; + if( p->pLog==0 ) return; + sqlite3_fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); + fflush(p->pLog); } -#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ /* -** Print the timing results. +** SQL function: shell_putsnl(X) +** +** Write the text X to the screen (or whatever output is being directed) +** adding a newline at the end, and then return X. */ -static void endTimer(ShellState *p){ - if( p->enableTimer ){ - sqlite3_int64 iEnd = timeOfDay(); - struct rusage sEnd; - getrusage(RUSAGE_SELF, &sEnd); - p->prevTimer = (iEnd - iBegin)*0.000001; - cli_printf(p->out, "Run Time: real %.6f user %.6f sys %.6f\n", - p->prevTimer, - timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), - timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); - if( p->enableTimer==1 ) p->enableTimer = 0; - iBegin = 0; - } +static void shellPutsFunc( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + ShellState *p = (ShellState*)sqlite3_user_data(pCtx); + (void)nVal; + sqlite3_fprintf(p->out, "%s\n", sqlite3_value_text(apVal[0])); + sqlite3_result_value(pCtx, apVal[0]); } -#define BEGIN_TIMER(X) beginTimer(X) -#define END_TIMER(X) endTimer(X) -#define ELAPSE_TIME(X) elapseTime(X) -#define HAS_TIMER 1 - -#elif (defined(_WIN32) || defined(WIN32)) - -/* Saved resource information for the beginning of an operation */ -static HANDLE hProcess; -static FILETIME ftKernelBegin; -static FILETIME ftUserBegin; -static sqlite3_int64 ftWallBegin; -typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, - LPFILETIME, LPFILETIME); -static GETPROCTIMES getProcessTimesAddr = NULL; - /* -** Check to see if we have timer support. Return 1 if necessary -** support found (or found previously). +** If in safe mode, print an error message described by the arguments +** and exit immediately. */ -static int hasTimer(void){ - if( getProcessTimesAddr ){ - return 1; - } else { - /* GetProcessTimes() isn't supported in WIN95 and some other Windows - ** versions. See if the version we are running on has it, and if it - ** does, save off a pointer to it and the current process handle. - */ - hProcess = GetCurrentProcess(); - if( hProcess ){ - HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); - if( NULL != hinstLib ){ - getProcessTimesAddr = - (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); - if( NULL != getProcessTimesAddr ){ - return 1; - } - FreeLibrary(hinstLib); - } - } +static void failIfSafeMode( + ShellState *p, + const char *zErrMsg, + ... +){ + if( p->bSafeMode ){ + va_list ap; + char *zMsg; + va_start(ap, zErrMsg); + zMsg = sqlite3_vmprintf(zErrMsg, ap); + va_end(ap); + sqlite3_fprintf(stderr, "line %lld: %s\n", p->lineno, zMsg); + exit(1); } - return 0; } /* -** Begin timing an operation +** SQL function: edit(VALUE) +** edit(VALUE,EDITOR) +** +** These steps: +** +** (1) Write VALUE into a temporary file. +** (2) Run program EDITOR on that temporary file. +** (3) Read the temporary file back and return its content as the result. +** (4) Delete the temporary file +** +** If the EDITOR argument is omitted, use the value in the VISUAL +** environment variable. If still there is no EDITOR, through an error. +** +** Also throw an error if the EDITOR program returns a non-zero exit code. */ -static void beginTimer(ShellState *p){ - if( (p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0) - && getProcessTimesAddr - ){ - FILETIME ftCreation, ftExit; - getProcessTimesAddr(hProcess,&ftCreation,&ftExit, - &ftKernelBegin,&ftUserBegin); - ftWallBegin = timeOfDay(); - } -} - -/* Return the difference of two FILETIME structs in seconds */ -static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ - sqlite_int64 i64Start = *((sqlite_int64 *) pStart); - sqlite_int64 i64End = *((sqlite_int64 *) pEnd); - return (double) ((i64End - i64Start) / 10000000.0); -} - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK -/* Return the time since the start of the timer in -** seconds. */ -static double elapseTime(ShellState *NotUsed){ - (void)NotUsed; - if( ftWallBegin==0 ) return 0.0; - return (timeOfDay() - ftWallBegin)*0.000001; -} -#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ - -/* -** Print the timing results. -*/ -static void endTimer(ShellState *p){ - if( p->enableTimer && getProcessTimesAddr){ - FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; - sqlite3_int64 ftWallEnd = timeOfDay(); - getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); - p->prevTimer = (ftWallEnd - ftWallBegin)*0.000001; -#ifdef _WIN64 - /* microsecond precision on 64-bit windows */ - cli_printf(p->out, "Run Time: real %.6f user %f sys %f\n", - p->prevTimer, - timeDiff(&ftUserBegin, &ftUserEnd), - timeDiff(&ftKernelBegin, &ftKernelEnd)); -#else - /* millisecond precisino on 32-bit windows */ - cli_printf(p->out, "Run Time: real %.3f user %.3f sys %.3f\n", - p->prevTimer, - timeDiff(&ftUserBegin, &ftUserEnd), - timeDiff(&ftKernelBegin, &ftKernelEnd)); -#endif - if( p->enableTimer==1 ) p->enableTimer = 0; - ftWallBegin = 0; - } -} - -#define BEGIN_TIMER(X) beginTimer(X) -#define ELAPSE_TIME(X) elapseTime(X) -#define END_TIMER(X) endTimer(X) -#define HAS_TIMER hasTimer() - -#else -#define BEGIN_TIMER(X) /* no-op */ -#define ELAPSE_TIME(X) 0.0 -#define END_TIMER(X) /*no-op*/ -#define HAS_TIMER 0 -#endif -/************************* END PERFORMANCE TIMER ******************************/ - -/* -** Clear a display mode, freeing any allocated memory that it -** contains. -*/ -static void modeFree(Mode *p){ - u8 autoExplain = p->autoExplain; - free(p->spec.aWidth); - free(p->spec.aAlign); - free(p->spec.zColumnSep); - free(p->spec.zRowSep); - free(p->spec.zTableName); - free(p->spec.zNull); - memset(p, 0, sizeof(*p)); - p->spec.iVersion = 1; - p->autoExplain = autoExplain; -} - -/* -** Duplicate Mode pSrc into pDest. pDest is assumed to be -** uninitialized prior to invoking this routine. -*/ -static void modeDup(Mode *pDest, Mode *pSrc){ - memcpy(pDest, pSrc, sizeof(*pDest)); - if( pDest->spec.aWidth ){ - size_t sz = sizeof(pSrc->spec.aWidth[0]) * pSrc->spec.nWidth; - pDest->spec.aWidth = malloc( sz ); - if( pDest->spec.aWidth ){ - memcpy(pDest->spec.aWidth, pSrc->spec.aWidth, sz); - }else{ - pDest->spec.nWidth = 0; - } - } - if( pDest->spec.aAlign ){ - size_t sz = sizeof(pSrc->spec.aAlign[0]) * pSrc->spec.nAlign; - pDest->spec.aAlign = malloc( sz ); - if( pDest->spec.aAlign ){ - memcpy(pDest->spec.aAlign, pSrc->spec.aAlign, sz); - }else{ - pDest->spec.nAlign = 0; - } - } - if( pDest->spec.zColumnSep ){ - pDest->spec.zColumnSep = strdup(pSrc->spec.zColumnSep); - } - if( pDest->spec.zRowSep ){ - pDest->spec.zRowSep = strdup(pSrc->spec.zRowSep); - } - if( pDest->spec.zTableName ){ - pDest->spec.zTableName = strdup(pSrc->spec.zTableName); - } - if( pDest->spec.zNull ){ - pDest->spec.zNull = strdup(pSrc->spec.zNull); - } -} - -/* -** Set a string value to a copy of the zNew string in memory -** obtained from system malloc(). -*/ -static void modeSetStr(char **az, const char *zNew){ - free(*az); - if( zNew==0 ){ - *az = 0; - }else{ - size_t n = strlen(zNew); - *az = malloc( n+1 ); - if( *az ){ - memcpy(*az, zNew, n+1 ); - } - } -} - -/* -** Change the mode to eMode -*/ -static void modeChange(ShellState *p, unsigned char eMode){ - const ModeInfo *pI; - if( eModemode; - pI = &aModeInfo[eMode]; - pM->eMode = eMode; - if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]); - if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]); - if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]); - pM->spec.eText = pI->eText; - pM->spec.eBlob = pI->eBlob; - if( (pM->mFlags & MFLG_HDR)==0 ){ - pM->spec.bTitles = pI->bHdr; - } - pM->spec.eTitle = pI->eHdr; - if( pI->mFlg & 0x01 ){ - pM->spec.bBorder = QRF_No; - }else{ - pM->spec.bBorder = QRF_Auto; - } - if( pI->mFlg & 0x02 ){ - pM->spec.bSplitColumn = QRF_Yes; - pM->bAutoScreenWidth = 1; - }else{ - pM->spec.bSplitColumn = QRF_No; - } - }else if( eMode>=MODE_USER && eMode-MODE_USERnSavedModes ){ - modeFree(&p->mode); - modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode); - }else if( eMode==MODE_BATCH ){ - u8 mFlags = p->mode.mFlags; - modeFree(&p->mode); - modeChange(p, MODE_List); - p->mode.mFlags = mFlags; - }else if( eMode==MODE_TTY ){ - u8 mFlags = p->mode.mFlags; - modeFree(&p->mode); - modeChange(p, MODE_QBox); - p->mode.bAutoScreenWidth = 1; - p->mode.spec.eText = QRF_TEXT_Relaxed; - p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT; - p->mode.spec.nLineLimit = DFLT_LINE_LIMIT; - p->mode.spec.bTextJsonb = QRF_Yes; - p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT; - p->mode.mFlags = mFlags; - } -} - -/* -** Set the mode to the default. It assumed that the mode has -** already been freed and zeroed prior to calling this routine. -*/ -static void modeDefault(ShellState *p){ - p->mode.spec.iVersion = 1; - p->mode.autoExplain = 1; - if( stdin_is_interactive || stdout_is_console ){ - modeChange(p, MODE_TTY); - }else{ - modeChange(p, MODE_BATCH); - } -} - -/* -** Find the number of a display mode given its name. Return -1 if -** the name does not match any mode. -** -** Saved modes are also searched if p!=NULL. The number returned -** for a saved mode is the index into the p->aSavedModes[] array -** plus MODE_USER. -** -** Two special mode names are also available: "batch" and "tty". -** evaluate to the default mode for batch operation and interactive -** operation on a TTY, respectively. -*/ -static int modeFind(ShellState *p, const char *zName){ - int i; - for(i=0; inSavedModes; i++){ - if( cli_strcmp(p->aSavedModes[i].zTag,zName)==0 ) return i+MODE_USER; - } - if( strcmp(zName,"batch")==0 ) return MODE_BATCH; - if( strcmp(zName,"tty")==0 ) return MODE_TTY; - return -1; -} - -/* -** Save or restore the current output mode -*/ -static void modePush(ShellState *p){ - if( p->nPopMode==0 ){ - modeFree(&p->modePrior); - modeDup(&p->modePrior,&p->mode); - } -} -static void modePop(ShellState *p){ - if( p->modePrior.spec.iVersion>0 ){ - modeFree(&p->mode); - p->mode = p->modePrior; - memset(&p->modePrior, 0, sizeof(p->modePrior)); - } -} - - -/* -** A callback for the sqlite3_log() interface. -*/ -static void shellLog(void *pArg, int iErrCode, const char *zMsg){ - ShellState *p = (ShellState*)pArg; - if( p->pLog==0 ) return; - cli_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); - fflush(p->pLog); -} - -/* -** SQL function: shell_putsnl(X) -** -** Write the text X to the screen (or whatever output is being directed) -** adding a newline at the end, and then return X. -*/ -static void shellPutsFunc( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - ShellState *p = (ShellState*)sqlite3_user_data(pCtx); - (void)nVal; - cli_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); - sqlite3_result_value(pCtx, apVal[0]); -} - -/* -** Compute the name of the location of an input error in memory -** obtained from sqlite3_malloc(). -*/ -static char *shellErrorLocation(ShellState *p){ - char *zLoc; - if( p->zErrPrefix ){ - zLoc = sqlite3_mprintf("%s", p->zErrPrefix); - }else if( p->zInFile==0 || strcmp(p->zInFile,"")==0){ - zLoc = sqlite3_mprintf("line %lld:", p->lineno); - }else{ - zLoc = sqlite3_mprintf("%s:%lld:", p->zInFile, p->lineno); - } - return zLoc; -} - -/* -** If in safe mode, print an error message described by the arguments -** and exit immediately. -*/ -static void failIfSafeMode( - ShellState *p, - const char *zErrMsg, - ... -){ - if( p->bSafeMode ){ - va_list ap; - char *zMsg; - char *zLoc = shellErrorLocation(p); - va_start(ap, zErrMsg); - zMsg = sqlite3_vmprintf(zErrMsg, ap); - va_end(ap); - cli_printf(stderr, "%s %s\n", zLoc, zMsg); - cli_exit(1); - } -} - -/* -** Issue an error message from a dot-command. -*/ -static void dotCmdError( - ShellState *p, /* Shell state */ - int iArg, /* Index of argument on which error occurred */ - const char *zBrief, /* Brief (<20 character) error description */ - const char *zDetail, /* Error details */ - ... -){ - FILE *out = stderr; - char *zLoc = shellErrorLocation(p); - if( zBrief!=0 && iArg>=0 && iArgdot.nArg ){ - int i = p->dot.aiOfst[iArg]; - int nPrompt = strlen30(zBrief) + 5; - cli_printf(out, "%s %s\n", zLoc, p->dot.zOrig); - if( i > nPrompt ){ - cli_printf(out, "%s %*s%s ---^\n", zLoc, 1+i-nPrompt, "", zBrief); - }else{ - cli_printf(out, "%s %*s^--- %s\n", zLoc, i, "", zBrief); - } - } - if( zDetail ){ - char *zMsg; - va_list ap; - va_start(ap, zDetail); - zMsg = sqlite3_vmprintf(zDetail,ap); - va_end(ap); - cli_printf(out,"%s %s\n", zLoc, zMsg); - sqlite3_free(zMsg); - } - sqlite3_free(zLoc); -} - - -/* -** SQL function: edit(VALUE) -** edit(VALUE,EDITOR) -** -** These steps: -** -** (1) Write VALUE into a temporary file. -** (2) Run program EDITOR on that temporary file. -** (3) Read the temporary file back and return its content as the result. -** (4) Delete the temporary file -** -** If the EDITOR argument is omitted, use the value in the VISUAL -** environment variable. If still there is no EDITOR, through an error. -** -** Also throw an error if the EDITOR program returns a non-zero exit code. -*/ -#ifndef SQLITE_NOHAVE_SYSTEM -static void editFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *zEditor; - char *zTempFile = 0; - sqlite3 *db; - char *zCmd = 0; - int bBin; - int rc; - int hasCRLF = 0; - FILE *f = 0; - sqlite3_int64 sz; - sqlite3_int64 x; - unsigned char *p = 0; +#ifndef SQLITE_NOHAVE_SYSTEM +static void editFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zEditor; + char *zTempFile = 0; + sqlite3 *db; + char *zCmd = 0; + int bBin; + int rc; + int hasCRLF = 0; + FILE *f = 0; + sqlite3_int64 sz; + sqlite3_int64 x; + unsigned char *p = 0; if( argc==2 ){ zEditor = (const char*)sqlite3_value_text(argv[1]); @@ -25210,12 +21695,28 @@ edit_func_end: } #endif /* SQLITE_NOHAVE_SYSTEM */ +/* +** Save or restore the current output mode +*/ +static void outputModePush(ShellState *p){ + p->modePrior = p->mode; + p->priorShFlgs = p->shellFlgs; + memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator)); + memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator)); +} +static void outputModePop(ShellState *p){ + p->mode = p->modePrior; + p->shellFlgs = p->priorShFlgs; + memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); + memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); +} + /* ** Set output mode to text or binary for Windows. */ static void setCrlfMode(ShellState *p){ #ifdef _WIN32 - if( p->mode.mFlags & MFLG_CRLF ){ + if( p->crlfMode ){ sqlite3_fsetmode(p->out, _O_TEXT); }else{ sqlite3_fsetmode(p->out, _O_BINARY); @@ -25225,6 +21726,126 @@ static void setCrlfMode(ShellState *p){ #endif } +/* +** Output the given string as a hex-encoded blob (eg. X'1234' ) +*/ +static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ + int i; + unsigned char *aBlob = (unsigned char*)pBlob; + + char *zStr = sqlite3_malloc64((i64)nBlob*2 + 1); + shell_check_oom(zStr); + + for(i=0; i> 4) ]; + zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ]; + } + zStr[i*2] = '\0'; + + sqlite3_fprintf(out, "X'%s'", zStr); + sqlite3_free(zStr); +} + +/* +** Output the given string as a quoted string using SQL quoting conventions: +** +** (1) Single quotes (') within the string are doubled +** (2) The while string is enclosed in '...' +** (3) Control characters other than \n, \t, and \r\n are escaped +** using \u00XX notation and if such substitutions occur, +** the whole string is enclosed in unistr('...') instead of '...'. +** +** Step (3) is omitted if the control-character escape mode is OFF. +** +** See also: output_quoted_escaped_string() which does the same except +** that it does not make exceptions for \n, \t, and \r\n in step (3). +*/ +static void output_quoted_string(ShellState *p, const char *zInX){ + int i; + int needUnistr = 0; + int needDblQuote = 0; + const unsigned char *z = (const unsigned char*)zInX; + unsigned char c; + FILE *out = p->out; + sqlite3_fsetmode(out, _O_BINARY); + if( z==0 ) return; + for(i=0; (c = z[i])!=0; i++){ + if( c=='\'' ){ needDblQuote = 1; } + if( c>0x1f ) continue; + if( c=='\t' || c=='\n' ) continue; + if( c=='\r' && z[i+1]=='\n' ) continue; + needUnistr = 1; + break; + } + if( (needDblQuote==0 && needUnistr==0) + || (needDblQuote==0 && p->eEscMode==SHELL_ESC_OFF) + ){ + sqlite3_fprintf(out, "'%s'",z); + }else if( p->eEscMode==SHELL_ESC_OFF ){ + char *zEncoded = sqlite3_mprintf("%Q", z); + sqlite3_fputs(zEncoded, out); + sqlite3_free(zEncoded); + }else{ + if( needUnistr ){ + sqlite3_fputs("unistr('", out); + }else{ + sqlite3_fputs("'", out); + } + while( *z ){ + for(i=0; (c = z[i])!=0; i++){ + if( c=='\'' ) break; + if( c>0x1f ) continue; + if( c=='\t' || c=='\n' ) continue; + if( c=='\r' && z[i+1]=='\n' ) continue; + break; + } + if( i ){ + sqlite3_fprintf(out, "%.*s", i, z); + z += i; + } + if( c==0 ) break; + if( c=='\'' ){ + sqlite3_fputs("''", out); + }else{ + sqlite3_fprintf(out, "\\u%04x", c); + } + z++; + } + if( needUnistr ){ + sqlite3_fputs("')", out); + }else{ + sqlite3_fputs("'", out); + } + } + setCrlfMode(p); +} + +/* +** Output the given string as a quoted string using SQL quoting conventions. +** Additionallly , escape the "\n" and "\r" characters so that they do not +** get corrupted by end-of-line translation facilities in some operating +** systems. +** +** This is like output_quoted_string() but with the addition of the \r\n +** escape mechanism. +*/ +static void output_quoted_escaped_string(ShellState *p, const char *z){ + char *zEscaped; + sqlite3_fsetmode(p->out, _O_BINARY); + if( p->eEscMode==SHELL_ESC_OFF ){ + zEscaped = sqlite3_mprintf("%Q", z); + }else{ + zEscaped = sqlite3_mprintf("%#Q", z); + } + sqlite3_fputs(zEscaped, p->out); + sqlite3_free(zEscaped); + setCrlfMode(p); +} + /* ** Find earliest of chars within s specified in zAny. ** With ns == ~0, is like strpbrk(s,zAny) and s must be 0-terminated. @@ -25288,14 +21909,13 @@ static void output_c_string(FILE *out, const char *z){ static const char *zDQBSRO = "\"\\\x7f"; /* double-quote, backslash, rubout */ char ace[3] = "\\?"; char cbsSay; - cli_puts(zq, out); - if( z==0 ) z = ""; + 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 ){ - cli_printf(out, "%.*s", (int)(pcEnd-z), z); + sqlite3_fprintf(out, "%.*s", (int)(pcEnd-z), z); } if( (c = *pcEnd)==0 ) break; ++pcEnd; @@ -25311,106 +21931,250 @@ static void output_c_string(FILE *out, const char *z){ } if( cbsSay ){ ace[1] = cbsSay; - cli_puts(ace, out); + sqlite3_fputs(ace, out); }else if( !isprint(c&0xff) ){ - cli_printf(out, "\\%03o", c&0xff); + sqlite3_fprintf(out, "\\%03o", c&0xff); }else{ ace[1] = (char)c; - cli_puts(ace+1, out); + sqlite3_fputs(ace+1, out); } z = pcEnd; } - cli_puts(zq, out); + sqlite3_fputs(zq, out); } -/* Encode input string z[] as a C-language string literal and -** append it to the sqlite3_str. If z is NULL render and empty string. +/* +** Output the given string as quoted according to JSON quoting rules. */ -static void append_c_string(sqlite3_str *out, const char *z){ - char c; +static void output_json_string(FILE *out, const char *z, i64 n){ + unsigned char c; static const char *zq = "\""; static long ctrlMask = ~0L; - static const char *zDQBSRO = "\"\\\x7f"; /* double-quote, backslash, rubout */ + static const char *zDQBS = "\"\\"; + const char *pcLimit; char ace[3] = "\\?"; char cbsSay; + if( z==0 ) z = ""; - sqlite3_str_appendall(out,zq); - 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; + pcLimit = z + ((n<0)? strlen(z) : (size_t)n); + 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 ){ - sqlite3_str_appendf(out, "%.*s", (int)(pcEnd-z), z); + sqlite3_fprintf(out, "%.*s", (int)(pcEnd-z), z); + z = pcEnd; } - if( (c = *pcEnd)==0 ) break; - ++pcEnd; + if( z >= pcLimit ) break; + c = (unsigned char)*(z++); switch( c ){ - case '\\': case '"': + case '"': case '\\': cbsSay = (char)c; break; - case '\t': cbsSay = 't'; break; + case '\b': cbsSay = 'b'; break; + case '\f': cbsSay = 'f'; break; case '\n': cbsSay = 'n'; break; case '\r': cbsSay = 'r'; break; - case '\f': cbsSay = 'f'; break; + case '\t': cbsSay = 't'; break; default: cbsSay = 0; break; } if( cbsSay ){ ace[1] = cbsSay; - sqlite3_str_appendall(out,ace); - }else if( !isprint(c&0xff) ){ - sqlite3_str_appendf(out, "\\%03o", c&0xff); + sqlite3_fputs(ace, out); + }else if( c<=0x1f || c>=0x7f ){ + sqlite3_fprintf(out, "\\u%04x", c); }else{ ace[1] = (char)c; - sqlite3_str_appendall(out, ace+1); + sqlite3_fputs(ace+1, out); } - z = pcEnd; } - sqlite3_str_appendall(out, zq); + sqlite3_fputs(zq, out); } /* -** This routine runs when the user presses Ctrl-C +** Escape the input string if it is needed and in accordance with +** eEscMode. +** +** Escaping is needed if the string contains any control characters +** other than \t, \n, and \r\n +** +** If no escaping is needed (the common case) then set *ppFree to NULL +** and return the original string. If escaping is needed, write the +** escaped string into memory obtained from sqlite3_malloc64() or the +** equivalent, and return the new string and set *ppFree to the new string +** as well. +** +** The caller is responsible for freeing *ppFree if it is non-NULL in order +** to reclaim memory. */ -static void interrupt_handler(int NotUsed){ - UNUSED_PARAMETER(NotUsed); - if( ++seenInterrupt>1 ) cli_exit(1); - if( globalDb ) sqlite3_interrupt(globalDb); -} +static const char *escapeOutput( + ShellState *p, + const char *zInX, + char **ppFree +){ + i64 i, j; + i64 nCtrl = 0; + unsigned char *zIn; + unsigned char c; + unsigned char *zOut; -/* Try to determine the screen width. Use the default if unable. -*/ -int shellScreenWidth(void){ - if( stdout_tty_width>0 ){ - return stdout_tty_width; - }else{ -#if defined(TIOCGSIZE) - struct ttysize ts; - if( ioctl(STDIN_FILENO, TIOCGSIZE, &ts)>=0 - || ioctl(STDOUT_FILENO, TIOCGSIZE, &ts)>=0 - || ioctl(STDERR_FILENO, TIOCGSIZE, &ts)>=0 - ){ - return ts.ts_cols; - } -#elif defined(TIOCGWINSZ) - struct winsize ws; - if( ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)>=0 - || ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws)>=0 - || ioctl(STDERR_FILENO, TIOCGWINSZ, &ws)>=0 - ){ - return ws.ws_col; - } -#elif defined(_WIN32) - CONSOLE_SCREEN_BUFFER_INFO csbi; - if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) - || GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi) - || GetConsoleScreenBufferInfo(GetStdHandle(STD_INPUT_HANDLE), &csbi) + + /* No escaping if disabled */ + if( p->eEscMode==SHELL_ESC_OFF ){ + *ppFree = 0; + return zInX; + } + + /* Count the number of control characters in the string. */ + zIn = (unsigned char*)zInX; + for(i=0; (c = zIn[i])!=0; i++){ + if( c<=0x1f + && c!='\t' + && c!='\n' + && (c!='\r' || zIn[i+1]!='\n') ){ - return csbi.srWindow.Right - csbi.srWindow.Left + 1; + nCtrl++; + } + } + if( nCtrl==0 ){ + *ppFree = 0; + return zInX; + } + if( p->eEscMode==SHELL_ESC_SYMBOL ) nCtrl *= 2; + zOut = sqlite3_malloc64( i + nCtrl + 1 ); + shell_check_oom(zOut); + for(i=j=0; (c = zIn[i])!=0; i++){ + if( c>0x1f + || c=='\t' + || c=='\n' + || (c=='\r' && zIn[i+1]=='\n') + ){ + continue; + } + if( i>0 ){ + memcpy(&zOut[j], zIn, i); + j += i; + } + zIn += i+1; + i = -1; + switch( p->eEscMode ){ + case SHELL_ESC_SYMBOL: + zOut[j++] = 0xe2; + zOut[j++] = 0x90; + zOut[j++] = 0x80+c; + break; + case SHELL_ESC_ASCII: + zOut[j++] = '^'; + zOut[j++] = 0x40+c; + break; + } + } + if( i>0 ){ + memcpy(&zOut[j], zIn, i); + j += i; + } + zOut[j] = 0; + *ppFree = (char*)zOut; + return (char*)zOut; +} + +/* +** Output the given string with characters that are special to +** HTML escaped. +*/ +static void output_html_string(FILE *out, const char *z){ + int i; + if( z==0 ) z = ""; + while( *z ){ + for(i=0; z[i] + && z[i]!='<' + && z[i]!='&' + && z[i]!='>' + && z[i]!='\"' + && z[i]!='\''; + i++){} + if( i>0 ){ + sqlite3_fprintf(out, "%.*s",i,z); + } + if( z[i]=='<' ){ + sqlite3_fputs("<", out); + }else if( z[i]=='&' ){ + sqlite3_fputs("&", out); + }else if( z[i]=='>' ){ + sqlite3_fputs(">", out); + }else if( z[i]=='\"' ){ + sqlite3_fputs(""", out); + }else if( z[i]=='\'' ){ + sqlite3_fputs("'", out); + }else{ + break; + } + z += i + 1; + } +} + +/* +** If a field contains any character identified by a 1 in the following +** array, then the string must be quoted for CSV. +*/ +static const char needCsvQuote[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +/* +** Output a single term of CSV. Actually, p->colSeparator is used for +** the separator, which may or may not be a comma. p->nullValue is +** the null value. Strings are quoted if necessary. The separator +** is only issued if bSep is true. +*/ +static void output_csv(ShellState *p, const char *z, int bSep){ + if( z==0 ){ + sqlite3_fprintf(p->out, "%s",p->nullValue); + }else{ + unsigned i; + for(i=0; z[i]; i++){ + if( needCsvQuote[((unsigned char*)z)[i]] ){ + i = 0; + break; + } + } + if( i==0 || strstr(z, p->colSeparator)!=0 ){ + char *zQuoted = sqlite3_mprintf("\"%w\"", z); + shell_check_oom(zQuoted); + sqlite3_fputs(zQuoted, p->out); + sqlite3_free(zQuoted); + }else{ + sqlite3_fputs(z, p->out); } -#endif -#define DEFAULT_SCREEN_WIDTH 80 - return DEFAULT_SCREEN_WIDTH; } + if( bSep ){ + sqlite3_fputs(p->colSeparator, p->out); + } +} + +/* +** This routine runs when the user presses Ctrl-C +*/ +static void interrupt_handler(int NotUsed){ + UNUSED_PARAMETER(NotUsed); + if( ++seenInterrupt>1 ) exit(1); + if( globalDb ) sqlite3_interrupt(globalDb); } #if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) @@ -25446,7 +22210,6 @@ static int safeModeAuth( "fts3_tokenizer", "load_extension", "readfile", - "realpath", "writefile", "zipfile", "zipfile_cds", @@ -25509,23 +22272,23 @@ static int shellAuth( az[1] = zA2; az[2] = zA3; az[3] = zA4; - cli_printf(p->out, "authorizer: %s", azAction[op]); + sqlite3_fprintf(p->out, "authorizer: %s", azAction[op]); for(i=0; i<4; i++){ - cli_puts(" ", p->out); + sqlite3_fputs(" ", p->out); if( az[i] ){ output_c_string(p->out, az[i]); }else{ - cli_puts("NULL", p->out); + sqlite3_fputs("NULL", p->out); } } - cli_puts("\n", p->out); + sqlite3_fputs("\n", p->out); if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4); return SQLITE_OK; } #endif /* -** Print a schema statement. This is helper routine to dump_callbac(). +** Print a schema statement. Part of MODE_Semi and MODE_Pretty output. ** ** This routine converts some CREATE TABLE statements for shadow tables ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements. @@ -25556,12 +22319,18 @@ static void printSchemaLine(FILE *out, const char *z, const char *zTail){ } } if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){ - cli_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); + sqlite3_fprintf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); }else{ - cli_printf(out, "%s%s", z, zTail); + sqlite3_fprintf(out, "%s%s", z, zTail); } sqlite3_free(zToFree); } +static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){ + char c = z[n]; + z[n] = 0; + printSchemaLine(out, z, zTail); + z[n] = c; +} /* ** Return true if string z[] has nothing but whitespace and comments to the @@ -25579,130 +22348,95 @@ static int wsToEol(const char *z){ } /* -** SQL Function: shell_format_schema(SQL,FLAGS) -** -** This function is internally by the CLI to assist with the -** ".schema", ".fullschema", and ".dump" commands. The first -** argument is the value from sqlite_schema.sql. The value returned -** is a modification of the input that can actually be run as SQL -** to recreate the schema object. -** -** When FLAGS is zero, the only changes is to append ";". If the -** 0x01 bit of FLAGS is set, then transformations are made to implement -** ".schema --indent". +** Add a new entry to the EXPLAIN QUERY PLAN data */ -static void shellFormatSchema( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - int flags; /* Value of 2nd parameter */ - const char *zSql; /* Value of 1st parameter */ - int nSql; /* Bytes of text in zSql[] */ - sqlite3_str *pOut; /* Output buffer */ - char *z; /* Writable copy of zSql */ - int i, j; /* Loop counters */ - int nParen = 0; - char cEnd = 0; - char c; - int nLine = 0; - int isIndex; - int isWhere = 0; +static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ + EQPGraphRow *pNew; + i64 nText; + if( zText==0 ) return; + nText = strlen(zText); + if( p->autoEQPtest ){ + sqlite3_fprintf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); + } + pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); + shell_check_oom(pNew); + pNew->iEqpId = iEqpId; + pNew->iParentId = p2; + memcpy(pNew->zText, zText, nText+1); + pNew->pNext = 0; + if( p->sGraph.pLast ){ + p->sGraph.pLast->pNext = pNew; + }else{ + p->sGraph.pRow = pNew; + } + p->sGraph.pLast = pNew; +} - assert( nVal==2 ); - pOut = sqlite3_str_new(sqlite3_context_db_handle(pCtx)); - nSql = sqlite3_value_bytes(apVal[0]); - zSql = (const char*)sqlite3_value_text(apVal[0]); - if( zSql==0 || zSql[0]==0 ) goto shellFormatSchema_finish; - flags = sqlite3_value_int(apVal[1]); - if( (flags & 0x01)==0 ){ - sqlite3_str_append(pOut, zSql, nSql); - sqlite3_str_append(pOut, ";", 1); - goto shellFormatSchema_finish; - } - if( sqlite3_strlike("CREATE VIEW%", zSql, 0)==0 - || sqlite3_strlike("CREATE TRIG%", zSql, 0)==0 - ){ - sqlite3_str_append(pOut, zSql, nSql); - sqlite3_str_append(pOut, ";", 1); - goto shellFormatSchema_finish; +/* +** Free and reset the EXPLAIN QUERY PLAN data that has been collected +** in p->sGraph. +*/ +static void eqp_reset(ShellState *p){ + EQPGraphRow *pRow, *pNext; + for(pRow = p->sGraph.pRow; pRow; pRow = pNext){ + pNext = pRow->pNext; + sqlite3_free(pRow); } - isIndex = sqlite3_strlike("CREATE INDEX%", zSql, 0)==0 - || sqlite3_strlike("CREATE UNIQUE INDEX%", zSql, 0)==0; - z = sqlite3_mprintf("%s", zSql); - if( z==0 ){ - sqlite3_str_free(pOut); - sqlite3_result_error_nomem(pCtx); - return; + memset(&p->sGraph, 0, sizeof(p->sGraph)); +} + +/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after +** pOld, or return the first such line if pOld is NULL +*/ +static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){ + EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; + while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; + return pRow; +} + +/* Render a single level of the graph that has iEqpId as its parent. Called +** recursively to render sublevels. +*/ +static void eqp_render_level(ShellState *p, int iEqpId){ + EQPGraphRow *pRow, *pNext; + i64 n = strlen(p->sGraph.zPrefix); + char *z; + for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ + pNext = eqp_next_row(p, iEqpId, pRow); + z = pRow->zText; + 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); + p->sGraph.zPrefix[n] = 0; + } } - j = 0; - for(i=0; IsSpace(z[i]); i++){} - for(; (c = z[i])!=0; i++){ - if( IsSpace(c) ){ - if( z[j-1]=='\r' ) z[j-1] = '\n'; - if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; - }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ - j--; - } - z[j++] = c; - } - while( j>0 && IsSpace(z[j-1]) ){ j--; } - z[j] = 0; - if( strlen30(z)>=79 ){ - for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */ - if( c==cEnd ){ - cEnd = 0; - }else if( cEnd!=0){ - /* No-op */ - }else if( c=='"' || c=='\'' || c=='`' ){ - cEnd = c; - }else if( c=='[' ){ - cEnd = ']'; - }else if( c=='-' && z[i+1]=='-' ){ - cEnd = '\n'; - }else if( c=='(' ){ - nParen++; - }else if( c==')' ){ - nParen--; - if( nLine>0 && nParen==0 && j>0 && !isWhere ){ - sqlite3_str_append(pOut, z, j); - sqlite3_str_append(pOut, "\n", 1); - j = 0; - } - }else if( (c=='w' || c=='W') - && nParen==0 && isIndex - && sqlite3_strnicmp("WHERE",&z[i],5)==0 - && !IsAlnum(z[i+5]) && z[i+5]!='_' ){ - isWhere = 1; - }else if( isWhere && (c=='A' || c=='a') - && nParen==0 - && sqlite3_strnicmp("AND",&z[i],3)==0 - && !IsAlnum(z[i+3]) && z[i+3]!='_' ){ - sqlite3_str_append(pOut, z, j); - sqlite3_str_append(pOut, "\n ", 5); - j = 0; - } - z[j++] = c; - if( nParen==1 && cEnd==0 - && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) - && !isWhere - ){ - if( c=='\n' ) j--; - sqlite3_str_append(pOut, z, j); - sqlite3_str_append(pOut, "\n ", 3); - j = 0; - nLine++; - while( IsSpace(z[i+1]) ){ i++; } +} + +/* +** Display and reset the EXPLAIN QUERY PLAN data +*/ +static void eqp_render(ShellState *p, i64 nCycle){ + EQPGraphRow *pRow = p->sGraph.pRow; + if( pRow ){ + if( pRow->zText[0]=='-' ){ + if( pRow->pNext==0 ){ + eqp_reset(p); + return; } + sqlite3_fprintf(p->out, "%s\n", pRow->zText+3); + p->sGraph.pRow = pRow->pNext; + sqlite3_free(pRow); + }else if( nCycle>0 ){ + sqlite3_fprintf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle); + }else{ + sqlite3_fputs("QUERY PLAN\n", p->out); } - z[j] = 0; + p->sGraph.zPrefix[0] = 0; + eqp_render_level(p, 0); + eqp_reset(p); } - sqlite3_str_appendall(pOut, z); - sqlite3_str_append(pOut, ";", 1); - sqlite3_free(z); - -shellFormatSchema_finish: - sqlite3_result_text(pCtx, sqlite3_str_finish(pOut), -1, sqlite3_free); } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK @@ -25712,134 +22446,605 @@ shellFormatSchema_finish: static int progress_handler(void *pClientData) { ShellState *p = (ShellState*)pClientData; p->nProgress++; - if( (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 - && ELAPSE_TIME(p)>=p->tmProgress - ){ - cli_printf(p->out, "Progress timeout after %.6f seconds\n", - ELAPSE_TIME(p)); - return 1; - } if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ - cli_printf(p->out, "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 ){ - cli_printf(p->out, "Progress %u\n", p->nProgress); + sqlite3_fprintf(p->out, "Progress %u\n", p->nProgress); } return 0; } #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ /* -** This is the callback routine from sqlite3_exec() that appends all -** output onto the end of a ShellText object. -*/ -static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){ - ShellText *p = (ShellText*)pArg; - int i; - UNUSED_PARAMETER(az); - if( azArg==0 ) return 0; - if( p->n ) appendText(p, "|", 0); - for(i=0; idb, - "SAVEPOINT selftest_init;\n" - "CREATE TABLE IF NOT EXISTS selftest(\n" - " tno INTEGER PRIMARY KEY,\n" /* Test number */ - " op TEXT,\n" /* Operator: memo run */ - " cmd TEXT,\n" /* Command text */ - " ans TEXT\n" /* Desired answer */ - ");" - "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n" - "INSERT INTO [_shell$self](rowid,op,cmd)\n" - " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n" - " 'memo','Tests generated by --init');\n" - "INSERT INTO [_shell$self]\n" - " SELECT 'run',\n" - " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql " - "FROM sqlite_schema ORDER BY 2'',224))',\n" - " hex(sha3_query('SELECT type,name,tbl_name,sql " - "FROM sqlite_schema ORDER BY 2',224));\n" - "INSERT INTO [_shell$self]\n" - " SELECT 'run'," - " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||" - " printf('%w',name) || '\" NOT INDEXED'',224))',\n" - " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n" - " FROM (\n" - " SELECT name FROM sqlite_schema\n" - " WHERE type='table'\n" - " AND name<>'selftest'\n" - " AND coalesce(rootpage,0)>0\n" - " )\n" - " ORDER BY name;\n" - "INSERT INTO [_shell$self]\n" - " VALUES('run','PRAGMA integrity_check','ok');\n" - "INSERT INTO selftest(tno,op,cmd,ans)" - " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" - "DROP TABLE [_shell$self];" - ,0,0,&zErrMsg); - if( zErrMsg ){ - cli_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); - sqlite3_free(zErrMsg); +static void print_dashes(FILE *out, int N){ + const char zDash[] = "--------------------------------------------------"; + const int nDash = sizeof(zDash) - 1; + while( N>nDash ){ + sqlite3_fputs(zDash, out); + N -= nDash; } - sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); + sqlite3_fprintf(out, "%.*s", N, zDash); } - /* -** Set the destination table field of the ShellState structure to -** the name of the table given. Escape any quote characters in the -** table name. +** Print a markdown or table-style row separator using ascii-art */ -static void set_table_name(ShellState *p, const char *zName){ - if( p->zDestTable ){ - sqlite3_free(p->zDestTable); - p->zDestTable = 0; +static void print_row_separator( + ShellState *p, + int nArg, + const char *zSep +){ + int i; + if( nArg>0 ){ + sqlite3_fputs(zSep, p->out); + print_dashes(p->out, p->actualWidth[0]+2); + for(i=1; iout); + print_dashes(p->out, p->actualWidth[i]+2); + } + sqlite3_fputs(zSep, p->out); } - if( zName==0 ) return; - p->zDestTable = sqlite3_mprintf("%s", zName); - shell_check_oom(p->zDestTable); + sqlite3_fputs("\n", p->out); } /* -** Maybe construct two lines of text that point out the position of a -** syntax error. Return a pointer to the text, in memory obtained from -** sqlite3_malloc(). Or, if the most recent error does not involve a -** specific token that we can point to, return an empty string. -** -** In all cases, the memory returned is obtained from sqlite3_malloc64() -** and should be released by the caller invoking sqlite3_free(). +** This is the callback routine that the shell +** invokes for each row of a query result. */ -static char *shell_error_context(const char *zSql, sqlite3 *db){ - int iOffset; - size_t len; - char *zCode; - char *zMsg; +static int shell_callback( + void *pArg, + int nArg, /* Number of result columns */ + char **azArg, /* Text of each result column */ + char **azCol, /* Column names */ + int *aiType /* Column types. Might be NULL */ +){ int i; - if( db==0 - || zSql==0 - || (iOffset = sqlite3_error_offset(db))<0 - || iOffset>=(int)strlen(zSql) - ){ - return sqlite3_mprintf(""); - } - while( iOffset>50 ){ - iOffset--; - zSql++; - while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; } - } + ShellState *p = (ShellState*)pArg; + + if( azArg==0 ) return 0; + switch( p->cMode ){ + case MODE_Count: + case MODE_Off: { + break; + } + case MODE_Line: { + int w = 5; + if( azArg==0 ) break; + for(i=0; iw ) w = len; + } + if( p->cnt++>0 ) sqlite3_fputs(p->rowSeparator, p->out); + for(i=0; inullValue, &pFree); + sqlite3_fprintf(p->out, "%*s = %s%s", w, azCol[i], + pDisplay, p->rowSeparator); + if( pFree ) sqlite3_free(pFree); + } + break; + } + case MODE_ScanExp: + 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, 15, 6, 13, 4, 4, 4, 13, 2, 13}; + static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 }; + + const int *aWidth = aExplainWidth; + const int *aMap = aExplainMap; + int nWidth = ArraySize(aExplainWidth); + int iIndent = 1; + + if( p->cMode==MODE_ScanExp ){ + aWidth = aScanExpWidth; + aMap = aScanExpMap; + nWidth = ArraySize(aScanExpWidth); + iIndent = 3; + } + if( nArg>nWidth ) nArg = nWidth; + + /* If this is the first row seen, print out the headers */ + if( p->cnt++==0 ){ + for(i=0; iout, aWidth[i], azCol[ aMap[i] ]); + sqlite3_fputs(i==nArg-1 ? "\n" : " ", p->out); + } + for(i=0; iout, aWidth[i]); + sqlite3_fputs(i==nArg-1 ? "\n" : " ", p->out); + } + } + + /* If there is no data, exit early. */ + if( azArg==0 ) break; + + for(i=0; iw ){ + w = strlenChar(zVal); + zSep = " "; + } + if( i==iIndent && p->aiIndent && p->pStmt ){ + if( p->iIndentnIndent ){ + sqlite3_fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); + } + p->iIndent++; + } + 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(p->out, azArg[0], ";\n"); + break; + } + case MODE_Pretty: { /* .schema and .fullschema with --indent */ + char *z; + int j; + int nParen = 0; + char cEnd = 0; + char c; + int nLine = 0; + int isIndex; + int isWhere = 0; + assert( nArg==1 ); + if( azArg[0]==0 ) break; + if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 + || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 + ){ + sqlite3_fprintf(p->out, "%s;\n", azArg[0]); + break; + } + isIndex = sqlite3_strlike("CREATE INDEX%", azArg[0], 0)==0 + || sqlite3_strlike("CREATE UNIQUE INDEX%", azArg[0], 0)==0; + z = sqlite3_mprintf("%s", azArg[0]); + shell_check_oom(z); + j = 0; + for(i=0; IsSpace(z[i]); i++){} + for(; (c = z[i])!=0; i++){ + if( IsSpace(c) ){ + if( z[j-1]=='\r' ) z[j-1] = '\n'; + if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; + }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ + j--; + } + z[j++] = c; + } + while( j>0 && IsSpace(z[j-1]) ){ j--; } + z[j] = 0; + if( strlen30(z)>=79 ){ + for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */ + if( c==cEnd ){ + cEnd = 0; + }else if( c=='"' || c=='\'' || c=='`' ){ + cEnd = c; + }else if( c=='[' ){ + cEnd = ']'; + }else if( c=='-' && z[i+1]=='-' ){ + cEnd = '\n'; + }else if( c=='(' ){ + nParen++; + }else if( c==')' ){ + nParen--; + if( nLine>0 && nParen==0 && j>0 && !isWhere ){ + printSchemaLineN(p->out, z, j, "\n"); + j = 0; + } + }else if( (c=='w' || c=='W') + && nParen==0 && isIndex + && sqlite3_strnicmp("WHERE",&z[i],5)==0 + && !IsAlnum(z[i+5]) && z[i+5]!='_' ){ + isWhere = 1; + }else if( isWhere && (c=='A' || c=='a') + && nParen==0 + && sqlite3_strnicmp("AND",&z[i],3)==0 + && !IsAlnum(z[i+3]) && z[i+3]!='_' ){ + printSchemaLineN(p->out, z, j, "\n "); + j = 0; + } + z[j++] = c; + if( nParen==1 && cEnd==0 + && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) + && !isWhere + ){ + if( c=='\n' ) j--; + printSchemaLineN(p->out, z, j, "\n "); + j = 0; + nLine++; + while( IsSpace(z[i+1]) ){ i++; } + } + } + z[j] = 0; + } + printSchemaLine(p->out, z, ";\n"); + sqlite3_free(z); + break; + } + case MODE_List: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout, "%s%s", zOut, + i==nArg-1 ? p->rowSeparator : p->colSeparator); + if( pFree ) sqlite3_free(pFree); + } + } + if( azArg==0 ) break; + for(i=0; inullValue; + zOut = escapeOutput(p, z, &pFree); + sqlite3_fputs(zOut, p->out); + if( pFree ) sqlite3_free(pFree); + sqlite3_fputs((icolSeparator : p->rowSeparator, p->out); + } + break; + } + case MODE_Www: + case MODE_Html: { + if( p->cnt==0 && p->cMode==MODE_Www ){ + sqlite3_fputs( + "\n" + "\n" + ,p->out + ); + } + if( p->cnt==0 && (p->showHeader || p->cMode==MODE_Www) ){ + sqlite3_fputs("", p->out); + for(i=0; i", p->out); + output_html_string(p->out, azCol[i]); + sqlite3_fputs("\n", p->out); + } + sqlite3_fputs("\n", p->out); + } + p->cnt++; + if( azArg==0 ) break; + sqlite3_fputs("", p->out); + for(i=0; i", p->out); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue); + sqlite3_fputs("\n", p->out); + } + sqlite3_fputs("\n", p->out); + break; + } + case MODE_Tcl: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout, azCol[i] ? azCol[i] : ""); + if(icolSeparator, p->out); + } + sqlite3_fputs(p->rowSeparator, p->out); + } + if( azArg==0 ) break; + for(i=0; iout, azArg[i] ? azArg[i] : p->nullValue); + if(icolSeparator, p->out); + } + sqlite3_fputs(p->rowSeparator, p->out); + break; + } + case MODE_Csv: { + sqlite3_fsetmode(p->out, _O_BINARY); + if( p->cnt++==0 && p->showHeader ){ + for(i=0; irowSeparator, p->out); + } + if( nArg>0 ){ + for(i=0; irowSeparator, p->out); + } + setCrlfMode(p); + break; + } + case MODE_Insert: { + if( azArg==0 ) break; + sqlite3_fprintf(p->out, "INSERT INTO %s",p->zDestTable); + if( p->showHeader ){ + sqlite3_fputs("(", p->out); + for(i=0; i0 ) sqlite3_fputs(",", p->out); + if( quoteChar(azCol[i]) ){ + char *z = sqlite3_mprintf("\"%w\"", azCol[i]); + shell_check_oom(z); + sqlite3_fputs(z, p->out); + sqlite3_free(z); + }else{ + sqlite3_fprintf(p->out, "%s", azCol[i]); + } + } + sqlite3_fputs(")", p->out); + } + p->cnt++; + for(i=0; i0 ? "," : " VALUES(", p->out); + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + sqlite3_fputs("NULL", p->out); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + if( ShellHasFlag(p, SHFLG_Newlines) ){ + output_quoted_string(p, azArg[i]); + }else{ + output_quoted_escaped_string(p, azArg[i]); + } + }else if( aiType && aiType[i]==SQLITE_INTEGER ){ + 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 ){ + sqlite3_fputs("9.0e+999", p->out); + }else if( ur==0xfff0000000000000LL ){ + sqlite3_fputs("-9.0e+999", p->out); + }else{ + sqlite3_int64 ir = (sqlite3_int64)r; + if( r==(double)ir ){ + sqlite3_snprintf(50,z,"%lld.0", ir); + }else{ + sqlite3_snprintf(50,z,"%!.20g", r); + } + 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(p->out, pBlob, nBlob); + }else if( isNumber(azArg[i], 0) ){ + sqlite3_fputs(azArg[i], p->out); + }else if( ShellHasFlag(p, SHFLG_Newlines) ){ + output_quoted_string(p, azArg[i]); + }else{ + output_quoted_escaped_string(p, azArg[i]); + } + } + sqlite3_fputs(");\n", p->out); + break; + } + case MODE_Json: { + if( azArg==0 ) break; + if( p->cnt==0 ){ + sqlite3_fputs("[{", p->out); + }else{ + sqlite3_fputs(",\n{", p->out); + } + p->cnt++; + for(i=0; iout, azCol[i], -1); + sqlite3_fputs(":", p->out); + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_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 ){ + sqlite3_fputs("9.0e+999", p->out); + }else if( ur==0xfff0000000000000LL ){ + sqlite3_fputs("-9.0e+999", p->out); + }else{ + sqlite3_snprintf(50,z,"%!.20g", r); + 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(p->out, pBlob, nBlob); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + output_json_string(p->out, azArg[i], -1); + }else{ + sqlite3_fputs(azArg[i], p->out); + } + if( iout); + } + } + sqlite3_fputs("}", p->out); + break; + } + case MODE_Quote: { + if( azArg==0 ) break; + if( p->cnt==0 && p->showHeader ){ + for(i=0; i0 ) sqlite3_fputs(p->colSeparator, p->out); + output_quoted_string(p, azCol[i]); + } + sqlite3_fputs(p->rowSeparator, p->out); + } + p->cnt++; + for(i=0; i0 ) sqlite3_fputs(p->colSeparator, p->out); + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + sqlite3_fputs("NULL", p->out); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + output_quoted_string(p, azArg[i]); + }else if( aiType && aiType[i]==SQLITE_INTEGER ){ + 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); + 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(p->out, pBlob, nBlob); + }else if( isNumber(azArg[i], 0) ){ + sqlite3_fputs(azArg[i], p->out); + }else{ + output_quoted_string(p, azArg[i]); + } + } + sqlite3_fputs(p->rowSeparator, p->out); + break; + } + case MODE_Ascii: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; i0 ) sqlite3_fputs(p->colSeparator, p->out); + sqlite3_fputs(azCol[i] ? azCol[i] : "", p->out); + } + sqlite3_fputs(p->rowSeparator, p->out); + } + if( azArg==0 ) break; + for(i=0; i0 ) sqlite3_fputs(p->colSeparator, p->out); + sqlite3_fputs(azArg[i] ? azArg[i] : p->nullValue, p->out); + } + sqlite3_fputs(p->rowSeparator, p->out); + break; + } + case MODE_EQP: { + eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); + break; + } + } + return 0; +} + +/* +** This is the callback routine that the SQLite library +** invokes for each row of a query result. +*/ +static int callback(void *pArg, int nArg, char **azArg, char **azCol){ + /* since we don't have type info, call the shell_callback with a NULL value */ + return shell_callback(pArg, nArg, azArg, azCol, NULL); +} + +/* +** This is the callback routine from sqlite3_exec() that appends all +** output onto the end of a ShellText object. +*/ +static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){ + ShellText *p = (ShellText*)pArg; + int i; + UNUSED_PARAMETER(az); + if( azArg==0 ) return 0; + if( p->n ) appendText(p, "|", 0); + for(i=0; idb, + "SAVEPOINT selftest_init;\n" + "CREATE TABLE IF NOT EXISTS selftest(\n" + " tno INTEGER PRIMARY KEY,\n" /* Test number */ + " op TEXT,\n" /* Operator: memo run */ + " cmd TEXT,\n" /* Command text */ + " ans TEXT\n" /* Desired answer */ + ");" + "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n" + "INSERT INTO [_shell$self](rowid,op,cmd)\n" + " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n" + " 'memo','Tests generated by --init');\n" + "INSERT INTO [_shell$self]\n" + " SELECT 'run',\n" + " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql " + "FROM sqlite_schema ORDER BY 2'',224))',\n" + " hex(sha3_query('SELECT type,name,tbl_name,sql " + "FROM sqlite_schema ORDER BY 2',224));\n" + "INSERT INTO [_shell$self]\n" + " SELECT 'run'," + " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||" + " printf('%w',name) || '\" NOT INDEXED'',224))',\n" + " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n" + " FROM (\n" + " SELECT name FROM sqlite_schema\n" + " WHERE type='table'\n" + " AND name<>'selftest'\n" + " AND coalesce(rootpage,0)>0\n" + " )\n" + " ORDER BY name;\n" + "INSERT INTO [_shell$self]\n" + " VALUES('run','PRAGMA integrity_check','ok');\n" + "INSERT INTO selftest(tno,op,cmd,ans)" + " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" + "DROP TABLE [_shell$self];" + ,0,0,&zErrMsg); + if( zErrMsg ){ + sqlite3_fprintf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); +} + + +/* +** Set the destination table field of the ShellState structure to +** the name of the table given. Escape any quote characters in the +** table name. +*/ +static void set_table_name(ShellState *p, const char *zName){ + if( p->zDestTable ){ + sqlite3_free(p->zDestTable); + p->zDestTable = 0; + } + if( zName==0 ) return; + if( quoteChar(zName) ){ + p->zDestTable = sqlite3_mprintf("\"%w\"", zName); + }else{ + p->zDestTable = sqlite3_mprintf("%s", zName); + } + shell_check_oom(p->zDestTable); +} + +/* +** Maybe construct two lines of text that point out the position of a +** syntax error. Return a pointer to the text, in memory obtained from +** sqlite3_malloc(). Or, if the most recent error does not involve a +** specific token that we can point to, return an empty string. +** +** In all cases, the memory returned is obtained from sqlite3_malloc64() +** and should be released by the caller invoking sqlite3_free(). +*/ +static char *shell_error_context(const char *zSql, sqlite3 *db){ + int iOffset; + size_t len; + char *zCode; + char *zMsg; + int i; + if( db==0 + || zSql==0 + || (iOffset = sqlite3_error_offset(db))<0 + || iOffset>=(int)strlen(zSql) + ){ + return sqlite3_mprintf(""); + } + while( iOffset>50 ){ + iOffset--; + zSql++; + while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; } + } len = strlen(zSql); if( len>78 ){ len = 78; @@ -25879,7 +23084,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); - cli_printf(p->out, "/**** 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++; @@ -25889,22 +23094,22 @@ static int run_table_dump_query( nResult = sqlite3_column_count(pSelect); while( rc==SQLITE_ROW ){ z = (const char*)sqlite3_column_text(pSelect, 0); - cli_printf(p->out, "%s", z); + sqlite3_fprintf(p->out, "%s", z); for(i=1; iout, ",%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] ){ - cli_puts("\n;\n", p->out); + sqlite3_fputs("\n;\n", p->out); }else{ - cli_puts(";\n", p->out); + sqlite3_fputs(";\n", p->out); } rc = sqlite3_step(pSelect); } rc = sqlite3_finalize(pSelect); if( rc!=SQLITE_OK ){ - cli_printf(p->out, "/**** ERROR: (%d) %s *****/\n", + sqlite3_fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; } @@ -25964,7 +23169,7 @@ static void displayLinuxIoStats(FILE *out){ for(i=0; ipStmt; char z[100]; nCol = sqlite3_column_count(pStmt); - cli_printf(out, "%-36s %d\n", "Number of output columns:", nCol); + sqlite3_fprintf(out, "%-36s %d\n", "Number of output columns:", nCol); for(i=0; istatsOn==3 ){ if( pArg->pStmt ){ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset); - cli_printf(out, "VM-steps: %d\n", iCur); + sqlite3_fprintf(out, "VM-steps: %d\n", iCur); } return 0; } @@ -26070,55 +23275,55 @@ static int display_stats( iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Successful lookaside attempts: %d\n", iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Lookaside failures due to size: %d\n", iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset); - cli_printf(out, + 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); - cli_printf(out, + sqlite3_fprintf(out, "Pager Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); - cli_printf(out, + sqlite3_fprintf(out, "Page cache hits: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); - cli_printf(out, + sqlite3_fprintf(out, "Page cache misses: %d\n", iCur); iHiwtr64 = iCur64 = -1; sqlite3_db_status64(db, SQLITE_DBSTATUS_TEMPBUF_SPILL, &iCur64, &iHiwtr64, 0); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); - cli_printf(out, + sqlite3_fprintf(out, "Page cache writes: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1); - cli_printf(out, + sqlite3_fprintf(out, "Page cache spills: %d\n", iCur); - cli_printf(out, + sqlite3_fprintf(out, "Temporary data spilled to disk: %lld\n", iCur64); sqlite3_db_status64(db, SQLITE_DBSTATUS_TEMPBUF_SPILL, &iCur64, &iHiwtr64, 1); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Schema Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur); } @@ -26126,33 +23331,33 @@ static int display_stats( int iHit, iMiss; iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Fullscan Steps: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Sort Operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); - cli_printf(out, + 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 ){ - cli_printf(out, + sqlite3_fprintf(out, "Bloom filter bypass taken: %d/%d\n", iHit, iHit+iMiss); } iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Virtual Machine Steps: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset); - cli_printf(out, + sqlite3_fprintf(out, "Reprepare operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Number of times run: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset); - cli_printf(out, + sqlite3_fprintf(out, "Memory used by prepared stmt: %d\n", iCur); } @@ -26165,17 +23370,278 @@ static int display_stats( return 0; } -/* -** Disable and restore .wheretrace and .treetrace/.selecttrace settings. -*/ -static unsigned int savedSelectTrace; -static unsigned int savedWhereTrace; -static void disable_debug_trace_modes(void){ - unsigned int zero = 0; - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace); - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero); - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace); - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero); + +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +static int scanStatsHeight(sqlite3_stmt *p, int iEntry){ + int iPid = 0; + int ret = 1; + sqlite3_stmt_scanstatus_v2(p, iEntry, + SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid + ); + while( iPid!=0 ){ + int ii; + for(ii=0; 1; ii++){ + int iId; + int res; + res = sqlite3_stmt_scanstatus_v2(p, ii, + SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iId + ); + if( res ) break; + if( iId==iPid ){ + sqlite3_stmt_scanstatus_v2(p, ii, + SQLITE_SCANSTAT_PARENTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid + ); + } + } + ret++; + } + return ret; +} +#endif + +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +static void display_explain_scanstats( + sqlite3 *db, /* Database to query */ + ShellState *pArg /* Pointer to ShellState */ +){ + static const int f = SQLITE_SCANSTAT_COMPLEX; + sqlite3_stmt *p = pArg->pStmt; + int ii = 0; + i64 nTotal = 0; + int nWidth = 0; + eqp_reset(pArg); + + for(ii=0; 1; ii++){ + const char *z = 0; + int n = 0; + if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){ + break; + } + n = (int)strlen(z) + scanStatsHeight(p, ii)*3; + if( n>nWidth ) nWidth = n; + } + nWidth += 4; + + sqlite3_stmt_scanstatus_v2(p, -1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); + for(ii=0; 1; ii++){ + i64 nLoop = 0; + i64 nRow = 0; + i64 nCycle = 0; + int iId = 0; + int iPid = 0; + const char *zo = 0; + const char *zName = 0; + char *zText = 0; + double rEst = 0.0; + + if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ + break; + } + sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_EST,f,(void*)&rEst); + sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); + sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); + sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); + sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); + sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); + sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NAME,f,(void*)&zName); + + zText = sqlite3_mprintf("%s", zo); + if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ + char *z = 0; + if( nCycle>=0 && nTotal>0 ){ + z = sqlite3_mprintf("%zcycles=%lld [%d%%]", z, + nCycle, ((nCycle*100)+nTotal/2) / nTotal + ); + } + if( nLoop>=0 ){ + z = sqlite3_mprintf("%z%sloops=%lld", z, z ? " " : "", nLoop); + } + if( nRow>=0 ){ + z = sqlite3_mprintf("%z%srows=%lld", z, z ? " " : "", nRow); + } + + if( zName && pArg->scanstatsOn>1 ){ + double rpl = (double)nRow / (double)nLoop; + z = sqlite3_mprintf("%z rpl=%.1f est=%.1f", z, rpl, rEst); + } + + zText = sqlite3_mprintf( + "% *z (%z)", -1*(nWidth-scanStatsHeight(p, ii)*3), zText, z + ); + } + + eqp_append(pArg, iId, iPid, zText); + sqlite3_free(zText); + } + + eqp_render(pArg, nTotal); +} +#endif + + +/* +** Parameter azArray points to a zero-terminated array of strings. zStr +** points to a single nul-terminated string. Return non-zero if zStr +** is equal, according to strcmp(), to any of the strings in the array. +** Otherwise, return zero. +*/ +static int str_in_array(const char *zStr, const char **azArray){ + int i; + for(i=0; azArray[i]; i++){ + if( 0==cli_strcmp(zStr, azArray[i]) ) return 1; + } + return 0; +} + +/* +** If compiled statement pSql appears to be an EXPLAIN statement, allocate +** and populate the ShellState.aiIndent[] array with the number of +** spaces each opcode should be indented before it is output. +** +** The indenting rules are: +** +** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent +** all opcodes that occur between the p2 jump destination and the opcode +** itself by 2 spaces. +** +** * Do the previous for "Return" instructions for when P2 is positive. +** See tag-20220407a in wherecode.c and vdbe.c. +** +** * For each "Goto", if the jump destination is earlier in the program +** and ends on one of: +** Yield SeekGt SeekLt RowSetRead Rewind +** or if the P1 parameter is one instead of zero, +** then indent all opcodes between the earlier instruction +** and "Goto" by 2 spaces. +*/ +static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ + int *abYield = 0; /* True if op is an OP_Yield */ + int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ + int iOp; /* Index of operation in p->aiIndent[] */ + + const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", + "Return", 0 }; + const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", + "Rewind", 0 }; + const char *azGoto[] = { "Goto", 0 }; + + /* The caller guarantees that the leftmost 4 columns of the statement + ** passed to this function are equivalent to the leftmost 4 columns + ** of EXPLAIN statement output. In practice the statement may be + ** an EXPLAIN, or it may be a query on the bytecode() virtual table. */ + assert( sqlite3_column_count(pSql)>=4 ); + assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 0), "addr" ) ); + assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 1), "opcode" ) ); + assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 2), "p1" ) ); + assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 3), "p2" ) ); + + for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ + int i; + int iAddr = sqlite3_column_int(pSql, 0); + const char *zOp = (const char*)sqlite3_column_text(pSql, 1); + int p1 = sqlite3_column_int(pSql, 2); + int p2 = sqlite3_column_int(pSql, 3); + + /* Assuming that p2 is an instruction address, set variable p2op to the + ** index of that instruction in the aiIndent[] array. p2 and p2op may be + ** different if the current instruction is part of a sub-program generated + ** by an SQL trigger or foreign key. */ + int p2op = (p2 + (iOp-iAddr)); + + /* Grow the p->aiIndent array as required */ + if( iOp>=nAlloc ){ + nAlloc += 100; + p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); + shell_check_oom(p->aiIndent); + abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); + shell_check_oom(abYield); + } + + abYield[iOp] = str_in_array(zOp, azYield); + p->aiIndent[iOp] = 0; + p->nIndent = iOp+1; + if( str_in_array(zOp, azNext) && p2op>0 ){ + for(i=p2op; iaiIndent[i] += 2; + } + if( str_in_array(zOp, azGoto) && p2opaiIndent[i] += 2; + } + } + + p->iIndent = 0; + sqlite3_free(abYield); + sqlite3_reset(pSql); +} + +/* +** Free the array allocated by explain_data_prepare(). +*/ +static void explain_data_delete(ShellState *p){ + sqlite3_free(p->aiIndent); + p->aiIndent = 0; + p->nIndent = 0; + p->iIndent = 0; +} + +static void exec_prepared_stmt(ShellState*, sqlite3_stmt*); + +/* +** Display scan stats. +*/ +static void display_scanstats( + sqlite3 *db, /* Database to query */ + ShellState *pArg /* Pointer to ShellState */ +){ +#ifndef SQLITE_ENABLE_STMT_SCANSTATUS + UNUSED_PARAMETER(db); + UNUSED_PARAMETER(pArg); +#else + if( pArg->scanstatsOn==3 ){ + const char *zSql = + " SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec," + " format('% 6s (%.2f%%)'," + " CASE WHEN ncycle<100_000 THEN ncycle || ' '" + " WHEN ncycle<100_000_000 THEN (ncycle/1_000) || 'K'" + " WHEN ncycle<100_000_000_000 THEN (ncycle/1_000_000) || 'M'" + " ELSE (ncycle/1000_000_000) || 'G' END," + " ncycle*100.0/(sum(ncycle) OVER ())" + " ) AS cycles" + " FROM bytecode(?)"; + + int rc = SQLITE_OK; + sqlite3_stmt *pStmt = 0; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc==SQLITE_OK ){ + sqlite3_stmt *pSave = pArg->pStmt; + pArg->pStmt = pStmt; + sqlite3_bind_pointer(pStmt, 1, pSave, "stmt-pointer", 0); + + pArg->cnt = 0; + pArg->cMode = MODE_ScanExp; + explain_data_prepare(pArg, pStmt); + exec_prepared_stmt(pArg, pStmt); + explain_data_delete(pArg); + + sqlite3_finalize(pStmt); + pArg->pStmt = pSave; + } + }else{ + display_explain_scanstats(db, pArg); + } +#endif +} + +/* +** Disable and restore .wheretrace and .treetrace/.selecttrace settings. +*/ +static unsigned int savedSelectTrace; +static unsigned int savedWhereTrace; +static void disable_debug_trace_modes(void){ + unsigned int zero = 0; + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero); } static void restore_debug_trace_modes(void){ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace); @@ -26256,8 +23722,6 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){ memcpy(zBuf, &zVar[6], szVar-5); sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8); } - }else if( strcmp(zVar, "$TIMER")==0 ){ - sqlite3_bind_double(pStmt, i, pArg->prevTimer); #ifdef SQLITE_ENABLE_CARRAY }else if( strncmp(zVar, "$carray_", 8)==0 ){ static char *azColorNames[] = { @@ -26296,59 +23760,633 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){ sqlite3_finalize(pQ); } -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION) /* -** This function is called to process SQL if the previous shell command -** was ".expert". It passes the SQL in the second argument directly to -** the sqlite3expert object. +** UTF8 box-drawing characters. Imagine box lines like this: ** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error -** code. In this case, (*pzErr) may be set to point to a buffer containing -** an English language error message. It is the responsibility of the -** caller to eventually free this buffer using sqlite3_free(). +** 1 +** | +** 4 --+-- 2 +** | +** 3 +** +** Each box characters has between 2 and 4 of the lines leading from +** the center. The characters are here identified by the numbers of +** their corresponding lines. */ -static int expertHandleSQL( - ShellState *pState, - const char *zSql, - char **pzErr +#define BOX_24 "\342\224\200" /* U+2500 --- */ +#define BOX_13 "\342\224\202" /* U+2502 | */ +#define BOX_23 "\342\224\214" /* U+250c ,- */ +#define BOX_34 "\342\224\220" /* U+2510 -, */ +#define BOX_12 "\342\224\224" /* U+2514 '- */ +#define BOX_14 "\342\224\230" /* U+2518 -' */ +#define BOX_123 "\342\224\234" /* U+251c |- */ +#define BOX_134 "\342\224\244" /* U+2524 -| */ +#define BOX_234 "\342\224\254" /* U+252c -,- */ +#define BOX_124 "\342\224\264" /* U+2534 -'- */ +#define BOX_1234 "\342\224\274" /* U+253c -|- */ + +/* Draw horizontal line N characters long using unicode box +** characters +*/ +static void print_box_line(FILE *out, int N){ + const char zDash[] = + BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 + BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24; + const int nDash = sizeof(zDash) - 1; + N *= 3; + while( N>nDash ){ + sqlite3_fputs(zDash, out); + N -= nDash; + } + sqlite3_fprintf(out, "%.*s", N, zDash); +} + +/* +** Draw a horizontal separator for a MODE_Box table. +*/ +static void print_box_row_separator( + ShellState *p, + int nArg, + const char *zSep1, + const char *zSep2, + const char *zSep3 ){ - assert( pState->expert.pExpert ); - assert( pzErr==0 || *pzErr==0 ); - return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr); + int i; + if( nArg>0 ){ + sqlite3_fputs(zSep1, p->out); + print_box_line(p->out, p->actualWidth[0]+2); + for(i=1; iout); + print_box_line(p->out, p->actualWidth[i]+2); + } + sqlite3_fputs(zSep3, p->out); + } + sqlite3_fputs("\n", p->out); } /* -** This function is called either to silently clean up the object -** created by the ".expert" command (if bCancel==1), or to generate a -** report from it and then clean it up (if bCancel==0). +** z[] is a line of text that is to be displayed the .mode box or table or +** similar tabular formats. z[] might contain control characters such +** as \n, \t, \f, or \r. ** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error -** code. In this case, (*pzErr) may be set to point to a buffer containing -** an English language error message. It is the responsibility of the -** caller to eventually free this buffer using sqlite3_free(). +** Compute characters to display on the first line of z[]. Stop at the +** first \r, \n, or \f. Expand \t into spaces. Return a copy (obtained +** from malloc()) of that first line, which caller should free sometime. +** Write anything to display on the next line into *pzTail. If this is +** the last line, write a NULL into *pzTail. (*pzTail is not allocated.) */ -static int expertFinish( - ShellState *pState, - int bCancel, - char **pzErr +static char *translateForDisplayAndDup( + ShellState *p, /* To access current settings */ + const unsigned char *z, /* Input text to be transformed */ + const unsigned char **pzTail, /* OUT: Tail of the input for next line */ + int mxWidth, /* Max width. 0 means no limit */ + u8 bWordWrap /* If true, avoid breaking mid-word */ ){ - int rc = SQLITE_OK; - sqlite3expert *p = pState->expert.pExpert; - FILE *out = pState->out; - assert( p ); - assert( bCancel || pzErr==0 || *pzErr==0 ); - if( bCancel==0 ){ - int bVerbose = pState->expert.bVerbose; + int i; /* Input bytes consumed */ + int j; /* Output bytes generated */ + int k; /* Input bytes to be displayed */ + int n; /* Output column number */ + unsigned char *zOut; /* Output text */ - rc = sqlite3_expert_analyze(p, pzErr); - if( rc==SQLITE_OK ){ - int nQuery = sqlite3_expert_count(p); + if( z==0 ){ + *pzTail = 0; + return 0; + } + if( mxWidth<0 ) mxWidth = -mxWidth; + if( mxWidth==0 ) mxWidth = 1000000; + i = j = n = 0; + while( n=0xc0 ){ + int u; + int len = decodeUtf8(&z[i], &u); + i += len; + j += len; + n += cli_wcwidth(u); + continue; + } + if( c>=' ' ){ + n++; + i++; + j++; + continue; + } + if( c==0 || c=='\n' || (c=='\r' && z[i+1]=='\n') ) break; + if( c=='\t' ){ + do{ + n++; + j++; + }while( (n&7)!=0 && neEscMode==SHELL_ESC_OFF && (k = isVt100(&z[i]))>0 ){ + i += k; + j += k; + }else{ + n++; + j += 3; + i++; + } + } + if( n>=mxWidth && bWordWrap ){ + /* Perhaps try to back up to a better place to break the line */ + for(k=i; k>i/2; k--){ + if( IsSpace(z[k-1]) ) break; + } + if( k<=i/2 ){ + for(k=i; k>i/2; k--){ + if( IsAlnum(z[k-1])!=IsAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break; + } + } + if( k<=i/2 ){ + k = i; + }else{ + i = k; + while( z[i]==' ' ) i++; + } + }else{ + k = i; + } + if( n>=mxWidth && z[i]>=' ' ){ + *pzTail = &z[i]; + }else if( z[i]=='\r' && z[i+1]=='\n' ){ + *pzTail = z[i+2] ? &z[i+2] : 0; + }else if( z[i]==0 || z[i+1]==0 ){ + *pzTail = 0; + }else{ + *pzTail = &z[i+1]; + } + zOut = malloc( j+1 ); + shell_check_oom(zOut); + i = j = n = 0; + while( i=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++; + zOut[j++] = z[i++]; + continue; + } + if( c==0 ) break; + if( z[i]=='\t' ){ + do{ + n++; + zOut[j++] = ' '; + }while( (n&7)!=0 && neEscMode ){ + case SHELL_ESC_SYMBOL: + zOut[j++] = 0xe2; + zOut[j++] = 0x90; + zOut[j++] = 0x80 + c; + break; + case SHELL_ESC_ASCII: + zOut[j++] = '^'; + zOut[j++] = 0x40 + c; + break; + case SHELL_ESC_OFF: { + int nn; + if( c==0x1b && (nn = isVt100(&z[i]))>0 ){ + memcpy(&zOut[j], &z[i], nn); + j += nn; + i += nn - 1; + }else{ + zOut[j++] = c; + } + break; + } + } + i++; + } + zOut[j] = 0; + return (char*)zOut; +} + +/* Return true if the text string z[] contains characters that need +** unistr() escaping. +*/ +static int needUnistr(const unsigned char *z){ + unsigned char c; + if( z==0 ) return 0; + while( (c = *z)>0x1f || c=='\t' || c=='\n' || (c=='\r' && z[1]=='\n') ){ z++; } + return c!=0; +} + +/* Extract the value of the i-th current column for pStmt as an SQL literal +** value. Memory is obtained from sqlite3_malloc64() and must be freed by +** the caller. +*/ +static char *quoted_column(sqlite3_stmt *pStmt, int i){ + switch( sqlite3_column_type(pStmt, i) ){ + case SQLITE_NULL: { + return sqlite3_mprintf("NULL"); + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i)); + } + case SQLITE_TEXT: { + const unsigned char *zText = sqlite3_column_text(pStmt,i); + return sqlite3_mprintf(needUnistr(zText)?"%#Q":"%Q",zText); + } + case SQLITE_BLOB: { + int j; + sqlite3_str *pStr = sqlite3_str_new(0); + const unsigned char *a = sqlite3_column_blob(pStmt,i); + int n = sqlite3_column_bytes(pStmt,i); + sqlite3_str_append(pStr, "x'", 2); + for(j=0; jcmOpts.bWordWrap; + const char *zEmpty = ""; + const char *zShowNull = p->nullValue; + + rc = sqlite3_step(pStmt); + if( rc!=SQLITE_ROW ) return; + nColumn = sqlite3_column_count(pStmt); + if( nColumn==0 ) goto columnar_end; + nAlloc = nColumn*4; + if( nAlloc<=0 ) nAlloc = 1; + azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); + shell_check_oom(azData); + azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) ); + shell_check_oom(azNextLine); + memset((void*)azNextLine, 0, nColumn*sizeof(char*) ); + if( p->cmOpts.bQuote ){ + azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) ); + shell_check_oom(azQuoted); + memset(azQuoted, 0, nColumn*sizeof(char*) ); + } + abRowDiv = sqlite3_malloc64( nAlloc/nColumn ); + shell_check_oom(abRowDiv); + if( nColumn>p->nWidth ){ + p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int)); + shell_check_oom(p->colWidth); + for(i=p->nWidth; icolWidth[i] = 0; + p->nWidth = nColumn; + p->actualWidth = &p->colWidth[nColumn]; + } + memset(p->actualWidth, 0, nColumn*sizeof(int)); + for(i=0; icolWidth[i]; + if( w<0 ) w = -w; + p->actualWidth[i] = w; + } + for(i=0; icolWidth[i]; + if( wx==0 ){ + wx = p->cmOpts.iWrap; + } + if( wx<0 ) wx = -wx; + uz = (const unsigned char*)sqlite3_column_name(pStmt,i); + if( uz==0 ) uz = (u8*)""; + azData[i] = translateForDisplayAndDup(p, uz, &zNotUsed, wx, bw); + } + do{ + int useNextLine = bNextLine; + bNextLine = 0; + if( (nRow+2)*nColumn >= nAlloc ){ + nAlloc *= 2; + azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*)); + shell_check_oom(azData); + abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn); + shell_check_oom(abRowDiv); + } + abRowDiv[nRow] = 1; + nRow++; + for(i=0; icolWidth[i]; + if( wx==0 ){ + wx = p->cmOpts.iWrap; + } + if( wx<0 ) wx = -wx; + if( useNextLine ){ + uz = azNextLine[i]; + if( uz==0 ) uz = (u8*)zEmpty; + }else if( p->cmOpts.bQuote ){ + assert( azQuoted!=0 ); + sqlite3_free(azQuoted[i]); + azQuoted[i] = quoted_column(pStmt,i); + uz = (const unsigned char*)azQuoted[i]; + }else{ + uz = (const unsigned char*)sqlite3_column_text(pStmt,i); + if( uz==0 ) uz = (u8*)zShowNull; + } + azData[nRow*nColumn + i] + = translateForDisplayAndDup(p, uz, &azNextLine[i], wx, bw); + if( azNextLine[i] ){ + bNextLine = 1; + abRowDiv[nRow-1] = 0; + bMultiLineRowExists = 1; + } + } + }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW ); + nTotal = nColumn*(nRow+1); + for(i=0; ip->actualWidth[j] ) p->actualWidth[j] = n; + } + if( seenInterrupt ) goto columnar_end; + switch( p->cMode ){ + case MODE_Column: { + colSep = " "; + rowSep = "\n"; + if( p->showHeader ){ + for(i=0; iactualWidth[i]; + if( p->colWidth[i]<0 ) w = -w; + utf8_width_print(p->out, w, azData[i]); + sqlite3_fputs(i==nColumn-1?"\n":" ", p->out); + } + for(i=0; iout, p->actualWidth[i]); + sqlite3_fputs(i==nColumn-1?"\n":" ", p->out); + } + } + break; + } + case MODE_Table: { + colSep = " | "; + rowSep = " |\n"; + print_row_separator(p, nColumn, "+"); + sqlite3_fputs("| ", p->out); + for(i=0; iactualWidth[i]; + n = strlenChar(azData[i]); + 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; + } + case MODE_Markdown: { + colSep = " | "; + rowSep = " |\n"; + sqlite3_fputs("| ", p->out); + for(i=0; iactualWidth[i]; + n = strlenChar(azData[i]); + 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; + } + case MODE_Box: { + colSep = " " BOX_13 " "; + rowSep = " " BOX_13 "\n"; + print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34); + sqlite3_fputs(BOX_13 " ", p->out); + for(i=0; iactualWidth[i]; + n = strlenChar(azData[i]); + 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" "); + } + print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134); + break; + } + } + for(i=nColumn, j=0; icMode!=MODE_Column ){ + 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(p->out, w, z); + if( j==nColumn-1 ){ + sqlite3_fputs(rowSep, p->out); + if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1cMode==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 ){ + sqlite3_fputs("\n", p->out); + } + } + j = -1; + if( seenInterrupt ) goto columnar_end; + }else{ + sqlite3_fputs(colSep, p->out); + } + } + if( p->cMode==MODE_Table ){ + print_row_separator(p, nColumn, "+"); + }else if( p->cMode==MODE_Box ){ + print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14); + } +columnar_end: + if( seenInterrupt ){ + sqlite3_fputs("Interrupt\n", p->out); + } + nData = (nRow+1)*nColumn; + for(i=0; icMode==MODE_Column + || pArg->cMode==MODE_Table + || pArg->cMode==MODE_Box + || pArg->cMode==MODE_Markdown + ){ + exec_prepared_stmt_columnar(pArg, pStmt); + return; + } + + /* perform the first step. this will tell us if we + ** have a result set or not and how wide it is. + */ + rc = sqlite3_step(pStmt); + /* if we have a result set... */ + if( SQLITE_ROW == rc ){ + /* allocate space for col name ptr, value ptr, and type */ + int nCol = sqlite3_column_count(pStmt); + void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); + if( !pData ){ + shell_out_of_memory(); + }else{ + char **azCols = (char **)pData; /* Names of result columns */ + char **azVals = &azCols[nCol]; /* Results */ + int *aiTypes = (int *)&azVals[nCol]; /* Result types */ + int i, x; + assert(sizeof(int) <= sizeof(char *)); + /* save off ptrs to column names */ + for(i=0; icMode==MODE_Insert || pArg->cMode==MODE_Quote) + ){ + azVals[i] = ""; + }else{ + azVals[i] = (char*)sqlite3_column_text(pStmt, i); + } + if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ + rc = SQLITE_NOMEM; + break; /* from for */ + } + } /* end for */ + + /* if data and types extracted successfully... */ + if( SQLITE_ROW == rc ){ + /* call the supplied callback with the result row data */ + if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){ + rc = SQLITE_ABORT; + }else{ + rc = sqlite3_step(pStmt); + } + } + } while( SQLITE_ROW == rc ); + sqlite3_free(pData); + if( pArg->cMode==MODE_Json ){ + sqlite3_fputs("]\n", pArg->out); + }else if( pArg->cMode==MODE_Www ){ + sqlite3_fputs("
\n
\n", pArg->out);
+      }else if( pArg->cMode==MODE_Count ){
+        char zBuf[200];
+        sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
+                         nRow, nRow!=1 ? "s" : "");
+        printf("%s", zBuf);
+      }
+    }
+  }
+}
+
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
+/*
+** This function is called to process SQL if the previous shell command
+** was ".expert". It passes the SQL in the second argument directly to
+** the sqlite3expert object.
+**
+** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
+** code. In this case, (*pzErr) may be set to point to a buffer containing
+** an English language error message. It is the responsibility of the
+** caller to eventually free this buffer using sqlite3_free().
+*/
+static int expertHandleSQL(
+  ShellState *pState,
+  const char *zSql,
+  char **pzErr
+){
+  assert( pState->expert.pExpert );
+  assert( pzErr==0 || *pzErr==0 );
+  return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
+}
+
+/*
+** This function is called either to silently clean up the object
+** created by the ".expert" command (if bCancel==1), or to generate a
+** report from it and then clean it up (if bCancel==0).
+**
+** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
+** code. In this case, (*pzErr) may be set to point to a buffer containing
+** an English language error message. It is the responsibility of the
+** caller to eventually free this buffer using sqlite3_free().
+*/
+static int expertFinish(
+  ShellState *pState,
+  int bCancel,
+  char **pzErr
+){
+  int rc = SQLITE_OK;
+  sqlite3expert *p = pState->expert.pExpert;
+  FILE *out = pState->out;
+  assert( p );
+  assert( bCancel || pzErr==0 || *pzErr==0 );
+  if( bCancel==0 ){
+    int bVerbose = pState->expert.bVerbose;
+
+    rc = sqlite3_expert_analyze(p, pzErr);
+    if( rc==SQLITE_OK ){
+      int nQuery = sqlite3_expert_count(p);
       int i;
 
       if( bVerbose ){
         const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
-        cli_puts("-- Candidates -----------------------------\n", out);
-        cli_printf(out, "%s\n", zCand);
+        sqlite3_fputs("-- Candidates -----------------------------\n", out);
+        sqlite3_fprintf(out, "%s\n", zCand);
       }
       for(i=0; i=2 && 0==cli_strncmp(z, "-sample", n) ){
       if( i==(nArg-1) ){
-        cli_printf(stderr, "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 ){
-          cli_printf(stderr,"value out of range: %s\n", azArg[i]);
+          sqlite3_fprintf(stderr,"value out of range: %s\n", azArg[i]);
           rc = SQLITE_ERROR;
         }
       }
     }
     else{
-      cli_printf(stderr,"unknown option: %s\n", z);
+      sqlite3_fprintf(stderr,"unknown option: %s\n", z);
       rc = SQLITE_ERROR;
     }
   }
@@ -26415,7 +24453,7 @@ static int expertDotCommand(
   if( rc==SQLITE_OK ){
     pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
     if( pState->expert.pExpert==0 ){
-      cli_printf(stderr,
+      sqlite3_fprintf(stderr,
           "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
       rc = SQLITE_ERROR;
     }else{
@@ -26430,15 +24468,6 @@ static int expertDotCommand(
 }
 #endif /* !SQLITE_OMIT_VIRTUALTABLE && !SQLITE_OMIT_AUTHORIZATION */
 
-/*
-** QRF write callback
-*/
-static int shellWriteQR(void *pX, const char *z, sqlite3_int64 n){
-  ShellState *pArg = (ShellState*)pX;
-  cli_printf(pArg->out, "%.*s", (int)n, z);
-  return SQLITE_OK;
-}
-
 /*
 ** Execute a statement or set of statements.  Print
 ** any result rows/columns depending on the current mode
@@ -26458,31 +24487,10 @@ static int shell_exec(
   int rc2;
   const char *zLeftover;          /* Tail of unprocessed SQL */
   sqlite3 *db = pArg->db;
-  unsigned char eStyle;
-  sqlite3_qrf_spec spec;
 
   if( pzErrMsg ){
     *pzErrMsg = NULL;
   }
-  memcpy(&spec, &pArg->mode.spec, sizeof(spec));
-  spec.xWrite = shellWriteQR;
-  spec.pWriteArg = (void*)pArg;
-  if( pArg->mode.eMode==MODE_Insert && ShellHasFlag(pArg, SHFLG_PreserveRowid) ){
-    spec.bTitles = QRF_SW_On;
-  }
-  assert( pArg->mode.eMode>=0 && pArg->mode.eModemode.eMode].eStyle;
-  if( pArg->mode.bAutoScreenWidth ){
-    spec.nScreenWidth = shellScreenWidth();
-  }
-  if( spec.eBlob==QRF_BLOB_Auto ){
-    switch( spec.eText ){
-      case QRF_TEXT_Relaxed: /* fall through */
-      case QRF_TEXT_Sql:  spec.eBlob = QRF_BLOB_Sql;   break;
-      case QRF_TEXT_Json: spec.eBlob = QRF_BLOB_Json;  break;
-      default:            spec.eBlob = QRF_BLOB_Text;  break;
-    }
-  }
 
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
   if( pArg->expert.pExpert ){
@@ -26491,7 +24499,7 @@ static int shell_exec(
   }
 #endif
 
-  while( zSql && zSql[0] && (SQLITE_OK == rc) ){
+  while( zSql[0] && (SQLITE_OK == rc) ){
     static const char *zStmtSql;
     rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
     if( SQLITE_OK != rc ){
@@ -26499,7 +24507,6 @@ static int shell_exec(
         *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
       }
     }else{
-      int isExplain;
       if( !pStmt ){
         /* this happens for a comment or white-space */
         zSql = zLeftover;
@@ -26510,78 +24517,89 @@ static int shell_exec(
       if( zStmtSql==0 ) zStmtSql = "";
       while( IsSpace(zStmtSql[0]) ) zStmtSql++;
 
-      /* save off the prepared statement handle */
+      /* save off the prepared statement handle and reset row count */
       if( pArg ){
         pArg->pStmt = pStmt;
+        pArg->cnt = 0;
       }
-     
+
       /* Show the EXPLAIN QUERY PLAN if .eqp is on */
-      isExplain = sqlite3_stmt_isexplain(pStmt);
-      if( pArg && pArg->mode.autoEQP && isExplain==0 && pArg->dot.nArg==0 ){
+      if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
+        sqlite3_stmt *pExplain;
         int triggerEQP = 0;
-        u8 savedEnableTimer = pArg->enableTimer;
-        pArg->enableTimer = 0;
         disable_debug_trace_modes();
         sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
-        if( pArg->mode.autoEQP>=AUTOEQP_trigger ){
+        if( pArg->autoEQP>=AUTOEQP_trigger ){
           sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
         }
-        sqlite3_reset(pStmt);
-        spec.eStyle = QRF_STYLE_Auto;
-        sqlite3_stmt_explain(pStmt, 2);
-        sqlite3_format_query_result(pStmt, &spec, 0);
-        if( pArg->mode.autoEQP>=AUTOEQP_full ){
-          sqlite3_reset(pStmt);
-          sqlite3_stmt_explain(pStmt, 1);
-          sqlite3_format_query_result(pStmt, &spec, 0);
+        pExplain = pStmt;
+        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);
+            int iParentId = sqlite3_column_int(pExplain, 1);
+            if( zEQPLine==0 ) zEQPLine = "";
+            if( zEQPLine[0]=='-' ) eqp_render(pArg, 0);
+            eqp_append(pArg, iEqpId, iParentId, zEQPLine);
+          }
+          eqp_render(pArg, 0);
         }
-
-        if( pArg->mode.autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
+        if( pArg->autoEQP>=AUTOEQP_full ){
+          /* Also do an EXPLAIN for ".eqp full" mode */
+          sqlite3_reset(pExplain);
+          rc = sqlite3_stmt_explain(pExplain, 1);
+          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);
+          }
+        }
+        if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
           sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
         }
         sqlite3_reset(pStmt);
         sqlite3_stmt_explain(pStmt, 0);
         restore_debug_trace_modes();
-        pArg->enableTimer = savedEnableTimer;
       }
 
-      bind_prepared_stmt(pArg, pStmt);
-      if( isExplain && pArg->mode.autoExplain ){
-        spec.eStyle = isExplain==1 ? QRF_STYLE_Explain : QRF_STYLE_Eqp;
-        sqlite3_format_query_result(pStmt, &spec, pzErrMsg);
-      }else if( pArg->mode.eMode==MODE_Www ){
-        cli_printf(pArg->out,
-              "
\n" - "\n"); - spec.eStyle = QRF_STYLE_Html; - sqlite3_format_query_result(pStmt, &spec, pzErrMsg); - cli_printf(pArg->out, - "
\n" - "
");
-      }else{
-        spec.eStyle = eStyle;
-        sqlite3_format_query_result(pStmt, &spec, pzErrMsg);
+      if( pArg ){
+        int bIsExplain = (sqlite3_stmt_isexplain(pStmt)==1);
+        pArg->cMode = pArg->mode;
+        if( pArg->autoExplain ){
+          if( bIsExplain ){
+            pArg->cMode = MODE_Explain;
+          }
+          if( sqlite3_stmt_isexplain(pStmt)==2 ){
+            pArg->cMode = MODE_EQP;
+          }
+        }
+
+        /* If the shell is currently in ".explain" mode, gather the extra
+        ** data required to add indents to the output.*/
+        if( pArg->cMode==MODE_Explain && bIsExplain ){
+          explain_data_prepare(pArg, pStmt);
+        }
       }
 
+      bind_prepared_stmt(pArg, pStmt);
+      exec_prepared_stmt(pArg, pStmt);
+      explain_data_delete(pArg);
+      eqp_render(pArg, 0);
+
       /* print usage stats if stats on */
       if( pArg && pArg->statsOn ){
         display_stats(db, pArg, 0);
       }
 
       /* print loop-counters if required */
-      if( pArg && pArg->mode.scanstatsOn ){
-        char *zErr = 0;
-        switch( pArg->mode.scanstatsOn ){
-          case 1:   spec.eStyle = QRF_STYLE_Stats;     break;
-          case 2:   spec.eStyle = QRF_STYLE_StatsEst;  break;
-          default:  spec.eStyle = QRF_STYLE_StatsVm;   break;
-        }
-        sqlite3_reset(pStmt);
-        rc = sqlite3_format_query_result(pStmt, &spec, &zErr);
-        if( rc ){
-          cli_printf(stderr, "Stats query failed: %s\n", zErr);
-          sqlite3_free(zErr);
-        }          
+      if( pArg && pArg->scanstatsOn ){
+        display_scanstats(db, pArg);
       }
 
       /* Finalize the statement just executed. If this fails, save a
@@ -26777,14 +24795,14 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
     */
     if( db_int(p->db, "SELECT count(*) FROM sqlite_sequence")>0 ){
       if( !p->writableSchema ){
-        cli_puts("PRAGMA writable_schema=ON;\n", p->out);
+        sqlite3_fputs("PRAGMA writable_schema=ON;\n", p->out);
         p->writableSchema = 1;
       }
-      cli_puts("CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);\n"
+      sqlite3_fputs("CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);\n"
                     "DELETE FROM sqlite_sequence;\n", p->out);
     }
   }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
-    if( !dataOnly ) cli_puts("ANALYZE sqlite_schema;\n", p->out);
+    if( !dataOnly ) sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
   }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
     return 0;
   }else if( dataOnly ){
@@ -26792,7 +24810,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 ){
-      cli_puts("PRAGMA writable_schema=ON;\n", p->out);
+      sqlite3_fputs("PRAGMA writable_schema=ON;\n", p->out);
       p->writableSchema = 1;
     }
     zIns = sqlite3_mprintf(
@@ -26800,7 +24818,7 @@ 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);
-    cli_printf(p->out, "%s\n", zIns);
+    sqlite3_fprintf(p->out, "%s\n", zIns);
     sqlite3_free(zIns);
     return 0;
   }else{
@@ -26812,7 +24830,8 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
     ShellText sTable;
     char **azCol;
     int i;
-    Mode savedMode;
+    char *savedDestTable;
+    int savedMode;
 
     azCol = tableColumnList(p, zTable);
     if( azCol==0 ){
@@ -26855,20 +24874,18 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
     appendText(&sSelect, " FROM ", 0);
     appendText(&sSelect, zTable, quoteChar(zTable));
 
-
+    savedDestTable = p->zDestTable;
     savedMode = p->mode;
-    p->mode.spec.zTableName = (char*)zTable;
-    p->mode.eMode = MODE_Insert;
-    p->mode.spec.eText = QRF_TEXT_Sql;
-    p->mode.spec.eBlob = QRF_BLOB_Sql;
-    p->mode.spec.bTitles = QRF_No;
+    p->zDestTable = sTable.zTxt;
+    p->mode = p->cMode = MODE_Insert;
     rc = shell_exec(p, sSelect.zTxt, 0);
     if( (rc&0xff)==SQLITE_CORRUPT ){
-      cli_puts("/****** CORRUPTION ERROR *******/\n", p->out);
+      sqlite3_fputs("/****** CORRUPTION ERROR *******/\n", p->out);
       toggleSelectOrder(p->db);
       shell_exec(p, sSelect.zTxt, 0);
       toggleSelectOrder(p->db);
     }
+    p->zDestTable = savedDestTable;
     p->mode = savedMode;
     freeText(&sTable);
     freeText(&sSelect);
@@ -26894,9 +24911,9 @@ static int run_schema_dump_query(
   if( rc==SQLITE_CORRUPT ){
     char *zQ2;
     int len = strlen30(zQuery);
-    cli_puts("/****** CORRUPTION ERROR *******/\n", p->out);
+    sqlite3_fputs("/****** CORRUPTION ERROR *******/\n", p->out);
     if( zErr ){
-      cli_printf(p->out, "/****** %s ******/\n", zErr);
+      sqlite3_fprintf(p->out, "/****** %s ******/\n", zErr);
       sqlite3_free(zErr);
       zErr = 0;
     }
@@ -26905,7 +24922,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 ){
-      cli_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
+      sqlite3_fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
     }else{
       rc = SQLITE_CORRUPT;
     }
@@ -26963,8 +24980,8 @@ static const char *(azHelp[]) = {
   ".cd DIRECTORY            Change the working directory to DIRECTORY",
 #endif
   ".changes on|off          Show number of rows changed by SQL",
-  ".check OPTIONS ...       Verify the results of a .testcase",
 #ifndef SQLITE_SHELL_FIDDLE
+  ".check GLOB              Fail if output since .testcase does not match",
   ".clone NEWDB             Clone data into NEWDB from the existing database",
 #endif
   ".connection [close] [#]  Open or close an auxiliary database connection",
@@ -27006,10 +25023,23 @@ static const char *(azHelp[]) = {
   "   --schema SCHEMA         Use SCHEMA instead of \"main\"",
   "   --help                  Show CMD details",
   ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
-  ",headers on|off          Turn display of headers on or off",
+  ".headers on|off          Turn display of headers on or off",
   ".help ?-all? ?PATTERN?   Show help text for PATTERN",
 #ifndef SQLITE_SHELL_FIDDLE
   ".import FILE TABLE       Import data from FILE into TABLE",
+  "   Options:",
+  "     --ascii               Use \\037 and \\036 as column and row separators",
+  "     --csv                 Use , and \\n as column and row separators",
+  "     --skip N              Skip the first N rows of input",
+  "     --schema S            Target table to be S.TABLE",
+  "     -v                    \"Verbose\" - increase auxiliary output",
+  "   Notes:",
+  "     *  If TABLE does not exist, it is created.  The first row of input",
+  "        determines the column names.",
+  "     *  If neither --csv or --ascii are used, the input mode is derived",
+  "        from the \".mode\" output mode",
+  "     *  If FILE begins with \"|\" then it is a command that generates the",
+  "        input text.",
 #endif
 #ifndef SQLITE_OMIT_TEST_CONTROL
   ".imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
@@ -27034,12 +25064,42 @@ static const char *(azHelp[]) = {
   ".log on|off              Turn logging on or off.",
 #endif
   ".mode ?MODE? ?OPTIONS?   Set output mode",
+  "   MODE is one of:",
+  "     ascii       Columns/rows delimited by 0x1F and 0x1E",
+  "     box         Tables using unicode box-drawing characters",
+  "     csv         Comma-separated values",
+  "     column      Output in columns.  (See .width)",
+  "     html        HTML  code",
+  "     insert      SQL insert statements for TABLE",
+  "     json        Results in a JSON array",
+  "     line        One value per line",
+  "     list        Values delimited by \"|\"",
+  "     markdown    Markdown table format",
+  "     qbox        Shorthand for \"box --wrap 60 --quote\"",
+  "     quote       Escape answers as for SQL",
+  "     table       ASCII-art table",
+  "     tabs        Tab-separated values",
+  "     tcl         TCL list elements",
+  "   OPTIONS: (for columnar modes or insert mode):",
+  "     --escape T     ctrl-char escape; T is one of: symbol, ascii, off",
+  "     --wrap N       Wrap output lines to no longer than N characters",
+  "     --wordwrap B   Wrap or not at word boundaries per B (on/off)",
+  "     --ww           Shorthand for \"--wordwrap 1\"",
+  "     --quote        Quote output text as SQL literals",
+  "     --noquote      Do not quote output text",
+  "     TABLE          The name of SQL table used for \"insert\" mode",
 #ifndef SQLITE_SHELL_FIDDLE
   ".nonce STRING            Suspend safe mode for one command if nonce matches",
 #endif
   ".nullvalue STRING        Use STRING in place of NULL values",
 #ifndef SQLITE_SHELL_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",
+  "       --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." */
@@ -27065,6 +25125,14 @@ static const char *(azHelp[]) = {
   "        --zip           FILE is a ZIP archive",
 #ifndef SQLITE_SHELL_FIDDLE
   ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
+  "   If FILE begins with '|' then open it as a pipe.",
+  "   If FILE is 'off' then output is disabled.",
+  "   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",
   "   clear                   Erase all bindings",
@@ -27080,7 +25148,6 @@ static const char *(azHelp[]) = {
   "   --once                    Do no more than one progress interrupt",
   "   --quiet|-q                No output except at interrupts",
   "   --reset                   Reset the count for each input and interrupt",
-  "   --timeout S               Halt after running for S seconds",
 #endif
   ".prompt MAIN CONTINUE    Replace the standard prompts",
 #ifndef SQLITE_SHELL_FIDDLE
@@ -27108,7 +25175,7 @@ static const char *(azHelp[]) = {
   "    Options:",
   "       --init               Create a new SELFTEST table",
   "       -v                   Verbose output",
-  ",separator COL ?ROW?     Change the column and row separators",
+  ".separator COL ?ROW?     Change the column and row separators",
 #if defined(SQLITE_ENABLE_SESSION)
   ".session ?NAME? CMD ...  Create or control sessions",
   "   Subcommands:",
@@ -27135,7 +25202,7 @@ static const char *(azHelp[]) = {
 #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
   ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
 #endif
-  ",show                    Show the current values for various settings",
+  ".show                    Show the current values for various settings",
   ".stats ?ARG?             Show stats or turn stats on or off",
   "   off                      Turn off automatic stat display",
   "   on                       Turn on automatic stat display",
@@ -27145,11 +25212,13 @@ static const char *(azHelp[]) = {
   ".system CMD ARGS...      Run CMD ARGS... in a system shell",
 #endif
   ".tables ?TABLE?          List names of tables matching LIKE pattern TABLE",
-  ".testcase NAME           Begin a test case.",
+#ifndef SQLITE_SHELL_FIDDLE
+  ",testcase NAME           Begin redirecting output to 'testcase-out.txt'",
+#endif
   ",testctrl CMD ...        Run various sqlite3_test_control() operations",
   "                           Run \".testctrl\" with no arguments for details",
   ".timeout MS              Try opening locked tables for MS milliseconds",
-  ".timer on|off|once       Turn SQL timer on or off.",
+  ".timer on|off            Turn SQL timer on or off",
 #ifndef SQLITE_OMIT_TRACE
   ".trace ?OPTIONS?         Output each SQL statement as it is run",
   "    FILE                    Send output to FILE",
@@ -27174,7 +25243,7 @@ static const char *(azHelp[]) = {
   ".vfsinfo ?AUX?           Information about the top-level VFS",
   ".vfslist                 List all available VFSes",
   ".vfsname ?AUX?           Print the name of the VFS stack",
-  ",width NUM1 NUM2 ...     Set minimum column widths for columnar output",
+  ".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",
@@ -27182,202 +25251,6 @@ static const char *(azHelp[]) = {
 #endif
 };
 
-/**************************************************************
-** "Usage" help text automatically generated from comments */
-static const struct {
-  const char *zCmd;   /* Name of the dot-command */
-  const char *zUsage; /* Documentation */
-} aUsage[] = {
-  { ".import",
-"USAGE: .import [OPTIONS] FILE TABLE\n"
-"\n"
-"Import CSV or similar text from FILE into TABLE.  If TABLE does\n"
-"not exist, it is created using the first row of FILE as the column\n"
-"names.  If FILE begins with \"|\" then it is a command that is run\n"
-"and the output from the command is used as the input data.  If\n"
-"FILE begins with \"<<\" followed by a label, then content is read from\n"
-"the script until the first line that matches the label.\n"
-"\n"
-"The content of FILE is interpreted using RFC-4180 (\"CSV\") quoting\n"
-"rules unless the current mode is \"ascii\" or \"tabs\" or unless one\n"
-"the --ascii option is used.\n"
-"\n"
-"The column and row separators must be single ASCII characters.  If\n"
-"multiple characters or a Unicode character are specified for the\n"
-"separators, then only the first byte of the separator is used.  Except,\n"
-"if the row separator is \\n and the mode is not --ascii, then \\r\\n is\n"
-"understood as a row separator too.\n"
-"\n"
-"Options:\n"
-"  --ascii         Do not use RFC-4180 quoting.  Use \\037 and \\036\n"
-"                  as column and row separators on input, unless other\n"
-"                  delimiters are specified using --colsep and/or --rowsep\n"
-"  --colsep CHAR   Use CHAR as the column separator.\n"
-"  --csv           Input is standard RFC-4180 CSV.\n"
-"  --esc CHAR      Use CHAR as an escape character in unquoted CSV inputs.\n"
-"  --qesc CHAR     Use CHAR as an escape character in quoted CSV inputs.\n"
-"  --rowsep CHAR   Use CHAR as the row separator.\n"
-"  --schema S      When creating TABLE, put it in schema S\n"
-"  --skip N        Ignore the first N rows of input\n"
-"  -v              Verbose mode\n"
-  },
-  { ".mode",
-"USAGE: .mode [MODE] [OPTIONS]\n"
-"\n"
-"Change the output mode to MODE and/or apply OPTIONS to the output mode.\n"
-"Arguments are processed from left to right.  If no arguments, show the\n"
-"current output mode and relevant options.\n"
-"\n"
-"Options:\n"
-"  --align STRING           Set the alignment of text in columnar modes\n"
-"                           String consists of characters 'L', 'C', 'R'\n"
-"                           meaning \"left\", \"centered\", and \"right\", with\n"
-"                           one letter per column starting from the left.\n"
-"                           Unspecified alignment defaults to 'L'.\n"
-"  --blob-quote ARG         ARG can be \"auto\", \"text\", \"sql\", \"hex\", \"tcl\",\n"
-"                           \"json\", or \"size\".  Default is \"auto\".\n"
-"  --border on|off          Show outer border on \"box\" and \"table\" modes.\n"
-"  --charlimit N            Set the maximum number of output characters to\n"
-"                           show for any single SQL value to N. Longer values\n"
-"                           truncated. Zero means \"no limit\".\n"
-"  --colsep STRING          Use STRING as the column separator\n"
-"  --escape ESC             Enable/disable escaping of control characters\n"
-"                           found in the output. ESC can be \"off\", \"ascii\",\n"
-"                           or \"symbol\".\n"
-"  --linelimit N            Set the maximum number of output lines to show for\n"
-"                           any single SQL value to N. Longer values are\n"
-"                           truncated. Zero means \"no limit\". Only works\n"
-"                           in \"line\" mode and in columnar modes.\n"
-"  --limits L,C,T           Shorthand for \"--linelimit L --charlimit C\n"
-"                           --titlelimit T\". The \",T\" can be omitted in which\n"
-"                           case the --titlelimit is unchanged.  The argument\n"
-"                           can also be \"off\" to mean \"0,0,0\" or \"on\" to\n"
-"                           mean \"5,300,20\".\n"
-"  --list                   List available modes\n"
-"  --null STRING            Render SQL NULL values as the given string\n"
-"  --once                   Setting changes to the right are reverted after\n"
-"                           the next SQL command.\n"
-"  --quote ARG              Enable/disable quoting of text. ARG can be\n"
-"                           \"off\", \"on\", \"sql\", \"relaxed\", \"csv\", \"html\",\n"
-"                           \"tcl\", or \"json\". \"off\" means show the text as-is.\n"
-"                           \"on\" is an alias for \"sql\".\n"
-"  --reset                  Changes all mode settings back to their default.\n"
-"  --rowsep STRING          Use STRING as the row separator\n"
-"  --sw|--screenwidth N     Declare the screen width of the output device\n"
-"                           to be N characters.  An attempt may be made to\n"
-"                           wrap output text to fit within this limit. Zero\n"
-"                           means \"no limit\".  Or N can be \"auto\" to set the\n"
-"                           width automatically.\n"
-"  --tablename NAME         Set the name of the table for \"insert\" mode.\n"
-"  --tag NAME               Save mode to the left as NAME.\n"
-"  --textjsonb BOOLEAN      If enabled, JSONB text is displayed as text JSON.\n"
-"  --title ARG              Whether or not to show column headers, and if so\n"
-"                           how to encode them.  ARG can be \"off\", \"on\",\n"
-"                           \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n"
-"  --titlelimit N           Limit the length of column titles to N characters.\n"
-"  -v|--verbose             Verbose output\n"
-"  --widths LIST            Set the columns widths for columnar modes. The\n"
-"                           argument is a list of integers, one for each\n"
-"                           column. A \"0\" width means use a dynamic width\n"
-"                           based on the actual width of data. If there are\n"
-"                           fewer entries in LIST than columns, \"0\" is used\n"
-"                           for the unspecified widths.\n"
-"  --wordwrap BOOLEAN       Enable/disable word wrapping\n"
-"  --wrap N                 Wrap columns wider than N characters\n"
-"  --ww                     Shorthand for \"--wordwrap on\"\n"
-  },
-  { ".output",
-"USAGE: .output [OPTIONS] [FILE]\n"
-"\n"
-"Begin redirecting output to FILE.  Or if FILE is omitted, revert\n"
-"to sending output to the console.  If FILE begins with \"|\" then\n"
-"the remainder of file is taken as a pipe and output is directed\n"
-"into that pipe.  If FILE is \"memory\" then output is captured in an\n"
-"internal memory buffer.  If FILE is \"off\" then output is redirected\n"
-"into /dev/null or the equivalent.\n"
-"\n"
-"Options:\n"
-"  --bom             Prepend a byte-order mark to the output\n"
-"  -e                Accumulate output in a temporary text file then\n"
-"                    launch a text editor when the redirection ends.\n"
-"  --error-prefix X  Use X as the left-margin prefix for error messages.\n"
-"                    Set to an empty string to restore the default.\n"
-"  --keep            Keep redirecting output to its current destination.\n"
-"                    Use this option in combination with --show or\n"
-"                    with --error-prefix when you do not want to stop\n"
-"                    a current redirection.\n"
-"  --plain           Use plain text rather than HTML tables with -w\n"
-"  --show            Show output text captured by .testcase or by\n"
-"                    redirecting to \"memory\".\n"
-"  -w                Show the output in a web browser.  Output is\n"
-"                    written into a temporary HTML file until the\n"
-"                    redirect ends, then the web browser is launched.\n"
-"                    Query results  are shown as HTML tables, unless\n"
-"                    the --plain is used too.\n"
-"  -x                Show the output in a spreadsheet.  Output is\n"
-"                    written to a temp file as CSV then the spreadsheet\n"
-"                    is launched when\n"
-  },
-  { ".once",
-"USAGE: .once [OPTIONS] FILE ...\n"
-"\n"
-"Write the output for the next line of SQL or the next dot-command into\n"
-"FILE.  If FILE begins with \"|\" then it is a program into which output\n"
-"is written. The FILE argument should be omitted if one of the -e, -w,\n"
-"or -x options is used.\n"
-"\n"
-"Options:\n"
-"  -e                Capture output into a temporary file then bring up\n"
-"                    a text editor on that temporary file.\n"
-"  --plain           Use plain text rather than HTML tables with -w\n"
-"  -w                Capture output into an HTML file then bring up that\n"
-"                    file in a web browser\n"
-"  -x                Show the output in a spreadsheet.  Output is\n"
-"                    written to a temp file as CSV then the spreadsheet\n"
-"                    is launched when\n"
-  },
-  { ".check",
-"USAGE: .check [OPTIONS] PATTERN\n"
-"\n"
-"Verify results of commands since the most recent .testcase command.\n"
-"Restore output to the console, unless --keep is used.\n"
-"\n"
-"If PATTERN starts with \"< return false
-**    * If the size of the file is not a multiple of 512 -> return false
-**    * If sqlite3_open() fails -> return false
-**    * if sqlite3_prepare() or sqlite3_step() fails -> return false
-**    * Otherwise -> return true
-*/
-static int isDatabaseFile(const char *zFile, int openFlags){
-  sqlite3 *db = 0;
-  sqlite3_stmt *pStmt = 0;
-  int rc;
-  sqlite3_int64 sz = fileSize(zFile);
-  if( sz<512 || (sz%512)!=0 ) return 0;
-  if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK
-   && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
-           ==SQLITE_OK
-   && sqlite3_step(pStmt)==SQLITE_ROW
-  ){
-    rc = 1;
-  }else{
-    rc = 0;
-  }
-  sqlite3_finalize(pStmt);
-  sqlite3_close(db);
-  return rc;
-}
-
 /*
 ** Try to deduce the type of file for zName based on its content.  Return
 ** one of the SHELL_OPEN_* constants.
@@ -27647,12 +25464,20 @@ static int isDatabaseFile(const char *zFile, int openFlags){
 int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
   FILE *f;
   size_t n;
+  sqlite3 *db = 0;
+  sqlite3_stmt *pStmt = 0;
   int rc = SHELL_OPEN_UNSPEC;
   char zBuf[100];
   if( access(zName,0)!=0 ) goto database_type_by_name;
-  if( isDatabaseFile(zName, openFlags) ){
+  if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
+   && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
+           ==SQLITE_OK
+   && sqlite3_step(pStmt)==SQLITE_ROW
+  ){
     rc = SHELL_OPEN_NORMAL;
   }
+  sqlite3_finalize(pStmt);
+  sqlite3_close(db);
   if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
   f = sqlite3_fopen(zName, "rb");
   if( f==0 ) goto database_type_by_name;
@@ -27687,35 +25512,6 @@ database_type_by_name:
   return rc;
 }
 
-/*
-** If the text in z[] is the name of a readable file and that file appears
-** to contain SQL text and/or dot-commands, then return true.  If z[] is
-** not a file, or if the file is unreadable, or if the file is a database
-** or anything else that is not SQL text and dot-commands, then return false.
-**
-** If the bLeaveUninit flag is set, then be sure to leave SQLite in an
-** uninitialized state.  This means invoking sqlite3_shutdown() after any
-** SQLite API is used.
-**
-** Some amount of guesswork is involved in this decision.
-*/
-static int isScriptFile(const char *z, int bLeaveUninit){
-  sqlite3_int64 sz = fileSize(z);
-  if( sz<=0 ) return 0;
-  if( (sz%512)==0 ){
-    int rc;
-    sqlite3_initialize();
-    rc = isDatabaseFile(z, SQLITE_OPEN_READONLY);
-    if( bLeaveUninit ){
-      sqlite3_shutdown();
-    }
-    if( rc ) return 0;  /* Is a database */
-  }
-  if( sqlite3_strlike("%.sql",z,0)==0 ) return 1;
-  if( sqlite3_strlike("%.txt",z,0)==0 ) return 1;
-  return 0;
-}
-
 #ifndef SQLITE_OMIT_DESERIALIZE
 /*
 ** Reconstruct an in-memory database using the output from the "dbtotxt"
@@ -27737,7 +25533,7 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
   if( zDbFilename ){
     in = sqlite3_fopen(zDbFilename, "r");
     if( in==0 ){
-      cli_printf(stderr,"cannot open \"%s\" for reading\n", zDbFilename);
+      sqlite3_fprintf(stderr,"cannot open \"%s\" for reading\n", zDbFilename);
       return 0;
     }
     nLine = 0;
@@ -27753,7 +25549,7 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
   if( rc!=2 ) goto readHexDb_error;
   if( n<0 ) goto readHexDb_error;
   if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
-    cli_puts("invalid pagesize\n", stderr);
+    sqlite3_fputs("invalid pagesize\n", stderr);
     goto readHexDb_error;
   }
   sz = ((i64)n+pgsz-1)&~(pgsz-1); /* Round up to nearest multiple of pgsz */
@@ -27764,7 +25560,7 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
     int j = 0;                    /* Page number from "| page" line */
     int k = 0;                    /* Offset from "| page" line */
     if( nLine>=2000000000 ){
-      cli_printf(stderr, "input too big\n");
+      sqlite3_fprintf(stderr, "input too big\n");
       goto readHexDb_error;
     }
     rc = sscanf(zLine, "| page %d offset %d", &j, &k);
@@ -27805,7 +25601,7 @@ readHexDb_error:
     p->lineno = nLine;
   }
   sqlite3_free(a);
-  cli_printf(stderr,"Error on line %lld of --hexdb input\n", nLine);
+  sqlite3_fprintf(stderr,"Error on line %lld of --hexdb input\n", nLine);
   return 0;
 }
 #endif /* SQLITE_OMIT_DESERIALIZE */
@@ -27910,19 +25706,19 @@ static void open_db(ShellState *p, int openFlags){
       }
     }
     if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
-      cli_printf(stderr,"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 ){
-        cli_exit(1);
+        exit(1);
       }
       sqlite3_close(p->db);
       sqlite3_open(":memory:", &p->db);
       if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
-        cli_puts("Also: unable to open substitute in-memory database.\n",
+        sqlite3_fputs("Also: unable to open substitute in-memory database.\n",
                       stderr);
-        cli_exit(1);
+        exit(1);
       }else{
-        cli_printf(stderr,
+        sqlite3_fprintf(stderr,
               "Notice: using substitute in-memory database instead of \"%s\"\n",
               zDbFilename);
       }
@@ -28000,8 +25796,6 @@ static void open_db(ShellState *p, int openFlags){
                             shellModuleSchema, 0, 0);
     sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
                             shellPutsFunc, 0, 0);
-    sqlite3_create_function(p->db, "shell_format_schema", 2, SQLITE_UTF8, p,
-                            shellFormatSchema, 0, 0);
     sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
                             shellUSleepFunc, 0, 0);
 #ifndef SQLITE_NOHAVE_SYSTEM
@@ -28036,7 +25830,7 @@ static void open_db(ShellState *p, int openFlags){
                    SQLITE_DESERIALIZE_RESIZEABLE |
                    SQLITE_DESERIALIZE_FREEONCLOSE);
       if( rc ){
-        cli_printf(stderr,"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);
@@ -28051,7 +25845,7 @@ static void open_db(ShellState *p, int openFlags){
     }
 #endif
     sqlite3_db_config(
-        p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->mode.scanstatsOn, (int*)0
+        p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0
     );
   }
 }
@@ -28062,7 +25856,7 @@ static void open_db(ShellState *p, int openFlags){
 void close_db(sqlite3 *db){
   int rc = sqlite3_close(db);
   if( rc ){
-    cli_printf(stderr,
+    sqlite3_fprintf(stderr,
         "Error: sqlite3_close() returns %d: %s\n", rc, sqlite3_errmsg(db));
   }
 }
@@ -28235,7 +26029,7 @@ static int booleanValue(const char *zArg){
   if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
     return 0;
   }
-  cli_printf(stderr,
+  sqlite3_fprintf(stderr,
        "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg);
   return 0;
 }
@@ -28263,18 +26057,18 @@ 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(ShellState *p, const char *zFile){
+static FILE *output_file_open(const char *zFile){
   FILE *f;
   if( cli_strcmp(zFile,"stdout")==0 ){
     f = stdout;
   }else if( cli_strcmp(zFile, "stderr")==0 ){
     f = stderr;
-  }else if( cli_strcmp(zFile, "off")==0 || p->bSafeMode ){
+  }else if( cli_strcmp(zFile, "off")==0 ){
     f = 0;
   }else{
     f = sqlite3_fopen(zFile, "w");
     if( f==0 ){
-      cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile);
+      sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zFile);
     }
   }
   return f;
@@ -28327,12 +26121,12 @@ static int sql_trace_callback(
   switch( mType ){
     case SQLITE_TRACE_ROW:
     case SQLITE_TRACE_STMT: {
-      cli_printf(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;
-      cli_printf(p->traceOut,
+      sqlite3_fprintf(p->traceOut,
                       "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
       break;
     }
@@ -28361,9 +26155,7 @@ struct ImportCtx {
   const char *zFile;  /* Name of the input file */
   FILE *in;           /* Read the CSV text from this input stream */
   int (SQLITE_CDECL *xCloser)(FILE*);      /* Func to close in */
-  char *zIn;          /* Input text */
   char *z;            /* Accumulated text for a field */
-  i64 nUsed;          /* Bytes of zIn[] used so far */
   i64 n;              /* Number of bytes in z */
   i64 nAlloc;         /* Space allocated for z[] */
   int nLine;          /* Current line number */
@@ -28373,8 +26165,6 @@ struct ImportCtx {
   int cTerm;          /* Character that terminated the most recent field */
   int cColSep;        /* The column separator character.  (Usually ",") */
   int cRowSep;        /* The row separator character.  (Usually "\n") */
-  int cQEscape;       /* Escape character with "...".  0 for none */
-  int cUQEscape;      /* Escape character not with "...".  0 for none */
 };
 
 /* Clean up resourced used by an ImportCtx */
@@ -28385,28 +26175,9 @@ static void import_cleanup(ImportCtx *p){
   }
   sqlite3_free(p->z);
   p->z = 0;
-  if( p->zIn ){
-    sqlite3_free(p->zIn);
-    p->zIn = 0;
-  }
-}
-
-/* Read a single character of the .import input text.  Return EOF
-** at end-of-file.
-*/
-static int import_getc(ImportCtx *p){
-  if( p->in ){
-    return fgetc(p->in);
-  }else if( p->zIn && p->zIn[p->nUsed]!=0 ){
-    return p->zIn[p->nUsed++];
-  }else{
-    return EOF;
-  }
 }
 
-/* Append a single byte to the field value begin constructed
-** in the p->z[] buffer
-*/
+/* Append a single byte to z[] */
 static void import_append_char(ImportCtx *p, int c){
   if( p->n+1>=p->nAlloc ){
     p->nAlloc += p->nAlloc + 100;
@@ -28422,8 +26193,8 @@ static void import_append_char(ImportCtx *p, int c){
 **   +  Input comes from p->in.
 **   +  Store results in p->z of length p->n.  Space to hold p->z comes
 **      from sqlite3_malloc64().
-**   +  Use p->cColSep as the column separator.  The default is ",".
-**   +  Use p->cRowSep as the row separator.  The default is "\n".
+**   +  Use p->cSep as the column separator.  The default is ",".
+**   +  Use p->rSep as the row separator.  The default is "\n".
 **   +  Keep track of the line number in p->nLine.
 **   +  Store the character that terminates the field in p->cTerm.  Store
 **      EOF on end-of-file.
@@ -28434,7 +26205,7 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
   int cSep = (u8)p->cColSep;
   int rSep = (u8)p->cRowSep;
   p->n = 0;
-  c = import_getc(p);
+  c = fgetc(p->in);
   if( c==EOF || seenInterrupt ){
     p->cTerm = EOF;
     return 0;
@@ -28443,17 +26214,10 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
     int pc, ppc;
     int startLine = p->nLine;
     int cQuote = c;
-    int cEsc = (u8)p->cQEscape;
     pc = ppc = 0;
     while( 1 ){
-      c = import_getc(p);
+      c = fgetc(p->in);
       if( c==rSep ) p->nLine++;
-      if( c==cEsc && cEsc!=0 ){
-        c = import_getc(p);
-        import_append_char(p, c);
-        ppc = pc = 0;
-        continue;
-      }
       if( c==cQuote ){
         if( pc==cQuote ){
           pc = 0;
@@ -28470,11 +26234,11 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
         break;
       }
       if( pc==cQuote && c!='\r' ){
-        cli_printf(stderr,"%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 ){
-        cli_printf(stderr,"%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;
@@ -28486,13 +26250,12 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
   }else{
     /* If this is the first field being parsed and it begins with the
     ** UTF-8 BOM  (0xEF BB BF) then skip the BOM */
-    int cEsc = p->cUQEscape;
     if( (c&0xff)==0xef && p->bNotFirst==0 ){
       import_append_char(p, c);
-      c = import_getc(p);
+      c = fgetc(p->in);
       if( (c&0xff)==0xbb ){
         import_append_char(p, c);
-        c = import_getc(p);
+        c = fgetc(p->in);
         if( (c&0xff)==0xbf ){
           p->bNotFirst = 1;
           p->n = 0;
@@ -28501,9 +26264,8 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
       }
     }
     while( c!=EOF && c!=cSep && c!=rSep ){
-      if( c==cEsc && cEsc!=0 ) c = import_getc(p);
       import_append_char(p, c);
-      c = import_getc(p);
+      c = fgetc(p->in);
     }
     if( c==rSep ){
       p->nLine++;
@@ -28521,8 +26283,8 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
 **   +  Input comes from p->in.
 **   +  Store results in p->z of length p->n.  Space to hold p->z comes
 **      from sqlite3_malloc64().
-**   +  Use p->cColSep as the column separator.  The default is "\x1F".
-**   +  Use p->cRowSep as the row separator.  The default is "\x1E".
+**   +  Use p->cSep as the column separator.  The default is "\x1F".
+**   +  Use p->rSep as the row separator.  The default is "\x1E".
 **   +  Keep track of the row number in p->nLine.
 **   +  Store the character that terminates the field in p->cTerm.  Store
 **      EOF on end-of-file.
@@ -28533,14 +26295,14 @@ static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
   int cSep = (u8)p->cColSep;
   int rSep = (u8)p->cRowSep;
   p->n = 0;
-  c = import_getc(p);
+  c = fgetc(p->in);
   if( c==EOF || seenInterrupt ){
     p->cTerm = EOF;
     return 0;
   }
   while( c!=EOF && c!=cSep && c!=rSep ){
     import_append_char(p, c);
-    c = import_getc(p);
+    c = fgetc(p->in);
   }
   if( c==rSep ){
     p->nLine++;
@@ -28575,7 +26337,7 @@ static void tryToCloneData(
   shell_check_oom(zQuery);
   rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
   if( rc ){
-    cli_printf(stderr,"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;
   }
@@ -28592,7 +26354,7 @@ static void tryToCloneData(
   memcpy(zInsert+i, ");", 3);
   rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
   if( rc ){
-    cli_printf(stderr,"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;
   }
@@ -28628,7 +26390,7 @@ static void tryToCloneData(
       } /* End for */
       rc = sqlite3_step(pInsert);
       if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
-        cli_printf(stderr,"Error %d: %s\n",
+        sqlite3_fprintf(stderr,"Error %d: %s\n",
               sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb));
       }
       sqlite3_reset(pInsert);
@@ -28646,7 +26408,7 @@ static void tryToCloneData(
     shell_check_oom(zQuery);
     rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
     if( rc ){
-      cli_printf(stderr,"Warning: cannot step \"%s\" backwards", zTable);
+      sqlite3_fprintf(stderr,"Warning: cannot step \"%s\" backwards", zTable);
       break;
     }
   } /* End for(k=0...) */
@@ -28683,7 +26445,7 @@ static void tryToCloneSchema(
   shell_check_oom(zQuery);
   rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
   if( rc ){
-    cli_printf(stderr,
+    sqlite3_fprintf(stderr,
           "Error: (%d) %s on [%s]\n", sqlite3_extended_errcode(p->db),
           sqlite3_errmsg(p->db), zQuery);
     goto end_schema_xfer;
@@ -28693,10 +26455,10 @@ static void tryToCloneSchema(
     zSql = sqlite3_column_text(pQuery, 1);
     if( zName==0 || zSql==0 ) continue;
     if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){
-      cli_printf(stdout, "%s... ", zName); fflush(stdout);
+      sqlite3_fprintf(stdout, "%s... ", zName); fflush(stdout);
       sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
       if( zErrMsg ){
-        cli_printf(stderr,"Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
+        sqlite3_fprintf(stderr,"Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
         sqlite3_free(zErrMsg);
         zErrMsg = 0;
       }
@@ -28714,7 +26476,7 @@ static void tryToCloneSchema(
     shell_check_oom(zQuery);
     rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
     if( rc ){
-      cli_printf(stderr,"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;
     }
@@ -28723,10 +26485,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;
-      cli_printf(stdout, "%s... ", zName); fflush(stdout);
+      sqlite3_fprintf(stdout, "%s... ", zName); fflush(stdout);
       sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
       if( zErrMsg ){
-        cli_printf(stderr,"Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
+        sqlite3_fprintf(stderr,"Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
         sqlite3_free(zErrMsg);
         zErrMsg = 0;
       }
@@ -28750,12 +26512,12 @@ static void tryToClone(ShellState *p, const char *zNewDb){
   int rc;
   sqlite3 *newDb = 0;
   if( access(zNewDb,0)==0 ){
-    cli_printf(stderr,"File \"%s\" already exists.\n", zNewDb);
+    sqlite3_fprintf(stderr,"File \"%s\" already exists.\n", zNewDb);
     return;
   }
   rc = sqlite3_open(zNewDb, &newDb);
   if( rc ){
-    cli_printf(stderr,
+    sqlite3_fprintf(stderr,
         "Cannot create output database: %s\n", sqlite3_errmsg(newDb));
   }else{
     sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
@@ -28774,12 +26536,12 @@ static void tryToClone(ShellState *p, const char *zNewDb){
 */
 static void output_redir(ShellState *p, FILE *pfNew){
   if( p->out != stdout ){
-    cli_puts("Output already redirected.\n", stderr);
+    sqlite3_fputs("Output already redirected.\n", stderr);
   }else{
     p->out = pfNew;
     setCrlfMode(p);
-    if( p->mode.eMode==MODE_Www ){
-      cli_puts(
+    if( p->mode==MODE_Www ){
+      sqlite3_fputs(
         "\n"
         "
\n",
         p->out
@@ -28801,8 +26563,8 @@ static void output_reset(ShellState *p){
     pclose(p->out);
 #endif
   }else{
-    if( p->mode.eMode==MODE_Www ){
-      cli_puts("
\n", p->out); + if( p->mode==MODE_Www ){ + sqlite3_fputs("\n", p->out); } output_file_close(p->out); #ifndef SQLITE_NOHAVE_SYSTEM @@ -28818,7 +26580,7 @@ static void output_reset(ShellState *p){ char *zCmd; zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile); if( system(zCmd) ){ - cli_printf(stderr,"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 @@ -28826,7 +26588,7 @@ static void output_reset(ShellState *p){ sqlite3_sleep(2000); } sqlite3_free(zCmd); - modePop(p); + outputModePop(p); p->doXdgOpen = 0; } #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ @@ -28834,10 +26596,6 @@ static void output_reset(ShellState *p){ p->outfile[0] = 0; p->out = stdout; setCrlfMode(p); - if( cli_output_capture ){ - sqlite3_str_free(cli_output_capture); - cli_output_capture = 0; - } } #else # define output_redir(SS,pfO) @@ -28922,7 +26680,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 ){ - cli_printf(stderr,"error: %s\n", sqlite3_errmsg(p->db)); + sqlite3_fprintf(stderr,"error: %s\n", sqlite3_errmsg(p->db)); sqlite3_finalize(pStmt); return 1; } @@ -28935,28 +26693,28 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ memcpy(aHdr, pb, 100); sqlite3_finalize(pStmt); }else{ - cli_puts("unable to read database header\n", stderr); + sqlite3_fputs("unable to read database header\n", stderr); sqlite3_finalize(pStmt); return 1; } i = get2byteInt(aHdr+16); if( i==1 ) i = 65536; - cli_printf(p->out, "%-20s %d\n", "database page size:", i); - cli_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); - cli_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); - cli_printf(p->out, "%-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; iout, "%-20s %u", aField[i].zName, val); + sqlite3_fprintf(p->out, "%-20s %u", aField[i].zName, val); switch( ofst ){ case 56: { - if( val==1 ) cli_puts(" (utf8)", p->out); - if( val==2 ) cli_puts(" (utf16le)", p->out); - if( val==3 ) cli_puts(" (utf16be)", p->out); + if( val==1 ) sqlite3_fputs(" (utf8)", p->out); + if( val==2 ) sqlite3_fputs(" (utf16le)", p->out); + if( val==3 ) sqlite3_fputs(" (utf16be)", p->out); } } - cli_puts("\n", p->out); + sqlite3_fputs("\n", p->out); } if( zDb==0 ){ zSchemaTab = sqlite3_mprintf("main.sqlite_schema"); @@ -28967,11 +26725,11 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ } for(i=0; idb, aQuery[i].zSql, zSchemaTab); - cli_printf(p->out, "%-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); - cli_printf(p->out, "%-20s %u\n", "data version", iDataVersion); + sqlite3_fprintf(p->out, "%-20s %u\n", "data version", iDataVersion); return 0; } #endif /* SQLITE_SHELL_HAVE_RECOVER */ @@ -29031,7 +26789,7 @@ static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){ } zName = strdup(zTail); shell_check_oom(zName); - cli_printf(p->out, "| size %lld pagesize %d filename %s\n", + sqlite3_fprintf(p->out, "| size %lld pagesize %d filename %s\n", nPage*pgSz, pgSz, zName); sqlite3_finalize(pStmt); pStmt = 0; @@ -29047,27 +26805,27 @@ static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){ for(j=0; j<16 && aLine[j]==0; j++){} if( j==16 ) continue; if( !seenPageLabel ){ - cli_printf(p->out, "| page %lld offset %lld\n",pgno,(pgno-1)*pgSz); + sqlite3_fprintf(p->out, "| page %lld offset %lld\n",pgno,(pgno-1)*pgSz); seenPageLabel = 1; } - cli_printf(p->out, "| %5d:", i); - for(j=0; j<16; j++) cli_printf(p->out, " %02x", aLine[j]); - cli_printf(p->out, " "); + sqlite3_fprintf(p->out, "| %5d:", i); + for(j=0; j<16; j++) sqlite3_fprintf(p->out, " %02x", aLine[j]); + sqlite3_fprintf(p->out, " "); for(j=0; j<16; j++){ unsigned char c = (unsigned char)aLine[j]; - cli_printf(p->out, "%c", bShow[c]); + sqlite3_fprintf(p->out, "%c", bShow[c]); } - cli_printf(p->out, "\n"); + sqlite3_fprintf(p->out, "\n"); } } sqlite3_finalize(pStmt); - cli_printf(p->out, "| end %s\n", zName); + sqlite3_fprintf(p->out, "| end %s\n", zName); free(zName); return 0; dbtotxt_error: if( rc ){ - cli_printf(stderr, "ERROR: %s\n", sqlite3_errmsg(p->db)); + sqlite3_fprintf(stderr, "ERROR: %s\n", sqlite3_errmsg(p->db)); } sqlite3_finalize(pStmt); free(zName); @@ -29078,7 +26836,7 @@ dbtotxt_error: ** Print the given string as an error message. */ static void shellEmitError(const char *zErr){ - cli_printf(stderr,"Error: %s\n", zErr); + sqlite3_fprintf(stderr,"Error: %s\n", zErr); } /* ** Print the current sqlite3_errmsg() value to stderr and return 1. @@ -29261,42 +27019,39 @@ static void clearTempFile(ShellState *p){ p->zTempFile = 0; } -/* Forward reference */ -static char *find_home_dir(int clearFlag); - /* ** Create a new temp file name with the given suffix. -** -** Because the classic temp folders like /tmp are no longer -** accessible to web browsers, for security reasons, create the -** temp file in the user's home directory. */ static void newTempFile(ShellState *p, const char *zSuffix){ - char *zHome; /* Home directory */ - int i; /* Loop counter */ - sqlite3_uint64 r = 0; /* Integer with 64 bits of randomness */ - char zRand[32]; /* Text string with 160 bits of randomness */ + clearTempFile(p); + sqlite3_free(p->zTempFile); + p->zTempFile = 0; + if( p->db ){ + sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile); + } + if( p->zTempFile==0 ){ + /* If p->db is an in-memory database then the TEMPFILENAME file-control + ** will not work and we will need to fallback to guessing */ + char *zTemp; + sqlite3_uint64 r; + sqlite3_randomness(sizeof(r), &r); + zTemp = getenv("TEMP"); + if( zTemp==0 ) zTemp = getenv("TMP"); + if( zTemp==0 ){ #ifdef _WIN32 - const char cDirSep = '\\'; + zTemp = "\\tmp"; #else - const char cDirSep = '/'; + zTemp = "/tmp"; #endif - - for(i=0; i<31; i++){ - if( (i%12)==0 ) sqlite3_randomness(sizeof(r),&r); - zRand[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[r%36]; - r /= 36; + } + p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix); + }else{ + p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix); } - zRand[i] = 0; - clearTempFile(p); - sqlite3_free(p->zTempFile); - p->zTempFile = 0; - zHome = find_home_dir(0); - p->zTempFile = sqlite3_mprintf("%s%ctemp-%s.%s", - zHome,cDirSep,zRand,zSuffix); shell_check_oom(p->zTempFile); } + /* ** The implementation of SQL scalar function fkey_collate_clause(), used ** by the ".lint fkey-indexes" command. This scalar function is always @@ -29441,7 +27196,7 @@ static int lintFkeyIndexes( zIndent = " "; } else{ - cli_printf(stderr, + sqlite3_fprintf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n", azArg[0], azArg[1]); return SQLITE_ERROR; } @@ -29486,22 +27241,22 @@ static int lintFkeyIndexes( if( rc!=SQLITE_OK ) break; if( res<0 ){ - cli_puts("Error: internal error", stderr); + sqlite3_fputs("Error: internal error", stderr); break; }else{ if( bGroupByParent && (bVerbose || res==0) && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) ){ - cli_printf(out, "-- Parent table %s\n", zParent); + sqlite3_fprintf(out, "-- Parent table %s\n", zParent); sqlite3_free(zPrev); zPrev = sqlite3_mprintf("%s", zParent); } if( res==0 ){ - cli_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); + sqlite3_fprintf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); }else if( bVerbose ){ - cli_printf(out, + sqlite3_fprintf(out, "%s/* no extra indexes required for %s -> %s */\n", zIndent, zFrom, zTarget ); @@ -29511,16 +27266,16 @@ static int lintFkeyIndexes( sqlite3_free(zPrev); if( rc!=SQLITE_OK ){ - cli_printf(stderr,"%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; - cli_printf(stderr,"%s\n", sqlite3_errmsg(db)); + sqlite3_fprintf(stderr,"%s\n", sqlite3_errmsg(db)); } }else{ - cli_printf(stderr,"%s\n", sqlite3_errmsg(db)); + sqlite3_fprintf(stderr,"%s\n", sqlite3_errmsg(db)); } return rc; @@ -29540,9 +27295,9 @@ static int lintDotCommand( return lintFkeyIndexes(pState, azArg, nArg); usage: - cli_printf(stderr,"Usage %s sub-command ?switches...?\n", azArg[0]); - cli_printf(stderr, "Where sub-commands are:\n"); - cli_printf(stderr, " 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; } @@ -29556,7 +27311,7 @@ static void shellPrepare( if( *pRc==SQLITE_OK ){ int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); if( rc!=SQLITE_OK ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "sql error: %s (%d)\n", sqlite3_errmsg(db), sqlite3_errcode(db)); *pRc = rc; } @@ -29601,7 +27356,7 @@ static void shellFinalize( int rc = sqlite3_finalize(pStmt); if( *pRc==SQLITE_OK ){ if( rc!=SQLITE_OK ){ - cli_printf(stderr,"SQL error: %s\n", sqlite3_errmsg(db)); + sqlite3_fprintf(stderr,"SQL error: %s\n", sqlite3_errmsg(db)); } *pRc = rc; } @@ -29623,7 +27378,7 @@ void shellReset( if( *pRc==SQLITE_OK ){ if( rc!=SQLITE_OK ){ sqlite3 *db = sqlite3_db_handle(pStmt); - cli_printf(stderr,"SQL error: %s\n", sqlite3_errmsg(db)); + sqlite3_fprintf(stderr,"SQL error: %s\n", sqlite3_errmsg(db)); } *pRc = rc; } @@ -29676,9 +27431,9 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ va_end(ap); shellEmitError(z); if( pAr->fromCmdLine ){ - cli_puts("Use \"-A\" for more help\n", stderr); + sqlite3_fputs("Use \"-A\" for more help\n", stderr); }else{ - cli_puts("Use \".archive --help\" for more help\n", stderr); + sqlite3_fputs("Use \".archive --help\" for more help\n", stderr); } sqlite3_free(z); return SQLITE_ERROR; @@ -29778,7 +27533,7 @@ static int arParseCommand( struct ArSwitch *pEnd = &aSwitch[nSwitch]; if( nArg<=1 ){ - cli_printf(stderr, "Wrong number of arguments. Usage:\n"); + sqlite3_fprintf(stderr, "Wrong number of arguments. Usage:\n"); return arUsage(stderr); }else{ char *z = azArg[1]; @@ -29879,2488 +27634,920 @@ static int arParseCommand( zArg = azArg[++iArg]; } if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR; - } - } - } - } - if( pAr->eCmd==0 ){ - cli_printf(stderr, "Required argument missing. Usage:\n"); - return arUsage(stderr); - } - return SQLITE_OK; -} - -/* -** This function assumes that all arguments within the ArCommand.azArg[] -** array refer to archive members, as for the --extract, --list or --remove -** commands. It checks that each of them are "present". If any specified -** file is not present in the archive, an error is printed to stderr and an -** error code returned. Otherwise, if all specified arguments are present -** in the archive, SQLITE_OK is returned. Here, "present" means either an -** exact equality when pAr->bGlob is false or a "name GLOB pattern" match -** when pAr->bGlob is true. -** -** This function strips any trailing '/' characters from each argument. -** This is consistent with the way the [tar] command seems to work on -** Linux. -*/ -static int arCheckEntries(ArCommand *pAr){ - int rc = SQLITE_OK; - if( pAr->nArg ){ - int i, j; - sqlite3_stmt *pTest = 0; - const char *zSel = (pAr->bGlob) - ? "SELECT name FROM %s WHERE glob($name,name)" - : "SELECT name FROM %s WHERE name=$name"; - - shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable); - j = sqlite3_bind_parameter_index(pTest, "$name"); - for(i=0; inArg && rc==SQLITE_OK; i++){ - char *z = pAr->azArg[i]; - int n = strlen30(z); - int bOk = 0; - while( n>0 && z[n-1]=='/' ) n--; - z[n] = '\0'; - sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pTest) ){ - bOk = 1; - } - shellReset(&rc, pTest); - if( rc==SQLITE_OK && bOk==0 ){ - cli_printf(stderr,"not found in archive: %s\n", z); - rc = SQLITE_ERROR; - } - } - shellFinalize(&rc, pTest); - } - return rc; -} - -/* -** Format a WHERE clause that can be used against the "sqlar" table to -** identify all archive members that match the command arguments held -** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning. -** The caller is responsible for eventually calling sqlite3_free() on -** any non-NULL (*pzWhere) value. Here, "match" means strict equality -** when pAr->bGlob is false and GLOB match when pAr->bGlob is true. -*/ -static void arWhereClause( - int *pRc, - ArCommand *pAr, - char **pzWhere /* OUT: New WHERE clause */ -){ - char *zWhere = 0; - if( *pRc==SQLITE_OK ){ - if( pAr->nArg==0 ){ - zWhere = sqlite3_mprintf("1"); - }else{ - char *z1 = sqlite3_mprintf(pAr->bGlob ? "" : "name IN("); - char *z2 = sqlite3_mprintf(""); - const char *zSep1 = ""; - const char *zSep2 = ""; - - int i; - for(i=0; inArg && z1 && z2; i++){ - const char *z = pAr->azArg[i]; - int n = strlen30(z); - - if( pAr->bGlob ){ - z1 = sqlite3_mprintf("%z%sname GLOB '%q'", z1, zSep2, z); - z2 = sqlite3_mprintf( - "%z%ssubstr(name,1,%d) GLOB '%q/'", z2, zSep2, n+1,z - ); - }else{ - z1 = sqlite3_mprintf("%z%s'%q'", z1, zSep1, z); - z2 = sqlite3_mprintf("%z%ssubstr(name,1,%d) = '%q/'",z2,zSep2,n+1,z); - } - zSep1 = ", "; - zSep2 = " OR "; - } - if( z1==0 || z2==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - zWhere = sqlite3_mprintf("(%s%s OR (name GLOB '*/*' AND (%s))) ", - z1, pAr->bGlob==0 ? ")" : "", z2 - ); - } - sqlite3_free(z1); - sqlite3_free(z2); - } - } - *pzWhere = zWhere; -} - -/* -** Implementation of .ar "lisT" command. -*/ -static int arListCommand(ArCommand *pAr){ - const char *zSql = "SELECT %s FROM %s WHERE %s"; - const char *azCols[] = { - "name", - "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name" - }; - - char *zWhere = 0; - sqlite3_stmt *pSql = 0; - int rc; - - rc = arCheckEntries(pAr); - arWhereClause(&rc, pAr, &zWhere); - - shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], - pAr->zSrcTable, zWhere); - if( pAr->bDryRun ){ - cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql)); - }else{ - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ - if( pAr->bVerbose ){ - cli_printf(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{ - cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0)); - } - } - } - shellFinalize(&rc, pSql); - sqlite3_free(zWhere); - return rc; -} - -/* -** Implementation of .ar "Remove" command. -*/ -static int arRemoveCommand(ArCommand *pAr){ - int rc = 0; - char *zSql = 0; - char *zWhere = 0; - - if( pAr->nArg ){ - /* Verify that args actually exist within the archive before proceeding. - ** And formulate a WHERE clause to match them. */ - rc = arCheckEntries(pAr); - arWhereClause(&rc, pAr, &zWhere); - } - if( rc==SQLITE_OK ){ - zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;", - pAr->zSrcTable, zWhere); - if( pAr->bDryRun ){ - cli_printf(pAr->out, "%s\n", zSql); - }else{ - char *zErr = 0; - rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); - if( rc!=SQLITE_OK ){ - sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); - }else{ - rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0); - } - } - if( zErr ){ - cli_printf(stdout, "ERROR: %s\n", zErr); /* stdout? */ - sqlite3_free(zErr); - } - } - } - sqlite3_free(zWhere); - sqlite3_free(zSql); - return rc; -} - -/* -** Implementation of .ar "eXtract" command. -*/ -static int arExtractCommand(ArCommand *pAr){ - const char *zSql1 = - "WITH dest(dpath,dlen) AS (SELECT realpath($dir),length(realpath($dir)))\n" - "SELECT ($dir || name),\n" - " CASE WHEN $dryrun THEN 0\n" - " ELSE writefile($dir||name, %s, mode, mtime) END\n" - " FROM dest CROSS JOIN %s\n" - " WHERE (%s)\n" - " AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */ - " AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */ - " AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */ - - const char *azExtraArg[] = { - "sqlar_uncompress(data, sz)", - "data" - }; - - sqlite3_stmt *pSql = 0; - int rc = SQLITE_OK; - char *zDir = 0; - char *zWhere = 0; - int i, j; - - /* If arguments are specified, check that they actually exist within - ** the archive before proceeding. And formulate a WHERE clause to - ** match them. */ - rc = arCheckEntries(pAr); - arWhereClause(&rc, pAr, &zWhere); - - if( rc==SQLITE_OK ){ - if( pAr->zDir ){ - zDir = sqlite3_mprintf("%s/", pAr->zDir); - }else{ - zDir = sqlite3_mprintf(""); - } - if( zDir==0 ) rc = SQLITE_NOMEM; - } - - shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, - azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere - ); - - if( rc==SQLITE_OK ){ - j = sqlite3_bind_parameter_index(pSql, "$dir"); - sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); - j = sqlite3_bind_parameter_index(pSql, "$dryrun"); - sqlite3_bind_int(pSql, j, pAr->bDryRun); - - /* Run the SELECT statement twice - ** (0) writefile() all files and directories - ** (1) writefile() for directory again - ** The second pass is so that the timestamps for extracted directories - ** will be reset to the value in the archive, since populating them - ** in the first pass will have changed the timestamp. */ - for(i=0; i<2; i++){ - j = sqlite3_bind_parameter_index(pSql, "$pass"); - sqlite3_bind_int(pSql, j, i); - if( pAr->bDryRun ){ - cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql)); - if( pAr->bVerbose==0 ) break; - } - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ - if( i==0 && pAr->bVerbose ){ - cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0)); - } - } - if( pAr->bDryRun ) break; - shellReset(&rc, pSql); - } - shellFinalize(&rc, pSql); - } - - sqlite3_free(zDir); - sqlite3_free(zWhere); - return rc; -} - -/* -** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out. -*/ -static int arExecSql(ArCommand *pAr, const char *zSql){ - int rc; - if( pAr->bDryRun ){ - cli_printf(pAr->out, "%s\n", zSql); - rc = SQLITE_OK; - }else{ - char *zErr = 0; - rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); - if( zErr ){ - cli_printf(stdout, "ERROR: %s\n", zErr); - sqlite3_free(zErr); - } - } - return rc; -} - - -/* -** Implementation of .ar "create", "insert", and "update" commands. -** -** create -> Create a new SQL archive -** insert -> Insert or reinsert all files listed -** update -> Insert files that have changed or that were not -** previously in the archive -** -** Create the "sqlar" table in the database if it does not already exist. -** Then add each file in the azFile[] array to the archive. Directories -** are added recursively. If argument bVerbose is non-zero, a message is -** printed on stdout for each file archived. -** -** The create command is the same as update, except that it drops -** any existing "sqlar" table before beginning. The "insert" command -** always overwrites every file named on the command-line, where as -** "update" only overwrites if the size or mtime or mode has changed. -*/ -static int arCreateOrUpdateCommand( - ArCommand *pAr, /* Command arguments and options */ - int bUpdate, /* true for a --create. */ - int bOnlyIfChanged /* Only update if file has changed */ -){ - const char *zCreate = - "CREATE TABLE IF NOT EXISTS sqlar(\n" - " name TEXT PRIMARY KEY, -- name of the file\n" - " mode INT, -- access permissions\n" - " mtime INT, -- last modification time\n" - " sz INT, -- original file size\n" - " data BLOB -- compressed content\n" - ")"; - const char *zDrop = "DROP TABLE IF EXISTS sqlar"; - const char *zInsertFmt[2] = { - "REPLACE INTO %s(name,mode,mtime,sz,data)\n" - " SELECT\n" - " %s,\n" - " mode,\n" - " mtime,\n" - " CASE substr(lsmode(mode),1,1)\n" - " WHEN '-' THEN length(data)\n" - " WHEN 'd' THEN 0\n" - " ELSE -1 END,\n" - " sqlar_compress(data)\n" - " FROM fsdir(%Q,%Q) AS disk\n" - " WHERE lsmode(mode) NOT LIKE '?%%'%s;" - , - "REPLACE INTO %s(name,mode,mtime,data)\n" - " SELECT\n" - " %s,\n" - " mode,\n" - " mtime,\n" - " data\n" - " FROM fsdir(%Q,%Q) AS disk\n" - " WHERE lsmode(mode) NOT LIKE '?%%'%s;" - }; - int i; /* For iterating through azFile[] */ - int rc; /* Return code */ - const char *zTab = 0; /* SQL table into which to insert */ - char *zSql; - char zTemp[50]; - char *zExists = 0; - - arExecSql(pAr, "PRAGMA page_size=512"); - rc = arExecSql(pAr, "SAVEPOINT ar;"); - if( rc!=SQLITE_OK ) return rc; - zTemp[0] = 0; - if( pAr->bZip ){ - /* Initialize the zipfile virtual table, if necessary */ - if( pAr->zFile ){ - sqlite3_uint64 r; - sqlite3_randomness(sizeof(r),&r); - sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r); - zTab = zTemp; - zSql = sqlite3_mprintf( - "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)", - zTab, pAr->zFile - ); - rc = arExecSql(pAr, zSql); - sqlite3_free(zSql); - }else{ - zTab = "zip"; - } - }else{ - /* Initialize the table for an SQLAR */ - zTab = "sqlar"; - if( bUpdate==0 ){ - rc = arExecSql(pAr, zDrop); - if( rc!=SQLITE_OK ) goto end_ar_transaction; - } - rc = arExecSql(pAr, zCreate); - } - if( bOnlyIfChanged ){ - zExists = sqlite3_mprintf( - " AND NOT EXISTS(" - "SELECT 1 FROM %s AS mem" - " WHERE mem.name=disk.name" - " AND mem.mtime=disk.mtime" - " AND mem.mode=disk.mode)", zTab); - }else{ - zExists = sqlite3_mprintf(""); - } - if( zExists==0 ) rc = SQLITE_NOMEM; - for(i=0; inArg && rc==SQLITE_OK; i++){ - char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab, - pAr->bVerbose ? "shell_putsnl(name)" : "name", - pAr->azArg[i], pAr->zDir, zExists); - rc = arExecSql(pAr, zSql2); - sqlite3_free(zSql2); - } -end_ar_transaction: - if( rc!=SQLITE_OK ){ - sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); - }else{ - rc = arExecSql(pAr, "RELEASE ar;"); - if( pAr->bZip && pAr->zFile ){ - zSql = sqlite3_mprintf("DROP TABLE %s", zTemp); - arExecSql(pAr, zSql); - sqlite3_free(zSql); - } - } - sqlite3_free(zExists); - return rc; -} - -/* -** Implementation of ".ar" dot command. -*/ -static int arDotCommand( - ShellState *pState, /* Current shell tool state */ - int fromCmdLine, /* True if -A command-line option, not .ar cmd */ - char **azArg, /* Array of arguments passed to dot command */ - int nArg /* Number of entries in azArg[] */ -){ - ArCommand cmd; - int rc; - memset(&cmd, 0, sizeof(cmd)); - cmd.fromCmdLine = fromCmdLine; - rc = arParseCommand(azArg, nArg, &cmd); - if( rc==SQLITE_OK ){ - int eDbType = SHELL_OPEN_UNSPEC; - cmd.p = pState; - cmd.out = pState->out; - cmd.db = pState->db; - if( cmd.zFile ){ - eDbType = deduceDatabaseType(cmd.zFile, 1, 0); - }else{ - eDbType = pState->openMode; - } - if( eDbType==SHELL_OPEN_ZIPFILE ){ - if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ - if( cmd.zFile==0 ){ - cmd.zSrcTable = sqlite3_mprintf("zip"); - }else{ - cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile); - } - } - cmd.bZip = 1; - }else if( cmd.zFile ){ - int flags; - if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; - if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT - || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){ - flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; - }else{ - flags = SQLITE_OPEN_READONLY; - } - cmd.db = 0; - if( cmd.bDryRun ){ - cli_printf(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 ){ - cli_printf(stderr, "cannot open file: %s (%s)\n", - cmd.zFile, sqlite3_errmsg(cmd.db)); - goto end_ar_command; - } - sqlite3_fileio_init(cmd.db, 0, 0); - sqlite3_sqlar_init(cmd.db, 0, 0); - sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, - shellPutsFunc, 0, 0); - - } - if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ - if( cmd.eCmd!=AR_CMD_CREATE - && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) - ){ - cli_printf(stderr, "database does not contain an 'sqlar' table\n"); - rc = SQLITE_ERROR; - goto end_ar_command; - } - cmd.zSrcTable = sqlite3_mprintf("sqlar"); - } - - switch( cmd.eCmd ){ - case AR_CMD_CREATE: - rc = arCreateOrUpdateCommand(&cmd, 0, 0); - break; - - case AR_CMD_EXTRACT: - rc = arExtractCommand(&cmd); - break; - - case AR_CMD_LIST: - rc = arListCommand(&cmd); - break; - - case AR_CMD_HELP: - arUsage(pState->out); - break; - - case AR_CMD_INSERT: - rc = arCreateOrUpdateCommand(&cmd, 1, 0); - break; - - case AR_CMD_REMOVE: - rc = arRemoveCommand(&cmd); - break; - - default: - assert( cmd.eCmd==AR_CMD_UPDATE ); - rc = arCreateOrUpdateCommand(&cmd, 1, 1); - break; - } - } -end_ar_command: - if( cmd.db!=pState->db ){ - close_db(cmd.db); - } - sqlite3_free(cmd.zSrcTable); - - return rc; -} -/* End of the ".archive" or ".ar" command logic -*******************************************************************************/ -#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ - -#if SQLITE_SHELL_HAVE_RECOVER - -/* -** This function is used as a callback by the recover extension. Simply -** print the supplied SQL statement to stdout. -*/ -static int recoverSqlCb(void *pCtx, const char *zSql){ - ShellState *pState = (ShellState*)pCtx; - cli_printf(pState->out, "%s;\n", zSql); - return SQLITE_OK; -} - -/* -** This function is called to recover data from the database. A script -** to construct a new database containing all recovered data is output -** on stream pState->out. -*/ -static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ - int rc = SQLITE_OK; - const char *zRecoveryDb = ""; /* Name of "recovery" database. Debug only */ - const char *zLAF = "lost_and_found"; - int bFreelist = 1; /* 0 if --ignore-freelist is specified */ - int bRowids = 1; /* 0 if --no-rowids */ - sqlite3_recover *p = 0; - int i = 0; - - for(i=1; iout, azArg[0]); - return 1; - } - } - - p = sqlite3_recover_init_sql( - pState->db, "main", recoverSqlCb, (void*)pState - ); - - if( !pState->bSafeMode ){ - sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */ - } - sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF); - sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids); - sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist); - - cli_printf(pState->out, ".dbconfig defensive off\n"); - sqlite3_recover_run(p); - if( sqlite3_recover_errcode(p)!=SQLITE_OK ){ - const char *zErr = sqlite3_recover_errmsg(p); - int errCode = sqlite3_recover_errcode(p); - cli_printf(stderr,"sql error: %s (%d)\n", zErr, errCode); - } - rc = sqlite3_recover_finish(p); - return rc; -} -#endif /* SQLITE_SHELL_HAVE_RECOVER */ - -/* -** Implementation of ".intck STEPS_PER_UNLOCK" command. -*/ -static int intckDatabaseCmd(ShellState *pState, i64 nStepPerUnlock){ - sqlite3_intck *p = 0; - int rc = SQLITE_OK; - - rc = sqlite3_intck_open(pState->db, "main", &p); - if( rc==SQLITE_OK ){ - i64 nStep = 0; - i64 nError = 0; - const char *zErr = 0; - while( SQLITE_OK==sqlite3_intck_step(p) ){ - const char *zMsg = sqlite3_intck_message(p); - if( zMsg ){ - cli_printf(pState->out, "%s\n", zMsg); - nError++; - } - nStep++; - if( nStepPerUnlock && (nStep % nStepPerUnlock)==0 ){ - sqlite3_intck_unlock(p); - } - } - rc = sqlite3_intck_error(p, &zErr); - if( zErr ){ - cli_printf(stderr,"%s\n", zErr); - } - sqlite3_intck_close(p); - - cli_printf(pState->out, "%lld steps, %lld errors\n", nStep, nError); - } - - return rc; -} - -/* - * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it. - * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE, - * close db and set it to 0, and return the columns spec, to later - * be sqlite3_free()'ed by the caller. - * The return is 0 when either: - * (a) The db was not initialized and zCol==0 (There are no columns.) - * (b) zCol!=0 (Column was added, db initialized as needed.) - * The 3rd argument, pRenamed, references an out parameter. If the - * pointer is non-zero, its referent will be set to a summary of renames - * done if renaming was necessary, or set to 0 if none was done. The out - * string (if any) must be sqlite3_free()'ed by the caller. - */ -#ifdef SHELL_DEBUG -#define rc_err_oom_die(rc) \ - if( rc==SQLITE_NOMEM ) shell_check_oom(0); \ - else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \ - cli_printf(stderr,"E:%d\n",rc), assert(0) -#else -static void rc_err_oom_die(int rc){ - if( rc==SQLITE_NOMEM ) shell_check_oom(0); - assert(rc==SQLITE_OK||rc==SQLITE_DONE); -} -#endif - -#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */ -static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB); -#else /* Otherwise, memory is faster/better for the transient DB. */ -static const char *zCOL_DB = ":memory:"; -#endif - -/* Define character (as C string) to separate generated column ordinal - * from protected part of incoming column names. This defaults to "_" - * so that incoming column identifiers that did not need not be quoted - * remain usable without being quoted. It must be one character. - */ -#ifndef SHELL_AUTOCOLUMN_SEP -# define AUTOCOLUMN_SEP "_" -#else -# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP) -#endif - -static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){ - /* Queries and D{D,M}L used here */ - static const char * const zTabMake = "\ -CREATE TABLE ColNames(\ - cpos INTEGER PRIMARY KEY,\ - name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\ -CREATE VIEW RepeatedNames AS \ -SELECT DISTINCT t.name FROM ColNames t \ -WHERE t.name COLLATE NOCASE IN (\ - SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\ -);\ -"; - static const char * const zTabFill = "\ -INSERT INTO ColNames(name,nlen,chop,reps,suff)\ - VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\ -"; - static const char * const zHasDupes = "\ -SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\ - 1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')" -#else /* ...RENAME_MINIMAL_ONE_PASS */ -"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */ -" SELECT 0 AS nlz" -" UNION" -" SELECT nlz+1 AS nlz FROM Lzn" -" WHERE EXISTS(" -" SELECT 1" -" FROM ColNames t, ColNames o" -" WHERE" -" iif(t.name IN (SELECT * FROM RepeatedNames)," -" printf('%s"AUTOCOLUMN_SEP"%s'," -" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2))," -" t.name" -" )" -" =" -" iif(o.name IN (SELECT * FROM RepeatedNames)," -" printf('%s"AUTOCOLUMN_SEP"%s'," -" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2))," -" o.name" -" )" -" COLLATE NOCASE" -" AND o.cpos<>t.cpos" -" GROUP BY t.cpos" -" )" -") UPDATE Colnames AS t SET" -" chop = 0," /* No chopping, never touch incoming names. */ -" suff = iif(name IN (SELECT * FROM RepeatedNames)," -" printf('"AUTOCOLUMN_SEP"%s', substring(" -" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2))," -" ''" -" )" -#endif - ; - static const char * const zCollectVar = "\ -SELECT\ - '('||x'0a'\ - || group_concat(\ - cname||' ANY',\ - ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ - ||')' AS ColsSpec \ -FROM (\ - SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \ - FROM ColNames ORDER BY cpos\ -)"; - static const char * const zRenamesDone = - "SELECT group_concat(" - " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff))," - " ','||x'0a')" - "FROM ColNames WHERE suff<>'' OR chop!=0" - ; - int rc; - sqlite3_stmt *pStmt = 0; - assert(pDb!=0); - if( zColNew ){ - /* Add initial or additional column. Init db if necessary. */ - if( *pDb==0 ){ - if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0; -#ifdef SHELL_COLFIX_DB - if(*zCOL_DB!=':') - sqlite3_exec(*pDb,"drop table if exists ColNames;" - "drop view if exists RepeatedNames;",0,0,0); -#endif -#undef SHELL_COLFIX_DB - rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0); - rc_err_oom_die(rc); - } - assert(*pDb!=0); - rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0); - rc_err_oom_die(rc); - rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0); - rc_err_oom_die(rc); - rc = sqlite3_step(pStmt); - rc_err_oom_die(rc); - sqlite3_finalize(pStmt); - return 0; - }else if( *pDb==0 ){ - return 0; - }else{ - /* Formulate the columns spec, close the DB, zero *pDb. */ - char *zColsSpec = 0; - int hasDupes = db_int(*pDb, "%s", zHasDupes); - int nDigits = (hasDupes)? db_int(*pDb, "%s", zColDigits) : 0; - if( hasDupes ){ -#ifdef SHELL_COLUMN_RENAME_CLEAN - rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0); - rc_err_oom_die(rc); -#endif - rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); - rc_err_oom_die(rc); - rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); - rc_err_oom_die(rc); - sqlite3_bind_int(pStmt, 1, nDigits); - rc = sqlite3_step(pStmt); - sqlite3_finalize(pStmt); - if( rc!=SQLITE_DONE ) rc_err_oom_die(SQLITE_NOMEM); - } - assert(db_int(*pDb, "%s", zHasDupes)==0); /* Consider: remove this */ - rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0); - rc_err_oom_die(rc); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_ROW ){ - zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); - }else{ - zColsSpec = 0; - } - if( pzRenamed!=0 ){ - if( !hasDupes ) *pzRenamed = 0; - else{ - sqlite3_finalize(pStmt); - if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0) - && SQLITE_ROW==sqlite3_step(pStmt) ){ - *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); - }else - *pzRenamed = 0; + } } } - sqlite3_finalize(pStmt); - sqlite3_close(*pDb); - *pDb = 0; - return zColsSpec; } + if( pAr->eCmd==0 ){ + sqlite3_fprintf(stderr, "Required argument missing. Usage:\n"); + return arUsage(stderr); + } + return SQLITE_OK; } /* -** Check if the sqlite_schema table contains one or more virtual tables. If -** parameter zLike is not NULL, then it is an SQL expression that the -** sqlite_schema row must also match. If one or more such rows are found, -** print the following warning to the output: +** This function assumes that all arguments within the ArCommand.azArg[] +** array refer to archive members, as for the --extract, --list or --remove +** commands. It checks that each of them are "present". If any specified +** file is not present in the archive, an error is printed to stderr and an +** error code returned. Otherwise, if all specified arguments are present +** in the archive, SQLITE_OK is returned. Here, "present" means either an +** exact equality when pAr->bGlob is false or a "name GLOB pattern" match +** when pAr->bGlob is true. ** -** WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled +** This function strips any trailing '/' characters from each argument. +** This is consistent with the way the [tar] command seems to work on +** Linux. */ -static int outputDumpWarning(ShellState *p, const char *zLike){ +static int arCheckEntries(ArCommand *pAr){ int rc = SQLITE_OK; - sqlite3_stmt *pStmt = 0; - shellPreparePrintf(p->db, &rc, &pStmt, - "SELECT 1 FROM sqlite_schema o WHERE " - "sql LIKE 'CREATE VIRTUAL TABLE%%' AND %s", zLike ? zLike : "true" - ); - if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - cli_puts("/* WARNING: " - "Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */\n", - p->out - ); + if( pAr->nArg ){ + int i, j; + sqlite3_stmt *pTest = 0; + const char *zSel = (pAr->bGlob) + ? "SELECT name FROM %s WHERE glob($name,name)" + : "SELECT name FROM %s WHERE name=$name"; + + shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable); + j = sqlite3_bind_parameter_index(pTest, "$name"); + for(i=0; inArg && rc==SQLITE_OK; i++){ + char *z = pAr->azArg[i]; + int n = strlen30(z); + int bOk = 0; + while( n>0 && z[n-1]=='/' ) n--; + z[n] = '\0'; + sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pTest) ){ + bOk = 1; + } + shellReset(&rc, pTest); + if( rc==SQLITE_OK && bOk==0 ){ + sqlite3_fprintf(stderr,"not found in archive: %s\n", z); + rc = SQLITE_ERROR; + } + } + shellFinalize(&rc, pTest); } - shellFinalize(&rc, pStmt); return rc; } /* -** Fault-Simulator state and logic. +** Format a WHERE clause that can be used against the "sqlar" table to +** identify all archive members that match the command arguments held +** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning. +** The caller is responsible for eventually calling sqlite3_free() on +** any non-NULL (*pzWhere) value. Here, "match" means strict equality +** when pAr->bGlob is false and GLOB match when pAr->bGlob is true. */ -static struct { - int iId; /* ID that triggers a simulated fault. -1 means "any" */ - int iErr; /* The error code to return on a fault */ - int iCnt; /* Trigger the fault only if iCnt is already zero */ - int iInterval; /* Reset iCnt to this value after each fault */ - int eVerbose; /* When to print output */ - int nHit; /* Number of hits seen so far */ - int nRepeat; /* Turn off after this many hits. 0 for never */ - int nSkip; /* Skip this many before first fault */ -} faultsim_state = {-1, 0, 0, 0, 0, 0, 0, 0}; +static void arWhereClause( + int *pRc, + ArCommand *pAr, + char **pzWhere /* OUT: New WHERE clause */ +){ + char *zWhere = 0; + if( *pRc==SQLITE_OK ){ + if( pAr->nArg==0 ){ + zWhere = sqlite3_mprintf("1"); + }else{ + char *z1 = sqlite3_mprintf(pAr->bGlob ? "" : "name IN("); + char *z2 = sqlite3_mprintf(""); + const char *zSep1 = ""; + const char *zSep2 = ""; + + int i; + for(i=0; inArg && z1 && z2; i++){ + const char *z = pAr->azArg[i]; + int n = strlen30(z); + + if( pAr->bGlob ){ + z1 = sqlite3_mprintf("%z%sname GLOB '%q'", z1, zSep2, z); + z2 = sqlite3_mprintf( + "%z%ssubstr(name,1,%d) GLOB '%q/'", z2, zSep2, n+1,z + ); + }else{ + z1 = sqlite3_mprintf("%z%s'%q'", z1, zSep1, z); + z2 = sqlite3_mprintf("%z%ssubstr(name,1,%d) = '%q/'",z2,zSep2,n+1,z); + } + zSep1 = ", "; + zSep2 = " OR "; + } + if( z1==0 || z2==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + zWhere = sqlite3_mprintf("(%s%s OR (name GLOB '*/*' AND (%s))) ", + z1, pAr->bGlob==0 ? ")" : "", z2 + ); + } + sqlite3_free(z1); + sqlite3_free(z2); + } + } + *pzWhere = zWhere; +} /* -** This is the fault-sim callback +** Implementation of .ar "lisT" command. */ -static int faultsim_callback(int iArg){ - if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){ - return SQLITE_OK; - } - if( faultsim_state.iCnt ){ - if( faultsim_state.iCnt>0 ) faultsim_state.iCnt--; - if( faultsim_state.eVerbose>=2 ){ - cli_printf(stdout, - "FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt); +static int arListCommand(ArCommand *pAr){ + const char *zSql = "SELECT %s FROM %s WHERE %s"; + const char *azCols[] = { + "name", + "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name" + }; + + char *zWhere = 0; + sqlite3_stmt *pSql = 0; + int rc; + + rc = arCheckEntries(pAr); + arWhereClause(&rc, pAr, &zWhere); + + shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], + pAr->zSrcTable, zWhere); + if( pAr->bDryRun ){ + sqlite3_fprintf(pAr->out, "%s\n", sqlite3_sql(pSql)); + }else{ + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ + if( pAr->bVerbose ){ + 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{ + sqlite3_fprintf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0)); + } } - return SQLITE_OK; } - if( faultsim_state.eVerbose>=1 ){ - cli_printf(stdout, - "FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr); + shellFinalize(&rc, pSql); + sqlite3_free(zWhere); + return rc; +} + +/* +** Implementation of .ar "Remove" command. +*/ +static int arRemoveCommand(ArCommand *pAr){ + int rc = 0; + char *zSql = 0; + char *zWhere = 0; + + if( pAr->nArg ){ + /* Verify that args actually exist within the archive before proceeding. + ** And formulate a WHERE clause to match them. */ + rc = arCheckEntries(pAr); + arWhereClause(&rc, pAr, &zWhere); } - faultsim_state.iCnt = faultsim_state.iInterval; - faultsim_state.nHit++; - if( faultsim_state.nRepeat>0 && faultsim_state.nRepeat<=faultsim_state.nHit ){ - faultsim_state.iCnt = -1; + if( rc==SQLITE_OK ){ + zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;", + pAr->zSrcTable, zWhere); + if( pAr->bDryRun ){ + sqlite3_fprintf(pAr->out, "%s\n", zSql); + }else{ + char *zErr = 0; + rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); + if( rc!=SQLITE_OK ){ + sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); + }else{ + rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0); + } + } + if( zErr ){ + sqlite3_fprintf(stdout, "ERROR: %s\n", zErr); /* stdout? */ + sqlite3_free(zErr); + } + } } - return faultsim_state.iErr; + sqlite3_free(zWhere); + sqlite3_free(zSql); + return rc; } /* -** pickStr(zArg, &zErr, zS1, zS2, ..., ""); -** -** Try to match zArg against zS1, zS2, and so forth until the first -** emptry string. Return the index of the match or -1 if none is found. -** If no match is found, and &zErr is not NULL, then write into -** zErr a message describing the valid choices. +** Implementation of .ar "eXtract" command. */ -static int pickStr(const char *zArg, char **pzErr, ...){ - int i, n; - const char *z; - sqlite3_str *pMsg; - va_list ap; - va_start(ap, pzErr); - i = 0; - while( (z = va_arg(ap,const char*))!=0 && z[0]!=0 ){ - if( cli_strcmp(zArg, z)==0 ) return i; - i++; +static int arExtractCommand(ArCommand *pAr){ + const char *zSql1 = + "SELECT " + " ($dir || name)," + " writefile(($dir || name), %s, mode, mtime) " + "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" + " AND name NOT GLOB '*..[/\\]*'"; + + const char *azExtraArg[] = { + "sqlar_uncompress(data, sz)", + "data" + }; + + sqlite3_stmt *pSql = 0; + int rc = SQLITE_OK; + char *zDir = 0; + char *zWhere = 0; + int i, j; + + /* If arguments are specified, check that they actually exist within + ** the archive before proceeding. And formulate a WHERE clause to + ** match them. */ + rc = arCheckEntries(pAr); + arWhereClause(&rc, pAr, &zWhere); + + if( rc==SQLITE_OK ){ + if( pAr->zDir ){ + zDir = sqlite3_mprintf("%s/", pAr->zDir); + }else{ + zDir = sqlite3_mprintf(""); + } + if( zDir==0 ) rc = SQLITE_NOMEM; } - va_end(ap); - if( pzErr==0 ) return -1; - n = i; - pMsg = sqlite3_str_new(0); - va_start(ap, pzErr); - sqlite3_str_appendall(pMsg, "should be"); - i = 0; - while( (z = va_arg(ap, const char*))!=0 && z[0]!=0 ){ - if( i==n-1 ){ - sqlite3_str_append(pMsg,", or",4); - }else if( i>0 ){ - sqlite3_str_append(pMsg, ",", 1); + + shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, + azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere + ); + + if( rc==SQLITE_OK ){ + j = sqlite3_bind_parameter_index(pSql, "$dir"); + sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); + + /* Run the SELECT statement twice. The first time, writefile() is called + ** for all archive members that should be extracted. The second time, + ** only for the directories. This is because the timestamps for + ** extracted directories must be reset after they are populated (as + ** populating them changes the timestamp). */ + for(i=0; i<2; i++){ + j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); + sqlite3_bind_int(pSql, j, i); + if( pAr->bDryRun ){ + sqlite3_fprintf(pAr->out, "%s\n", sqlite3_sql(pSql)); + }else{ + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ + if( i==0 && pAr->bVerbose ){ + sqlite3_fprintf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0)); + } + } + } + shellReset(&rc, pSql); } - sqlite3_str_appendf(pMsg, " %s", z); - i++; + shellFinalize(&rc, pSql); } - va_end(ap); - *pzErr = sqlite3_str_finish(pMsg); - return -1; + + sqlite3_free(zDir); + sqlite3_free(zWhere); + return rc; } /* -** DOT-COMMAND: .import -** -** USAGE: .import [OPTIONS] FILE TABLE -** -** Import CSV or similar text from FILE into TABLE. If TABLE does -** not exist, it is created using the first row of FILE as the column -** names. If FILE begins with "|" then it is a command that is run -** and the output from the command is used as the input data. If -** FILE begins with "<<" followed by a label, then content is read from -** the script until the first line that matches the label. -** -** The content of FILE is interpreted using RFC-4180 ("CSV") quoting -** rules unless the current mode is "ascii" or "tabs" or unless one -** the --ascii option is used. -** -** The column and row separators must be single ASCII characters. If -** multiple characters or a Unicode character are specified for the -** separators, then only the first byte of the separator is used. Except, -** if the row separator is \n and the mode is not --ascii, then \r\n is -** understood as a row separator too. -** -** Options: -** --ascii Do not use RFC-4180 quoting. Use \037 and \036 -** as column and row separators on input, unless other -** delimiters are specified using --colsep and/or --rowsep -** --colsep CHAR Use CHAR as the column separator. -** --csv Input is standard RFC-4180 CSV. -** --esc CHAR Use CHAR as an escape character in unquoted CSV inputs. -** --qesc CHAR Use CHAR as an escape character in quoted CSV inputs. -** --rowsep CHAR Use CHAR as the row separator. -** --schema S When creating TABLE, put it in schema S -** --skip N Ignore the first N rows of input -** -v Verbose mode -*/ -static int dotCmdImport(ShellState *p){ - int nArg = p->dot.nArg; /* Number of arguments */ - char **azArg = p->dot.azArg;/* Argument list */ - char *zTable = 0; /* Insert data into this table */ - char *zSchema = 0; /* Schema of zTable */ - char *zFile = 0; /* Name of file to extra content from */ - sqlite3_stmt *pStmt = NULL; /* A statement */ - int nCol; /* Number of columns in the table */ - i64 nByte; /* Number of bytes in an SQL string */ - int i, j; /* Loop counters */ - int needCommit; /* True to COMMIT or ROLLBACK at end */ - char *zSql = 0; /* An SQL statement */ - ImportCtx sCtx; /* Reader context */ - char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ - int eVerbose = 0; /* Larger for more console output */ - i64 nSkip = 0; /* Initial lines to skip */ - i64 iLineOffset = 0; /* Offset to the first line of input */ - char *zCreate = 0; /* CREATE TABLE statement text */ - int rc; /* Result code */ - - failIfSafeMode(p, "cannot run .import in safe mode"); - memset(&sCtx, 0, sizeof(sCtx)); - if( p->mode.eMode==MODE_Ascii ){ - xRead = ascii_read_one_field; +** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out. +*/ +static int arExecSql(ArCommand *pAr, const char *zSql){ + int rc; + if( pAr->bDryRun ){ + sqlite3_fprintf(pAr->out, "%s\n", zSql); + rc = SQLITE_OK; }else{ - xRead = csv_read_one_field; - } - for(i=1; imode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){ - sCtx.cColSep = p->mode.spec.zColumnSep[0]; - }else{ - sCtx.cColSep = ','; + char *zErr = 0; + rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); + if( zErr ){ + sqlite3_fprintf(stdout, "ERROR: %s\n", zErr); + sqlite3_free(zErr); } } - if( (sCtx.cColSep & 0x80)!=0 ){ - eputz("Error: .import column separator must be ASCII\n"); - return 1; - } - if( sCtx.cRowSep==0 ){ - if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){ - sCtx.cRowSep = p->mode.spec.zRowSep[0]; + return rc; +} + + +/* +** Implementation of .ar "create", "insert", and "update" commands. +** +** create -> Create a new SQL archive +** insert -> Insert or reinsert all files listed +** update -> Insert files that have changed or that were not +** previously in the archive +** +** Create the "sqlar" table in the database if it does not already exist. +** Then add each file in the azFile[] array to the archive. Directories +** are added recursively. If argument bVerbose is non-zero, a message is +** printed on stdout for each file archived. +** +** The create command is the same as update, except that it drops +** any existing "sqlar" table before beginning. The "insert" command +** always overwrites every file named on the command-line, where as +** "update" only overwrites if the size or mtime or mode has changed. +*/ +static int arCreateOrUpdateCommand( + ArCommand *pAr, /* Command arguments and options */ + int bUpdate, /* true for a --create. */ + int bOnlyIfChanged /* Only update if file has changed */ +){ + const char *zCreate = + "CREATE TABLE IF NOT EXISTS sqlar(\n" + " name TEXT PRIMARY KEY, -- name of the file\n" + " mode INT, -- access permissions\n" + " mtime INT, -- last modification time\n" + " sz INT, -- original file size\n" + " data BLOB -- compressed content\n" + ")"; + const char *zDrop = "DROP TABLE IF EXISTS sqlar"; + const char *zInsertFmt[2] = { + "REPLACE INTO %s(name,mode,mtime,sz,data)\n" + " SELECT\n" + " %s,\n" + " mode,\n" + " mtime,\n" + " CASE substr(lsmode(mode),1,1)\n" + " WHEN '-' THEN length(data)\n" + " WHEN 'd' THEN 0\n" + " ELSE -1 END,\n" + " sqlar_compress(data)\n" + " FROM fsdir(%Q,%Q) AS disk\n" + " WHERE lsmode(mode) NOT LIKE '?%%'%s;" + , + "REPLACE INTO %s(name,mode,mtime,data)\n" + " SELECT\n" + " %s,\n" + " mode,\n" + " mtime,\n" + " data\n" + " FROM fsdir(%Q,%Q) AS disk\n" + " WHERE lsmode(mode) NOT LIKE '?%%'%s;" + }; + int i; /* For iterating through azFile[] */ + int rc; /* Return code */ + const char *zTab = 0; /* SQL table into which to insert */ + char *zSql; + char zTemp[50]; + char *zExists = 0; + + arExecSql(pAr, "PRAGMA page_size=512"); + rc = arExecSql(pAr, "SAVEPOINT ar;"); + if( rc!=SQLITE_OK ) return rc; + zTemp[0] = 0; + if( pAr->bZip ){ + /* Initialize the zipfile virtual table, if necessary */ + if( pAr->zFile ){ + sqlite3_uint64 r; + sqlite3_randomness(sizeof(r),&r); + sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r); + zTab = zTemp; + zSql = sqlite3_mprintf( + "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)", + zTab, pAr->zFile + ); + rc = arExecSql(pAr, zSql); + sqlite3_free(zSql); }else{ - sCtx.cRowSep = '\n'; - } - } - if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){ - sCtx.cRowSep = '\n'; - } - if( (sCtx.cRowSep & 0x80)!=0 ){ - eputz("Error: .import row separator must be ASCII\n"); - return 1; - } - sCtx.zFile = zFile; - sCtx.nLine = 1; - if( sCtx.zFile[0]=='|' ){ -#ifdef SQLITE_OMIT_POPEN - eputz("Error: pipes are not supported in this OS\n"); - return 1; -#else - sCtx.in = sqlite3_popen(sCtx.zFile+1, "r"); - sCtx.zFile = ""; - sCtx.xCloser = pclose; -#endif - }else if( sCtx.zFile[0]=='<' && sCtx.zFile[1]=='<' && sCtx.zFile[2]!=0 ){ - /* Input text comes from subsequent lines of script until the zFile - ** delimiter */ - int nEndMark = strlen30(zFile)-2; - char *zEndMark = &zFile[2]; - sqlite3_str *pContent = sqlite3_str_new(p->db); - int ckEnd = 1; - i64 iStart = p->lineno; - char zLine[2000]; - sCtx.zFile = p->zInFile; - sCtx.nLine = p->lineno+1; - iLineOffset = p->lineno; - while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ - if( ckEnd && cli_strncmp(zLine,zEndMark,nEndMark)==0 ){ - ckEnd = 2; - if( strchr(zLine,'\n') ) p->lineno++; - break; - } - if( strchr(zLine,'\n') ){ - p->lineno++; - ckEnd = 1; - }else{ - ckEnd = 0; - } - sqlite3_str_appendall(pContent, zLine); - } - sCtx.zIn = sqlite3_str_finish(pContent); - if( sCtx.zIn==0 ){ - sCtx.zIn = sqlite3_mprintf(""); - } - if( ckEnd<2 ){ - i64 savedLn = p->lineno; - p->lineno = iStart; - dotCmdError(p, 0, 0,"Content terminator \"%s\" not found.",zEndMark); - p->lineno = savedLn; - import_cleanup(&sCtx); - return 1; + zTab = "zip"; } }else{ - sCtx.in = sqlite3_fopen(sCtx.zFile, "rb"); - sCtx.xCloser = fclose; - } - if( sCtx.in==0 && sCtx.zIn==0 ){ - dotCmdError(p, 0, 0, "cannot open \"%s\"", zFile); - import_cleanup(&sCtx); - return 1; - } - if( eVerbose>=1 ){ - char zSep[2]; - zSep[1] = 0; - zSep[0] = sCtx.cColSep; - cli_puts("Column separator ", p->out); - output_c_string(p->out, zSep); - cli_puts(", row separator ", p->out); - zSep[0] = sCtx.cRowSep; - output_c_string(p->out, zSep); - cli_puts("\n", p->out); - } - sCtx.z = sqlite3_malloc64(120); - if( sCtx.z==0 ){ - import_cleanup(&sCtx); - shell_out_of_memory(); - } - /* Below, resources must be freed before exit. */ - while( nSkip>0 ){ - nSkip--; - while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} - } - import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ - if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) - && 0==db_int(p->db, "SELECT count(*) FROM \"%w\".sqlite_schema" - " WHERE name=%Q AND type='view'", - zSchema ? zSchema : "main", zTable) - ){ - /* Table does not exist. Create it. */ - sqlite3 *dbCols = 0; - char *zRenames = 0; - char *zColDefs; - zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", - zSchema ? zSchema : "main", zTable); - while( xRead(&sCtx) ){ - zAutoColumn(sCtx.z, &dbCols, 0); - if( sCtx.cTerm!=sCtx.cColSep ) break; - } - zColDefs = zAutoColumn(0, &dbCols, &zRenames); - if( zRenames!=0 ){ - cli_printf((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 ){ - cli_printf(stderr,"%s: empty file\n", sCtx.zFile); - import_cleanup(&sCtx); - sqlite3_free(zCreate); - return 1; - } - zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs); - if( zCreate==0 ){ - import_cleanup(&sCtx); - shell_out_of_memory(); - } - if( eVerbose>=1 ){ - cli_printf(p->out, "%s\n", zCreate); - } - rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); - if( rc ){ - cli_printf(stderr, - "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db)); - } - sqlite3_free(zCreate); - zCreate = 0; - if( rc ){ - import_cleanup(&sCtx); - return 1; + /* Initialize the table for an SQLAR */ + zTab = "sqlar"; + if( bUpdate==0 ){ + rc = arExecSql(pAr, zDrop); + if( rc!=SQLITE_OK ) goto end_ar_transaction; } + rc = arExecSql(pAr, zCreate); } - zSql = sqlite3_mprintf("SELECT count(*) FROM pragma_table_info(%Q,%Q);", - zTable, zSchema); - if( zSql==0 ){ - import_cleanup(&sCtx); - shell_out_of_memory(); - } - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - zSql = 0; - if( rc ){ - if (pStmt) sqlite3_finalize(pStmt); - shellDatabaseError(p->db); - import_cleanup(&sCtx); - return 1; - } - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - nCol = sqlite3_column_int(pStmt, 0); + if( bOnlyIfChanged ){ + zExists = sqlite3_mprintf( + " AND NOT EXISTS(" + "SELECT 1 FROM %s AS mem" + " WHERE mem.name=disk.name" + " AND mem.mtime=disk.mtime" + " AND mem.mode=disk.mode)", zTab); }else{ - nCol = 0; + zExists = sqlite3_mprintf(""); } - sqlite3_finalize(pStmt); - pStmt = 0; - if( nCol==0 ) return 0; /* no columns, no error */ - - nByte = 64 /* space for "INSERT INTO", "VALUES(", ")\0" */ - + (zSchema ? strlen(zSchema)*2 + 2: 0) /* Quoted schema name */ - + strlen(zTable)*2 + 2 /* Quoted table name */ - + nCol*2; /* Space for ",?" for each column */ - zSql = sqlite3_malloc64( nByte ); - if( zSql==0 ){ - import_cleanup(&sCtx); - shell_out_of_memory(); + if( zExists==0 ) rc = SQLITE_NOMEM; + for(i=0; inArg && rc==SQLITE_OK; i++){ + char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab, + pAr->bVerbose ? "shell_putsnl(name)" : "name", + pAr->azArg[i], pAr->zDir, zExists); + rc = arExecSql(pAr, zSql2); + sqlite3_free(zSql2); } - if( zSchema ){ - sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?", - zSchema, zTable); +end_ar_transaction: + if( rc!=SQLITE_OK ){ + sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); }else{ - sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); - } - j = strlen30(zSql); - for(i=1; i=2 ){ - cli_printf(p->out, "Insert using: %s\n", zSql); - } - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - zSql = 0; - if( rc ){ - shellDatabaseError(p->db); - if (pStmt) sqlite3_finalize(pStmt); - import_cleanup(&sCtx); - return 1; + rc = arExecSql(pAr, "RELEASE ar;"); + if( pAr->bZip && pAr->zFile ){ + zSql = sqlite3_mprintf("DROP TABLE %s", zTemp); + arExecSql(pAr, zSql); + sqlite3_free(zSql); + } } - needCommit = sqlite3_get_autocommit(p->db); - if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); - do{ - int startLine = sCtx.nLine; - for(i=0; imode.eMode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break; - /* - ** For CSV mode, per RFC 4180, accept EOF in lieu of final - ** record terminator but only for last field of multi-field row. - ** (If there are too few fields, it's not valid CSV anyway.) - */ - if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){ - z = ""; - } - sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); - if( iout; + cmd.db = pState->db; + if( cmd.zFile ){ + eDbType = deduceDatabaseType(cmd.zFile, 1, 0); + }else{ + eDbType = pState->openMode; + } + if( eDbType==SHELL_OPEN_ZIPFILE ){ + if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ + if( cmd.zFile==0 ){ + cmd.zSrcTable = sqlite3_mprintf("zip"); + }else{ + cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile); } - cli_printf(stderr,"%s:%d: expected %d columns but found %d" - " - filling the rest with NULL\n", - sCtx.zFile, startLine, nCol, i+1); - i += 2; - while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; } } - } - if( sCtx.cTerm==sCtx.cColSep ){ - do{ - xRead(&sCtx); - i++; - }while( sCtx.cTerm==sCtx.cColSep ); - cli_printf(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 ){ - cli_printf(stderr,"%s:%d: INSERT failed: %s\n", - sCtx.zFile, startLine, sqlite3_errmsg(p->db)); - sCtx.nErr++; - if( bail_on_error ) break; + cmd.bZip = 1; + }else if( cmd.zFile ){ + int flags; + if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; + if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT + || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){ + flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; }else{ - sCtx.nRow++; + flags = SQLITE_OPEN_READONLY; + } + cmd.db = 0; + if( cmd.bDryRun ){ + 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 ){ + 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); + sqlite3_sqlar_init(cmd.db, 0, 0); + sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, + shellPutsFunc, 0, 0); + + } + if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ + if( cmd.eCmd!=AR_CMD_CREATE + && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) + ){ + sqlite3_fprintf(stderr, "database does not contain an 'sqlar' table\n"); + rc = SQLITE_ERROR; + goto end_ar_command; } + cmd.zSrcTable = sqlite3_mprintf("sqlar"); } - }while( sCtx.cTerm!=EOF ); - import_cleanup(&sCtx); - sqlite3_finalize(pStmt); - if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); - if( eVerbose>0 ){ - cli_printf(p->out, - "Added %d rows with %d errors using %d lines of input\n", - sCtx.nRow, sCtx.nErr, sCtx.nLine-1-iLineOffset); + switch( cmd.eCmd ){ + case AR_CMD_CREATE: + rc = arCreateOrUpdateCommand(&cmd, 0, 0); + break; + + case AR_CMD_EXTRACT: + rc = arExtractCommand(&cmd); + break; + + case AR_CMD_LIST: + rc = arListCommand(&cmd); + break; + + case AR_CMD_HELP: + arUsage(pState->out); + break; + + case AR_CMD_INSERT: + rc = arCreateOrUpdateCommand(&cmd, 1, 0); + break; + + case AR_CMD_REMOVE: + rc = arRemoveCommand(&cmd); + break; + + default: + assert( cmd.eCmd==AR_CMD_UPDATE ); + rc = arCreateOrUpdateCommand(&cmd, 1, 1); + break; + } + } +end_ar_command: + if( cmd.db!=pState->db ){ + close_db(cmd.db); } - return sCtx.nErr ? 1 : 0; + sqlite3_free(cmd.zSrcTable); + + return rc; } +/* End of the ".archive" or ".ar" command logic +*******************************************************************************/ +#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ +#if SQLITE_SHELL_HAVE_RECOVER /* -** This function computes what to show the user about the configured -** titles (or column-names). Output is an integer between 0 and 3: -** -** 0: The titles do not matter. Never show anything. -** 1: Show "--titles off" -** 2: Show "--titles on" -** 3: Show "--title VALUE" where VALUE is an encoding method -** to use, one of: plain sql csv html tcl json -** -** Inputs are: -** -** spec.bTitles (bT) Whether or not to show the titles -** spec.eTitle (eT) The actual encoding to be used for titles -** ModeInfo.bHdr (bH) Default value for spec.bTitles -** ModeInfo.eHdr (eH) Default value for spec.eTitle -** bAll Whether the -v option is used +** This function is used as a callback by the recover extension. Simply +** print the supplied SQL statement to stdout. */ -static int modeTitleDsply(ShellState *p, int bAll){ - int eMode = p->mode.eMode; - const ModeInfo *pI = &aModeInfo[eMode]; - int bT = p->mode.spec.bTitles; - int eT = p->mode.spec.eTitle; - int bH = pI->bHdr; - int eH = pI->eHdr; +static int recoverSqlCb(void *pCtx, const char *zSql){ + ShellState *pState = (ShellState*)pCtx; + sqlite3_fprintf(pState->out, "%s;\n", zSql); + return SQLITE_OK; +} - /* Variable "v" is the truth table that will determine the answer - ** - ** Actual encoding is different from default - ** vvvvvvvv */ - sqlite3_uint64 v = 0x0133013311220102; - /* ^^^^ ^^^^ - ** Upper 2-byte groups for when ON/OFF disagrees with - ** the default. */ - - if( bH==0 ) return 0; /* Header not appliable. Ex: off, count */ - - if( eT==0 ) eT = eH; /* Fill in missing spec.eTitle */ - if( bT==0 ) bT = bH; /* Fill in missing spec.bTitles */ - - if( eT!=eH ) v >>= 32; /* Encoding disagree in upper 4-bytes */ - if( bT!=bH ) v >>= 16; /* ON/OFF disagree in upper 2-byte pairs */ - if( bT<2 ) v >>= 8; /* ON in even bytes, OFF in odd bytes (1st byte 0) */ - if( !bAll ) v >>= 4; /* bAll values are in the lower half-byte */ - - return v & 3; /* Return the selected truth-table entry */ -} - -/* -** DOT-COMMAND: .mode -** -** USAGE: .mode [MODE] [OPTIONS] -** -** Change the output mode to MODE and/or apply OPTIONS to the output mode. -** Arguments are processed from left to right. If no arguments, show the -** current output mode and relevant options. -** -** Options: -** --align STRING Set the alignment of text in columnar modes -** String consists of characters 'L', 'C', 'R' -** meaning "left", "centered", and "right", with -** one letter per column starting from the left. -** Unspecified alignment defaults to 'L'. -** --blob-quote ARG ARG can be "auto", "text", "sql", "hex", "tcl", -** "json", or "size". Default is "auto". -** --border on|off Show outer border on "box" and "table" modes. -** --charlimit N Set the maximum number of output characters to -** show for any single SQL value to N. Longer values -** truncated. Zero means "no limit". -** --colsep STRING Use STRING as the column separator -** --escape ESC Enable/disable escaping of control characters -** found in the output. ESC can be "off", "ascii", -** or "symbol". -** --linelimit N Set the maximum number of output lines to show for -** any single SQL value to N. Longer values are -** truncated. Zero means "no limit". Only works -** in "line" mode and in columnar modes. -** --limits L,C,T Shorthand for "--linelimit L --charlimit C -** --titlelimit T". The ",T" can be omitted in which -** case the --titlelimit is unchanged. The argument -** can also be "off" to mean "0,0,0" or "on" to -** mean "5,300,20". -** --list List available modes -** --null STRING Render SQL NULL values as the given string -** --once Setting changes to the right are reverted after -** the next SQL command. -** --quote ARG Enable/disable quoting of text. ARG can be -** "off", "on", "sql", "relaxed", "csv", "html", -** "tcl", or "json". "off" means show the text as-is. -** "on" is an alias for "sql". -** --reset Changes all mode settings back to their default. -** --rowsep STRING Use STRING as the row separator -** --sw|--screenwidth N Declare the screen width of the output device -** to be N characters. An attempt may be made to -** wrap output text to fit within this limit. Zero -** means "no limit". Or N can be "auto" to set the -** width automatically. -** --tablename NAME Set the name of the table for "insert" mode. -** --tag NAME Save mode to the left as NAME. -** --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON. -** --title ARG Whether or not to show column headers, and if so -** how to encode them. ARG can be "off", "on", -** "sql", "csv", "html", "tcl", or "json". -** --titlelimit N Limit the length of column titles to N characters. -** -v|--verbose Verbose output -** --widths LIST Set the columns widths for columnar modes. The -** argument is a list of integers, one for each -** column. A "0" width means use a dynamic width -** based on the actual width of data. If there are -** fewer entries in LIST than columns, "0" is used -** for the unspecified widths. -** --wordwrap BOOLEAN Enable/disable word wrapping -** --wrap N Wrap columns wider than N characters -** --ww Shorthand for "--wordwrap on" -*/ -static int dotCmdMode(ShellState *p){ - int nArg = p->dot.nArg; /* Number of arguments */ - char **azArg = p->dot.azArg;/* Argument list */ - int eMode = -1; /* New mode value, or -1 for none */ - int iMode = -1; /* Index of the argument that is the mode name */ - int i; /* Loop counter */ - int k; /* Misc index variable */ - int chng = 0; /* True if anything has changed */ - int bAll = 0; /* Show all details of the mode */ +/* +** This function is called to recover data from the database. A script +** to construct a new database containing all recovered data is output +** on stream pState->out. +*/ +static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ + int rc = SQLITE_OK; + const char *zRecoveryDb = ""; /* Name of "recovery" database. Debug only */ + const char *zLAF = "lost_and_found"; + int bFreelist = 1; /* 0 if --ignore-freelist is specified */ + int bRowids = 1; /* 0 if --no-rowids */ + sqlite3_recover *p = 0; + int i = 0; for(i=1; i=0 - && eMode!=MODE_Www - ){ - iMode = i; - modeChange(p, eMode); - /* (Legacy) If the mode is MODE_Insert and the next argument - ** is not an option, then the next argument must be the table - ** name. - */ - if( i+1mode.spec.zTableName, azArg[i]); - } - chng = 1; - }else if( optionMatch(z,"align") ){ - char *zAlign; - int nAlign; - int nErr = 0; - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } + n = strlen30(z); + if( n<=17 && memcmp("-ignore-freelist", z, n)==0 ){ + bFreelist = 0; + }else + if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){ + /* This option determines the name of the ATTACH-ed database used + ** internally by the recovery extension. The default is "" which + ** means to use a temporary database that is automatically deleted + ** when closed. This option is undocumented and might disappear at + ** any moment. */ i++; - zAlign = azArg[i]; - nAlign = 0x3fff & strlen(zAlign); - free(p->mode.spec.aAlign); - p->mode.spec.aAlign = malloc(nAlign); - shell_check_oom(p->mode.spec.aAlign); - for(k=0; kmode.spec.aAlign[k] = c; - } - p->mode.spec.nAlign = nAlign; - chng = 1; - if( nErr ){ - dotCmdError(p, i, "bad alignment string", - "Should contain only characters L, C, and R."); - return 1; - } - }else if( pickStr(z,0,"-blob","-blob-quote","")>=0 ){ - if( (++i)>=nArg ){ - dotCmdError(p, i-1, "missing argument", 0); - return 1; - } - k = pickStr(azArg[i], 0, - "auto", "text", "sql", "hex", "tcl", "json", "size", ""); - /* 0 1 2 3 4 5 6 - ** Must match QRF_BLOB_xxxx values. See also tag-20251124a */ - if( k>=0 ){ - p->mode.spec.eBlob = k & 0xff; - } - chng = 1; - }else if( optionMatch(z,"border") ){ - if( (++i)>=nArg ){ - dotCmdError(p, i-1, "missing argument", 0); - return 1; - } - k = pickStr(azArg[i], 0, "auto", "off", "on", ""); - if( k>=0 ){ - p->mode.spec.bBorder = k & 0x3; - } - chng = 1; - }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","-titlelimit","")) ){ - int w; /* 0 1 */ - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - w = integerValue(azArg[++i]); - switch( k ){ - case 0: p->mode.spec.nCharLimit = w; break; - case 1: p->mode.spec.nLineLimit = w; break; - default: p->mode.spec.nTitleLimit = w; break; - } - chng = 1; - }else if( 0<=(k=pickStr(z,0,"-tablename","-rowsep","-colsep","-null","")) ){ - /* 0 1 2 3 */ - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } + zRecoveryDb = azArg[i]; + }else + if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){ i++; - switch( k ){ - case 0: modeSetStr(&p->mode.spec.zTableName, azArg[i]); break; - case 1: modeSetStr(&p->mode.spec.zRowSep, azArg[i]); break; - case 2: modeSetStr(&p->mode.spec.zColumnSep, azArg[i]); break; - case 3: modeSetStr(&p->mode.spec.zNull, azArg[i]); break; - } - chng = 1; - }else if( optionMatch(z,"escape") ){ - /* See similar code at tag-20250224-1 */ - char *zErr = 0; - if( (++i)>=nArg ){ - dotCmdError(p, i-1, "missing argument", 0); - return 1; - } /* 0 1 2 <-- One less than QRF_ESC_ */ - k = pickStr(azArg[i],&zErr,"off","ascii","symbol",""); - if( k<0 ){ - dotCmdError(p, i, "unknown escape type", "%s", zErr); - sqlite3_free(zErr); - return 1; - } - p->mode.spec.eEsc = k+1; - chng = 1; - }else if( optionMatch(z,"limits") ){ - if( (++i)>=nArg ){ - dotCmdError(p, i-1, "missing argument", 0); - return 1; - } - k = pickStr(azArg[i],0,"on","off",""); - if( k==0 ){ - p->mode.spec.nLineLimit = DFLT_LINE_LIMIT; - p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT; - p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT; - }else if( k==1 ){ - p->mode.spec.nLineLimit = 0; - p->mode.spec.nCharLimit = 0; - p->mode.spec.nTitleLimit = 0; - }else{ - int L, C, T = 0; - int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T); - if( nNum<2 || L<0 || C<0 || T<0){ - dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C" - " and T are unsigned integers"); - return 1; - } - p->mode.spec.nLineLimit = L; - p->mode.spec.nCharLimit = C; - if( nNum==3 ) p->mode.spec.nTitleLimit = T; - } - chng = 1; - }else if( optionMatch(z,"list") ){ - int ii; - cli_puts("available modes:", p->out); - for(ii=0; iiout, " %s", aModeInfo[ii].zName); - } - for(ii=0; iinSavedModes; ii++){ - cli_printf(p->out, " %s", p->aSavedModes[ii].zTag); - } - cli_puts(" batch tty\n", p->out); - chng = 1; /* Not really a change, but we still want to suppress the - ** "current mode" output */ - }else if( optionMatch(z,"once") ){ - p->nPopMode = 0; - modePush(p); - p->nPopMode = 1; - }else if( optionMatch(z,"noquote") ){ - /* (undocumented legacy) --noquote always turns quoting off */ - p->mode.spec.eText = QRF_TEXT_Plain; - p->mode.spec.eBlob = QRF_BLOB_Auto; - chng = 1; - }else if( optionMatch(z,"quote") ){ - if( i+10 || strcmp(azArg[i+1],"off")==0 || modeFind(p, azArg[i+1])<0) - ){ - /* --quote is followed by an argument other that is not an option - ** or a mode name. See it must be a boolean or a keyword to describe - ** how to set quoting. */ - i++; - if( (k = pickStr(azArg[i],0,"no","yes","0","1",""))>=0 ){ - k &= 1; /* 0 for "off". 1 for "on". */ - }else{ - char *zErr = 0; - k = pickStr(azArg[i],&zErr, - "off","on","sql","csv","html","tcl","json","relaxed",""); - /* 0 1 2 3 4 5 6 7 */ - if( k<0 ){ - dotCmdError(p, i, "unknown", "%z", zErr); - return 1; - } - } - }else{ - /* (Legacy) no following boolean argument. Turn quoting on */ - k = 1; - } - switch( k ){ - case 1: /* on */ - modeSetStr(&p->mode.spec.zNull, "NULL"); - /* Fall through */ - case 2: /* sql */ - p->mode.spec.eText = QRF_TEXT_Sql; - break; - case 3: /* csv */ - p->mode.spec.eText = QRF_TEXT_Csv; - break; - case 4: /* html */ - p->mode.spec.eText = QRF_TEXT_Html; - break; - case 5: /* tcl */ - p->mode.spec.eText = QRF_TEXT_Tcl; - break; - case 6: /* json */ - p->mode.spec.eText = QRF_TEXT_Json; - break; - case 7: /* relaxed */ - p->mode.spec.eText = QRF_TEXT_Relaxed; - break; - default: /* off */ - p->mode.spec.eText = QRF_TEXT_Plain; - break; - } - chng = 1; - }else if( optionMatch(z,"reset") ){ - int saved_eMode = p->mode.eMode; - modeFree(&p->mode); - modeChange(p, saved_eMode); - }else if( optionMatch(z,"screenwidth") || optionMatch(z,"sw") ){ - if( (++i)>=nArg ){ - dotCmdError(p, i-1, "missing argument", 0); - return 1; - } - k = pickStr(azArg[i],0,"off","auto",""); - if( k==0 ){ - p->mode.bAutoScreenWidth = 0; - p->mode.spec.nScreenWidth = 0; - }else if( k==1 ){ - p->mode.bAutoScreenWidth = 1; - }else{ - i64 w = integerValue(azArg[i]); - p->mode.bAutoScreenWidth = 0; - if( w<0 ) w = 0; - if( w>QRF_MAX_WIDTH ) w = QRF_MAX_WIDTH; - p->mode.spec.nScreenWidth = w; - } - chng = 1; - }else if( optionMatch(z,"tag") ){ - size_t nByte; - int n; - const char *zTag; - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - zTag = azArg[++i]; - if( modeFind(p, zTag)>=0 ){ - dotCmdError(p, i, "mode already exists", 0); - return 1; - } - if( p->nSavedModes > MODE_N_USER ){ - dotCmdError(p, i-1, "cannot add more modes", 0); - return 1; - } - n = p->nSavedModes++; - nByte = sizeof(p->aSavedModes[0]); - nByte *= n+1; - p->aSavedModes = realloc( p->aSavedModes, nByte ); - shell_check_oom(p->aSavedModes); - p->aSavedModes[n].zTag = strdup(zTag); - shell_check_oom(p->aSavedModes[n].zTag); - modeDup(&p->aSavedModes[n].mode, &p->mode); - chng = 1; - }else if( optionMatch(z,"textjsonb") ){ - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - p->mode.spec.bTextJsonb = booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; - chng = 1; - }else if( optionMatch(z,"titles") || optionMatch(z,"title") ){ - char *zErr = 0; - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - k = pickStr(azArg[++i],&zErr, - "off","on","plain","sql","csv","html","tcl","json",""); - /* 0 1 2 3 4 5 6 7 */ - if( k<0 ){ - dotCmdError(p, i, "bad --titles value","%z", zErr); - return 1; - } - p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No; - p->mode.mFlags &= ~MFLG_HDR; - p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr; - chng = 1; - }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){ - int nWidth = 0; - short int *aWidth; - const char *zW; - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - zW = azArg[++i]; - /* Every width value takes at least 2 bytes in the input string to - ** specify, so strlen(zW) bytes should be plenty of space to hold the - ** result. */ - aWidth = malloc( strlen(zW) ); - while( IsSpace(zW[0]) ) zW++; - while( zW[0] ){ - int w = 0; - int nDigit = 0; - k = zW[0]=='-' && IsDigit(zW[1]); - while( IsDigit(zW[k]) ){ - w = w*10 + zW[k] - '0'; - if( w>QRF_MAX_WIDTH ){ - dotCmdError(p,i+1,"width too big", - "Maximum column width is %d", QRF_MAX_WIDTH); - free(aWidth); - return 1; - } - nDigit++; - k++; - } - if( nDigit==0 ){ - dotCmdError(p,i+1,"syntax error", - "should be a comma-separated list if integers"); - free(aWidth); - return 1; - } - if( zW[0]=='-' ) w = -w; - aWidth[nWidth++] = w; - zW += k; - if( zW[0]==',' ) zW++; - while( IsSpace(zW[0]) ) zW++; - } - free(p->mode.spec.aWidth); - p->mode.spec.aWidth = aWidth; - p->mode.spec.nWidth = nWidth; - chng = 1; - }else if( optionMatch(z,"wrap") ){ - int w; - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - w = integerValue(azArg[++i]); - if( w<(-QRF_MAX_WIDTH) ) w = -QRF_MAX_WIDTH; - if( w>QRF_MAX_WIDTH ) w = QRF_MAX_WIDTH; - p->mode.spec.nWrap = w; - chng = 1; - }else if( optionMatch(z,"ww") ){ - p->mode.spec.bWordWrap = QRF_Yes; - chng = 1; - }else if( optionMatch(z,"wordwrap") ){ - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - p->mode.spec.bWordWrap = (u8)booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; - chng = 1; - }else if( optionMatch(z,"v") || optionMatch(z,"verbose") ){ - bAll = 1; - }else if( z[0]=='-' ){ - dotCmdError(p, i, "bad option", "Use \".help .mode\" for more info"); - return 1; - }else{ - dotCmdError(p, i, iMode>0?"bad argument":"unknown mode", - "Use \".help .mode\" for more info"); + zLAF = azArg[i]; + }else + if( n<=10 && memcmp("-no-rowids", z, n)==0 ){ + bRowids = 0; + } + else{ + sqlite3_fprintf(stderr,"unexpected option: %s\n", azArg[i]); + showHelp(pState->out, azArg[0]); return 1; } } - if( !chng || bAll ){ - const ModeInfo *pI = aModeInfo + p->mode.eMode; - sqlite3_str *pDesc = sqlite3_str_new(p->db); - char *zDesc; - const char *zSetting; - if( p->nPopMode ) sqlite3_str_appendall(pDesc, "--once "); - sqlite3_str_appendall(pDesc,pI->zName); - if( bAll || (p->mode.spec.nAlign && pI->eCx==2) ){ - int ii; - sqlite3_str_appendall(pDesc, " --align \""); - for(ii=0; iimode.spec.nAlign; ii++){ - unsigned char a = p->mode.spec.aAlign[ii]; - sqlite3_str_appendchar(pDesc, 1, "LLCR"[a&3]); - } - sqlite3_str_append(pDesc, "\"", 1); - } - if( bAll - || (p->mode.spec.bBorder==QRF_No) != ((pI->mFlg&1)!=0) - ){ - sqlite3_str_appendf(pDesc," --border %s", - p->mode.spec.bBorder==QRF_No ? "off" : "on"); - } - if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){ - const char *azBQuote[] = - { "auto", "text", "sql", "hex", "tcl", "json", "size" }; - /* 0 1 2 3 4 5 6 - ** Must match QRF_BLOB_xxxx values. See all instances of tag-20251124a */ - u8 e = p->mode.spec.eBlob; - sqlite3_str_appendf(pDesc, " --blob-quote %s", azBQuote[e]); - } - zSetting = aModeStr[pI->eCSep]; - if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zColumnSep)!=0) ){ - sqlite3_str_appendf(pDesc, " --colsep "); - append_c_string(pDesc, p->mode.spec.zColumnSep); - } - if( bAll || p->mode.spec.eEsc!=QRF_Auto ){ - sqlite3_str_appendf(pDesc, " --escape %s",qrfEscNames[p->mode.spec.eEsc]); - } - if( bAll - || (p->mode.spec.nLineLimit>0 && pI->eCx>0) - || p->mode.spec.nCharLimit>0 - || (p->mode.spec.nTitleLimit>0 && pI->eCx>0) - ){ - if( p->mode.spec.nLineLimit==0 - && p->mode.spec.nCharLimit==0 - && p->mode.spec.nTitleLimit==0 - ){ - sqlite3_str_appendf(pDesc, " --limits off"); - }else if( p->mode.spec.nLineLimit==DFLT_LINE_LIMIT - && p->mode.spec.nCharLimit==DFLT_CHAR_LIMIT - && p->mode.spec.nTitleLimit==DFLT_TITLE_LIMIT - ){ - sqlite3_str_appendf(pDesc, " --limits on"); - }else{ - sqlite3_str_appendf(pDesc, " --limits %d,%d,%d", - p->mode.spec.nLineLimit, p->mode.spec.nCharLimit, - p->mode.spec.nTitleLimit); - } - } - zSetting = aModeStr[pI->eNull]; - if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zNull)!=0) ){ - sqlite3_str_appendf(pDesc, " --null "); - append_c_string(pDesc, p->mode.spec.zNull); - } - if( bAll - || (pI->eText!=p->mode.spec.eText && (pI->eText>1 || p->mode.spec.eText>1)) - ){ - sqlite3_str_appendf(pDesc," --quote %s",qrfQuoteNames[p->mode.spec.eText]); - } - zSetting = aModeStr[pI->eRSep]; - if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zRowSep)!=0) ){ - sqlite3_str_appendf(pDesc, " --rowsep "); - append_c_string(pDesc, p->mode.spec.zRowSep); - } - if( bAll - || (pI->eCx && (p->mode.spec.nScreenWidth>0 || p->mode.bAutoScreenWidth)) - ){ - if( p->mode.bAutoScreenWidth ){ - sqlite3_str_appendall(pDesc, " --sw auto"); - }else{ - sqlite3_str_appendf(pDesc," --sw %d", - p->mode.spec.nScreenWidth); - } - } - if( bAll || p->mode.eMode==MODE_Insert ){ - sqlite3_str_appendf(pDesc," --tablename "); - append_c_string(pDesc, p->mode.spec.zTableName); - } - if( bAll || p->mode.spec.bTextJsonb ){ - sqlite3_str_appendf(pDesc," --textjsonb %s", - p->mode.spec.bTextJsonb==QRF_Yes ? "on" : "off"); - } - k = modeTitleDsply(p, bAll); - if( k==1 ){ - sqlite3_str_appendall(pDesc, " --titles off"); - }else if( k==2 ){ - sqlite3_str_appendall(pDesc, " --titles on"); - }else if( k==3 ){ - static const char *azTitle[] = - { "plain", "sql", "csv", "html", "tcl", "json"}; - sqlite3_str_appendf(pDesc, " --titles %s", - azTitle[p->mode.spec.eTitle-1]); - } - if( p->mode.spec.nWidth>0 && (bAll || pI->eCx==2) ){ - int ii; - const char *zSep = " --widths "; - for(ii=0; iimode.spec.nWidth; ii++){ - sqlite3_str_appendf(pDesc, "%s%d", zSep, (int)p->mode.spec.aWidth[ii]); - zSep = ","; - } - }else if( bAll ){ - sqlite3_str_appendall(pDesc, " --widths \"\""); - } - if( bAll || (pI->eCx>0 && p->mode.spec.bWordWrap) ){ - if( bAll ){ - sqlite3_str_appendf(pDesc, " --wordwrap %s", - p->mode.spec.bWordWrap==QRF_Yes ? "on" : "off"); + p = sqlite3_recover_init_sql( + pState->db, "main", recoverSqlCb, (void*)pState + ); + + sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */ + sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF); + sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids); + sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist); + + sqlite3_fprintf(pState->out, ".dbconfig defensive off\n"); + sqlite3_recover_run(p); + if( sqlite3_recover_errcode(p)!=SQLITE_OK ){ + const char *zErr = sqlite3_recover_errmsg(p); + int errCode = sqlite3_recover_errcode(p); + sqlite3_fprintf(stderr,"sql error: %s (%d)\n", zErr, errCode); + } + rc = sqlite3_recover_finish(p); + return rc; +} +#endif /* SQLITE_SHELL_HAVE_RECOVER */ + +/* +** Implementation of ".intck STEPS_PER_UNLOCK" command. +*/ +static int intckDatabaseCmd(ShellState *pState, i64 nStepPerUnlock){ + sqlite3_intck *p = 0; + int rc = SQLITE_OK; + + rc = sqlite3_intck_open(pState->db, "main", &p); + if( rc==SQLITE_OK ){ + i64 nStep = 0; + i64 nError = 0; + const char *zErr = 0; + while( SQLITE_OK==sqlite3_intck_step(p) ){ + const char *zMsg = sqlite3_intck_message(p); + if( zMsg ){ + sqlite3_fprintf(pState->out, "%s\n", zMsg); + nError++; } - if( p->mode.spec.nWrap ){ - sqlite3_str_appendf(pDesc, " --wrap %d", p->mode.spec.nWrap); + nStep++; + if( nStepPerUnlock && (nStep % nStepPerUnlock)==0 ){ + sqlite3_intck_unlock(p); } - if( !bAll ) sqlite3_str_append(pDesc, " --ww", 5); } - zDesc = sqlite3_str_finish(pDesc); - cli_printf(p->out, ".mode %s\n", zDesc); - fflush(p->out); - sqlite3_free(zDesc); + rc = sqlite3_intck_error(p, &zErr); + if( zErr ){ + sqlite3_fprintf(stderr,"%s\n", zErr); + } + sqlite3_intck_close(p); + + sqlite3_fprintf(pState->out, "%lld steps, %lld errors\n", nStep, nError); } - return 0; + + return rc; } /* -** DOT-COMMAND: .output -** USAGE: .output [OPTIONS] [FILE] -** -** Begin redirecting output to FILE. Or if FILE is omitted, revert -** to sending output to the console. If FILE begins with "|" then -** the remainder of file is taken as a pipe and output is directed -** into that pipe. If FILE is "memory" then output is captured in an -** internal memory buffer. If FILE is "off" then output is redirected -** into /dev/null or the equivalent. -** -** Options: -** --bom Prepend a byte-order mark to the output -** -e Accumulate output in a temporary text file then -** launch a text editor when the redirection ends. -** --error-prefix X Use X as the left-margin prefix for error messages. -** Set to an empty string to restore the default. -** --keep Keep redirecting output to its current destination. -** Use this option in combination with --show or -** with --error-prefix when you do not want to stop -** a current redirection. -** --plain Use plain text rather than HTML tables with -w -** --show Show output text captured by .testcase or by -** redirecting to "memory". -** -w Show the output in a web browser. Output is -** written into a temporary HTML file until the -** redirect ends, then the web browser is launched. -** Query results are shown as HTML tables, unless -** the --plain is used too. -** -x Show the output in a spreadsheet. Output is -** written to a temp file as CSV then the spreadsheet -** is launched when -** -** DOT-COMMAND: .once -** USAGE: .once [OPTIONS] FILE ... -** -** Write the output for the next line of SQL or the next dot-command into -** FILE. If FILE begins with "|" then it is a program into which output -** is written. The FILE argument should be omitted if one of the -e, -w, -** or -x options is used. -** -** Options: -** -e Capture output into a temporary file then bring up -** a text editor on that temporary file. -** --plain Use plain text rather than HTML tables with -w -** -w Capture output into an HTML file then bring up that -** file in a web browser -** -x Show the output in a spreadsheet. Output is -** written to a temp file as CSV then the spreadsheet -** is launched when -** -** DOT-COMMAND: .excel -** Shorthand for ".once -x" -** -** DOT-COMMAND: .www [--plain] -** Shorthand for ".once -w" or ".once --plain -w" -*/ -static int dotCmdOutput(ShellState *p){ - int nArg = p->dot.nArg; /* Number of arguments */ - char **azArg = p->dot.azArg; /* Text of the arguments */ - char *zFile = 0; /* The FILE argument */ - int i; /* Loop counter */ - int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */ - int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */ - int bPlain = 0; /* --plain option */ - int bKeep = 0; /* Keep redirecting */ - static const char *zBomUtf8 = "\357\273\277"; - const char *zBom = 0; - char c = azArg[0][0]; - int n = strlen30(azArg[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( n>=2 && cli_strncmp(azArg[0],"once",n)==0 ){ - bOnce = 1; - } - for(i=1; i=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - free(p->zErrPrefix); - i++; - p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]); - }else{ - dotCmdError(p, i, "unknown option", 0); - sqlite3_free(zFile); - return 1; - } - }else if( zFile==0 && eMode==0 ){ - if( bKeep ){ - dotCmdError(p, i, "incompatible with prior options",0); - goto dotCmdOutput_error; - } - if( cli_strcmp(z, "memory")==0 && bOnce ){ - dotCmdError(p, 0, "cannot redirect to \"memory\"", 0); - goto dotCmdOutput_error; - } - if( cli_strcmp(z, "off")==0 ){ -#ifdef _WIN32 - zFile = sqlite3_mprintf("nul"); + * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it. + * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE, + * close db and set it to 0, and return the columns spec, to later + * be sqlite3_free()'ed by the caller. + * The return is 0 when either: + * (a) The db was not initialized and zCol==0 (There are no columns.) + * (b) zCol!=0 (Column was added, db initialized as needed.) + * The 3rd argument, pRenamed, references an out parameter. If the + * pointer is non-zero, its referent will be set to a summary of renames + * done if renaming was necessary, or set to 0 if none was done. The out + * string (if any) must be sqlite3_free()'ed by the caller. + */ +#ifdef SHELL_DEBUG +#define rc_err_oom_die(rc) \ + if( rc==SQLITE_NOMEM ) shell_check_oom(0); \ + else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \ + sqlite3_fprintf(stderr,"E:%d\n",rc), assert(0) #else - zFile = sqlite3_mprintf("/dev/null"); +static void rc_err_oom_die(int rc){ + if( rc==SQLITE_NOMEM ) shell_check_oom(0); + assert(rc==SQLITE_OK||rc==SQLITE_DONE); +} #endif - }else{ - zFile = sqlite3_mprintf("%s", z); - } - if( zFile && zFile[0]=='|' ){ - while( i+1nPopOutput = 2; - }else{ - p->nPopOutput = 0; - } - if( !bKeep ) output_reset(p); -#ifndef SQLITE_NOHAVE_SYSTEM - if( eMode=='e' || eMode=='x' || eMode=='w' ){ - p->doXdgOpen = 1; - modePush(p); - if( eMode=='x' ){ - /* spreadsheet mode. Output as CSV. */ - newTempFile(p, "csv"); - p->mode.mFlags &= ~MFLG_ECHO; - p->mode.eMode = MODE_Csv; - modeSetStr(&p->mode.spec.zColumnSep, SEP_Comma); - modeSetStr(&p->mode.spec.zRowSep, SEP_CrLf); -#ifdef _WIN32 - zBom = zBomUtf8; /* Always include the BOM on Windows, as Excel does - ** not work without it. */ + +#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */ +static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB); +#else /* Otherwise, memory is faster/better for the transient DB. */ +static const char *zCOL_DB = ":memory:"; #endif - }else if( eMode=='w' ){ - /* web-browser mode. */ - newTempFile(p, "html"); - if( !bPlain ) p->mode.eMode = MODE_Www; - }else{ - /* text editor mode */ - newTempFile(p, "txt"); - } - sqlite3_free(zFile); - zFile = sqlite3_mprintf("%s", p->zTempFile); - } -#endif /* SQLITE_NOHAVE_SYSTEM */ - if( !bKeep ) shell_check_oom(zFile); - if( bKeep ){ - /* no-op */ - }else if( cli_strcmp(zFile,"memory")==0 ){ - if( cli_output_capture ){ - sqlite3_str_free(cli_output_capture); - } - cli_output_capture = sqlite3_str_new(0); - }else if( zFile[0]=='|' ){ -#ifdef SQLITE_OMIT_POPEN - eputz("Error: pipes are not supported in this OS\n"); - output_redir(p, stdout); - goto dotCmdOutput_error; + +/* Define character (as C string) to separate generated column ordinal + * from protected part of incoming column names. This defaults to "_" + * so that incoming column identifiers that did not need not be quoted + * remain usable without being quoted. It must be one character. + */ +#ifndef SHELL_AUTOCOLUMN_SEP +# define AUTOCOLUMN_SEP "_" #else - FILE *pfPipe = sqlite3_popen(zFile + 1, "w"); - if( pfPipe==0 ){ - assert( stderr!=NULL ); - cli_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); - goto dotCmdOutput_error; - }else{ - output_redir(p, pfPipe); - if( zBom ) cli_puts(zBom, pfPipe); - sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); - } +# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP) #endif - }else{ - FILE *pfFile = output_file_open(p, zFile); - if( pfFile==0 ){ - if( cli_strcmp(zFile,"off")!=0 ){ - assert( stderr!=NULL ); - cli_printf(stderr,"Error: cannot write to \"%s\"\n", zFile); - } - goto dotCmdOutput_error; - } else { - output_redir(p, pfFile); - if( zBom ) cli_puts(zBom, pfFile); - if( bPlain && eMode=='w' ){ - cli_puts( - "\n\n\n", - pfFile - ); - } - sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); - } - } - sqlite3_free(zFile); - return 0; - -dotCmdOutput_error: - sqlite3_free(zFile); - return 1; -} -/* -** DOT-COMMAND: .check -** USAGE: .check [OPTIONS] PATTERN -** -** Verify results of commands since the most recent .testcase command. -** Restore output to the console, unless --keep is used. -** -** If PATTERN starts with "<<ENDMARK" then the actual pattern is taken from -** subsequent lines of text up to the first line that begins with ENDMARK. -** All pattern lines and the ENDMARK are discarded. -** -** Options: -** --exact Do an exact comparison including leading and -** trailing whitespace. -** --glob Treat PATTERN as a GLOB -** --keep Do not reset the testcase. More .check commands -** will follow. -** --notglob Output should not match PATTERN -** --show Write testcase output to the screen, for debugging. -*/ -static int dotCmdCheck(ShellState *p){ - int nArg = p->dot.nArg; /* Number of arguments */ - char **azArg = p->dot.azArg; /* Text of the arguments */ - int i; /* Loop counter */ - int k; /* Result of pickStr() */ - char *zTest; /* Textcase result */ - int bKeep = 0; /* --keep option */ - char *zCheck = 0; /* PATTERN argument */ - char *zPattern = 0; /* Actual test pattern */ - int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --exact */ - int isOk; /* True if results are OK */ - sqlite3_int64 iStart = p->lineno; /* Line number of .check statement */ - - if( p->zTestcase[0]==0 ){ - dotCmdError(p, 0, "no .testcase is active", 0); - return 1; - } - for(i=1; i<nArg; i++){ - char *z = azArg[i]; - if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++; - if( cli_strcmp(z,"-keep")==0 ){ - bKeep = 1; - }else if( cli_strcmp(z,"-show")==0 ){ - if( cli_output_capture ){ - sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture)); - } - bKeep = 1; - }else if( z[0]=='-' - && (k = pickStr(&z[1],0,"glob","notglob","exact",""))>=0 - ){ - if( eCheck && eCheck!=k+1 ){ - dotCmdError(p, i, "incompatible with prior options",0); - return 1; - } - eCheck = k+1; - }else if( zCheck ){ - dotCmdError(p, i, "unknown option", 0); - return 1; - }else{ - zCheck = azArg[i]; - } - } - if( zCheck==0 ){ - dotCmdError(p, 0, "no PATTERN specified", 0); - return 1; - } - if( cli_output_capture && sqlite3_str_length(cli_output_capture) ){ - zTest = sqlite3_str_value(cli_output_capture); - shell_check_oom(zTest); - }else{ - zTest = ""; - } - p->nTestRun++; - if( zCheck[0]=='<' && zCheck[1]=='<' && zCheck[2]!=0 ){ - int nCheck = strlen30(zCheck); - sqlite3_str *pPattern = sqlite3_str_new(p->db); - char zLine[2000]; - while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ - if( strchr(zLine,'\n') ) p->lineno++; - if( cli_strncmp(&zCheck[2],zLine,nCheck-2)==0 ) break; - sqlite3_str_appendall(pPattern, zLine); - } - zPattern = sqlite3_str_finish(pPattern); - if( zPattern==0 ){ - zPattern = sqlite3_mprintf(""); +static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){ + /* Queries and D{D,M}L used here */ + static const char * const zTabMake = "\ +CREATE TABLE ColNames(\ + cpos INTEGER PRIMARY KEY,\ + name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\ +CREATE VIEW RepeatedNames AS \ +SELECT DISTINCT t.name FROM ColNames t \ +WHERE t.name COLLATE NOCASE IN (\ + SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\ +);\ +"; + static const char * const zTabFill = "\ +INSERT INTO ColNames(name,nlen,chop,reps,suff)\ + VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\ +"; + static const char * const zHasDupes = "\ +SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\ + <count(name) FROM ColNames\ +"; +#ifdef SHELL_COLUMN_RENAME_CLEAN + static const char * const zDedoctor = "\ +UPDATE ColNames SET chop=iif(\ + (substring(name,nlen,1) BETWEEN '0' AND '9')\ + AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\ + nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\ + 0\ +)\ +"; +#endif + static const char * const zSetReps = "\ +UPDATE ColNames AS t SET reps=\ +(SELECT count(*) FROM ColNames d \ + WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\ + COLLATE NOCASE\ +)\ +"; +#ifdef SQLITE_ENABLE_MATH_FUNCTIONS + static const char * const zColDigits = "\ +SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \ +"; +#else + /* Counting on SQLITE_MAX_COLUMN < 100,000 here. (32767 is the hard limit.) */ + static const char * const zColDigits = "\ +SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \ + WHEN (nc < 1000) THEN 3 WHEN (nc < 10000) THEN 4 \ + ELSE 5 FROM (SELECT count(*) AS nc FROM ColNames) \ +"; +#endif + static const char * const zRenameRank = +#ifdef SHELL_COLUMN_RENAME_CLEAN + "UPDATE ColNames AS t SET suff=" + "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')" +#else /* ...RENAME_MINIMAL_ONE_PASS */ +"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */ +" SELECT 0 AS nlz" +" UNION" +" SELECT nlz+1 AS nlz FROM Lzn" +" WHERE EXISTS(" +" SELECT 1" +" FROM ColNames t, ColNames o" +" WHERE" +" iif(t.name IN (SELECT * FROM RepeatedNames)," +" printf('%s"AUTOCOLUMN_SEP"%s'," +" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2))," +" t.name" +" )" +" =" +" iif(o.name IN (SELECT * FROM RepeatedNames)," +" printf('%s"AUTOCOLUMN_SEP"%s'," +" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2))," +" o.name" +" )" +" COLLATE NOCASE" +" AND o.cpos<>t.cpos" +" GROUP BY t.cpos" +" )" +") UPDATE Colnames AS t SET" +" chop = 0," /* No chopping, never touch incoming names. */ +" suff = iif(name IN (SELECT * FROM RepeatedNames)," +" printf('"AUTOCOLUMN_SEP"%s', substring(" +" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2))," +" ''" +" )" +#endif + ; + static const char * const zCollectVar = "\ +SELECT\ + '('||x'0a'\ + || group_concat(\ + cname||' TEXT',\ + ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ + ||')' AS ColsSpec \ +FROM (\ + SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \ + FROM ColNames ORDER BY cpos\ +)"; + static const char * const zRenamesDone = + "SELECT group_concat(" + " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff))," + " ','||x'0a')" + "FROM ColNames WHERE suff<>'' OR chop!=0" + ; + int rc; + sqlite3_stmt *pStmt = 0; + assert(pDb!=0); + if( zColNew ){ + /* Add initial or additional column. Init db if necessary. */ + if( *pDb==0 ){ + if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0; +#ifdef SHELL_COLFIX_DB + if(*zCOL_DB!=':') + sqlite3_exec(*pDb,"drop table if exists ColNames;" + "drop view if exists RepeatedNames;",0,0,0); +#endif +#undef SHELL_COLFIX_DB + rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0); + rc_err_oom_die(rc); } + assert(*pDb!=0); + rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0); + rc_err_oom_die(rc); + rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0); + rc_err_oom_die(rc); + rc = sqlite3_step(pStmt); + rc_err_oom_die(rc); + sqlite3_finalize(pStmt); + return 0; + }else if( *pDb==0 ){ + return 0; }else{ - zPattern = zCheck; - } - shell_check_oom(zPattern); - switch( eCheck ){ - case 1: { - char *zGlob = sqlite3_mprintf("*%s*", zPattern); - isOk = testcase_glob(zGlob, zTest)!=0; - sqlite3_free(zGlob); - break; - } - case 2: { - char *zGlob = sqlite3_mprintf("*%s*", zPattern); - isOk = testcase_glob(zGlob, zTest)==0; - sqlite3_free(zGlob); - break; + /* Formulate the columns spec, close the DB, zero *pDb. */ + char *zColsSpec = 0; + int hasDupes = db_int(*pDb, "%s", zHasDupes); + int nDigits = (hasDupes)? db_int(*pDb, "%s", zColDigits) : 0; + if( hasDupes ){ +#ifdef SHELL_COLUMN_RENAME_CLEAN + rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0); + rc_err_oom_die(rc); +#endif + rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); + rc_err_oom_die(rc); + rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); + rc_err_oom_die(rc); + sqlite3_bind_int(pStmt, 1, nDigits); + rc = sqlite3_step(pStmt); + sqlite3_finalize(pStmt); + if( rc!=SQLITE_DONE ) rc_err_oom_die(SQLITE_NOMEM); } - case 3: { - isOk = cli_strcmp(zTest,zPattern)==0; - break; + assert(db_int(*pDb, "%s", zHasDupes)==0); /* Consider: remove this */ + rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0); + rc_err_oom_die(rc); + rc = sqlite3_step(pStmt); + if( rc==SQLITE_ROW ){ + zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); + }else{ + zColsSpec = 0; } - default: { - /* Skip leading and trailing \n and \r on both pattern and test output */ - const char *z1 = zPattern; - const char *z2 = zTest; - size_t n1, n2; - while( z1[0]=='\n' || z1[0]=='\r' ) z1++; - n1 = strlen(z1); - while( n1>0 && (z1[n1-1]=='\n' || z1[n1-1]=='\r') ) n1--; - while( z2[0]=='\n' || z2[0]=='\r' ) z2++; - n2 = strlen(z2); - while( n2>0 && (z2[n2-1]=='\n' || z2[n2-1]=='\r') ) n2--; - isOk = n1==n2 && memcmp(z1,z2,n1)==0; - break; + if( pzRenamed!=0 ){ + if( !hasDupes ) *pzRenamed = 0; + else{ + sqlite3_finalize(pStmt); + if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0) + && SQLITE_ROW==sqlite3_step(pStmt) ){ + *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); + }else + *pzRenamed = 0; + } } + sqlite3_finalize(pStmt); + sqlite3_close(*pDb); + *pDb = 0; + return zColsSpec; } - if( !isOk ){ - sqlite3_fprintf(stderr, - "%s:%lld: .check failed for testcase %s\n", - p->zInFile, iStart, p->zTestcase); - p->nTestErr++; - sqlite3_fprintf(stderr, "Expected: [%s]\n", zPattern); - sqlite3_fprintf(stderr, "Got: [%s]\n", zTest); - } - if( zPattern!=zCheck ){ - sqlite3_free(zPattern); - } - if( !bKeep ){ - output_reset(p); - p->zTestcase[0] = 0; - } - return 0; } /* -** DOT-COMMAND: .testcase -** USAGE: .testcase [OPTIONS] NAME -** -** Start a new test case identified by NAME. All output -** through the next ".check" command is captured for comparison. See the -** ".check" commandn for additional informatioon. +** Check if the sqlite_schema table contains one or more virtual tables. If +** parameter zLike is not NULL, then it is an SQL expression that the +** sqlite_schema row must also match. If one or more such rows are found, +** print the following warning to the output: ** -** Options: -** --error-prefix TEXT Change error message prefix text to TEXT +** WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */ -static int dotCmdTestcase(ShellState *p){ - int nArg = p->dot.nArg; /* Number of arguments */ - char **azArg = p->dot.azArg; /* Text of the arguments */ - int i; /* Loop counter */ - const char *zName = 0; /* Testcase name */ - - for(i=1; i<nArg; i++){ - char *z = azArg[i]; - if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++; - if( optionMatch(z,"error-prefix") ){ - if( i+1>=nArg ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - free(p->zErrPrefix); - i++; - p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]); - }else if( zName ){ - dotCmdError(p, i, "unknown option", 0); - return 1; - }else{ - zName = azArg[i]; - } - } - output_reset(p); - if( cli_output_capture ){ - sqlite3_str_free(cli_output_capture); - } - cli_output_capture = sqlite3_str_new(0); - if( zName ){ - sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", zName); - }else{ - sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s:%lld", - p->zInFile, p->lineno); +static int outputDumpWarning(ShellState *p, const char *zLike){ + int rc = SQLITE_OK; + sqlite3_stmt *pStmt = 0; + shellPreparePrintf(p->db, &rc, &pStmt, + "SELECT 1 FROM sqlite_schema o WHERE " + "sql LIKE 'CREATE VIRTUAL TABLE%%' AND %s", zLike ? zLike : "true" + ); + if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ + sqlite3_fputs("/* WARNING: " + "Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */\n", + p->out + ); } - return 0; + shellFinalize(&rc, pStmt); + return rc; } /* -** Enlarge the space allocated in p->dot so that it can hold more -** than nArg parsed command-line arguments. +** Fault-Simulator state and logic. */ -static void parseDotRealloc(ShellState *p, int nArg){ - p->dot.nAlloc = nArg+22; - p->dot.azArg = realloc(p->dot.azArg,p->dot.nAlloc*sizeof(char*)); - shell_check_oom(p->dot.azArg); - p->dot.aiOfst = realloc(p->dot.aiOfst,p->dot.nAlloc*sizeof(int)); - shell_check_oom(p->dot.aiOfst); - p->dot.abQuot = realloc(p->dot.abQuot,p->dot.nAlloc); - shell_check_oom(p->dot.abQuot); -} - +static struct { + int iId; /* ID that triggers a simulated fault. -1 means "any" */ + int iErr; /* The error code to return on a fault */ + int iCnt; /* Trigger the fault only if iCnt is already zero */ + int iInterval; /* Reset iCnt to this value after each fault */ + int eVerbose; /* When to print output */ + int nHit; /* Number of hits seen so far */ + int nRepeat; /* Turn off after this many hits. 0 for never */ + int nSkip; /* Skip this many before first fault */ +} faultsim_state = {-1, 0, 0, 0, 0, 0, 0, 0}; /* -** Parse input line zLine up into individual arguments. Retain the -** parse in the p->dot substructure. +** This is the fault-sim callback */ -static void parseDotCmdArgs(const char *zLine, ShellState *p){ - char *z; - int h = 1; - int nArg = 0; - size_t szLine; - - p->dot.zOrig = zLine; - free(p->dot.zCopy); - z = p->dot.zCopy = strdup(zLine); - shell_check_oom(z); - szLine = strlen(z); - while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; - if( szLine>0 && z[szLine-1]==';' ){ - szLine--; - while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; - } - z[szLine] = 0; - parseDotRealloc(p, 2); - while( z[h] ){ - while( IsSpace(z[h]) ){ h++; } - if( z[h]==0 ) break; - if( nArg+2>p->dot.nAlloc ){ - parseDotRealloc(p, nArg); - } - if( z[h]=='\'' || z[h]=='"' ){ - int delim = z[h++]; - p->dot.abQuot[nArg] = 1; - p->dot.azArg[nArg] = &z[h]; - p->dot.aiOfst[nArg] = h; - while( z[h] && z[h]!=delim ){ - if( z[h]=='\\' && delim=='"' && z[h+1]!=0 ) h++; - h++; - } - if( z[h]==delim ){ - z[h++] = 0; - } - if( delim=='"' ) resolve_backslashes(p->dot.azArg[nArg]); - }else{ - p->dot.abQuot[nArg] = 0; - p->dot.azArg[nArg] = &z[h]; - p->dot.aiOfst[nArg] = h; - while( z[h] && !IsSpace(z[h]) ){ h++; } - if( z[h] ) z[h++] = 0; +static int faultsim_callback(int iArg){ + if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){ + return SQLITE_OK; + } + if( faultsim_state.iCnt ){ + if( faultsim_state.iCnt>0 ) faultsim_state.iCnt--; + if( faultsim_state.eVerbose>=2 ){ + sqlite3_fprintf(stdout, + "FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt); } - nArg++; + return SQLITE_OK; + } + if( faultsim_state.eVerbose>=1 ){ + sqlite3_fprintf(stdout, + "FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr); + } + faultsim_state.iCnt = faultsim_state.iInterval; + faultsim_state.nHit++; + if( faultsim_state.nRepeat>0 && faultsim_state.nRepeat<=faultsim_state.nHit ){ + faultsim_state.iCnt = -1; } - p->dot.nArg = nArg; - p->dot.azArg[nArg] = 0; + return faultsim_state.iErr; } /* @@ -32369,11 +28556,12 @@ static void parseDotCmdArgs(const char *zLine, ShellState *p){ ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ -static int do_meta_command(const char *zLine, ShellState *p){ - int nArg; +static int do_meta_command(char *zLine, ShellState *p){ + int h = 1; + int nArg = 0; int n, c; int rc = 0; - char **azArg; + char *azArg[52]; #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION) if( p->expert.pExpert ){ @@ -32381,11 +28569,29 @@ static int do_meta_command(const char *zLine, ShellState *p){ } #endif - /* Parse the input line into tokens stored in p->dot. + /* Parse the input line into tokens. */ - parseDotCmdArgs(zLine, p); - nArg = p->dot.nArg; - azArg = p->dot.azArg; + while( zLine[h] && nArg<ArraySize(azArg)-1 ){ + while( IsSpace(zLine[h]) ){ h++; } + if( zLine[h]==0 ) break; + if( zLine[h]=='\'' || zLine[h]=='"' ){ + int delim = zLine[h++]; + azArg[nArg++] = &zLine[h]; + while( zLine[h] && zLine[h]!=delim ){ + if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++; + h++; + } + if( zLine[h]==delim ){ + zLine[h++] = 0; + } + if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); + }else{ + azArg[nArg++] = &zLine[h]; + while( zLine[h] && !IsSpace(zLine[h]) ){ h++; } + if( zLine[h] ) zLine[h++] = 0; + } + } + azArg[nArg] = 0; /* Process the input line. */ @@ -32397,7 +28603,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ #ifndef SQLITE_OMIT_AUTHORIZATION if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){ if( nArg!=2 ){ - cli_printf(stderr, "Usage: .auth ON|OFF\n"); + sqlite3_fprintf(stderr, "Usage: .auth ON|OFF\n"); rc = 1; goto meta_command_exit; } @@ -32444,7 +28650,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ bAsync = 1; }else { - dotCmdError(p, j, "unknown option", "should be -append or -async"); + sqlite3_fprintf(stderr,"unknown option: %s\n", azArg[j]); return 1; } }else if( zDestFile==0 ){ @@ -32453,19 +28659,19 @@ static int do_meta_command(const char *zLine, ShellState *p){ zDb = zDestFile; zDestFile = azArg[j]; }else{ - cli_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n"); + sqlite3_fprintf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n"); return 1; } } if( zDestFile==0 ){ - cli_printf(stderr, "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 ){ - cli_printf(stderr,"Error: cannot open \"%s\"\n", zDestFile); + sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zDestFile); close_db(pDest); return 1; } @@ -32526,7 +28732,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ rc = chdir(azArg[1]); #endif if( rc ){ - cli_printf(stderr,"Cannot change to directory \"%s\"\n", azArg[1]); + sqlite3_fprintf(stderr,"Cannot change to directory \"%s\"\n", azArg[1]); rc = 1; } }else{ @@ -32545,13 +28751,31 @@ static int do_meta_command(const char *zLine, ShellState *p){ } }else +#ifndef SQLITE_SHELL_FIDDLE /* Cancel output redirection, if it is currently set (by .testcase) ** Then read the content of the testcase-out.txt file and compare against ** azArg[1]. If there are differences, report an error and exit. */ if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){ - rc = dotCmdCheck(p); + char *zRes = 0; + output_reset(p); + if( nArg!=2 ){ + eputz("Usage: .check GLOB-PATTERN\n"); + rc = 2; + }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ + rc = 2; + }else if( testcase_glob(azArg[1],zRes)==0 ){ + sqlite3_fprintf(stderr, + "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", + p->zTestcase, azArg[1], zRes); + rc = 1; + }else{ + sqlite3_fprintf(p->out, "testcase-%s ok\n", p->zTestcase); + p->nCheck++; + } + sqlite3_free(zRes); }else +#endif /* !defined(SQLITE_SHELL_FIDDLE) */ #ifndef SQLITE_SHELL_FIDDLE if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){ @@ -32579,9 +28803,9 @@ static int do_meta_command(const char *zLine, ShellState *p){ zFile = "(temporary-file)"; } if( p->pAuxDb == &p->aAuxDb[i] ){ - cli_printf(stdout, "ACTIVE %d: %s\n", i, zFile); + sqlite3_fprintf(stdout, "ACTIVE %d: %s\n", i, zFile); }else if( p->aAuxDb[i].db!=0 ){ - cli_printf(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 ){ @@ -32617,17 +28841,12 @@ static int do_meta_command(const char *zLine, ShellState *p){ ){ if( nArg==2 ){ #ifdef _WIN32 - if( booleanValue(azArg[1]) ){ - p->mode.mFlags |= MFLG_CRLF; - }else{ - p->mode.mFlags &= ~MFLG_CRLF; - } + p->crlfMode = booleanValue(azArg[1]); #else - p->mode.mFlags &= ~MFLG_CRLF; + p->crlfMode = 0; #endif } - cli_printf(stderr, "crlf is %s\n", - (p->mode.mFlags & MFLG_CRLF)!=0 ? "ON" : "OFF"); + sqlite3_fprintf(stderr, "crlf is %s\n", p->crlfMode ? "ON" : "OFF"); }else if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){ @@ -32657,7 +28876,7 @@ static int do_meta_command(const 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]; - cli_printf(p->out, "%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"); @@ -32683,7 +28902,6 @@ static int do_meta_command(const char *zLine, ShellState *p){ { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, - { "fp_digits", SQLITE_DBCONFIG_FP_DIGITS }, { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, @@ -32700,24 +28918,16 @@ static int do_meta_command(const char *zLine, ShellState *p){ for(ii=0; ii<ArraySize(aDbConfig); ii++){ if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; if( nArg>=3 ){ - if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){ - sqlite3_db_config(p->db, aDbConfig[ii].op, atoi(azArg[2]), 0); - }else{ - sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); - } + sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); } sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); - if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){ - cli_printf(p->out, "%19s %d\n", aDbConfig[ii].zName, v); - }else{ - cli_printf(p->out, "%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) ){ - dotCmdError(p, 1, "unknown dbconfig", - "Enter \".dbconfig\" with no arguments for a list"); + sqlite3_fprintf(stderr,"Error: unknown dbconfig \"%s\"\n", azArg[1]); + eputz("Enter \".dbconfig\" with no arguments for a list\n"); } }else @@ -32736,19 +28946,19 @@ static int do_meta_command(const char *zLine, ShellState *p){ char *zLike = 0; char *zSql; int i; + int savedShowHeader = p->showHeader; int savedShellFlags = p->shellFlgs; - Mode saved_mode; ShellClearFlag(p, - SHFLG_PreserveRowid|SHFLG_DumpDataOnly|SHFLG_DumpNoSys); + SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo + |SHFLG_DumpDataOnly|SHFLG_DumpNoSys); for(i=1; i<nArg; i++){ if( azArg[i][0]=='-' ){ const char *z = azArg[i]+1; if( z[0]=='-' ) z++; if( cli_strcmp(z,"preserve-rowids")==0 ){ #ifdef SQLITE_OMIT_VIRTUALTABLE - dotCmdError(p, i, "unable", - "The --preserve-rowids option is not compatible" - " with SQLITE_OMIT_VIRTUALTABLE"); + eputz("The --preserve-rowids option is not compatible" + " with SQLITE_OMIT_VIRTUALTABLE\n"); rc = 1; sqlite3_free(zLike); goto meta_command_exit; @@ -32757,7 +28967,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ #endif }else if( cli_strcmp(z,"newlines")==0 ){ - /*ShellSetFlag(p, SHFLG_Newlines);*/ + ShellSetFlag(p, SHFLG_Newlines); }else if( cli_strcmp(z,"data-only")==0 ){ ShellSetFlag(p, SHFLG_DumpDataOnly); @@ -32766,7 +28976,8 @@ static int do_meta_command(const char *zLine, ShellState *p){ ShellSetFlag(p, SHFLG_DumpNoSys); }else { - dotCmdError(p, i, "unknown option", 0); + sqlite3_fprintf(stderr, + "Unknown option \"%s\" on \".dump\"\n", azArg[i]); rc = 1; sqlite3_free(zLike); goto meta_command_exit; @@ -32796,17 +29007,16 @@ static int do_meta_command(const char *zLine, ShellState *p){ open_db(p, 0); - modeDup(&saved_mode, &p->mode); outputDumpWarning(p, zLike); if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ /* 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. */ - cli_puts("PRAGMA foreign_keys=OFF;\n", p->out); - cli_puts("BEGIN TRANSACTION;\n", p->out); + sqlite3_fputs("PRAGMA foreign_keys=OFF;\n", p->out); + sqlite3_fputs("BEGIN TRANSACTION;\n", p->out); } p->writableSchema = 0; - p->mode.spec.bTitles = QRF_No; + p->showHeader = 0; /* Set writable_schema=ON since doing so forces SQLite to initialize ** as much of the schema as it can even if the sqlite_schema table is ** corrupt. */ @@ -32835,27 +29045,22 @@ static int do_meta_command(const char *zLine, ShellState *p){ } sqlite3_free(zLike); if( p->writableSchema ){ - cli_puts("PRAGMA writable_schema=OFF;\n", p->out); + 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 ){ - cli_puts(p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n", p->out); + sqlite3_fputs(p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n", p->out); } + p->showHeader = savedShowHeader; p->shellFlgs = savedShellFlags; - modeFree(&p->mode); - p->mode = saved_mode; rc = p->nErr>0; }else if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){ if( nArg==2 ){ - if( booleanValue(azArg[1]) ){ - p->mode.mFlags |= MFLG_ECHO; - }else{ - p->mode.mFlags &= ~MFLG_ECHO; - } + setOrClearFlag(p, SHFLG_Echo, azArg[1]); }else{ eputz("Usage: .echo on|off\n"); rc = 1; @@ -32869,24 +29074,28 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){ if( nArg==2 ){ - if( p->mode.autoEQPtrace ){ + p->autoEQPtest = 0; + if( p->autoEQPtrace ){ if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0); - p->mode.autoEQPtrace = 0; + p->autoEQPtrace = 0; } if( cli_strcmp(azArg[1],"full")==0 ){ - p->mode.autoEQP = AUTOEQP_full; + p->autoEQP = AUTOEQP_full; }else if( cli_strcmp(azArg[1],"trigger")==0 ){ - p->mode.autoEQP = AUTOEQP_trigger; + p->autoEQP = AUTOEQP_trigger; #ifdef SQLITE_DEBUG + }else if( cli_strcmp(azArg[1],"test")==0 ){ + p->autoEQP = AUTOEQP_on; + p->autoEQPtest = 1; }else if( cli_strcmp(azArg[1],"trace")==0 ){ - p->mode.autoEQP = AUTOEQP_full; - p->mode.autoEQPtrace = 1; + p->autoEQP = AUTOEQP_full; + p->autoEQPtrace = 1; open_db(p, 0); sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0); sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0); #endif }else{ - p->mode.autoEQP = (u8)booleanValue(azArg[1]); + p->autoEQP = (u8)booleanValue(azArg[1]); } }else{ eputz("Usage: .eqp off|on|trace|trigger|full\n"); @@ -32896,7 +29105,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ #ifndef SQLITE_SHELL_FIDDLE if( c=='e' && cli_strncmp(azArg[0], "exit", n)==0 ){ - if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) cli_exit(rc); + if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); rc = 2; }else #endif @@ -32904,19 +29113,31 @@ static int do_meta_command(const char *zLine, ShellState *p){ /* The ".explain" command is automatic now. It is largely pointless. It ** retained purely for backwards compatibility */ if( c=='e' && cli_strncmp(azArg[0], "explain", n)==0 ){ + int val = 1; if( nArg>=2 ){ if( cli_strcmp(azArg[1],"auto")==0 ){ - p->mode.autoExplain = 1; + val = 99; }else{ - p->mode.autoExplain = booleanValue(azArg[1]); + val = booleanValue(azArg[1]); } } + if( val==1 && p->mode!=MODE_Explain ){ + p->normalMode = p->mode; + p->mode = MODE_Explain; + p->autoExplain = 0; + }else if( val==0 ){ + if( p->mode==MODE_Explain ) p->mode = p->normalMode; + p->autoExplain = 0; + }else if( val==99 ){ + if( p->mode==MODE_Explain ) p->mode = p->normalMode; + p->autoExplain = 1; + } }else #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION) if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){ if( p->bSafeMode ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "Cannot run experimental commands such as \"%s\" in safe mode\n", azArg[0]); rc = 1; @@ -32974,9 +29195,9 @@ static int do_meta_command(const char *zLine, ShellState *p){ /* --help lists all file-controls */ if( cli_strcmp(zCmd,"help")==0 ){ - cli_puts("Available file-controls:\n", p->out); + sqlite3_fputs("Available file-controls:\n", p->out); for(i=0; i<ArraySize(aCtrl); i++){ - cli_printf(p->out, + sqlite3_fprintf(p->out, " .filectrl %s %s\n", aCtrl[i].zCtrlName, aCtrl[i].zUsage); } rc = 1; @@ -32992,7 +29213,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ filectrl = aCtrl[i].ctrlCode; iCtrl = i; }else{ - cli_printf(stderr,"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; @@ -33000,7 +29221,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ } } if( filectrl<0 ){ - cli_printf(stderr,"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){ @@ -33044,7 +29265,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( nArg!=2 ) break; sqlite3_file_control(p->db, zSchema, filectrl, &z); if( z ){ - cli_printf(p->out, "%s\n", z); + sqlite3_fprintf(p->out, "%s\n", z); sqlite3_free(z); } isOk = 2; @@ -33058,30 +29279,31 @@ static int do_meta_command(const char *zLine, ShellState *p){ } x = -1; sqlite3_file_control(p->db, zSchema, filectrl, &x); - cli_printf(p->out, "%d\n", x); + sqlite3_fprintf(p->out, "%d\n", x); isOk = 2; break; } } } if( isOk==0 && iCtrl>=0 ){ - cli_printf(p->out, "Usage: .filectrl %s %s\n", + 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); - cli_printf(p->out, "%s\n", zBuf); + sqlite3_fprintf(p->out, "%s\n", zBuf); } }else if( c=='f' && cli_strncmp(azArg[0], "fullschema", n)==0 ){ ShellState data; int doStats = 0; - int hasStat[5]; - int flgs = 0; - char *zSql; + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.cMode = data.mode = MODE_Semi; if( nArg==2 && optionMatch(azArg[1], "indent") ){ + data.cMode = data.mode = MODE_Pretty; nArg = 1; } if( nArg!=1 ){ @@ -33090,82 +29312,385 @@ static int do_meta_command(const char *zLine, ShellState *p){ goto meta_command_exit; } open_db(p, 0); - zSql = sqlite3_mprintf( - "SELECT shell_format_schema(sql,%d) FROM" + rc = sqlite3_exec(p->db, + "SELECT sql FROM" " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_schema UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " "WHERE type!='meta' AND sql NOTNULL" - " AND name NOT LIKE 'sqlite__%%' ESCAPE '_' " - "ORDER BY x", flgs); - memcpy(&data, p, sizeof(data)); - data.mode.spec.bTitles = QRF_No; - data.mode.eMode = MODE_List; - data.mode.spec.eText = QRF_TEXT_Plain; - data.mode.spec.nCharLimit = 0; - data.mode.spec.zRowSep = "\n"; - rc = shell_exec(&data,zSql,0); - sqlite3_free(zSql); + " AND name NOT LIKE 'sqlite__%' ESCAPE '_' " + "ORDER BY x", + callback, &data, 0 + ); if( rc==SQLITE_OK ){ sqlite3_stmt *pStmt; - memset(hasStat, 0, sizeof(hasStat)); rc = sqlite3_prepare_v2(p->db, - "SELECT substr(name,12,1) FROM sqlite_schema" + "SELECT rowid FROM sqlite_schema" " WHERE name GLOB 'sqlite_stat[134]'", -1, &pStmt, 0); if( rc==SQLITE_OK ){ - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - int k = sqlite3_column_int(pStmt,0); - assert( k==1 || k==3 || k==4 ); - hasStat[k] = 1; - doStats = 1; - } + doStats = sqlite3_step(pStmt)==SQLITE_ROW; + sqlite3_finalize(pStmt); } - sqlite3_finalize(pStmt); } if( doStats==0 ){ - cli_puts("/* No STAT tables available */\n", p->out); + sqlite3_fputs("/* No STAT tables available */\n", p->out); + }else{ + 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); + sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out); + } + }else + + if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ + if( nArg==2 ){ + p->showHeader = booleanValue(azArg[1]); + p->shellFlgs |= SHFLG_HeaderSet; + }else{ + eputz("Usage: .headers on|off\n"); + rc = 1; + } + }else + + if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){ + if( nArg>=2 ){ + n = showHelp(p->out, azArg[1]); + if( n==0 ){ + sqlite3_fprintf(p->out, "Nothing matches '%s'\n", azArg[1]); + } + }else{ + showHelp(p->out, 0); + } + }else + +#ifndef SQLITE_SHELL_FIDDLE + if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){ + char *zTable = 0; /* Insert data into this table */ + char *zSchema = 0; /* Schema of zTable */ + char *zFile = 0; /* Name of file to extra content from */ + sqlite3_stmt *pStmt = NULL; /* A statement */ + int nCol; /* Number of columns in the table */ + i64 nByte; /* Number of bytes in an SQL string */ + int i, j; /* Loop counters */ + int needCommit; /* True to COMMIT or ROLLBACK at end */ + int nSep; /* Number of bytes in p->colSeparator[] */ + char *zSql = 0; /* An SQL statement */ + ImportCtx sCtx; /* Reader context */ + char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ + int eVerbose = 0; /* Larger for more console output */ + i64 nSkip = 0; /* Initial lines to skip */ + int useOutputMode = 1; /* Use output mode to determine separators */ + char *zCreate = 0; /* CREATE TABLE statement text */ + + failIfSafeMode(p, "cannot run .import in safe mode"); + memset(&sCtx, 0, sizeof(sCtx)); + if( p->mode==MODE_Ascii ){ + xRead = ascii_read_one_field; + }else{ + xRead = csv_read_one_field; + } + rc = 1; + for(i=1; i<nArg; i++){ + char *z = azArg[i]; + if( z[0]=='-' && z[1]=='-' ) z++; + if( z[0]!='-' ){ + if( zFile==0 ){ + zFile = z; + }else if( zTable==0 ){ + zTable = z; + }else{ + sqlite3_fprintf(p->out, "ERROR: extra argument: \"%s\". Usage:\n",z); + showHelp(p->out, "import"); + goto meta_command_exit; + } + }else if( cli_strcmp(z,"-v")==0 ){ + eVerbose++; + }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){ + zSchema = azArg[++i]; + }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){ + nSkip = integerValue(azArg[++i]); + }else if( cli_strcmp(z,"-ascii")==0 ){ + sCtx.cColSep = SEP_Unit[0]; + sCtx.cRowSep = SEP_Record[0]; + xRead = ascii_read_one_field; + useOutputMode = 0; + }else if( cli_strcmp(z,"-csv")==0 ){ + sCtx.cColSep = ','; + sCtx.cRowSep = '\n'; + xRead = csv_read_one_field; + useOutputMode = 0; + }else{ + sqlite3_fprintf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z); + showHelp(p->out, "import"); + goto meta_command_exit; + } + } + if( zTable==0 ){ + sqlite3_fprintf(p->out, "ERROR: missing %s argument. Usage:\n", + zFile==0 ? "FILE" : "TABLE"); + showHelp(p->out, "import"); + goto meta_command_exit; + } + seenInterrupt = 0; + open_db(p, 0); + if( useOutputMode ){ + /* If neither the --csv or --ascii options are specified, then set + ** the column and row separator characters from the output mode. */ + nSep = strlen30(p->colSeparator); + if( nSep==0 ){ + eputz("Error: non-null column separator required for import\n"); + goto meta_command_exit; + } + if( nSep>1 ){ + eputz("Error: multi-character column separators not allowed" + " for import\n"); + goto meta_command_exit; + } + nSep = strlen30(p->rowSeparator); + if( nSep==0 ){ + eputz("Error: non-null row separator required for import\n"); + goto meta_command_exit; + } + if( nSep==2 && p->mode==MODE_Csv + && cli_strcmp(p->rowSeparator,SEP_CrLf)==0 + ){ + /* When importing CSV (only), if the row separator is set to the + ** default output row separator, change it to the default input + ** row separator. This avoids having to maintain different input + ** and output row separators. */ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + nSep = strlen30(p->rowSeparator); + } + if( nSep>1 ){ + eputz("Error: multi-character row separators not allowed" + " for import\n"); + goto meta_command_exit; + } + sCtx.cColSep = (u8)p->colSeparator[0]; + sCtx.cRowSep = (u8)p->rowSeparator[0]; + } + sCtx.zFile = zFile; + sCtx.nLine = 1; + if( sCtx.zFile[0]=='|' ){ +#ifdef SQLITE_OMIT_POPEN + eputz("Error: pipes are not supported in this OS\n"); + goto meta_command_exit; +#else + sCtx.in = sqlite3_popen(sCtx.zFile+1, "r"); + sCtx.zFile = "<pipe>"; + sCtx.xCloser = pclose; +#endif }else{ - cli_puts("ANALYZE sqlite_schema;\n", p->out); - data.mode.eMode = MODE_Insert; - if( hasStat[1] ){ - data.mode.spec.zTableName = "sqlite_stat1"; - shell_exec(&data, "SELECT * FROM sqlite_stat1", 0); + sCtx.in = sqlite3_fopen(sCtx.zFile, "rb"); + sCtx.xCloser = fclose; + } + if( sCtx.in==0 ){ + 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; + 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(p->out, zSep); + sqlite3_fputs("\n", p->out); + } + sCtx.z = sqlite3_malloc64(120); + if( sCtx.z==0 ){ + import_cleanup(&sCtx); + shell_out_of_memory(); + } + /* Below, resources must be freed before exit. */ + while( nSkip>0 ){ + nSkip--; + while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} + } + import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ + if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) + && 0==db_int(p->db, "SELECT count(*) FROM \"%w\".sqlite_schema" + " WHERE name=%Q AND type='view'", + zSchema ? zSchema : "main", zTable) + ){ + /* Table does not exist. Create it. */ + sqlite3 *dbCols = 0; + char *zRenames = 0; + char *zColDefs; + zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", + zSchema ? zSchema : "main", zTable); + while( xRead(&sCtx) ){ + zAutoColumn(sCtx.z, &dbCols, 0); + if( sCtx.cTerm!=sCtx.cColSep ) break; + } + zColDefs = zAutoColumn(0, &dbCols, &zRenames); + if( zRenames!=0 ){ + 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 ){ + 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); + if( zCreate==0 ){ + import_cleanup(&sCtx); + shell_out_of_memory(); + } + if( eVerbose>=1 ){ + 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 ){ + import_cleanup(&sCtx); + rc = 1; + goto meta_command_exit; + } + } + zSql = sqlite3_mprintf("SELECT count(*) FROM pragma_table_info(%Q,%Q);", + zTable, zSchema); + if( zSql==0 ){ + import_cleanup(&sCtx); + shell_out_of_memory(); + } + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + zSql = 0; + if( rc ){ + if (pStmt) sqlite3_finalize(pStmt); + shellDatabaseError(p->db); + import_cleanup(&sCtx); + rc = 1; + goto meta_command_exit; + } + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + nCol = sqlite3_column_int(pStmt, 0); + }else{ + nCol = 0; + } + sqlite3_finalize(pStmt); + pStmt = 0; + if( nCol==0 ) return 0; /* no columns, no error */ + + nByte = 64 /* space for "INSERT INTO", "VALUES(", ")\0" */ + + (zSchema ? strlen(zSchema)*2 + 2: 0) /* Quoted schema name */ + + strlen(zTable)*2 + 2 /* Quoted table name */ + + nCol*2; /* Space for ",?" for each column */ + zSql = sqlite3_malloc64( nByte ); + if( zSql==0 ){ + import_cleanup(&sCtx); + shell_out_of_memory(); + } + if( zSchema ){ + sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?", + zSchema, zTable); + }else{ + sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); + } + j = strlen30(zSql); + for(i=1; i<nCol; i++){ + zSql[j++] = ','; + zSql[j++] = '?'; + } + zSql[j++] = ')'; + zSql[j] = 0; + assert( j<nByte ); + if( eVerbose>=2 ){ + 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 ){ + shellDatabaseError(p->db); + if (pStmt) sqlite3_finalize(pStmt); + import_cleanup(&sCtx); + rc = 1; + goto meta_command_exit; + } + needCommit = sqlite3_get_autocommit(p->db); + if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); + do{ + int startLine = sCtx.nLine; + for(i=0; i<nCol; i++){ + char *z = xRead(&sCtx); + /* + ** Did we reach end-of-file before finding any columns? + ** If so, stop instead of NULL filling the remaining columns. + */ + if( z==0 && i==0 ) break; + /* + ** Did we reach end-of-file OR end-of-line before finding any + ** columns in ASCII mode? If so, stop instead of NULL filling + ** the remaining columns. + */ + if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break; + /* + ** For CSV mode, per RFC 4180, accept EOF in lieu of final + ** record terminator but only for last field of multi-field row. + ** (If there are too few fields, it's not valid CSV anyway.) + */ + if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){ + z = ""; + } + sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); + if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){ + 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; + while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; } + } } - if( hasStat[4] ){ - data.mode.spec.zTableName = "sqlite_stat4"; - shell_exec(&data, "SELECT * FROM sqlite_stat4", 0); + if( sCtx.cTerm==sCtx.cColSep ){ + do{ + xRead(&sCtx); + i++; + }while( sCtx.cTerm==sCtx.cColSep ); + 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 ){ + sqlite3_fprintf(stderr,"%s:%d: INSERT failed: %s\n", + sCtx.zFile, startLine, sqlite3_errmsg(p->db)); + sCtx.nErr++; + }else{ + sCtx.nRow++; + } } - cli_puts("ANALYZE sqlite_schema;\n", p->out); - } - }else - - if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ - if( nArg==2 ){ - p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; - p->mode.mFlags |= MFLG_HDR; - p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; - }else{ - eputz("Usage: .headers on|off\n"); - rc = 1; - } - }else + }while( sCtx.cTerm!=EOF ); - if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){ - if( nArg>=2 ){ - n = showHelp(p->out, azArg[1]); - if( n==0 ){ - cli_printf(p->out, "Nothing matches '%s'\n", azArg[1]); - } - }else{ - showHelp(p->out, 0); + import_cleanup(&sCtx); + sqlite3_finalize(pStmt); + if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); + if( eVerbose>0 ){ + sqlite3_fprintf(p->out, + "Added %d rows with %d errors using %d lines of input\n", + sCtx.nRow, sCtx.nErr, sCtx.nLine-1); } }else - -#ifndef SQLITE_SHELL_FIDDLE - if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){ - rc = dotCmdImport(p); - }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ #ifndef SQLITE_UNTESTABLE @@ -33197,10 +29722,10 @@ static int do_meta_command(const char *zLine, ShellState *p){ } zSql = sqlite3_mprintf( "SELECT rootpage, 0 FROM sqlite_schema" - " WHERE type='index' AND lower(name)=lower('%q')" + " WHERE name='%q' AND type='index'" "UNION ALL " "SELECT rootpage, 1 FROM sqlite_schema" - " WHERE type='table' AND lower(name)=lower('%q')" + " WHERE name='%q' AND type='table'" " AND sql LIKE '%%without%%rowid%%'", azArg[1], azArg[1] ); @@ -33238,7 +29763,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ } sqlite3_finalize(pStmt); if( i==0 || tnum==0 ){ - cli_printf(stderr,"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; @@ -33253,13 +29778,13 @@ static int do_meta_command(const 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 ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); }else{ - cli_printf(stdout, "%s;\n", zSql); + sqlite3_fprintf(stdout, "%s;\n", zSql); } }else{ - cli_printf(stderr,"SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); + sqlite3_fprintf(stderr,"SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); rc = 1; } sqlite3_free(zSql); @@ -33273,7 +29798,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( iArg==0 ) iArg = -1; } if( (nArg!=1 && nArg!=2) || iArg<0 ){ - cli_printf(stderr,"%s","Usage: .intck STEPS_PER_UNLOCK\n"); + sqlite3_fprintf(stderr,"%s","Usage: .intck STEPS_PER_UNLOCK\n"); rc = 1; goto meta_command_exit; } @@ -33294,7 +29819,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ }else{ iotrace = sqlite3_fopen(azArg[1], "w"); if( iotrace==0 ){ - cli_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); + sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); sqlite3IoTrace = 0; rc = 1; }else{ @@ -33313,7 +29838,6 @@ static int do_meta_command(const char *zLine, ShellState *p){ { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, { "column", SQLITE_LIMIT_COLUMN }, { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, - { "parser_depth", SQLITE_LIMIT_PARSER_DEPTH }, { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, @@ -33327,7 +29851,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ open_db(p, 0); if( nArg==1 ){ for(i=0; i<ArraySize(aLimit); i++){ - cli_printf(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 ){ @@ -33342,14 +29866,14 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( iLimit<0 ){ iLimit = i; }else{ - cli_printf(stderr,"ambiguous limit: \"%s\"\n", azArg[1]); + sqlite3_fprintf(stderr,"ambiguous limit: \"%s\"\n", azArg[1]); rc = 1; goto meta_command_exit; } } } if( iLimit<0 ){ - cli_printf(stderr,"unknown limit: \"%s\"\n" + sqlite3_fprintf(stderr,"unknown limit: \"%s\"\n" "enter \".limits\" with no arguments for a list.\n", azArg[1]); rc = 1; @@ -33358,10 +29882,9 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( nArg==3 ){ sqlite3_limit(p->db, aLimit[iLimit].limitCode, (int)integerValue(azArg[2])); - }else{ - cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName, - sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); } + sqlite3_fprintf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName, + sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); } }else @@ -33409,12 +29932,174 @@ static int do_meta_command(const char *zLine, ShellState *p){ } output_file_close(p->pLog); if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout"; - p->pLog = output_file_open(p, zFile); + p->pLog = output_file_open(zFile); } }else if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){ - rc = dotCmdMode(p); + const char *zMode = 0; + const char *zTabname = 0; + int i, n2; + int chng = 0; /* 0x01: change to cmopts. 0x02: Any other change */ + ColModeOpts cmOpts = ColModeOpts_default; + for(i=1; i<nArg; i++){ + const char *z = azArg[i]; + if( optionMatch(z,"wrap") && i+1<nArg ){ + cmOpts.iWrap = integerValue(azArg[++i]); + chng |= 1; + }else if( optionMatch(z,"ww") ){ + cmOpts.bWordWrap = 1; + chng |= 1; + }else if( optionMatch(z,"wordwrap") && i+1<nArg ){ + cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]); + chng |= 1; + }else if( optionMatch(z,"quote") ){ + cmOpts.bQuote = 1; + chng |= 1; + }else if( optionMatch(z,"noquote") ){ + cmOpts.bQuote = 0; + chng |= 1; + }else if( optionMatch(z,"escape") && i+1<nArg ){ + /* See similar code at tag-20250224-1 */ + const char *zEsc = azArg[++i]; + int k; + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){ + p->eEscMode = k; + chng |= 2; + break; + } + } + if( k>=ArraySize(shell_EscModeNames) ){ + sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\"" + " - choices:", zEsc); + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]); + } + sqlite3_fprintf(stderr, "\n"); + rc = 1; + goto meta_command_exit; + } + }else if( zMode==0 ){ + zMode = z; + /* Apply defaults for qbox pseudo-mode. If that + * overwrites already-set values, user was informed of this. + */ + chng |= 1; + if( cli_strcmp(z, "qbox")==0 ){ + ColModeOpts cmo = ColModeOpts_default_qbox; + zMode = "box"; + cmOpts = cmo; + } + }else if( zTabname==0 ){ + zTabname = z; + }else if( z[0]=='-' ){ + sqlite3_fprintf(stderr,"unknown option: %s\n", z); + eputz("options:\n" + " --escape MODE\n" + " --noquote\n" + " --quote\n" + " --wordwrap on/off\n" + " --wrap N\n" + " --ww\n"); + rc = 1; + goto meta_command_exit; + }else{ + sqlite3_fprintf(stderr,"extra argument: \"%s\"\n", z); + rc = 1; + goto meta_command_exit; + } + } + if( !chng ){ + if( p->mode==MODE_Column + || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) + ){ + sqlite3_fprintf(p->out, + "current output mode: %s --wrap %d --wordwrap %s " + "--%squote --escape %s\n", + modeDescr[p->mode], p->cmOpts.iWrap, + p->cmOpts.bWordWrap ? "on" : "off", + p->cmOpts.bQuote ? "" : "no", + shell_EscModeNames[p->eEscMode] + ); + }else{ + sqlite3_fprintf(p->out, + "current output mode: %s --escape %s\n", + modeDescr[p->mode], + shell_EscModeNames[p->eEscMode] + ); + } + } + if( zMode==0 ){ + zMode = modeDescr[p->mode]; + if( (chng&1)==0 ) cmOpts = p->cmOpts; + } + n2 = strlen30(zMode); + if( cli_strncmp(zMode,"lines",n2)==0 ){ + p->mode = MODE_Line; + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( cli_strncmp(zMode,"columns",n2)==0 ){ + p->mode = MODE_Column; + if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){ + p->showHeader = 1; + } + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + p->cmOpts = cmOpts; + }else if( cli_strncmp(zMode,"list",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( cli_strncmp(zMode,"html",n2)==0 ){ + p->mode = MODE_Html; + }else if( cli_strncmp(zMode,"tcl",n2)==0 ){ + p->mode = MODE_Tcl; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( cli_strncmp(zMode,"csv",n2)==0 ){ + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); + }else if( cli_strncmp(zMode,"tabs",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); + }else if( cli_strncmp(zMode,"insert",n2)==0 ){ + p->mode = MODE_Insert; + set_table_name(p, zTabname ? zTabname : "table"); + if( p->eEscMode==SHELL_ESC_OFF ){ + ShellSetFlag(p, SHFLG_Newlines); + }else{ + ShellClearFlag(p, SHFLG_Newlines); + } + }else if( cli_strncmp(zMode,"quote",n2)==0 ){ + p->mode = MODE_Quote; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( cli_strncmp(zMode,"ascii",n2)==0 ){ + p->mode = MODE_Ascii; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); + }else if( cli_strncmp(zMode,"markdown",n2)==0 ){ + p->mode = MODE_Markdown; + p->cmOpts = cmOpts; + }else if( cli_strncmp(zMode,"table",n2)==0 ){ + p->mode = MODE_Table; + p->cmOpts = cmOpts; + }else if( cli_strncmp(zMode,"box",n2)==0 ){ + p->mode = MODE_Box; + p->cmOpts = cmOpts; + }else if( cli_strncmp(zMode,"count",n2)==0 ){ + p->mode = MODE_Count; + }else if( cli_strncmp(zMode,"off",n2)==0 ){ + p->mode = MODE_Off; + }else if( cli_strncmp(zMode,"json",n2)==0 ){ + p->mode = MODE_Json; + }else{ + eputz("Error: mode should be one of: " + "ascii box column csv html insert json line list markdown " + "qbox quote table tabs tcl\n"); + rc = 1; + } + p->cMode = p->mode; }else #ifndef SQLITE_SHELL_FIDDLE @@ -33423,9 +30108,9 @@ static int do_meta_command(const char *zLine, ShellState *p){ eputz("Usage: .nonce NONCE\n"); rc = 1; }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){ - cli_printf(stderr,"line %lld: incorrect nonce: \"%s\"\n", + sqlite3_fprintf(stderr,"line %lld: incorrect nonce: \"%s\"\n", p->lineno, azArg[1]); - cli_exit(1); + exit(1); }else{ p->bSafeMode = 0; return 0; /* Return immediately to bypass the safe mode reset @@ -33436,7 +30121,8 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){ if( nArg==2 ){ - modeSetStr(&p->mode.spec.zNull, azArg[1]); + sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, + "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); }else{ eputz("Usage: .nullvalue STRING\n"); rc = 1; @@ -33451,8 +30137,6 @@ static int do_meta_command(const char *zLine, ShellState *p){ int openMode = SHELL_OPEN_UNSPEC; int openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; - if( p->bSafeMode ) openFlags = SQLITE_OPEN_READONLY; - /* Check for command-line arguments */ for(iName=1; iName<nArg; iName++){ const char *z = azArg[iName]; @@ -33460,10 +30144,10 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( optionMatch(z,"new") ){ newFlag = 1; #ifdef SQLITE_HAVE_ZLIB - }else if( optionMatch(z, "zip") && !p->bSafeMode ){ + }else if( optionMatch(z, "zip") ){ openMode = SHELL_OPEN_ZIPFILE; #endif - }else if( optionMatch(z, "append") && !p->bSafeMode ){ + }else if( optionMatch(z, "append") ){ openMode = SHELL_OPEN_APPENDVFS; }else if( optionMatch(z, "readonly") ){ openFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); @@ -33487,11 +30171,11 @@ static int do_meta_command(const char *zLine, ShellState *p){ }else #endif /* !SQLITE_SHELL_FIDDLE */ if( z[0]=='-' ){ - cli_printf(stderr,"unknown option: %s\n", z); + sqlite3_fprintf(stderr,"unknown option: %s\n", z); rc = 1; goto meta_command_exit; }else if( zFN ){ - cli_printf(stderr,"extra argument: \"%s\"\n", z); + sqlite3_fprintf(stderr,"extra argument: \"%s\"\n", z); rc = 1; goto meta_command_exit; }else{ @@ -33542,7 +30226,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ p->pAuxDb->zDbFilename = zNewFilename; open_db(p, OPEN_DB_KEEPALIVE); if( p->db==0 ){ - cli_printf(stderr,"Error: cannot open '%s'\n", zNewFilename); + sqlite3_fprintf(stderr,"Error: cannot open '%s'\n", zNewFilename); sqlite3_free(zNewFilename); }else{ p->pAuxDb->zFreeOnClose = zNewFilename; @@ -33562,7 +30246,145 @@ static int do_meta_command(const char *zLine, ShellState *p){ || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0) || (c=='w' && n==3 && cli_strcmp(azArg[0],"www")==0) ){ - rc = dotCmdOutput(p); + char *zFile = 0; + int i; + int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */ + 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; + } + for(i=1; i<nArg; i++){ + char *z = azArg[i]; + if( z[0]=='-' ){ + if( z[1]=='-' ) z++; + if( cli_strcmp(z,"-bom")==0 ){ + zBom = zBomUtf8; + }else if( cli_strcmp(z,"-plain")==0 ){ + bPlain = 1; + }else if( c=='o' && cli_strcmp(z,"-x")==0 ){ + eMode = 'x'; /* spreadsheet */ + }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{ + sqlite3_fprintf(p->out, + "ERROR: unknown option: \"%s\". Usage:\n", azArg[i]); + showHelp(p->out, azArg[0]); + rc = 1; + sqlite3_free(zFile); + goto meta_command_exit; + } + }else if( zFile==0 && eMode==0 ){ + if( cli_strcmp(z, "off")==0 ){ +#ifdef _WIN32 + zFile = sqlite3_mprintf("nul"); +#else + zFile = sqlite3_mprintf("/dev/null"); +#endif + }else{ + zFile = sqlite3_mprintf("%s", z); + } + if( zFile && zFile[0]=='|' ){ + while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]); + break; + } + }else{ + sqlite3_fprintf(p->out, + "ERROR: extra parameter: \"%s\". Usage:\n", azArg[i]); + showHelp(p->out, azArg[0]); + rc = 1; + sqlite3_free(zFile); + goto meta_command_exit; + } + } + if( zFile==0 ){ + zFile = sqlite3_mprintf("stdout"); + } + shell_check_oom(zFile); + if( bOnce ){ + p->outCount = 2; + }else{ + p->outCount = 0; + } + output_reset(p); +#ifndef SQLITE_NOHAVE_SYSTEM + if( eMode=='e' || eMode=='x' || eMode=='w' ){ + p->doXdgOpen = 1; + outputModePush(p); + if( eMode=='x' ){ + /* spreadsheet mode. Output as CSV. */ + newTempFile(p, "csv"); + ShellClearFlag(p, SHFLG_Echo); + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); +#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"); + } + sqlite3_free(zFile); + zFile = sqlite3_mprintf("%s", p->zTempFile); + } +#endif /* SQLITE_NOHAVE_SYSTEM */ + shell_check_oom(zFile); + if( zFile[0]=='|' ){ +#ifdef SQLITE_OMIT_POPEN + eputz("Error: pipes are not supported in this OS\n"); + rc = 1; + output_redir(p, stdout); +#else + FILE *pfPipe = sqlite3_popen(zFile + 1, "w"); + if( pfPipe==0 ){ + assert( stderr!=NULL ); + sqlite3_fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); + rc = 1; + }else{ + output_redir(p, pfPipe); + if( zBom ) sqlite3_fputs(zBom, pfPipe); + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); + } +#endif + }else{ + FILE *pfFile = output_file_open(zFile); + if( pfFile==0 ){ + if( cli_strcmp(zFile,"off")!=0 ){ + assert( stderr!=NULL ); + sqlite3_fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile); + } + rc = 1; + } else { + output_redir(p, pfFile); + 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); + } + } + sqlite3_free(zFile); }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ @@ -33599,7 +30421,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ "SELECT key, quote(value) " "FROM temp.sqlite_parameters;", -1, &pStmt, 0); while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - cli_printf(p->out, + sqlite3_fprintf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0), sqlite3_column_text(pStmt,1)); } @@ -33645,7 +30467,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rx!=SQLITE_OK ){ - cli_printf(p->out, "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; @@ -33675,10 +30497,10 @@ static int do_meta_command(const 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 ) cli_puts(" ", p->out); - cli_puts(azArg[i], p->out); + if( i>1 ) sqlite3_fputs(" ", p->out); + sqlite3_fputs(azArg[i], p->out); } - cli_puts("\n", p->out); + sqlite3_fputs("\n", p->out); }else #ifndef SQLITE_OMIT_PROGRESS_CALLBACK @@ -33705,19 +30527,6 @@ static int do_meta_command(const char *zLine, ShellState *p){ p->flgProgress |= SHELL_PROGRESS_ONCE; continue; } - if( cli_strcmp(z,"timeout")==0 ){ - if( i==nArg-1 ){ - dotCmdError(p, i, "missing argument", 0); - return 1; - } - i++; - p->tmProgress = atof(azArg[i]); - if( p->tmProgress>0.0 ){ - p->flgProgress = SHELL_PROGRESS_QUIET|SHELL_PROGRESS_TMOUT; - if( nn==0 ) nn = 100; - } - continue; - } if( cli_strcmp(z,"limit")==0 ){ if( i+1>=nArg ){ eputz("Error: missing argument on --limit\n"); @@ -33728,7 +30537,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ } continue; } - cli_printf(stderr,"Error: unknown option: \"%s\"\n", azArg[i]); + sqlite3_fprintf(stderr,"Error: unknown option: \"%s\"\n", azArg[i]); rc = 1; goto meta_command_exit; }else{ @@ -33772,7 +30581,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ #else p->in = sqlite3_popen(azArg[1]+1, "r"); if( p->in==0 ){ - cli_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); + sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); rc = 1; }else{ rc = process_input(p, "<pipe>"); @@ -33780,12 +30589,10 @@ static int do_meta_command(const char *zLine, ShellState *p){ } #endif }else if( (p->in = openChrSource(azArg[1]))==0 ){ - cli_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); + sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); rc = 1; }else{ - char *zFilename = strdup(azArg[1]); - rc = process_input(p, zFilename); - free(zFilename); + rc = process_input(p, azArg[1]); fclose(p->in); } p->in = inSaved; @@ -33815,7 +30622,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ } rc = sqlite3_open(zSrcFile, &pSrc); if( rc!=SQLITE_OK ){ - cli_printf(stderr,"Error: cannot open \"%s\"\n", zSrcFile); + sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zSrcFile); close_db(pSrc); return 1; } @@ -33853,21 +30660,21 @@ static int do_meta_command(const char *zLine, ShellState *p){ ){ if( nArg==2 ){ if( cli_strcmp(azArg[1], "vm")==0 ){ - p->mode.scanstatsOn = 3; + p->scanstatsOn = 3; }else if( cli_strcmp(azArg[1], "est")==0 ){ - p->mode.scanstatsOn = 2; + p->scanstatsOn = 2; }else{ - p->mode.scanstatsOn = (u8)booleanValue(azArg[1]); + p->scanstatsOn = (u8)booleanValue(azArg[1]); } open_db(p, 0); sqlite3_db_config( - p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->mode.scanstatsOn, (int*)0 + p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0 ); #if !defined(SQLITE_ENABLE_STMT_SCANSTATUS) eputz("Warning: .scanstats not available in this build.\n"); #elif !defined(SQLITE_ENABLE_BYTECODE_VTAB) - if( p->mode.scanstatsOn==3 ){ + if( p->scanstatsOn==3 ){ eputz("Warning: \".scanstats vm\" not available in this build.\n"); } #endif @@ -33878,6 +30685,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ }else if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){ + ShellText sSelect; ShellState data; char *zErrMsg = 0; const char *zDiv = "("; @@ -33885,27 +30693,22 @@ static int do_meta_command(const char *zLine, ShellState *p){ int iSchema = 0; int bDebug = 0; int bNoSystemTabs = 0; - int bIndent = 0; int ii; - sqlite3_str *pSql; - sqlite3_stmt *pStmt = 0; - + open_db(p, 0); memcpy(&data, p, sizeof(data)); - data.mode.spec.bTitles = QRF_No; - data.mode.eMode = MODE_List; - data.mode.spec.eText = QRF_TEXT_Plain; - data.mode.spec.nCharLimit = 0; - data.mode.spec.zRowSep = "\n"; + data.showHeader = 0; + data.cMode = data.mode = MODE_Semi; + initText(&sSelect); for(ii=1; ii<nArg; ii++){ if( optionMatch(azArg[ii],"indent") ){ - bIndent = 1; + data.cMode = data.mode = MODE_Pretty; }else if( optionMatch(azArg[ii],"debug") ){ bDebug = 1; }else if( optionMatch(azArg[ii],"nosys") ){ bNoSystemTabs = 1; }else if( azArg[ii][0]=='-' ){ - cli_printf(stderr,"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 ){ @@ -33922,85 +30725,96 @@ static int do_meta_command(const char *zLine, ShellState *p){ || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0; if( isSchema ){ - cli_printf(p->out, - "CREATE TABLE %ssqlite_schema (\n" + char *new_argv[2], *new_colv[2]; + new_argv[0] = sqlite3_mprintf( + "CREATE TABLE %s (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" - ");\n", - sqlite3_strlike("sqlite_t%",zName,0)==0 ? "temp." : "" - ); + ")", zName); + shell_check_oom(new_argv[0]); + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + sqlite3_free(new_argv[0]); } } - rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); - if( rc ){ - shellDatabaseError(p->db); + if( zDiv ){ + sqlite3_stmt *pStmt = 0; + rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", + -1, &pStmt, 0); + if( rc ){ + shellDatabaseError(p->db); + sqlite3_finalize(pStmt); + rc = 1; + goto meta_command_exit; + } + appendText(&sSelect, "SELECT sql FROM", 0); + iSchema = 0; + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); + char zScNum[30]; + sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); + appendText(&sSelect, zDiv, 0); + zDiv = " UNION ALL "; + appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); + if( sqlite3_stricmp(zDb, "main")!=0 ){ + appendText(&sSelect, zDb, '\''); + }else{ + appendText(&sSelect, "NULL", 0); + } + appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0); + appendText(&sSelect, zScNum, 0); + appendText(&sSelect, " AS snum, ", 0); + appendText(&sSelect, zDb, '\''); + appendText(&sSelect, " AS sname FROM ", 0); + appendText(&sSelect, zDb, quoteChar(zDb)); + appendText(&sSelect, ".sqlite_schema", 0); + } sqlite3_finalize(pStmt); - - rc = 1; - goto meta_command_exit; - } - pSql = sqlite3_str_new(p->db); - sqlite3_str_appendf(pSql, "SELECT sql FROM", 0); - iSchema = 0; - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *zDb = (const char*)sqlite3_column_text(pStmt, 1); - char zScNum[30]; - sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); - sqlite3_str_appendall(pSql, zDiv); - zDiv = " UNION ALL "; - if( sqlite3_stricmp(zDb, "main")==0 ){ - sqlite3_str_appendf(pSql, - "SELECT shell_format_schema(shell_add_schema(sql,NULL,name),%d)", - bIndent); - }else{ - sqlite3_str_appendf(pSql, - "SELECT shell_format_schema(shell_add_schema(sql,%Q,name),%d)", - zDb, bIndent); +#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS + if( zName ){ + appendText(&sSelect, + " UNION ALL SELECT shell_module_schema(name)," + " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", + 0); + } +#endif + appendText(&sSelect, ") WHERE ", 0); + if( zName ){ + char *zQarg = sqlite3_mprintf("%Q", zName); + int bGlob; + shell_check_oom(zQarg); + bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || + strchr(zName, '[') != 0; + if( strchr(zName, '.') ){ + appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); + }else{ + appendText(&sSelect, "lower(tbl_name)", 0); + } + appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0); + appendText(&sSelect, zQarg, 0); + if( !bGlob ){ + appendText(&sSelect, " ESCAPE '\\' ", 0); + } + appendText(&sSelect, " AND ", 0); + sqlite3_free(zQarg); } - sqlite3_str_appendf(pSql, - " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname", - ++iSchema, zDb); - sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb); - } - sqlite3_finalize(pStmt); -#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) \ - && !defined(SQLITE_OMIT_VIRTUALTABLE) - if( zName ){ - sqlite3_str_appendall(pSql, - " UNION ALL SELECT shell_module_schema(name)," - " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list"); - } -#endif - sqlite3_str_appendf(pSql, ") WHERE ", 0); - if( zName ){ - int bGlob; - bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || - strchr(zName, '[') != 0; - if( strchr(zName, '.') ){ - sqlite3_str_appendall(pSql, "lower(format('%%s.%%s',sname,tbl_name))"); - }else{ - sqlite3_str_appendall(pSql, "lower(tbl_name)"); + if( bNoSystemTabs ){ + appendText(&sSelect, "name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ", 0); } - if( bGlob ){ - sqlite3_str_appendf(pSql, " GLOB %Q AND ", zName); + appendText(&sSelect, "sql IS NOT NULL" + " ORDER BY snum, rowid", 0); + if( bDebug ){ + sqlite3_fprintf(p->out, "SQL: %s;\n", sSelect.zTxt); }else{ - sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName); + rc = sqlite3_exec(p->db, sSelect.zTxt, callback, &data, &zErrMsg); } + freeText(&sSelect); } - if( bNoSystemTabs ){ - sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCAPE '_' AND "); - } - sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid"); - if( bDebug ){ - cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql)); - }else{ - rc = shell_exec(&data, sqlite3_str_value(pSql), &zErrMsg); - } - sqlite3_str_free(pSql); - if( zErrMsg ){ shellEmitError(zErrMsg); sqlite3_free(zErrMsg); @@ -34056,7 +30870,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ }else{ rc = sqlite3session_attach(pSession->p, azCmd[1]); if( rc ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "ERROR: sqlite3session_attach() returns %d\n",rc); rc = 0; } @@ -34076,7 +30890,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( pSession->p==0 ) goto session_not_open; out = sqlite3_fopen(azCmd[1], "wb"); if( out==0 ){ - cli_printf(stderr,"ERROR: cannot open \"%s\" for writing\n", + sqlite3_fprintf(stderr,"ERROR: cannot open \"%s\" for writing\n", azCmd[1]); }else{ int szChng; @@ -34087,12 +30901,12 @@ static int do_meta_command(const char *zLine, ShellState *p){ rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); } if( rc ){ - cli_printf(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 ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "ERROR: Failed to write entire %d-byte output\n", szChng); } sqlite3_free(pChng); @@ -34120,7 +30934,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); if( pAuxDb->nSession ){ ii = sqlite3session_enable(pSession->p, ii); - cli_printf(p->out, + sqlite3_fprintf(p->out, "session %s enable flag = %d\n", pSession->zName, ii); } }else @@ -34157,7 +30971,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); if( pAuxDb->nSession ){ ii = sqlite3session_indirect(pSession->p, ii); - cli_printf(p->out, + sqlite3_fprintf(p->out, "session %s indirect flag = %d\n", pSession->zName, ii); } }else @@ -34170,7 +30984,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( nCmd!=1 ) goto session_syntax_error; if( pAuxDb->nSession ){ ii = sqlite3session_isempty(pSession->p); - cli_printf(p->out, + sqlite3_fprintf(p->out, "session %s isempty flag = %d\n", pSession->zName, ii); } }else @@ -34180,7 +30994,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ */ if( cli_strcmp(azCmd[0],"list")==0 ){ for(i=0; i<pAuxDb->nSession; i++){ - cli_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName); + sqlite3_fprintf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName); } }else @@ -34195,19 +31009,19 @@ static int do_meta_command(const 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 ){ - cli_printf(stderr,"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) ){ - cli_printf(stderr, + 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 ){ - cli_printf(stderr,"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; } @@ -34231,7 +31045,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ int i, v; for(i=1; i<nArg; i++){ v = booleanValue(azArg[i]); - cli_printf(p->out, "%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 ){ @@ -34240,7 +31054,7 @@ static int do_meta_command(const 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); - cli_puts(zBuf, p->out); + sqlite3_fputs(zBuf, p->out); } } }else @@ -34267,9 +31081,9 @@ static int do_meta_command(const char *zLine, ShellState *p){ bVerbose++; }else { - cli_printf(stderr, + sqlite3_fprintf(stderr, "Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]); - cli_puts("Should be one of: --init -v\n", stderr); + sqlite3_fputs("Should be one of: --init -v\n", stderr); rc = 1; goto meta_command_exit; } @@ -34314,10 +31128,10 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( zAns==0 ) continue; k = 0; if( bVerbose>0 ){ - cli_printf(stdout, "%d: %s %s\n", tno, zOp, zSql); + sqlite3_fprintf(stdout, "%d: %s %s\n", tno, zOp, zSql); } if( cli_strcmp(zOp,"memo")==0 ){ - cli_printf(p->out, "%s\n", zSql); + sqlite3_fprintf(p->out, "%s\n", zSql); }else if( cli_strcmp(zOp,"run")==0 ){ char *zErrMsg = 0; @@ -34326,22 +31140,22 @@ static int do_meta_command(const char *zLine, ShellState *p){ rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); nTest++; if( bVerbose ){ - cli_printf(p->out, "Result: %s\n", str.zTxt); + sqlite3_fprintf(p->out, "Result: %s\n", str.zTxt); } if( rc || zErrMsg ){ nErr++; rc = 1; - cli_printf(p->out, "%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.zTxt)!=0 ){ nErr++; rc = 1; - cli_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); - cli_printf(p->out, "%d: Got: [%s]\n", tno, str.zTxt); + sqlite3_fprintf(p->out, "%d: Expected: [%s]\n", tno, zAns); + sqlite3_fprintf(p->out, "%d: Got: [%s]\n", tno, str.zTxt); } } else{ - cli_printf(stderr, + sqlite3_fprintf(stderr, "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); rc = 1; break; @@ -34350,7 +31164,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ sqlite3_finalize(pStmt); } /* End loop over k */ freeText(&str); - cli_printf(p->out, "%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 ){ @@ -34359,10 +31173,12 @@ static int do_meta_command(const char *zLine, ShellState *p){ rc = 1; } if( nArg>=2 ){ - modeSetStr(&p->mode.spec.zColumnSep, azArg[1]); + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, + "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); } if( nArg>=3 ){ - modeSetStr(&p->mode.spec.zRowSep,azArg[2]); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, + "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); } }else @@ -34396,7 +31212,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ bDebug = 1; }else { - cli_printf(stderr, + sqlite3_fprintf(stderr, "Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]); showHelp(p->out, azArg[0]); rc = 1; @@ -34475,7 +31291,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ freeText(&sQuery); freeText(&sSql); if( bDebug ){ - cli_printf(p->out, "%s\n", zSql); + sqlite3_fprintf(p->out, "%s\n", zSql); }else{ shell_exec(p, zSql, 0); } @@ -34505,7 +31321,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ "' OR ') as query, tname from tabcols group by tname)" , zRevText); shell_check_oom(zRevText); - if( bDebug ) cli_printf(p->out, "%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 @@ -34518,7 +31334,7 @@ static int do_meta_command(const 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 ) cli_printf(p->out, "%s\n", zGenQuery); + if( bDebug ) sqlite3_fprintf(p->out, "%s\n", zGenQuery); if( lrc!=SQLITE_OK ){ rc = 1; }else{ @@ -34526,7 +31342,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ double countIrreversible = sqlite3_column_double(pCheckStmt, 0); if( countIrreversible>0 ){ int sz = (int)(countIrreversible + 0.5); - cli_printf(stderr, + sqlite3_fprintf(stderr, "Digest includes %d invalidly encoded text field%s.\n", sz, (sz>1)? "s": ""); } @@ -34565,7 +31381,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ x = zCmd!=0 ? system(zCmd) : 1; /*consoleRenewSetup();*/ sqlite3_free(zCmd); - if( x ) cli_printf(stderr,"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) */ @@ -34578,51 +31394,48 @@ static int do_meta_command(const char *zLine, ShellState *p){ rc = 1; goto meta_command_exit; } - cli_printf(p->out, "%12.12s: %s\n","echo", - azBool[(p->mode.mFlags & MFLG_ECHO)!=0]); - cli_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->mode.autoEQP&3]); - cli_printf(p->out, "%12.12s: %s\n","explain", - p->mode.autoExplain ? "auto" : "off"); - cli_printf(p->out, "%12.12s: %s\n","headers", - azBool[p->mode.spec.bTitles==QRF_Yes]); - if( p->mode.spec.eStyle==QRF_STYLE_Column - || p->mode.spec.eStyle==QRF_STYLE_Box - || p->mode.spec.eStyle==QRF_STYLE_Table - || p->mode.spec.eStyle==QRF_STYLE_Markdown + sqlite3_fprintf(p->out, "%12.12s: %s\n","echo", + azBool[ShellHasFlag(p, SHFLG_Echo)]); + 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"); + 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) ){ - cli_printf(p->out, + sqlite3_fprintf(p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode", - aModeInfo[p->mode.eMode].zName, p->mode.spec.nWrap, - p->mode.spec.bWordWrap==QRF_Yes ? "on" : "off", - p->mode.spec.eText==QRF_TEXT_Sql ? "" : "no"); + modeDescr[p->mode], p->cmOpts.iWrap, + p->cmOpts.bWordWrap ? "on" : "off", + p->cmOpts.bQuote ? "" : "no"); }else{ - cli_printf(p->out, "%12.12s: %s\n","mode", - aModeInfo[p->mode.eMode].zName); + sqlite3_fprintf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); } - cli_printf(p->out, "%12.12s: ", "nullvalue"); - output_c_string(p->out, p->mode.spec.zNull); - cli_puts("\n", p->out); - cli_printf(p->out, "%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"); - cli_printf(p->out, "%12.12s: ", "colseparator"); - output_c_string(p->out, p->mode.spec.zColumnSep); - cli_puts("\n", p->out); - cli_printf(p->out, "%12.12s: ", "rowseparator"); - output_c_string(p->out, p->mode.spec.zRowSep); - cli_puts("\n", p->out); + 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; } - cli_printf(p->out, "%12.12s: %s\n","stats", zOut); - cli_printf(p->out, "%12.12s: ", "width"); - for(i=0; i<p->mode.spec.nWidth; i++){ - cli_printf(p->out, "%d ", (int)p->mode.spec.aWidth[i]); + sqlite3_fprintf(p->out, "%12.12s: %s\n","stats", zOut); + sqlite3_fprintf(p->out, "%12.12s: ", "width"); + for (i=0;i<p->nWidth;i++) { + sqlite3_fprintf(p->out, "%d ", p->colWidth[i]); } - cli_puts("\n", p->out); - cli_printf(p->out, "%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 @@ -34648,9 +31461,11 @@ static int do_meta_command(const char *zLine, ShellState *p){ || cli_strncmp(azArg[0], "indexes", n)==0) ) ){ sqlite3_stmt *pStmt; - sqlite3_str *pSql; - const char *zPattern = nArg>1 ? azArg[1] : 0; - + char **azResult; + int nRow, nAlloc; + int ii; + ShellText s; + initText(&s); open_db(p, 0); rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); if( rc ){ @@ -34667,53 +31482,103 @@ static int do_meta_command(const char *zLine, ShellState *p){ sqlite3_finalize(pStmt); goto meta_command_exit; } - pSql = sqlite3_str_new(p->db); - while( sqlite3_step(pStmt)==SQLITE_ROW ){ + for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); if( zDbName==0 ) continue; - if( sqlite3_str_length(pSql) ){ - sqlite3_str_appendall(pSql, " UNION ALL "); - } + if( s.zTxt && s.zTxt[0] ) appendText(&s, " UNION ALL ", 0); if( sqlite3_stricmp(zDbName, "main")==0 ){ - sqlite3_str_appendall(pSql, "SELECT name FROM "); + appendText(&s, "SELECT name FROM ", 0); }else{ - sqlite3_str_appendf(pSql, "SELECT %Q||'.'||name FROM ", zDbName); + appendText(&s, "SELECT ", 0); + appendText(&s, zDbName, '\''); + appendText(&s, "||'.'||name FROM ", 0); } - sqlite3_str_appendf(pSql, "\"%w\".sqlite_schema", zDbName); + appendText(&s, zDbName, '"'); + appendText(&s, ".sqlite_schema ", 0); if( c=='t' ){ - sqlite3_str_appendf(pSql, - " WHERE type IN ('table','view')" - " AND name NOT LIKE 'sqlite__%%' ESCAPE '_'" - ); - if( zPattern ){ - sqlite3_str_appendf(pSql," AND name LIKE %Q", zPattern); - } + appendText(&s," WHERE type IN ('table','view')" + " AND name NOT LIKE 'sqlite__%' ESCAPE '_'" + " AND name LIKE ?1", 0); }else{ - sqlite3_str_appendf(pSql, " WHERE type='index'"); - if( zPattern ){ - sqlite3_str_appendf(pSql," AND tbl_name LIKE %Q", zPattern); - } + appendText(&s," WHERE type='index'" + " AND tbl_name LIKE ?1", 0); } } rc = sqlite3_finalize(pStmt); if( rc==SQLITE_OK ){ - sqlite3_str_appendall(pSql, " ORDER BY 1"); + appendText(&s, " ORDER BY 1", 0); + rc = sqlite3_prepare_v2(p->db, s.zTxt, -1, &pStmt, 0); } - - /* Run the SQL statement in "split" mode. */ - modePush(p); - modeChange(p, MODE_Split); - shell_exec(p, sqlite3_str_value(pSql), 0); - sqlite3_str_free(pSql); - modePop(p); + freeText(&s); if( rc ) return shellDatabaseError(p->db); + + /* Run the SQL statement prepared by the above block. Store the results + ** as an array of nul-terminated strings in azResult[]. */ + nRow = nAlloc = 0; + azResult = 0; + if( nArg>1 ){ + sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); + }else{ + sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); + } + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + if( nRow>=nAlloc ){ + char **azNew; + sqlite3_int64 n2 = 2*(sqlite3_int64)nAlloc + 10; + azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); + shell_check_oom(azNew); + nAlloc = (int)n2; + azResult = azNew; + } + azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); + shell_check_oom(azResult[nRow]); + nRow++; + } + if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ + rc = shellDatabaseError(p->db); + } + + /* Pretty-print the contents of array azResult[] to the output */ + if( rc==0 && nRow>0 ){ + int len, maxlen = 0; + int i, j; + int nPrintCol, nPrintRow; + for(i=0; i<nRow; i++){ + len = strlen30(azResult[i]); + if( len>maxlen ) maxlen = len; + } + nPrintCol = 80/(maxlen+2); + if( nPrintCol<1 ) nPrintCol = 1; + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; + for(i=0; i<nPrintRow; i++){ + for(j=i; j<nRow; j+=nPrintRow){ + char *zSp = j<nPrintRow ? "" : " "; + sqlite3_fprintf(p->out, + "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:""); + } + sqlite3_fputs("\n", p->out); + } + } + + for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); + sqlite3_free(azResult); }else - /* Set the p->zTestcase name and begin redirecting output into - ** the cli_output_capture sqlite3_str */ +#ifndef SQLITE_SHELL_FIDDLE + /* Begin redirecting output to the file "testcase-out.txt" */ if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){ - rc = dotCmdTestcase(p); + output_reset(p); + p->out = output_file_open("testcase-out.txt"); + if( p->out==0 ){ + eputz("Error: cannot open 'testcase-out.txt'\n"); + } + if( nArg>=2 ){ + sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); + }else{ + sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); + } }else +#endif /* !defined(SQLITE_SHELL_FIDDLE) */ #ifndef SQLITE_UNTESTABLE if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){ @@ -34766,10 +31631,10 @@ static int do_meta_command(const char *zLine, ShellState *p){ /* --help lists all test-controls */ if( cli_strcmp(zCmd,"help")==0 ){ - cli_puts("Available test-controls:\n", p->out); + sqlite3_fputs("Available test-controls:\n", p->out); for(i=0; i<ArraySize(aCtrl); i++){ if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue; - cli_printf(p->out, " .testctrl %s %s\n", + sqlite3_fprintf(p->out, " .testctrl %s %s\n", aCtrl[i].zCtrlName, aCtrl[i].zUsage); } rc = 1; @@ -34786,7 +31651,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ testctrl = aCtrl[i].ctrlCode; iCtrl = i; }else{ - cli_printf(stderr,"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; @@ -34794,7 +31659,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ } } if( testctrl<0 ){ - cli_printf(stderr,"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){ @@ -34874,13 +31739,13 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( sqlite3_stricmp(zLabel, aLabel[jj].zLabel)==0 ) break; } if( jj>=ArraySize(aLabel) ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "Error: no such optimization: \"%s\"\n", zLabel); - cli_puts("Should be one of:", stderr); + sqlite3_fputs("Should be one of:", stderr); for(jj=0; jj<ArraySize(aLabel); jj++){ - cli_printf(stderr," %s", aLabel[jj].zLabel); + sqlite3_fprintf(stderr," %s", aLabel[jj].zLabel); } - cli_puts("\n", stderr); + sqlite3_fputs("\n", stderr); rc = 1; goto meta_command_exit; } @@ -34898,23 +31763,23 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( m & newOpt ) nOff++; } if( nOff<12 ){ - cli_puts("+All", p->out); + sqlite3_fputs("+All", p->out); for(ii=0; ii<ArraySize(aLabel); ii++){ if( !aLabel[ii].bDsply ) continue; if( (newOpt & aLabel[ii].mask)!=0 ){ - cli_printf(p->out, " -%s", aLabel[ii].zLabel); + sqlite3_fprintf(p->out, " -%s", aLabel[ii].zLabel); } } }else{ - cli_puts("-All", p->out); + sqlite3_fputs("-All", p->out); for(ii=0; ii<ArraySize(aLabel); ii++){ if( !aLabel[ii].bDsply ) continue; if( (newOpt & aLabel[ii].mask)==0 ){ - cli_printf(p->out, " +%s", aLabel[ii].zLabel); + sqlite3_fprintf(p->out, " +%s", aLabel[ii].zLabel); } } } - cli_puts("\n", p->out); + sqlite3_fputs("\n", p->out); rc2 = isOk = 3; break; } @@ -34954,7 +31819,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ sqlite3 *db; if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){ sqlite3_randomness(sizeof(ii),&ii); - cli_printf(stdout, "-- random seed: %d\n", ii); + sqlite3_fprintf(stdout, "-- random seed: %d\n", ii); } if( nArg==3 ){ db = 0; @@ -35007,7 +31872,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ case SQLITE_TESTCTRL_SEEK_COUNT: { u64 x = 0; rc2 = sqlite3_test_control(testctrl, p->db, &x); - cli_printf(p->out, "%llu\n", x); + sqlite3_fprintf(p->out, "%llu\n", x); isOk = 3; break; } @@ -35038,11 +31903,11 @@ static int do_meta_command(const char *zLine, ShellState *p){ int val = 0; rc2 = sqlite3_test_control(testctrl, -id, &val); if( rc2!=SQLITE_OK ) break; - if( id>1 ) cli_puts(" ", p->out); - cli_printf(p->out, "%d: %d", id, val); + if( id>1 ) sqlite3_fputs(" ", p->out); + sqlite3_fprintf(p->out, "%d: %d", id, val); id++; } - if( id>1 ) cli_puts("\n", p->out); + if( id>1 ) sqlite3_fputs("\n", p->out); isOk = 3; } break; @@ -35081,7 +31946,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ int ii, jj, x; int *aOp; if( nArg!=4 ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "ERROR - should be: \".testctrl bitvec_test SIZE INT-ARRAY\"\n" ); rc = 1; @@ -35104,7 +31969,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ } aOp[jj] = x; x = sqlite3_test_control(testctrl, iSize, aOp); - cli_printf(p->out, "result: %d\n", x); + sqlite3_fprintf(p->out, "result: %d\n", x); free(aOp); break; } @@ -35127,21 +31992,21 @@ static int do_meta_command(const char *zLine, ShellState *p){ faultsim_state.nHit = 0; sqlite3_test_control(testctrl, faultsim_callback); }else if( cli_strcmp(z,"status")==0 ){ - cli_printf(p->out, "faultsim.iId: %d\n", + sqlite3_fprintf(p->out, "faultsim.iId: %d\n", faultsim_state.iId); - cli_printf(p->out, "faultsim.iErr: %d\n", + sqlite3_fprintf(p->out, "faultsim.iErr: %d\n", faultsim_state.iErr); - cli_printf(p->out, "faultsim.iCnt: %d\n", + sqlite3_fprintf(p->out, "faultsim.iCnt: %d\n", faultsim_state.iCnt); - cli_printf(p->out, "faultsim.nHit: %d\n", + sqlite3_fprintf(p->out, "faultsim.nHit: %d\n", faultsim_state.nHit); - cli_printf(p->out, "faultsim.iInterval: %d\n", + sqlite3_fprintf(p->out, "faultsim.iInterval: %d\n", faultsim_state.iInterval); - cli_printf(p->out, "faultsim.eVerbose: %d\n", + sqlite3_fprintf(p->out, "faultsim.eVerbose: %d\n", faultsim_state.eVerbose); - cli_printf(p->out, "faultsim.nRepeat: %d\n", + sqlite3_fprintf(p->out, "faultsim.nRepeat: %d\n", faultsim_state.nRepeat); - cli_printf(p->out, "faultsim.nSkip: %d\n", + 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++; @@ -35160,7 +32025,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ }else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){ bShowHelp = 1; }else{ - cli_printf(stderr, + sqlite3_fprintf(stderr, "Unrecognized fault_install argument: \"%s\"\n", azArg[kk]); rc = 1; @@ -35169,7 +32034,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ } } if( bShowHelp ){ - cli_puts( + sqlite3_fputs( "Usage: .testctrl fault_install ARGS\n" "Possible arguments:\n" " off Disable faultsim\n" @@ -35191,13 +32056,13 @@ static int do_meta_command(const char *zLine, ShellState *p){ } } if( isOk==0 && iCtrl>=0 ){ - cli_printf(p->out, + sqlite3_fprintf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); rc = 1; }else if( isOk==1 ){ - cli_printf(p->out, "%d\n", rc2); + sqlite3_fprintf(p->out, "%d\n", rc2); }else if( isOk==2 ){ - cli_printf(p->out, "0x%08x\n", rc2); + sqlite3_fprintf(p->out, "0x%08x\n", rc2); } }else #endif /* !defined(SQLITE_UNTESTABLE) */ @@ -35209,17 +32074,13 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){ if( nArg==2 ){ - if( cli_strcmp(azArg[1],"once")==0 ){ - p->enableTimer = 1; - }else{ - p->enableTimer = 2*booleanValue(azArg[1]); - } - if( p->enableTimer && !HAS_TIMER ){ + enableTimer = booleanValue(azArg[1]); + if( enableTimer && !HAS_TIMER ){ eputz("Error: timer not available on this system.\n"); - p->enableTimer = 0; + enableTimer = 0; } }else{ - eputz("Usage: .timer on|off|once\n"); + eputz("Usage: .timer on|off\n"); rc = 1; } }else @@ -35256,13 +32117,13 @@ static int do_meta_command(const char *zLine, ShellState *p){ mType |= SQLITE_TRACE_CLOSE; } else { - cli_printf(stderr,"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(p, z); + p->traceOut = output_file_open(z); } } if( p->traceOut==0 ){ @@ -35301,21 +32162,21 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){ char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit"; - cli_printf(p->out, "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 - cli_printf(p->out, "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__) - cli_printf(p->out, "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) - cli_printf(p->out, "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__) - cli_printf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz); + sqlite3_fprintf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz); #endif }else @@ -35325,10 +32186,10 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( p->db ){ sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs); if( pVfs ){ - cli_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName); - cli_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); - cli_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); - cli_printf(p->out, "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 @@ -35340,13 +32201,13 @@ static int do_meta_command(const 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){ - cli_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName, + sqlite3_fprintf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName, pVfs==pCurrent ? " <--- CURRENT" : ""); - cli_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); - cli_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); - cli_printf(p->out, "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 ){ - cli_puts("-----------------------------------\n", p->out); + sqlite3_fputs("-----------------------------------\n", p->out); } } }else @@ -35357,7 +32218,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( p->db ){ sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); if( zVfsName ){ - cli_printf(p->out, "%s\n", zVfsName); + sqlite3_fprintf(p->out, "%s\n", zVfsName); sqlite3_free(zVfsName); } } @@ -35370,31 +32231,31 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( c=='w' && cli_strncmp(azArg[0], "width", n)==0 ){ int j; - p->mode.spec.nWidth = nArg-1; - p->mode.spec.aWidth = realloc(p->mode.spec.aWidth, - (p->mode.spec.nWidth+1)*sizeof(short int)); - shell_check_oom(p->mode.spec.aWidth); + assert( nArg<=ArraySize(azArg) ); + p->nWidth = nArg-1; + p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2); + if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory(); + if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth]; for(j=1; j<nArg; j++){ i64 w = integerValue(azArg[j]); - if( w < -QRF_MAX_WIDTH ) w = -QRF_MAX_WIDTH; - if( w > QRF_MAX_WIDTH ) w = QRF_MAX_WIDTH; - p->mode.spec.aWidth[j-1] = (short int)w; + if( w < -30000 ) w = -30000; + if( w > +30000 ) w = +30000; + p->colWidth[j-1] = (int)w; } }else { - cli_printf(stderr,"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; } meta_command_exit: - if( p->nPopOutput ){ - p->nPopOutput--; - if( p->nPopOutput==0 ) output_reset(p); + if( p->outCount ){ + p->outCount--; + if( p->outCount==0 ) output_reset(p); } p->bSafeMode = p->bSafeModePersist; - p->dot.nArg = 0; return rc; } @@ -35631,9 +32492,9 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ open_db(p, 0); if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; - BEGIN_TIMER(p); + BEGIN_TIMER; rc = shell_exec(p, zSql, &zErrMsg); - END_TIMER(p); + END_TIMER(p->out); if( rc || zErrMsg ){ char zPrefix[100]; const char *zErrorTail; @@ -35657,7 +32518,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ }else{ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType); } - cli_printf(stderr,"%s %s\n", zPrefix, zErrorTail); + sqlite3_fprintf(stderr,"%s %s\n", zPrefix, zErrorTail); sqlite3_free(zErrMsg); zErrMsg = 0; return 1; @@ -35666,7 +32527,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)); - cli_printf(p->out, "%s\n", zLineBuf); + sqlite3_fprintf(p->out, "%s\n", zLineBuf); } if( doAutoDetectRestore(p, zSql) ) return 1; @@ -35674,8 +32535,8 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ } static void echo_group_input(ShellState *p, const char *zDo){ - if( p->mode.mFlags & MFLG_ECHO ){ - cli_printf(p->out, "%s\n", zDo); + if( ShellHasFlag(p, SHFLG_Echo) ){ + sqlite3_fprintf(p->out, "%s\n", zDo); fflush(p->out); } } @@ -35732,19 +32593,14 @@ static int process_input(ShellState *p, const char *zSrc){ int errCnt = 0; /* Number of errors seen */ i64 startline = 0; /* Line number for start of current input */ QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ - const char *saved_zInFile; /* Prior value of p->zInFile */ - i64 saved_lineno; /* Prior value of p->lineno */ if( p->inputNesting==MAX_INPUT_NESTING ){ /* This will be more informative in a later version. */ - cli_printf(stderr,"%s: Input nesting limit (%d) reached at line %lld." + sqlite3_fprintf(stderr,"%s: Input nesting limit (%d) reached at line %lld." " Check recursion.\n", zSrc, MAX_INPUT_NESTING, p->lineno); return 1; } ++p->inputNesting; - saved_zInFile = p->zInFile; - p->zInFile = zSrc; - saved_lineno = p->lineno; p->lineno = 0; CONTINUE_PROMPT_RESET; while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ @@ -35752,7 +32608,7 @@ static int process_input(ShellState *p, const char *zSrc){ zLine = one_input_line(p->in, zLine, nSql>0); if( zLine==0 ){ /* End of input */ - if( p->in==0 && stdin_is_interactive ) cli_puts("\n", p->out); + if( p->in==0 && stdin_is_interactive ) sqlite3_fputs("\n", p->out); break; } if( seenInterrupt ){ @@ -35809,7 +32665,7 @@ static int process_input(ShellState *p, const char *zSrc){ if( nSql>0x7fff0000 ){ char zSize[100]; sqlite3_snprintf(sizeof(zSize),zSize,"%,lld",nSql); - cli_printf(stderr, "%s:%lld: Input SQL is too big: %s bytes\n", + sqlite3_fprintf(stderr, "%s:%lld: Input SQL is too big: %s bytes\n", zSrc, startline, zSize); nSql = 0; errCnt++; @@ -35819,16 +32675,12 @@ static int process_input(ShellState *p, const char *zSrc){ errCnt += runOneSqlLine(p, zSql, p->in, startline); CONTINUE_PROMPT_RESET; nSql = 0; - if( p->nPopOutput ){ + if( p->outCount ){ output_reset(p); - p->nPopOutput = 0; + p->outCount = 0; }else{ clearTempFile(p); } - if( p->nPopMode ){ - modePop(p); - p->nPopMode = 0; - } p->bSafeMode = p->bSafeModePersist; qss = QSS_Start; }else if( nSql && QSS_PLAINWHITE(qss) ){ @@ -35846,8 +32698,6 @@ static int process_input(ShellState *p, const char *zSrc){ free(zSql); free(zLine); --p->inputNesting; - p->zInFile = saved_zInFile; - p->lineno = saved_lineno; return errCnt>0; } @@ -36008,13 +32858,13 @@ static void process_sqliterc( p->in = sqliterc ? sqlite3_fopen(sqliterc,"rb") : 0; if( p->in ){ if( stdin_is_interactive ){ - cli_printf(stderr,"-- Loading resources from %s\n", sqliterc); + sqlite3_fprintf(stderr,"-- Loading resources from %s\n", sqliterc); } - if( process_input(p, sqliterc) && bail_on_error ) cli_exit(1); + if( process_input(p, sqliterc) && bail_on_error ) exit(1); fclose(p->in); }else if( sqliterc_override!=0 ){ - cli_printf(stderr,"cannot open: \"%s\"\n", sqliterc); - if( bail_on_error ) cli_exit(1); + sqlite3_fprintf(stderr,"cannot open: \"%s\"\n", sqliterc); + if( bail_on_error ) exit(1); } p->in = inSaved; p->lineno = savedLineno; @@ -36036,8 +32886,8 @@ static const char zOptions[] = " -bail stop after hitting an error\n" " -batch force batch I/O\n" " -box set output mode to 'box'\n" - " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -column set output mode to 'column'\n" + " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" #if !defined(SQLITE_OMIT_DESERIALIZE) " -deserialize open the database using sqlite3_deserialize()\n" @@ -36068,7 +32918,6 @@ static const char zOptions[] = #endif " -newline SEP set output row separator. Default: '\\n'\n" " -nofollow refuse to open symbolic links to database files\n" - " -noinit Do not read the ~/.sqliterc file at startup\n" " -nonce STRING set the safe-mode escape nonce\n" " -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n" " -nullvalue TEXT set text string for NULL values. Default ''\n" @@ -36077,7 +32926,6 @@ static const char zOptions[] = " -quote set output mode to 'quote'\n" " -readonly open the database read-only\n" " -safe enable safe-mode\n" - " -screenwidth N use N as the default screenwidth \n" " -separator SEP set output column separator. Default: '|'\n" #ifdef SQLITE_ENABLE_SORTER_REFERENCES " -sorterref SIZE sorter references threshold size\n" @@ -36094,11 +32942,11 @@ static const char zOptions[] = #endif ; static void usage(int showDetail){ - cli_printf(stderr,"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 ){ - cli_printf(stderr,"OPTIONS include:\n%s", zOptions); + sqlite3_fprintf(stderr,"OPTIONS include:\n%s", zOptions); }else{ eputz("Use the -help option for additional information\n"); } @@ -36119,11 +32967,19 @@ static void verify_uninitialized(void){ /* ** Initialize the state information in data */ -static void main_init(ShellState *p) { - memset(p, 0, sizeof(*p)); - p->pAuxDb = &p->aAuxDb[0]; - p->shellFlgs = SHFLG_Lookaside; - sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p); +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); + data->showHeader = 0; + data->shellFlgs = SHFLG_Lookaside; + sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); #if !defined(SQLITE_SHELL_FIDDLE) verify_uninitialized(); #endif @@ -36138,18 +32994,22 @@ static void main_init(ShellState *p) { */ #if defined(_WIN32) || defined(WIN32) static void printBold(const char *zText){ +#if !SQLITE_OS_WINRT HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; GetConsoleScreenBufferInfo(out, &defaultScreenInfo); SetConsoleTextAttribute(out, FOREGROUND_RED|FOREGROUND_INTENSITY ); +#endif sputz(stdout, zText); +#if !SQLITE_OS_WINRT SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); +#endif } #else static void printBold(const char *zText){ - cli_printf(stdout, "\033[1m%s\033[0m", zText); + sqlite3_fprintf(stdout, "\033[1m%s\033[0m", zText); } #endif @@ -36159,9 +33019,9 @@ static void printBold(const char *zText){ */ static char *cmdline_option_value(int argc, char **argv, int i){ if( i==argc ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "%s: Error: missing argument to %s\n", argv[0], argv[argc-1]); - cli_exit(1); + exit(1); } return argv[i]; } @@ -36174,66 +33034,30 @@ static void sayAbnormalExit(void){ */ static int vfstraceOut(const char *z, void *pArg){ ShellState *p = (ShellState*)pArg; - cli_puts(z, p->out); + sqlite3_fputs(z, p->out); fflush(p->out); return 1; } -/* Alternative name to the entry point for Fiddle */ +#ifndef SQLITE_SHELL_IS_UTF8 +# if (defined(_WIN32) || defined(WIN32)) \ + && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__))) +# define SQLITE_SHELL_IS_UTF8 (0) +# else +# define SQLITE_SHELL_IS_UTF8 (1) +# endif +#endif + #ifdef SQLITE_SHELL_FIDDLE # define main fiddle_main #endif -/* Use the wmain() entry point on Windows. Translate arguments to -** UTF8, then invoke the traditional main() entry point which is -** renamed using a #define to utf8_main() . -*/ -#if defined(_WIN32) && !defined(main) -# define main utf8_main /* Rename entry point to utf_main() */ -int SQLITE_CDECL utf8_main(int,char**); /* Forward declaration */ -int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ - int rc, i; - char **argv = malloc( sizeof(char*) * (argc+1) ); - char **orig = argv; - if( argv==0 ){ - fprintf(stderr, "malloc failed\n"); - exit(1); - } - for(i=0; i<argc; i++){ - int nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0); - if( nByte==0 ){ - argv[i] = 0; - }else{ - argv[i] = malloc( nByte ); - if( argv[i]==0 ){ - fprintf(stderr, "malloc failed\n"); - exit(1); - } - nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i],nByte,0,0); - if( nByte==0 ){ - free(argv[i]); - argv[i] = 0; - } - } - } - argv[argc] = 0; - rc = utf8_main(argc, argv); - for(i=0; i<argc; i++) free(orig[i]); - free(argv); - return rc; -} -#endif /* WIN32 */ - -/* -** This is the main entry point for the process. Everything starts here. -** -** The "main" identifier may have been #defined to something else: -** -** utf8_main On Windows -** fiddle_main In Fiddle -** sqlite3_shell Other projects that use shell.c as a subroutine -*/ +#if SQLITE_SHELL_IS_UTF8 int SQLITE_CDECL main(int argc, char **argv){ +#else +int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ + char **argv; +#endif #ifdef SQLITE_DEBUG sqlite3_int64 mem_main_enter = 0; #endif @@ -36248,13 +33072,15 @@ int SQLITE_CDECL main(int argc, char **argv){ int rc = 0; int warnInmemoryDb = 0; int readStdin = 1; - int noInit = 0; /* Do not read ~/.sqliterc if true */ int nCmd = 0; int nOptsEnd = argc; int bEnableVfstrace = 0; char **azCmd = 0; - int *aiCmd = 0; const char *zVfs = 0; /* Value of -vfs command-line option */ +#if !SQLITE_SHELL_IS_UTF8 + char **argvToFree = 0; + int argcToFree = 0; +#endif setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ #ifdef SQLITE_SHELL_FIDDLE @@ -36273,7 +33099,7 @@ int SQLITE_CDECL main(int argc, char **argv){ if( getenv("SQLITE_DEBUG_BREAK") ){ if( isatty(0) && isatty(2) ){ char zLine[100]; - cli_printf(stderr, + sqlite3_fprintf(stderr, "attach debugger to process %d and press ENTER to continue...", GETPID()); if( sqlite3_fgets(zLine, sizeof(zLine), stdin)!=0 @@ -36283,7 +33109,11 @@ int SQLITE_CDECL main(int argc, char **argv){ } }else{ #if defined(_WIN32) || defined(WIN32) +#if SQLITE_OS_WINRT + __debugbreak(); +#else DebugBreak(); +#endif #elif defined(SIGTRAP) raise(SIGTRAP); #endif @@ -36301,7 +33131,7 @@ int SQLITE_CDECL main(int argc, char **argv){ #if USE_SYSTEM_SQLITE+0!=1 if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ - cli_printf(stderr, + sqlite3_fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", sqlite3_sourceid(), SQLITE_SOURCE_ID); exit(1); @@ -36309,6 +33139,32 @@ int SQLITE_CDECL main(int argc, char **argv){ #endif main_init(&data); + /* On Windows, we must translate command-line arguments into UTF-8. + ** The SQLite memory allocator subsystem has to be enabled in order to + ** do this. But we want to run an sqlite3_shutdown() afterwards so that + ** subsequent sqlite3_config() calls will work. So copy all results into + ** memory that does not come from the SQLite memory allocator. + */ +#if !SQLITE_SHELL_IS_UTF8 + sqlite3_initialize(); + argvToFree = malloc(sizeof(argv[0])*argc*2); + shell_check_oom(argvToFree); + argcToFree = argc; + argv = argvToFree + argc; + for(i=0; i<argc; i++){ + char *z = sqlite3_win32_unicode_to_utf8(wargv[i]); + i64 n; + shell_check_oom(z); + n = strlen(z); + argv[i] = malloc( n+1 ); + shell_check_oom(argv[i]); + memcpy(argv[i], z, n+1); + argvToFree[i] = argv[i]; + sqlite3_free(z); + } + sqlite3_shutdown(); +#endif + assert( argc>=1 && argv && argv[0] ); Argv0 = argv[0]; @@ -36324,7 +33180,7 @@ int SQLITE_CDECL main(int argc, char **argv){ } #endif - /* Do an initial pass through the command-line arguments to locate + /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, options affecting commands ** or SQL run from the command line, and the first command to execute. @@ -36336,20 +33192,16 @@ int SQLITE_CDECL main(int argc, char **argv){ char *z; z = argv[i]; if( z[0]!='-' || i>nOptsEnd ){ - if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){ + if( data.aAuxDb->zDbFilename==0 ){ data.aAuxDb->zDbFilename = z; }else{ /* Excess arguments are interpreted as SQL (or dot-commands) and ** mean that nothing is read from stdin */ readStdin = 0; - stdin_is_interactive = 0; nCmd++; azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); shell_check_oom(azCmd); - aiCmd = realloc(aiCmd, sizeof(aiCmd[0])*nCmd); - shell_check_oom(azCmd); azCmd[nCmd-1] = z; - aiCmd[nCmd-1] = i; } continue; } @@ -36372,15 +33224,6 @@ int SQLITE_CDECL main(int argc, char **argv){ ** we do the actual processing of arguments later in a second pass. */ stdin_is_interactive = 0; - stdout_is_console = 0; - modeChange(&data, MODE_BATCH); - }else if( cli_strcmp(z,"-screenwidth")==0 ){ - int n = atoi(cmdline_option_value(argc, argv, ++i)); - if( n<2 ){ - sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n"); - exit(1); - } - stdout_tty_width = n; }else if( cli_strcmp(z,"-utf8")==0 ){ }else if( cli_strcmp(z,"-no-utf8")==0 ){ }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ @@ -36414,7 +33257,7 @@ int SQLITE_CDECL main(int argc, char **argv){ int szHdr = 0; sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &szHdr); sz += szHdr; - cli_printf(stdout, "Page cache size increased to %d to accommodate" + sqlite3_fprintf(stdout, "Page cache size increased to %d to accommodate" " the %d-byte headers\n", (int)sz, szHdr); } verify_uninitialized(); @@ -36475,8 +33318,6 @@ int SQLITE_CDECL main(int argc, char **argv){ data.openFlags |= SQLITE_OPEN_READONLY; }else if( cli_strcmp(z,"-nofollow")==0 ){ data.openFlags |= SQLITE_OPEN_NOFOLLOW; - }else if( cli_strcmp(z,"-noinit")==0 ){ - noInit = 1; }else if( cli_strcmp(z,"-exclusive")==0 ){ /* UNDOCUMENTED */ data.openFlags |= SQLITE_OPEN_EXCLUSIVE; }else if( cli_strcmp(z,"-ifexists")==0 ){ @@ -36504,16 +33345,6 @@ int SQLITE_CDECL main(int argc, char **argv){ }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ /* skip over the argument */ i++; - }else if( cli_strcmp(z,"-test-argv")==0 ){ - /* Undocumented test option. Print the values in argv[] and exit. - ** Use this to verify that any translation of the argv[], for example - ** on Windows that receives wargv[] from the OS and must convert - ** to UTF8 prior to calling this routine. */ - int kk; - for(kk=0; kk<argc; kk++){ - sqlite3_fprintf(stdout,"argv[%d] = \"%s\"\n", kk, argv[kk]); - } - return 0; } } #ifndef SQLITE_SHELL_FIDDLE @@ -36540,27 +33371,8 @@ int SQLITE_CDECL main(int argc, char **argv){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); if( pVfs ){ sqlite3_vfs_register(pVfs, 1); - } -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) - else if( access(zVfs,0)==0 ){ - /* If the VFS name is not the name of an existing VFS, but it is - ** the name of a file, then try to load that file as an extension. - ** Presumably the extension implements the desired VFS. */ - sqlite3 *db = 0; - char *zErr = 0; - sqlite3_open(":memory:", &db); - sqlite3_enable_load_extension(db, 1); - rc = sqlite3_load_extension(db, zVfs, 0, &zErr); - sqlite3_close(db); - if( (rc&0xff)!=SQLITE_OK ){ - cli_printf(stderr, "could not load extension VFS \"%s\": %s\n", - zVfs, zErr); - exit(1); - } - } -#endif - else{ - cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs); + }else{ + sqlite3_fprintf(stderr,"no such VFS: \"%s\"\n", zVfs); exit(1); } } @@ -36570,10 +33382,9 @@ int SQLITE_CDECL main(int argc, char **argv){ data.pAuxDb->zDbFilename = ":memory:"; warnInmemoryDb = argc==1; #else - cli_printf(stderr, + sqlite3_fprintf(stderr, "%s: Error: no database filename specified\n", Argv0); - rc = 1; - goto shell_main_exit; + return 1; #endif } data.out = stdout; @@ -36583,7 +33394,6 @@ int SQLITE_CDECL main(int argc, char **argv){ #ifndef SQLITE_SHELL_FIDDLE sqlite3_appendvfs_init(0,0,0); #endif - modeDefault(&data); /* Go ahead and open the database file if it already exists. If the ** file does not exist, delay opening it. This prevents empty database @@ -36598,9 +33408,9 @@ int SQLITE_CDECL main(int argc, char **argv){ ** is given on the command line, look for a file named ~/.sqliterc and ** try to process it. */ - if( !noInit ) process_sqliterc(&data,zInitFile); + process_sqliterc(&data,zInitFile); - /* Make a second pass through the command-line arguments and set + /* Make a second pass through the command-line argument and set ** options. This second pass is delayed until after the initialization ** file is processed so that the command-line arguments will override ** settings in the initialization file. @@ -36612,44 +33422,45 @@ int SQLITE_CDECL main(int argc, char **argv){ if( cli_strcmp(z,"-init")==0 ){ i++; }else if( cli_strcmp(z,"-html")==0 ){ - modeChange(&data, MODE_Html); + data.mode = MODE_Html; }else if( cli_strcmp(z,"-list")==0 ){ - modeChange(&data, MODE_List); + data.mode = MODE_List; }else if( cli_strcmp(z,"-quote")==0 ){ - modeChange(&data, MODE_Quote); + data.mode = MODE_Quote; + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row); }else if( cli_strcmp(z,"-line")==0 ){ - modeChange(&data, MODE_Line); + data.mode = MODE_Line; }else if( cli_strcmp(z,"-column")==0 ){ - modeChange(&data, MODE_Column); + data.mode = MODE_Column; }else if( cli_strcmp(z,"-json")==0 ){ - modeChange(&data, MODE_Json); + data.mode = MODE_Json; }else if( cli_strcmp(z,"-markdown")==0 ){ - modeChange(&data, MODE_Markdown); + data.mode = MODE_Markdown; }else if( cli_strcmp(z,"-table")==0 ){ - modeChange(&data, MODE_Table); - }else if( cli_strcmp(z,"-psql")==0 ){ - modeChange(&data, MODE_Psql); + data.mode = MODE_Table; }else if( cli_strcmp(z,"-box")==0 ){ - modeChange(&data, MODE_Box); + data.mode = MODE_Box; }else if( cli_strcmp(z,"-csv")==0 ){ - modeChange(&data, MODE_Csv); + data.mode = MODE_Csv; + memcpy(data.colSeparator,",",2); }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ /* See similar code at tag-20250224-1 */ const char *zEsc = argv[++i]; int k; - for(k=0; k<ArraySize(qrfEscNames); k++){ - if( sqlite3_stricmp(zEsc,qrfEscNames[k])==0 ){ - data.mode.spec.eEsc = k; + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){ + data.eEscMode = k; break; } } - if( k>=ArraySize(qrfEscNames) ){ - cli_printf(stderr, "unknown control character escape mode \"%s\"" + if( k>=ArraySize(shell_EscModeNames) ){ + sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\"" " - choices:", zEsc); - for(k=0; k<ArraySize(qrfEscNames); k++){ - cli_printf(stderr, " %s", qrfEscNames[k]); + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]); } - cli_printf(stderr, "\n"); + sqlite3_fprintf(stderr, "\n"); exit(1); } #ifdef SQLITE_HAVE_ZLIB @@ -36669,40 +33480,44 @@ int SQLITE_CDECL main(int argc, char **argv){ data.openFlags |= SQLITE_OPEN_READONLY; }else if( cli_strcmp(z,"-nofollow")==0 ){ data.openFlags |= SQLITE_OPEN_NOFOLLOW; - }else if( cli_strcmp(z,"-noinit")==0 ){ - /* No-op */ }else if( cli_strcmp(z,"-exclusive")==0 ){ /* UNDOCUMENTED */ data.openFlags |= SQLITE_OPEN_EXCLUSIVE; }else if( cli_strcmp(z,"-ifexists")==0 ){ data.openFlags &= ~(SQLITE_OPEN_CREATE); if( data.openFlags==0 ) data.openFlags = SQLITE_OPEN_READWRITE; }else if( cli_strcmp(z,"-ascii")==0 ){ - modeChange(&data, MODE_Ascii); + data.mode = MODE_Ascii; + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,SEP_Unit); + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,SEP_Record); }else if( cli_strcmp(z,"-tabs")==0 ){ - modeChange(&data, MODE_Tabs); + data.mode = MODE_List; + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,SEP_Tab); + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,SEP_Row); }else if( cli_strcmp(z,"-separator")==0 ){ - modeSetStr(&data.mode.spec.zColumnSep, - cmdline_option_value(argc,argv,++i)); + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, + "%s",cmdline_option_value(argc,argv,++i)); }else if( cli_strcmp(z,"-newline")==0 ){ - modeSetStr(&data.mode.spec.zRowSep, - cmdline_option_value(argc,argv,++i)); + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, + "%s",cmdline_option_value(argc,argv,++i)); }else if( cli_strcmp(z,"-nullvalue")==0 ){ - modeSetStr(&data.mode.spec.zNull, - cmdline_option_value(argc,argv,++i)); + sqlite3_snprintf(sizeof(data.nullValue), data.nullValue, + "%s",cmdline_option_value(argc,argv,++i)); }else if( cli_strcmp(z,"-header")==0 ){ - data.mode.spec.bTitles = QRF_Yes; + data.showHeader = 1; + ShellSetFlag(&data, SHFLG_HeaderSet); }else if( cli_strcmp(z,"-noheader")==0 ){ - data.mode.spec.bTitles = QRF_No; + data.showHeader = 0; + ShellSetFlag(&data, SHFLG_HeaderSet); }else if( cli_strcmp(z,"-echo")==0 ){ - data.mode.mFlags |= MFLG_ECHO; + ShellSetFlag(&data, SHFLG_Echo); }else if( cli_strcmp(z,"-eqp")==0 ){ - data.mode.autoEQP = AUTOEQP_on; + data.autoEQP = AUTOEQP_on; }else if( cli_strcmp(z,"-eqpfull")==0 ){ - data.mode.autoEQP = AUTOEQP_full; + data.autoEQP = AUTOEQP_full; }else if( cli_strcmp(z,"-stats")==0 ){ data.statsOn = 1; }else if( cli_strcmp(z,"-scanstats")==0 ){ - data.mode.scanstatsOn = 1; + data.scanstatsOn = 1; }else if( cli_strcmp(z,"-backslash")==0 ){ /* Undocumented command-line option: -backslash ** Causes C-style backslash escapes to be evaluated in SQL statements @@ -36713,10 +33528,9 @@ int SQLITE_CDECL main(int argc, char **argv){ }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 ){ - cli_printf(stdout, "%s %s (%d-bit)\n", + sqlite3_fprintf(stdout, "%s %s (%d-bit)\n", sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*)); - rc = 0; - goto shell_main_exit; + return 0; }else if( cli_strcmp(z,"-interactive")==0 ){ /* Need to check for interactive override here to so that it can ** affect console setup (for Windows only) and testing thereof. @@ -36724,8 +33538,6 @@ int SQLITE_CDECL main(int argc, char **argv){ stdin_is_interactive = 1; }else if( cli_strcmp(z,"-batch")==0 ){ /* already handled */ - }else if( cli_strcmp(z,"-screenwidth")==0 ){ - i++; }else if( cli_strcmp(z,"-utf8")==0 ){ /* already handled */ }else if( cli_strcmp(z,"-no-utf8")==0 ){ @@ -36771,26 +33583,23 @@ int SQLITE_CDECL main(int argc, char **argv){ z = cmdline_option_value(argc,argv,++i); if( z[0]=='.' ){ rc = do_meta_command(z, &data); - if( rc && (bail_on_error || rc==2) ){ - if( rc==2 ) rc = 0; - goto shell_main_exit; - } + if( rc && bail_on_error ) return rc==2 ? 0 : rc; }else{ open_db(&data, 0); rc = shell_exec(&data, z, &zErrMsg); if( zErrMsg!=0 ){ shellEmitError(zErrMsg); sqlite3_free(zErrMsg); - if( !rc ) rc = 1; + if( bail_on_error ) return rc!=0 ? rc : 1; }else if( rc!=0 ){ - cli_printf(stderr,"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( bail_on_error ) goto shell_main_exit; } #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) }else if( cli_strncmp(z, "-A", 2)==0 ){ if( nCmd>0 ){ - cli_printf(stderr,"Error: cannot mix regular SQL or dot-commands" + sqlite3_fprintf(stderr,"Error: cannot mix regular SQL or dot-commands" " with \"%s\"\n", z); rc = 1; goto shell_main_exit; @@ -36803,7 +33612,6 @@ int SQLITE_CDECL main(int argc, char **argv){ arDotCommand(&data, 1, argv+i, argc-i); } readStdin = 0; - stdin_is_interactive = 0; break; #endif }else if( cli_strcmp(z,"-safe")==0 ){ @@ -36811,11 +33619,11 @@ int SQLITE_CDECL main(int argc, char **argv){ }else if( cli_strcmp(z,"-unsafe-testing")==0 ){ /* Acted upon in first pass. */ }else{ - cli_printf(stderr,"%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"); - rc = 1; - goto shell_main_exit; + return 1; } + data.cMode = data.mode; } if( !readStdin ){ @@ -36825,26 +33633,8 @@ int SQLITE_CDECL main(int argc, char **argv){ */ for(i=0; i<nCmd; i++){ echo_group_input(&data, azCmd[i]); - if( isScriptFile(azCmd[i],0) ){ - FILE *inSaved = data.in; - i64 savedLineno = data.lineno; - int res = 1; - if( (data.in = openChrSource(azCmd[i]))!=0 ){ - res = process_input(&data, azCmd[i]); - fclose(data.in); - } - data.in = inSaved; - data.lineno = savedLineno; - if( res ) i = nCmd; - }else if( azCmd[i][0]=='.' ){ - char *zErrCtx = malloc( 64 ); - shell_check_oom(zErrCtx); - sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]); - data.zInFile = "<cmdline>"; - data.zErrPrefix = zErrCtx; + if( azCmd[i][0]=='.' ){ rc = do_meta_command(azCmd[i], &data); - free(data.zErrPrefix); - data.zErrPrefix = 0; if( rc ){ if( rc==2 ) rc = 0; goto shell_main_exit; @@ -36856,23 +33646,13 @@ int SQLITE_CDECL main(int argc, char **argv){ if( zErrMsg!=0 ){ shellEmitError(zErrMsg); }else{ - cli_printf(stderr, + sqlite3_fprintf(stderr, "Error: unable to process SQL: %s\n", azCmd[i]); } sqlite3_free(zErrMsg); if( rc==0 ) rc = 1; goto shell_main_exit; } - if( data.nPopMode ){ - modePop(&data); - data.nPopMode = 0; - } - } - if( data.nPopOutput ){ - output_reset(&data); - data.nPopOutput = 0; - }else{ - clearTempFile(&data); } } }else{ @@ -36881,7 +33661,7 @@ int SQLITE_CDECL main(int argc, char **argv){ if( stdin_is_interactive ){ char *zHome; char *zHistory; - cli_printf(stdout, + sqlite3_fprintf(stdout, "SQLite version %s %.19s\n" /*extra-version-info*/ "Enter \".help\" for usage hints.\n", sqlite3_libversion(), sqlite3_sourceid()); @@ -36934,7 +33714,6 @@ int SQLITE_CDECL main(int argc, char **argv){ #endif shell_main_exit: free(azCmd); - free(aiCmd); set_table_name(&data, 0); if( data.db ){ session_close_all(&data, -1); @@ -36951,28 +33730,12 @@ int SQLITE_CDECL main(int argc, char **argv){ output_reset(&data); data.doXdgOpen = 0; clearTempFile(&data); - modeFree(&data.mode); - if( data.nSavedModes ){ - int ii; - for(ii=0; ii<data.nSavedModes; ii++){ - modeFree(&data.aSavedModes[ii].mode); - free(data.aSavedModes[ii].zTag); - } - free(data.aSavedModes); - } - free(data.zErrPrefix); +#if !SQLITE_SHELL_IS_UTF8 + for(i=0; i<argcToFree; i++) free(argvToFree[i]); + free(argvToFree); +#endif + free(data.colWidth); free(data.zNonce); - free(data.dot.zCopy); - free(data.dot.azArg); - free(data.dot.aiOfst); - free(data.dot.abQuot); - if( data.nTestRun ){ - sqlite3_fprintf(stdout, "%d test%s run with %d error%s\n", - data.nTestRun, data.nTestRun==1 ? "" : "s", - data.nTestErr, data.nTestErr==1 ? "" : "s"); - fflush(stdout); - rc = data.nTestErr>0; - } /* Clear the global data structure so that valgrind will detect memory ** leaks */ memset(&data, 0, sizeof(data)); @@ -36981,7 +33744,7 @@ int SQLITE_CDECL main(int argc, char **argv){ } #ifdef SQLITE_DEBUG if( sqlite3_memory_used()>mem_main_enter ){ - cli_printf(stderr,"Memory leaked: %u bytes\n", + sqlite3_fprintf(stderr,"Memory leaked: %u bytes\n", (unsigned int)(sqlite3_memory_used()-mem_main_enter)); } #endif @@ -37021,7 +33784,7 @@ sqlite3_vfs * fiddle_db_vfs(const char *zDbName){ /* Only for emcc experimentation purposes. */ sqlite3 * fiddle_db_arg(sqlite3 *arg){ - cli_printf(stdout, "fiddle_db_arg(%p)\n", (const void*)arg); + sqlite3_fprintf(stdout, "fiddle_db_arg(%p)\n", (const void*)arg); return arg; } @@ -37058,7 +33821,7 @@ void fiddle_reset_db(void){ ** Resolve problem reported in ** https://sqlite.org/forum/forumpost/0b41a25d65 */ - cli_puts("Rolling back in-progress transaction.\n", stdout); + 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); @@ -37125,4 +33888,3 @@ void fiddle_exec(const char * zSql){ } } #endif /* SQLITE_SHELL_FIDDLE */ -/************************* End src/shell.c.in ******************/ diff --git a/cgosqlite/sqlite3.c b/cgosqlite/sqlite3.c index e137809..00b742e 100644 --- a/cgosqlite/sqlite3.c +++ b/cgosqlite/sqlite3.c @@ -2,7 +2,7 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.52.0. By combining all the individual C code files into this +** version 3.51.2. 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 @@ -20,7 +20,7 @@ ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** 557aeb43869d3585137b17690cb3b64f7de6 with changes in files: +** b270f8339eb13b504d0b2ba154ebca966b7d with changes in files: ** ** */ @@ -469,12 +469,12 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.52.0" -#define SQLITE_VERSION_NUMBER 3052000 -#define SQLITE_SOURCE_ID "2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.52.0" -#define SQLITE_SCM_DATETIME "2026-03-06T16:01:44.367Z" +#define SQLITE_VERSION "3.51.2" +#define SQLITE_VERSION_NUMBER 3051002 +#define SQLITE_SOURCE_ID "2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075" +#define SQLITE_SCM_BRANCH "branch-3.51" +#define SQLITE_SCM_TAGS "release version-3.51.2" +#define SQLITE_SCM_DATETIME "2026-01-09T17:27:48.405Z" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1813,7 +1813,7 @@ typedef const char *sqlite3_filename; ** greater and the function pointer is not NULL) and will fall back ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. ** -** ^The xSetSystemCall(), xGetSystemCall(), and xNextSystemCall() interfaces +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces ** are not used by the SQLite core. These optional interfaces are provided ** by some VFSes to facilitate testing of the VFS code. By overriding ** system calls with functions under its control, a test program can @@ -2890,15 +2890,12 @@ struct sqlite3_mem_methods { ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] ** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt> ** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in -** [SQLITE_ENABLE_STMT_SCANSTATUS] builds. In this case, it sets or clears -** a flag that enables collection of run-time performance statistics -** used by [sqlite3_stmt_scanstatus_v2()] and the [nexec and ncycle] -** columns of the [bytecode virtual table]. -** For statistics to be collected, the flag must be set on -** the database handle both when the SQL statement is -** [sqlite3_prepare|prepared] and when it is [sqlite3_step|stepped]. -** The flag is set (collection of statistics is enabled) by default. -** <p>This option takes two arguments: an integer and a pointer to +** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears +** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() +** statistics. For statistics to be collected, the flag must be set on +** the database handle both when the SQL statement is prepared and when it +** is stepped. The flag is set (collection of statistics is enabled) +** by default. <p>This option takes two arguments: an integer and a pointer to ** an integer. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the statement scanstatus option. If the second argument ** is not NULL, then the value of the statement scanstatus setting after @@ -2971,22 +2968,6 @@ struct sqlite3_mem_methods { ** comments are allowed in SQL text after processing the first argument. ** </dd> ** -** [[SQLITE_DBCONFIG_FP_DIGITS]] -** <dt>SQLITE_DBCONFIG_FP_DIGITS</dt> -** <dd>The SQLITE_DBCONFIG_FP_DIGITS setting is a small integer that determines -** the number of significant digits that SQLite will attempt to preserve when -** converting floating point numbers (IEEE 754 "doubles") into text. The -** default value 17, as of SQLite version 3.52.0. The value was 15 in all -** prior versions.<p> -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is a small integer, between 3 and 23, or -** zero. The FP_DIGITS setting is changed to that small integer, or left -** altered if the first argument is zero or out of range. The second argument -** is a pointer to an integer. If the pointer is not NULL, then the value of -** the FP_DIGITS setting, after possibly being modified by the first -** arguments, is written into the integer to which the second argument points. -** </dd> -** ** </dl> ** ** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3> @@ -3004,10 +2985,9 @@ struct sqlite3_mem_methods { ** the first argument. ** ** <p>While most SQLITE_DBCONFIG options use the argument format -** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME], -** [SQLITE_DBCONFIG_LOOKASIDE], and [SQLITE_DBCONFIG_FP_DIGITS] options -** are different. See the documentation of those exceptional options for -** details. +** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME] +** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the +** documentation of those exceptional options for details. */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ @@ -3032,8 +3012,7 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */ -#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -4515,7 +4494,6 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** <li> sqlite3_errmsg() ** <li> sqlite3_errmsg16() ** <li> sqlite3_error_offset() -** <li> sqlite3_db_handle() ** </ul> ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language @@ -4562,7 +4540,7 @@ SQLITE_API const char *sqlite3_errstr(int); SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* -** CAPI3REF: Set Error Code And Message +** CAPI3REF: Set Error Codes And Message ** METHOD: sqlite3 ** ** Set the error code of the database handle passed as the first argument @@ -4681,10 +4659,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt> ** <dd>The maximum depth of the parse tree on any expression.</dd>)^ ** -** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt> -** <dd>The maximum depth of the LALR(1) parser stack used to analyze -** input SQL statements.</dd>)^ -** ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt> ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^ ** @@ -4729,7 +4703,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 -#define SQLITE_LIMIT_PARSER_DEPTH 12 /* ** CAPI3REF: Prepare Flags @@ -4774,29 +4747,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** fails, the sqlite3_prepare_v3() call returns the same error indications ** with or without this flag; it just omits the call to [sqlite3_log()] that ** logs the error. -** -** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt> -** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to enforce -** security constraints that would otherwise only be enforced when parsing -** the database schema. In other words, the SQLITE_PREPARE_FROM_DDL flag -** causes the SQL compiler to treat the SQL statement being prepared as if -** it had come from an attacker. When SQLITE_PREPARE_FROM_DDL is used and -** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] is off, SQL functions may only be called -** if they are tagged with [SQLITE_INNOCUOUS] and virtual tables may only -** be used if they are tagged with [SQLITE_VTAB_INNOCUOUS]. Best practice -** is to use the SQLITE_PREPARE_FROM_DDL option when preparing any SQL that -** is derived from parts of the database schema. In particular, virtual -** table implementations that run SQL statements that are derived from -** arguments to their CREATE VIRTUAL TABLE statement should always use -** [sqlite3_prepare_v3()] and set the SQLITE_PREPARE_FROM_DDL flag to -** prevent bypass of the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks. ** </dl> */ #define SQLITE_PREPARE_PERSISTENT 0x01 #define SQLITE_PREPARE_NORMALIZE 0x02 #define SQLITE_PREPARE_NO_VTAB 0x04 #define SQLITE_PREPARE_DONT_LOG 0x10 -#define SQLITE_PREPARE_FROM_DDL 0x20 /* ** CAPI3REF: Compiling An SQL Statement @@ -4810,9 +4766,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** The preferred routine to use is [sqlite3_prepare_v2()]. The ** [sqlite3_prepare()] interface is legacy and should be avoided. -** [sqlite3_prepare_v3()] has an extra -** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times -** needed for special purpose or to pass along security restrictions. +** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used +** for special purposes. ** ** The use of the UTF-8 interfaces is preferred, as SQLite currently ** does all parsing using UTF-8. The UTF-16 interfaces are provided @@ -5217,8 +5172,8 @@ typedef struct sqlite3_context sqlite3_context; ** it should be a pointer to well-formed UTF16 text. ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then ** it should be a pointer to a well-formed unicode string that is -** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT, -** or UTF16 otherwise. +** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 +** otherwise. ** ** [[byte-order determination rules]] ^The byte-order of ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) @@ -5264,15 +5219,10 @@ typedef struct sqlite3_context sqlite3_context; ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** -** ^The sixth argument (the E argument) -** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of -** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE] to specify the encoding of the text in the -** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the -** string argument is both UTF-8 encoded and is zero-terminated. In other -** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at -** least N+1 bytes and that the Z&#91;N&#93; byte is zero. If -** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the +** ^The sixth argument to sqlite3_bind_text64() must be one of +** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] +** to specify the encoding of the text in the third parameter. If +** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior ** is undefined. @@ -6139,51 +6089,6 @@ SQLITE_API int sqlite3_create_window_function( ** ** These constants define integer codes that represent the various ** text encodings supported by SQLite. -** -** <dl> -** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd> -** -** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16 -** with each code point being expressed "little endian" - the least significant -** byte first. This is the usual encoding, for example on Windows.</dd> -** -** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16 -** with each code point being expressed "big endian" - the most significant -** byte first. This encoding is less common, but is still sometimes seen, -** specially on older systems. -** -** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16 -** with each code point being expressed either little endian or as big -** endian, according to the native endianness of the host computer. -** -** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used -** to declare the preferred text for [application-defined SQL functions] -** created using [sqlite3_create_function()] and similar. If the preferred -** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep -** parameter) is SQLITE_ANY, that indicates that the function does not have -** a preference regarding the text encoding of its parameters and can take -** any text encoding that the SQLite core find convenient to supply. This -** option is deprecated. Please do not use it in new applications. -** -** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding -** value may be used as the 3rd parameter (the eTextRep parameter) to -** [sqlite3_create_collation()] and similar. This encoding value means -** that the application-defined collating sequence created expects its -** input strings to be in UTF16 in native byte order, and that the start -** of the strings must be aligned to a 2-byte boundary. -** -** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be -** used to specify the text encoding to strings input to [sqlite3_result_text64()] -** and [sqlite3_bind_text64()]. It means that the input string (call it "z") -** is UTF-8 encoded and that it is zero-terminated. If the length parameter -** (call it "n") is non-negative, this encoding option means that the caller -** guarantees that z array contains at least n+1 bytes and that the z&#91;n&#93; -** byte has a value of zero. -** This option gives the same output as SQLITE_UTF8, but can be more efficient -** by avoiding the need to make a copy of the input string, in some cases. -** However, if z is allocated to hold fewer than n+1 bytes or if the -** z&#91;n&#93; byte is not zero, undefined behavior may result. -** </dl> */ #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ @@ -6191,7 +6096,6 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ -#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */ /* ** CAPI3REF: Function Flags @@ -6697,14 +6601,10 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi ** ** There is no limit (other than available memory) on the number of different ** client data pointers (with different names) that can be attached to a -** single database connection. However, the current implementation stores -** the content on a linked list. Insert and retrieval performance will -** be proportional to the number of entries. The design use case, and -** the use case for which the implementation is optimized, is -** that an application will store only small number of client data names, -** typically just one or two. This interface is not intended to be a -** generalized key/value store for thousands or millions of keys. It -** will work for that, but performance might be disappointing. +** single database connection. However, the implementation is optimized +** for the case of having only one or two different client data names. +** Applications and wrapper libraries are discouraged from using more than +** one client data name each. ** ** There is no way to enumerate the client data pointers ** associated with a database connection. The N parameter can be thought @@ -6812,14 +6712,10 @@ typedef void (*sqlite3_destructor_type)(void*); ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. -** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an +** ^The sqlite3_result_text64() interface sets the return value of an ** application-defined function to be a text string in an encoding -** specified the E parameter, which must be one -** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that -** the result text is both UTF-8 and zero-terminated. In other words, -** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that -** the Z&#91;N&#93; is zero. +** specified by the fifth (and last) parameter, which must be one +** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces @@ -6906,7 +6802,7 @@ SQLITE_API void sqlite3_result_int(sqlite3_context*, int); SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); SQLITE_API void sqlite3_result_null(sqlite3_context*); SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n, +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); @@ -7845,7 +7741,7 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The sqlite3_load_extension() interface attempts to load an ** [SQLite extension] library contained in the file zFile. If ** the file cannot be loaded directly, attempts are made to load -** with various operating-system specific filename extensions added. +** with various operating-system specific extensions added. ** So for example, if "samplelib" cannot be loaded, then names like ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might ** be tried also. @@ -7853,10 +7749,10 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The entry point is zProc. ** ^(zProc may be 0, in which case SQLite will try to come up with an ** entry point name on its own. It first tries "sqlite3_extension_init". -** If that does not work, it tries names of the form "sqlite3_X_init" -** where X consists of the lower-case equivalent of all ASCII alphabetic -** characters or all ASCII alphanumeric characters in the filename from -** the last "/" to the first following "." and omitting any initial "lib".)^ +** If that does not work, it constructs a name "sqlite3_X_init" where +** X consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the @@ -9149,22 +9045,17 @@ SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ** pass the returned value to [sqlite3_free()] to avoid a memory leak. ** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ** errors were encountered during construction of the string. ^The -** [sqlite3_str_finish(X)] interface might also return a NULL pointer if the +** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ** string in [sqlite3_str] object X is zero bytes long. -** -** ^The [sqlite3_str_free(X)] interface destroys both the sqlite3_str object -** X and the string content it contains. Calling sqlite3_str_free(X) is -** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)). */ SQLITE_API char *sqlite3_str_finish(sqlite3_str*); -SQLITE_API void sqlite3_str_free(sqlite3_str*); /* ** CAPI3REF: Add Content To A Dynamic String ** METHOD: sqlite3_str ** -** These interfaces add or remove content to an sqlite3_str object -** previously obtained from [sqlite3_str_new()]. +** These interfaces add content to an sqlite3_str object previously obtained +** from [sqlite3_str_new()]. ** ** ^The [sqlite3_str_appendf(X,F,...)] and ** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] @@ -9187,10 +9078,6 @@ SQLITE_API void sqlite3_str_free(sqlite3_str*); ** ^The [sqlite3_str_reset(X)] method resets the string under construction ** inside [sqlite3_str] object X back to zero bytes in length. ** -** ^The [sqlite3_str_truncate(X,N)] method changes the length of the string -** under construction to be N bytes are less. This routine is a no-op if -** N is negative or if the string is already N bytes or smaller in size. -** ** These methods do not return a result code. ^If an error occurs, that fact ** is recorded in the [sqlite3_str] object and can be recovered by a ** subsequent call to [sqlite3_str_errcode(X)]. @@ -9201,7 +9088,6 @@ SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); SQLITE_API void sqlite3_str_reset(sqlite3_str*); -SQLITE_API void sqlite3_str_truncate(sqlite3_str*,int N); /* ** CAPI3REF: Status Of A Dynamic String @@ -11035,9 +10921,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** a variable pointed to by the "pOut" parameter. ** ** The "flags" parameter must be passed a mask of flags. At present only -** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX +** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX ** is specified, then status information is available for all elements -** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If +** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If ** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements ** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of ** the EXPLAIN QUERY PLAN output) are available. Invoking API @@ -11051,8 +10937,7 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** elements used to implement the statement - a non-zero value is returned and ** the variable that pOut points to is unchanged. ** -** See also: [sqlite3_stmt_scanstatus_reset()] and the -** [nexec and ncycle] columnes of the [bytecode virtual table]. +** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ @@ -11594,41 +11479,19 @@ SQLITE_API int sqlite3_deserialize( /* ** CAPI3REF: Bind array values to the CARRAY table-valued function ** -** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to -** parameter that is the first argument of the [carray() table-valued function]. -** The S parameter is a pointer to the [prepared statement] that uses the carray() -** functions. I is the parameter index to be bound. I must be the index of the -** parameter that is the first argument to the carray() table-valued function. -** P is a pointer to the array to be bound, and N is the number of elements in -** the array. The F argument is one of constants [SQLITE_CARRAY_INT32], -** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], -** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P. -** -** If the X argument is not a NULL pointer or one of the special -** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke -** the function X with argument D when it is finished using the data in P. -** The call to X(D) is a destructor for the array P. The destructor X(D) -** is invoked even if the call to sqlite3_carray_bind() fails. If the X -** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes -** that the data static and the destructor is never invoked. If the X -** parameter is the special-case value [SQLITE_TRANSIENT], then -** sqlite3_carray_bind_v2() makes its own private copy of the data prior -** to returning and never invokes the destructor X. -** -** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2() -** with a D parameter set to P. In other words, -** sqlite3_carray_bind(S,I,P,N,F,X) is same as -** sqlite3_carray_bind(S,I,P,N,F,X,P). -*/ -SQLITE_API int sqlite3_carray_bind_v2( - sqlite3_stmt *pStmt, /* Statement to be bound */ - int i, /* Parameter index */ - void *aData, /* Pointer to array data */ - int nData, /* Number of data elements */ - int mFlags, /* CARRAY flags */ - void (*xDel)(void*), /* Destructor for aData */ - void *pDel /* Optional argument to xDel() */ -); +** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to +** one of the first argument of the [carray() table-valued function]. The +** S parameter is a pointer to the [prepared statement] that uses the carray() +** functions. I is the parameter index to be bound. P is a pointer to the +** array to be bound, and N is the number of eements in the array. The +** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], +** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to +** indicate the datatype of the array being bound. The X argument is not a +** NULL pointer, then SQLite will invoke the function X on the P parameter +** after it has finished using P, even if the call to +** sqlite3_carray_bind() fails. The special-case finalizer +** SQLITE_TRANSIENT has no effect here. +*/ SQLITE_API int sqlite3_carray_bind( sqlite3_stmt *pStmt, /* Statement to be bound */ int i, /* Parameter index */ @@ -14473,27 +14336,6 @@ struct fts5_api { #endif #define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */ -/* -** Maximum size of any single memory allocation. -** -** This is not a limit on the total amount of memory used. This is -** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc(). -** -** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391 -** This provides a 256-byte safety margin for defense against 32-bit -** signed integer overflow bugs when computing memory allocation sizes. -** Paranoid applications might want to reduce the maximum allocation size -** further for an even larger safety margin. 0x3fffffff or 0x0fffffff -** or even smaller would be reasonable upper bounds on the size of a memory -** allocations for most applications. -*/ -#ifndef SQLITE_MAX_ALLOCATION_SIZE -# define SQLITE_MAX_ALLOCATION_SIZE 2147483391 -#endif -#if SQLITE_MAX_ALLOCATION_SIZE>2147483391 -# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391 -#endif - /* ** This is the maximum number of ** @@ -14529,42 +14371,21 @@ struct fts5_api { ** It used to be the case that setting this value to zero would ** turn the limit off. That is no longer true. It is not possible ** to turn this limit off. -** -** The hard limit is the largest possible 32-bit signed integer less -** 1024, or 2147482624. */ #ifndef SQLITE_MAX_SQL_LENGTH # define SQLITE_MAX_SQL_LENGTH 1000000000 #endif /* -** The maximum depth of an expression tree. The expression tree depth -** is also limited indirectly by SQLITE_MAX_SQL_LENGTH and by -** SQLITE_MAX_PARSER_DEPTH. Reducing the maximum complexity of -** expressions can help prevent excess memory usage by hostile SQL. -** -** A value of 0 for this compile-time option causes all expression -** depth limiting code to be omitted. +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. A value of 0 means that there is no limit. */ #ifndef SQLITE_MAX_EXPR_DEPTH # define SQLITE_MAX_EXPR_DEPTH 1000 #endif -/* -** The maximum depth of the LALR(1) stack used in the parser that -** interprets SQL inputs. The parser stack depth can also be limited -** indirectly by SQLITE_MAX_SQL_LENGTH. Limiting the parser stack -** depth can help prevent excess memory usage and excess CPU stack -** usage when processing hostile SQL. -** -** Prior to version 3.45.0 (2024-01-15), the parser stack was -** hard-coded to 100 entries, and that worked fine for almost all -** applications. So the upper bound on this limit need not be large. -*/ -#ifndef SQLITE_MAX_PARSER_DEPTH -# define SQLITE_MAX_PARSER_DEPTH 2500 -#endif - /* ** The maximum number of terms in a compound SELECT statement. ** The code generator for compound SELECT statements does one @@ -15450,7 +15271,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); # define float sqlite_int64 # define fabs(X) ((X)<0?-(X):(X)) # define sqlite3IsOverflow(X) 0 -# define INFINITY (9223372036854775807LL) # ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # endif @@ -15860,7 +15680,6 @@ typedef INT16_TYPE LogEst; #else # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) #endif -#define TWO_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&1)==0) /* ** Disable MMAP on platforms where it is known to not work @@ -17673,7 +17492,7 @@ typedef struct VdbeOpList VdbeOpList; ** Additional non-public SQLITE_PREPARE_* flags */ #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */ -#define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */ +#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */ /* ** Prototypes for the VDBE interface. See comments on the implementation @@ -17955,10 +17774,10 @@ struct PgHdr { PCache *pCache; /* PRIVATE: Cache that owns this page */ PgHdr *pDirty; /* Transient list of dirty sorted by pgno */ Pager *pPager; /* The pager this page is part of */ + Pgno pgno; /* Page number for this page */ #ifdef SQLITE_CHECK_PAGES - u64 pageHash; /* Hash of page content */ + u32 pageHash; /* Hash of page content */ #endif - Pgno pgno; /* Page number for this page */ u16 flags; /* PGHDR flags defined below */ /********************************************************************** @@ -18298,7 +18117,7 @@ struct Schema { ** The number of different kinds of things that can be limited ** using the sqlite3_limit() interface. */ -#define SQLITE_N_LIMIT (SQLITE_LIMIT_PARSER_DEPTH+1) +#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1) /* ** Lookaside malloc is a set of fixed-size buffers that can be used @@ -18452,7 +18271,6 @@ struct sqlite3 { u8 noSharedCache; /* True if no shared-cache backends */ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ u8 eOpenState; /* Current condition of the connection */ - u8 nFpDigit; /* Significant digits to keep on double->text */ int nextPagesize; /* Pagesize after VACUUM if >0 */ i64 nChange; /* Value returned by sqlite3_changes() */ i64 nTotalChange; /* Value returned by sqlite3_total_changes() */ @@ -20347,6 +20165,19 @@ struct Upsert { /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. +** +** See the header comment on the computeLimitRegisters() routine for a +** detailed description of the meaning of the iLimit and iOffset fields. +** +** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. +** These addresses must be stored so that we can go back and fill in +** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor +** the number of columns in P2 can be computed at the same time +** as the OP_OpenEphm instruction is coded because not +** enough information about the compound query is known at that point. +** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences +** for the result set. The KeyInfo for addrOpenEphm[2] contains collating +** sequences for the ORDER BY clause. */ struct Select { u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ @@ -20354,6 +20185,7 @@ struct Select { u32 selFlags; /* Various SF_* values */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ u32 selId; /* Unique identifier number for this SELECT */ + int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ ExprList *pEList; /* The fields of the result */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ @@ -20385,7 +20217,7 @@ struct Select { #define SF_Resolved 0x0000004 /* Identifiers have been resolved */ #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */ #define SF_HasAgg 0x0000010 /* Contains aggregate functions */ -#define SF_ClonedRhsIn 0x0000020 /* Cloned RHS of an IN operator */ +#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */ #define SF_Compound 0x0000100 /* Part of a compound query */ @@ -20395,14 +20227,14 @@ struct Select { #define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */ #define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */ #define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */ -/* 0x0008000 // available for reuse */ +#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */ #define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */ #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ -/* 0x0400000 // available for reuse */ +#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ #define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ @@ -20422,6 +20254,11 @@ struct Select { ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** +** SRT_Union Store results as a key in a temporary index +** identified by pDest->iSDParm. +** +** SRT_Except Remove results from the temporary index pDest->iSDParm. +** ** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result ** set is not empty. ** @@ -20485,28 +20322,30 @@ struct Select { ** table. (pDest->iSDParm) is the number of key columns in ** each index record in this case. */ -#define SRT_Exists 1 /* Store 1 if the result is not empty */ -#define SRT_Discard 2 /* Do not save the results anywhere */ -#define SRT_DistFifo 3 /* Like SRT_Fifo, but unique results only */ -#define SRT_DistQueue 4 /* Like SRT_Queue, but unique results only */ +#define SRT_Union 1 /* Store result as keys in an index */ +#define SRT_Except 2 /* Remove result from a UNION index */ +#define SRT_Exists 3 /* Store 1 if the result is not empty */ +#define SRT_Discard 4 /* Do not save the results anywhere */ +#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */ +#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */ /* The DISTINCT clause is ignored for all of the above. Not that ** IgnorableDistinct() implies IgnorableOrderby() */ #define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue) -#define SRT_Queue 5 /* Store result in an queue */ -#define SRT_Fifo 6 /* Store result as data with an automatic rowid */ +#define SRT_Queue 7 /* Store result in an queue */ +#define SRT_Fifo 8 /* Store result as data with an automatic rowid */ /* The ORDER BY clause is ignored for all of the above */ #define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo) -#define SRT_Output 7 /* Output each row of result */ -#define SRT_Mem 8 /* Store result in a memory cell */ -#define SRT_Set 9 /* Store results as keys in an index */ -#define SRT_EphemTab 10 /* Create transient tab and store like SRT_Table */ -#define SRT_Coroutine 11 /* Generate a single row of result */ -#define SRT_Table 12 /* Store result as data with an automatic rowid */ -#define SRT_Upfrom 13 /* Store result as data with rowid */ +#define SRT_Output 9 /* Output each row of result */ +#define SRT_Mem 10 /* Store result in a memory cell */ +#define SRT_Set 11 /* Store results as keys in an index */ +#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */ +#define SRT_Coroutine 13 /* Generate a single row of result */ +#define SRT_Table 14 /* Store result as data with an automatic rowid */ +#define SRT_Upfrom 15 /* Store result as data with rowid */ /* ** An instance of this object describes where to put of the results of @@ -20642,12 +20481,17 @@ struct Parse { u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ + u8 mayAbort; /* True if statement may throw an ABORT exception */ + u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ + u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ + u8 bReturning; /* Coding a RETURNING trigger */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ + u8 disableTriggers; /* True to disable triggers */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif @@ -20656,15 +20500,10 @@ struct Parse { u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER) ** and ALTER TABLE ADD COLUMN. */ #endif - bft disableTriggers:1; /* True to disable triggers */ - bft mayAbort :1; /* True if statement may throw an ABORT exception */ - bft hasCompound :1; /* Need to invoke convertCompoundSelectToSubquery() */ - bft bReturning :1; /* Coding a RETURNING trigger */ - bft bHasExists :1; /* Has a correlated "EXISTS (SELECT ....)" expression */ - bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ - bft bHasWith :1; /* True if statement contains WITH */ - bft okConstFactor:1; /* OK to factor out constants */ - bft checkSchema :1; /* Causes schema cookie check after an error */ + bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ + bft bHasWith :1; /* True if statement contains WITH */ + bft okConstFactor :1; /* OK to factor out constants */ + bft checkSchema :1; /* Causes schema cookie check after an error */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ @@ -20893,19 +20732,19 @@ struct Trigger { ** orconf -> stores the ON CONFLICT algorithm ** pSelect -> The content to be inserted - either a SELECT statement or ** a VALUES clause. -** pSrc -> Table to insert into. +** zTarget -> Dequoted name of the table to insert into. ** pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ... ** statement, then this stores the column-names to be ** inserted into. ** pUpsert -> The ON CONFLICT clauses for an Upsert ** ** (op == TK_DELETE) -** pSrc -> Table to delete from +** zTarget -> Dequoted name of the table to delete from. ** pWhere -> The WHERE clause of the DELETE statement if one is specified. ** Otherwise NULL. ** ** (op == TK_UPDATE) -** pSrc -> Table to update, followed by any FROM clause tables. +** zTarget -> Dequoted name of the table to update. ** pWhere -> The WHERE clause of the UPDATE statement if one is specified. ** Otherwise NULL. ** pExprList -> A list of the columns to update and the expressions to update @@ -20925,7 +20764,8 @@ struct TriggerStep { u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ - SrcList *pSrc; /* Table to insert/update/delete */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ + SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */ IdList *pIdList; /* Column names for INSERT */ @@ -21008,11 +20848,10 @@ typedef struct { /* ** Allowed values for mInitFlags */ -#define INITFLAG_AlterMask 0x0007 /* Types of ALTER */ +#define INITFLAG_AlterMask 0x0003 /* Types of ALTER */ #define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */ #define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */ #define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */ -#define INITFLAG_AlterDropCons 0x0004 /* Reparse after an ADD COLUMN */ /* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled ** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning @@ -21142,7 +20981,6 @@ struct Walker { NameContext *pNC; /* Naming context */ int n; /* A counter */ int iCur; /* A cursor number */ - int sz; /* String literal length */ SrcList *pSrcList; /* FROM clause */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */ @@ -21547,20 +21385,7 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*); SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); - -/* The SQLITE_THREAD_MISUSE_WARNINGS compile-time option used to be called -** SQLITE_ENABLE_MULTITHREADED_CHECKS. Keep that older macro for backwards -** compatibility, at least for a while... */ -#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS -# define SQLITE_THREAD_MISUSE_WARNINGS 1 -#endif - -/* SQLITE_THREAD_MISUSE_ABORT implies SQLITE_THREAD_MISUSE_WARNINGS */ -#ifdef SQLITE_THREAD_MISUSE_ABORT -# define SQLITE_THREAD_MISUSE_WARNINGS 1 -#endif - -#if defined(SQLITE_THREAD_MISUSE_WARNINGS) && !defined(SQLITE_MUTEX_OMIT) +#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT) SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*); #else # define sqlite3MutexWarnOnContention(x) @@ -21594,12 +21419,12 @@ struct PrintfArguments { ** value into an approximate decimal representation. */ struct FpDecode { + char sign; /* '+' or '-' */ + char isSpecial; /* 1: Infinity 2: NaN */ int n; /* Significant digits in the decode */ int iDP; /* Location of the decimal point */ char *z; /* Start of significant digits */ - char zBuf[20]; /* Storage for significant digits */ - char sign; /* '+' or '-' */ - char isSpecial; /* 1: Infinity 2: NaN */ + char zBuf[24]; /* Storage for significant digits */ }; SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int); @@ -21688,7 +21513,6 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int); #endif SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); -SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3*,int); SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); @@ -21842,7 +21666,6 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList Expr*,ExprList*,u32,Expr*); SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*); -SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect); SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*); SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); @@ -21940,7 +21763,6 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); -SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*); SQLITE_PRIVATE int sqlite3IsRowid(const char*); SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab); SQLITE_PRIVATE void sqlite3GenerateRowDelete( @@ -22009,16 +21831,17 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,SrcList*, IdList*, +SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*, Select*,u8,Upsert*, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,SrcList*,SrcList*,ExprList*, +SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*, Expr*, u8, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,SrcList*, Expr*, +SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*, const char*,const char*); SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); +SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*); # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) # define sqlite3IsToplevel(p) ((p)->pToplevel==0) #else @@ -22032,6 +21855,7 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Tab # define sqlite3ParseToplevel(p) p # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 +# define sqlite3TriggerStepSrc(A,B) 0 #endif SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); @@ -22064,7 +21888,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64); SQLITE_PRIVATE i64 sqlite3RealToI64(double); SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*); -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*); +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*); SQLITE_PRIVATE int sqlite3Atoi(const char*); @@ -22208,13 +22032,10 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); -SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*); -SQLITE_PRIVATE void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int); -SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); -SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int); +SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*); @@ -24629,7 +24450,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*)); -SQLITE_PRIVATE int sqlite3VdbeMemSetText(Mem*, const char*, i64, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); #ifdef SQLITE_OMIT_FLOATING_POINT # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 @@ -24648,14 +24468,13 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); -SQLITE_PRIVATE SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem*, int*); SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); @@ -25615,7 +25434,7 @@ static int parseDateOrTime( return 0; }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){ return setDateTimeToCurrent(context, p); - }else if( sqlite3AtoF(zDate, &r)>0 ){ + }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){ setRawDateNumber(p, r); return 0; }else if( (sqlite3StrICmp(zDate,"subsec")==0 @@ -26061,7 +25880,7 @@ static int parseModifier( ** date is already on the appropriate weekday, this is a no-op. */ if( sqlite3_strnicmp(z, "weekday ", 8)==0 - && sqlite3AtoF(&z[8], &r)>0 + && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0 && r>=0.0 && r<7.0 && (n=(int)r)==r ){ sqlite3_int64 Z; computeYMD_HMS(p); @@ -26132,11 +25951,9 @@ static int parseModifier( case '8': case '9': { double rRounder; - int i, rx; + int i; int Y,M,D,h,m,x; const char *z2 = z; - char *zCopy; - sqlite3 *db = sqlite3_context_db_handle(pCtx); char z0 = z[0]; for(n=1; z[n]; n++){ if( z[n]==':' ) break; @@ -26146,11 +25963,7 @@ static int parseModifier( if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break; } } - zCopy = sqlite3DbStrNDup(db, z, n); - if( zCopy==0 ) break; - rx = sqlite3AtoF(zCopy, &r)<=0; - sqlite3DbFree(db, zCopy); - if( rx ){ + if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){ assert( rc==1 ); break; } @@ -26970,7 +26783,7 @@ static void datedebugFunc( char *zJson; zJson = sqlite3_mprintf( "{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d," - "s:%.3f,validJD:%d,validYMD:%d,validHMS:%d," + "s:%.3f,validJD:%d,validYMS:%d,validHMS:%d," "nFloor:%d,rawS:%d,isError:%d,useSubsec:%d," "isUtc:%d,isLocal:%d}", x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz, @@ -29749,28 +29562,23 @@ static SQLITE_WSD int mutexIsInit = 0; #ifndef SQLITE_MUTEX_OMIT -#ifdef SQLITE_THREAD_MISUSE_WARNINGS +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS /* -** This block (enclosed by SQLITE_THREAD_MISUSE_WARNINGS) contains +** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains ** the implementation of a wrapper around the system default mutex ** implementation (sqlite3DefaultMutex()). ** ** Most calls are passed directly through to the underlying default ** mutex implementation. Except, if a mutex is configured by calling ** sqlite3MutexWarnOnContention() on it, then if contention is ever -** encountered within xMutexEnter() then a warning is emitted via -** sqlite3_log(). Furthermore, if SQLITE_THREAD_MISUSE_ABORT is -** defined then abort() is called after the sqlite3_log() warning. +** encountered within xMutexEnter() a warning is emitted via sqlite3_log(). ** -** This type of mutex is used on the database handle mutex when testing -** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. A failure -** indicates that the app ought to be using SQLITE_OPEN_FULLMUTEX or -** similar because it is trying to use the same database handle from -** two different connections at the same time. +** This type of mutex is used as the database handle mutex when testing +** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. */ /* -** Type for all mutexes used when SQLITE_THREAD_MISUSE_WARNINGS +** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS ** is defined. Variable CheckMutex.mutex is a pointer to the real mutex ** allocated by the system mutex implementation. Variable iType is usually set ** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST @@ -29806,12 +29614,11 @@ static int checkMutexNotheld(sqlite3_mutex *p){ */ static int checkMutexInit(void){ pGlobalMutexMethods = sqlite3DefaultMutex(); - return pGlobalMutexMethods->xMutexInit(); + return SQLITE_OK; } static int checkMutexEnd(void){ - int rc = pGlobalMutexMethods->xMutexEnd(); pGlobalMutexMethods = 0; - return rc; + return SQLITE_OK; } /* @@ -29888,9 +29695,6 @@ static void checkMutexEnter(sqlite3_mutex *p){ sqlite3_log(SQLITE_MISUSE, "illegal multi-threaded access to database connection" ); -#if SQLITE_THREAD_MISUSE_ABORT - abort(); -#endif } pGlobalMutexMethods->xMutexEnter(pCheck->mutex); } @@ -29942,7 +29746,7 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){ pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION; } } -#endif /* ifdef SQLITE_THREAD_MISUSE_WARNINGS */ +#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */ /* ** Initialize the mutex system. @@ -29959,7 +29763,7 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){ sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; if( sqlite3GlobalConfig.bCoreMutex ){ -#ifdef SQLITE_THREAD_MISUSE_WARNINGS +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS pFrom = multiThreadedCheckMutex(); #else pFrom = sqlite3DefaultMutex(); @@ -30807,6 +30611,14 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ # define SQLITE_OS_WINCE 0 #endif +/* +** Determine if we are dealing with WinRT, which provides only a subset of +** the full Win32 API. +*/ +#if !defined(SQLITE_OS_WINRT) +# define SQLITE_OS_WINRT 0 +#endif + /* ** For WinCE, some API function parameters do not appear to be declared as ** volatile. @@ -30821,7 +30633,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() ** functions are not available (e.g. those not using MSVC, Cygwin, etc). */ -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && \ +#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) # define SQLITE_OS_WIN_THREADS 1 #else @@ -30938,7 +30750,11 @@ static int winMutexInit(void){ if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ int i; for(i=0; i<ArraySize(winMutex_staticMutexes); i++){ +#if SQLITE_OS_WINRT + InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0); +#else InitializeCriticalSection(&winMutex_staticMutexes[i].mutex); +#endif } winMutex_isInit = 1; }else{ @@ -31028,7 +30844,11 @@ static sqlite3_mutex *winMutexAlloc(int iType){ p->trace = 1; #endif #endif +#if SQLITE_OS_WINRT + InitializeCriticalSectionEx(&p->mutex, 0, 0); +#else InitializeCriticalSection(&p->mutex); +#endif } break; } @@ -31492,6 +31312,27 @@ static void mallocWithAlarm(int n, void **pp){ *pp = p; } +/* +** Maximum size of any single memory allocation. +** +** This is not a limit on the total amount of memory used. This is +** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc(). +** +** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391 +** This provides a 256-byte safety margin for defense against 32-bit +** signed integer overflow bugs when computing memory allocation sizes. +** Paranoid applications might want to reduce the maximum allocation size +** further for an even larger safety margin. 0x3fffffff or 0x0fffffff +** or even smaller would be reasonable upper bounds on the size of a memory +** allocations for most applications. +*/ +#ifndef SQLITE_MAX_ALLOCATION_SIZE +# define SQLITE_MAX_ALLOCATION_SIZE 2147483391 +#endif +#if SQLITE_MAX_ALLOCATION_SIZE>2147483391 +# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391 +#endif + /* ** Allocate memory. This routine is like sqlite3_malloc() except that it ** assumes the memory subsystem has already been initialized. @@ -31715,7 +31556,8 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ sqlite3_free(pOld); /* IMP: R-26507-47431 */ return 0; } - if( nBytes>SQLITE_MAX_ALLOCATION_SIZE ){ + if( nBytes>=0x7fffff00 ){ + /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */ return 0; } nOld = sqlite3MallocSize(pOld); @@ -32653,7 +32495,7 @@ SQLITE_API void sqlite3_str_vappendf( }else{ iRound = precision+1; } - sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16); + sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16); if( s.isSpecial ){ if( s.isSpecial==2 ){ bufpt = flag_zeropad ? "null" : "NaN"; @@ -33332,14 +33174,6 @@ SQLITE_API int sqlite3_str_length(sqlite3_str *p){ return p ? p->nChar : 0; } -/* Truncate the text of the string to be no more than N bytes. */ -SQLITE_API void sqlite3_str_truncate(sqlite3_str *p, int N){ - if( p!=0 && N>=0 && (u32)N<p->nChar ){ - p->nChar = N; - p->zText[p->nChar] = 0; - } -} - /* Return the current value for p */ SQLITE_API char *sqlite3_str_value(sqlite3_str *p){ if( p==0 || p->nChar==0 ) return 0; @@ -33360,17 +33194,6 @@ SQLITE_API void sqlite3_str_reset(StrAccum *p){ p->zText = 0; } -/* -** Destroy a dynamically allocate sqlite3_str object and all -** of its content, all in one call. -*/ -SQLITE_API void sqlite3_str_free(sqlite3_str *p){ - if( p ){ - sqlite3_str_reset(p); - sqlite3_free(p); - } -} - /* ** Initialize a string accumulator. ** @@ -34984,13 +34807,7 @@ SQLITE_PRIVATE void sqlite3TreeViewTrigger( SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); } SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);} SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); } -SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ - TreeView *pView = 0; - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, "SRCLIST"); - sqlite3TreeViewSrcList(pView,p); - sqlite3TreeViewPop(&pView); -} +SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); } SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); } SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); } SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); } @@ -36510,262 +36327,48 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ return h; } -/* -** Two inputs are multiplied to get a 128-bit result. Return -** the high-order 64 bits of that result. -*/ -static u64 sqlite3Multiply128(u64 a, u64 b){ -#if (defined(__GNUC__) || defined(__clang__)) \ - && (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) - return ((__uint128_t)a * b) >> 64; -#elif defined(_MSC_VER) && defined(_M_X64) - return __umulh(a, b); -#else - u64 a1 = (u32)a; - u64 a2 = a >> 32; - u64 b1 = (u32)b; - u64 b2 = b >> 32; - u64 p0 = a1 * b1; - u64 p1 = a1 * b2; - u64 p2 = a2 * b1; - u64 p3 = a2 * b2; - u64 carry = ((p0 >> 32) + (u32)p1 + (u32)p2) >> 32; - return p3 + (p1 >> 32) + (p2 >> 32) + carry; -#endif -} - -/* -** Return a u64 with the N-th bit set. -*/ -#define U64_BIT(N) (((u64)1)<<(N)) - -/* -** Range of powers of 10 that we need to deal with when converting -** IEEE754 doubles to and from decimal. -*/ -#define POWERSOF10_FIRST (-348) -#define POWERSOF10_LAST (+347) - -/* -** For any p between -348 and +347, return the integer part of -** -** pow(10,p) * pow(2,63-pow10to2(p)) -** -** Or, in other words, for any p in range, return the most significant -** 64 bits of pow(10,p). The pow(10,p) value is shifted left or right, -** as appropriate so the most significant 64 bits fit exactly into a -** 64-bit unsigned integer. -** -** Algorithm: -** -** (1) For p between 0 and 26, return the value directly from the aBase[] -** lookup table. -** -** (2) For p outside the range 0 to 26, use aScale[] for the initial value -** then refine that result (if necessary) by a single multiplication -** against aBase[]. -*/ -static u64 powerOfTen(int p){ - static const u64 aBase[] = { - 0x8000000000000000LLU, /* 0: 1.0e+0 << 63 */ - 0xa000000000000000LLU, /* 1: 1.0e+1 << 60 */ - 0xc800000000000000LLU, /* 2: 1.0e+2 << 57 */ - 0xfa00000000000000LLU, /* 3: 1.0e+3 << 54 */ - 0x9c40000000000000LLU, /* 4: 1.0e+4 << 50 */ - 0xc350000000000000LLU, /* 5: 1.0e+5 << 47 */ - 0xf424000000000000LLU, /* 6: 1.0e+6 << 44 */ - 0x9896800000000000LLU, /* 7: 1.0e+7 << 40 */ - 0xbebc200000000000LLU, /* 8: 1.0e+8 << 37 */ - 0xee6b280000000000LLU, /* 9: 1.0e+9 << 34 */ - 0x9502f90000000000LLU, /* 10: 1.0e+10 << 30 */ - 0xba43b74000000000LLU, /* 11: 1.0e+11 << 27 */ - 0xe8d4a51000000000LLU, /* 12: 1.0e+12 << 24 */ - 0x9184e72a00000000LLU, /* 13: 1.0e+13 << 20 */ - 0xb5e620f480000000LLU, /* 14: 1.0e+14 << 17 */ - 0xe35fa931a0000000LLU, /* 15: 1.0e+15 << 14 */ - 0x8e1bc9bf04000000LLU, /* 16: 1.0e+16 << 10 */ - 0xb1a2bc2ec5000000LLU, /* 17: 1.0e+17 << 7 */ - 0xde0b6b3a76400000LLU, /* 18: 1.0e+18 << 4 */ - 0x8ac7230489e80000LLU, /* 19: 1.0e+19 >> 0 */ - 0xad78ebc5ac620000LLU, /* 20: 1.0e+20 >> 3 */ - 0xd8d726b7177a8000LLU, /* 21: 1.0e+21 >> 6 */ - 0x878678326eac9000LLU, /* 22: 1.0e+22 >> 10 */ - 0xa968163f0a57b400LLU, /* 23: 1.0e+23 >> 13 */ - 0xd3c21bcecceda100LLU, /* 24: 1.0e+24 >> 16 */ - 0x84595161401484a0LLU, /* 25: 1.0e+25 >> 20 */ - 0xa56fa5b99019a5c8LLU, /* 26: 1.0e+26 >> 23 */ - }; - static const u64 aScale[] = { - 0x8049a4ac0c5811aeLLU, /* 0: 1.0e-351 << 1229 */ - 0xcf42894a5dce35eaLLU, /* 1: 1.0e-324 << 1140 */ - 0xa76c582338ed2622LLU, /* 2: 1.0e-297 << 1050 */ - 0x873e4f75e2224e68LLU, /* 3: 1.0e-270 << 960 */ - 0xda7f5bf590966849LLU, /* 4: 1.0e-243 << 871 */ - 0xb080392cc4349dedLLU, /* 5: 1.0e-216 << 781 */ - 0x8e938662882af53eLLU, /* 6: 1.0e-189 << 691 */ - 0xe65829b3046b0afaLLU, /* 7: 1.0e-162 << 602 */ - 0xba121a4650e4ddecLLU, /* 8: 1.0e-135 << 512 */ - 0x964e858c91ba2655LLU, /* 9: 1.0e-108 << 422 */ - 0xf2d56790ab41c2a3LLU, /* 10: 1.0e-81 << 333 */ - 0xc428d05aa4751e4dLLU, /* 11: 1.0e-54 << 243 */ - 0x9e74d1b791e07e48LLU, /* 12: 1.0e-27 << 153 */ - 0x8000000000000000LLU, /* 13: 1.0e+0 << 63 */ - 0xcecb8f27f4200f3aLLU, /* 14: 1.0e+27 >> 26 */ - 0xa70c3c40a64e6c52LLU, /* 15: 1.0e+54 >> 116 */ - 0x86f0ac99b4e8dafdLLU, /* 16: 1.0e+81 >> 206 */ - 0xda01ee641a708deaLLU, /* 17: 1.0e+108 >> 295 */ - 0xb01ae745b101e9e4LLU, /* 18: 1.0e+135 >> 385 */ - 0x8e41ade9fbebc27dLLU, /* 19: 1.0e+162 >> 475 */ - 0xe5d3ef282a242e82LLU, /* 20: 1.0e+189 >> 564 */ - 0xb9a74a0637ce2ee1LLU, /* 21: 1.0e+216 >> 654 */ - 0x95f83d0a1fb69cd9LLU, /* 22: 1.0e+243 >> 744 */ - 0xf24a01a73cf2dcd0LLU, /* 23: 1.0e+270 >> 833 */ - 0xc3b8358109e84f07LLU, /* 24: 1.0e+297 >> 923 */ - 0x9e19db92b4e31ba9LLU, /* 25: 1.0e+324 >> 1013 */ - }; - int g, n; - u64 x, y; - - assert( p>=POWERSOF10_FIRST && p<=POWERSOF10_LAST ); - if( p<0 ){ - g = p/27; - n = p%27; - if( n ){ - g--; - n += 27; - } - }else if( p<27 ){ - return aBase[p]; - }else{ - g = p/27; - n = p%27; - } - y = aScale[g+13]; - if( n==0 ){ - return y; - } - x = sqlite3Multiply128(aBase[n],y); - if( (U64_BIT(63) & x)==0 ){ - x = (x<<1)|1; - } - return x; -} - -/* -** pow10to2(x) computes floor(log2(pow(10,x))). -** pow2to10(y) computes floor(log10(pow(2,y))). -** -** Conceptually, pow10to2(p) converts a base-10 exponent p into -** a corresponding base-2 exponent, and pow2to10(e) converts a base-2 -** exponent into a base-10 exponent. -** -** The conversions are based on the observation that: -** -** ln(10.0)/ln(2.0) == 108853/32768 (approximately) -** ln(2.0)/ln(10.0) == 78913/262144 (approximately) +/* Double-Double multiplication. (x[0],x[1]) *= (y,yy) ** -** These ratios are approximate, but they are accurate to 5 digits, -** which is close enough for the usage here. Right-shift is used -** for division so that rounding of negative numbers happens in the -** right direction. -*/ -static int pwr10to2(int p){ return (p*108853) >> 15; } -static int pwr2to10(int p){ return (p*78913) >> 18; } - -/* -** Count leading zeros for a 64-bit unsigned integer. -*/ -static int countLeadingZeros(u64 m){ -#if defined(__GNUC__) || defined(__clang__) - return __builtin_clzll(m); -#else - int n = 0; - if( m <= 0x00000000ffffffffULL) { n += 32; m <<= 32; } - if( m <= 0x0000ffffffffffffULL) { n += 16; m <<= 16; } - if( m <= 0x00ffffffffffffffULL) { n += 8; m <<= 8; } - if( m <= 0x0fffffffffffffffULL) { n += 4; m <<= 4; } - if( m <= 0x3fffffffffffffffULL) { n += 2; m <<= 2; } - if( m <= 0x7fffffffffffffffULL) { n += 1; } - return n; -#endif -} - -/* -** Given m and e, which represent a quantity r == m*pow(2,e), -** return values *pD and *pP such that r == (*pD)*pow(10,*pP), -** approximately. *pD should contain at least n significant digits. -** -** The input m is required to have its highest bit set. In other words, -** m should be left-shifted, and e decremented, to maximize the value of m. -*/ -static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){ - int p; - u64 h; - assert( n>=1 && n<=18 ); - p = n - 1 - pwr2to10(e+63); - h = sqlite3Multiply128(m, powerOfTen(p)); - assert( -(e + pwr10to2(p) + 2) >= 0 ); - assert( -(e + pwr10to2(p) + 1) <= 63 ); - if( n==18 ){ - h >>= -(e + pwr10to2(p) + 2); - *pD = (h + ((h<<1)&2))>>1; - }else{ - *pD = h >> -(e + pwr10to2(p) + 1); - } - *pP = -p; -} - -/* -** Return an IEEE754 floating point value that approximates d*pow(10,p). +** Reference: +** T. J. Dekker, "A Floating-Point Technique for Extending the +** Available Precision". 1971-07-26. */ -static double sqlite3Fp10Convert2(u64 d, int p){ - u64 out; - int e1; - int lz; - int lp; - int x; - u64 h; - double r; - assert( (d & U64_BIT(63))==0 ); - assert( d!=0 ); - if( p<POWERSOF10_FIRST ){ - return 0.0; - } - if( p>POWERSOF10_LAST ){ - return INFINITY; - } - lz = countLeadingZeros(d); - lp = pwr10to2(p); - e1 = lz - (lp + 11); - if( e1>1074 ){ - if( e1>=1130 ) return 0.0; - e1 = 1074; - } - h = sqlite3Multiply128(d<<lz, powerOfTen(p)); - x = lz - (e1 + lp + 3); - assert( x >= 0 ); - assert( x <= 63 ); - out = h >> x; - if( out >= U64_BIT(55)-2 ){ - out >>= 1; - e1--; - } - if( e1<=(-972) ){ - return INFINITY; - } - out = (out + 2) >> 2; - if( (out & U64_BIT(52))!=0 ){ - out = (out & ~U64_BIT(52)) | ((u64)(1075-e1)<<52); - } - memcpy(&r, &out, 8); - return r; +static void dekkerMul2(volatile double *x, double y, double yy){ + /* + ** The "volatile" keywords on parameter x[] and on local variables + ** below are needed force intermediate results to be truncated to + ** binary64 rather than be carried around in an extended-precision + ** format. The truncation is necessary for the Dekker algorithm to + ** work. Intel x86 floating point might omit the truncation without + ** the use of volatile. + */ + volatile double tx, ty, p, q, c, cc; + double hx, hy; + u64 m; + memcpy(&m, (void*)&x[0], 8); + m &= 0xfffffffffc000000LL; + memcpy(&hx, &m, 8); + tx = x[0] - hx; + memcpy(&m, &y, 8); + m &= 0xfffffffffc000000LL; + memcpy(&hy, &m, 8); + ty = y - hy; + p = hx*hy; + q = hx*ty + tx*hy; + c = p+q; + cc = p - c + q + tx*ty; + cc = x[0]*yy + x[1]*y + cc; + x[0] = c + cc; + x[1] = c - x[0]; + x[1] += cc; } /* ** The string z[] is an text representation of a real number. ** Convert this string to a double and write it into *pResult. ** -** z[] must be UTF-8 and zero-terminated. +** The string z[] is length bytes in length (bytes, not characters) and +** uses the encoding enc. The string is not necessarily zero-terminated. ** ** Return TRUE if the result is a valid real number (or integer) and FALSE ** if the string is empty or contains extraneous text. More specifically @@ -36792,131 +36395,198 @@ static double sqlite3Fp10Convert2(u64 d, int p){ #if defined(_MSC_VER) #pragma warning(disable : 4756) #endif -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){ +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ #ifndef SQLITE_OMIT_FLOATING_POINT + int incr; + const char *zEnd; /* sign * significand * (10 ^ (esign * exponent)) */ - int neg = 0; /* True for a negative value */ - u64 s = 0; /* mantissa */ - int d = 0; /* Value is s * pow(10,d) */ + int sign = 1; /* sign of significand */ + u64 s = 0; /* significand */ + int d = 0; /* adjust exponent for shifting decimal point */ + int esign = 1; /* sign of exponent */ + int e = 0; /* exponent */ + 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 */ + int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ + u64 s2; /* round-tripped significand */ + double rr[2]; + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ + if( length==0 ) return 0; + + if( enc==SQLITE_UTF8 ){ + incr = 1; + zEnd = z + length; + }else{ + int i; + incr = 2; + length &= ~1; + assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + testcase( enc==SQLITE_UTF16LE ); + testcase( enc==SQLITE_UTF16BE ); + for(i=3-enc; i<length && z[i]==0; i+=2){} + if( i<length ) eType = -100; + zEnd = &z[i^1]; + z += (enc&1); + } /* skip leading spaces */ - while( sqlite3Isspace(*z) ) z++; + while( z<zEnd && sqlite3Isspace(*z) ) z+=incr; + if( z>=zEnd ) return 0; /* get sign of significand */ if( *z=='-' ){ - neg = 1; - z++; + sign = -1; + z+=incr; }else if( *z=='+' ){ - z++; + z+=incr; } /* copy max significant digits to significand */ - while( sqlite3Isdigit(*z) ){ + while( z<zEnd && sqlite3Isdigit(*z) ){ s = s*10 + (*z - '0'); - z++; nDigit++; - if( s>=((LARGEST_INT64-9)/10) ){ + z+=incr; nDigit++; + if( s>=((LARGEST_UINT64-9)/10) ){ /* skip non-significant significand digits ** (increase exponent by d to shift decimal left) */ - while( sqlite3Isdigit(*z) ){ z++; d++; } + while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; } } } + if( z>=zEnd ) goto do_atof_calc; /* if decimal point is present */ if( *z=='.' ){ - z++; + z+=incr; eType++; /* copy digits from after decimal to significand ** (decrease exponent by d to shift decimal right) */ - while( sqlite3Isdigit(*z) ){ - if( s<((LARGEST_INT64-9)/10) ){ + while( z<zEnd && sqlite3Isdigit(*z) ){ + if( s<((LARGEST_UINT64-9)/10) ){ s = s*10 + (*z - '0'); d--; nDigit++; } - z++; + z+=incr; } } + if( z>=zEnd ) goto do_atof_calc; /* if exponent is present */ if( *z=='e' || *z=='E' ){ - int esign = 1; /* sign of exponent */ - z++; + z+=incr; + eValid = 0; eType++; + /* This branch is needed to avoid a (harmless) buffer overread. The + ** special comment alerts the mutation tester that the correct answer + ** is obtained even if the branch is omitted */ + if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/ + /* get sign of exponent */ if( *z=='-' ){ esign = -1; - z++; + z+=incr; }else if( *z=='+' ){ - z++; + z+=incr; } /* copy digits to exponent */ - if( sqlite3Isdigit(*z) ){ - int exp = *z - '0'; - z++; - while( sqlite3Isdigit(*z) ){ - exp = exp<10000 ? (exp*10 + (*z - '0')) : 10000; - z++; - } - d += esign*exp; - }else{ - eType = -1; + while( z<zEnd && sqlite3Isdigit(*z) ){ + e = e<10000 ? (e*10 + (*z - '0')) : 10000; + z+=incr; + eValid = 1; } } /* skip trailing spaces */ - while( sqlite3Isspace(*z) ) z++; + while( z<zEnd && sqlite3Isspace(*z) ) z+=incr; +do_atof_calc: /* Zero is a special case */ if( s==0 ){ - *pResult = neg ? -0.0 : +0.0; + *pResult = sign<0 ? -0.0 : +0.0; + goto atof_return; + } + + /* adjust exponent by d, and update sign */ + e = (e*esign) + d; + + /* Try to adjust the exponent to make it smaller */ + while( e>0 && s<((LARGEST_UINT64-0x7ff)/10) ){ + s *= 10; + e--; + } + while( e<0 && (s%10)==0 ){ + s /= 10; + e++; + } + + rr[0] = (double)s; + assert( sizeof(s2)==sizeof(rr[0]) ); +#ifdef SQLITE_DEBUG + rr[1] = 18446744073709549568.0; + memcpy(&s2, &rr[1], sizeof(s2)); + assert( s2==0x43efffffffffffffLL ); +#endif + /* Largest double that can be safely converted to u64 + ** vvvvvvvvvvvvvvvvvvvvvv */ + if( rr[0]<=18446744073709549568.0 ){ + s2 = (u64)rr[0]; + rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); }else{ - *pResult = sqlite3Fp10Convert2(s,d); - if( neg ) *pResult = -*pResult; - assert( !sqlite3IsNaN(*pResult) ); + rr[1] = 0.0; } + assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */ + 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); + } + } + *pResult = rr[0]+rr[1]; + if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; + if( sign<0 ) *pResult = -*pResult; + assert( !sqlite3IsNaN(*pResult) ); + +atof_return: /* return true if number and no extra non-whitespace characters after */ - if( z[0]==0 && nDigit>0 ){ + if( z==zEnd && nDigit>0 && eValid && eType>0 ){ return eType; - }else if( eType>=2 && nDigit>0 ){ + }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){ return -1; }else{ return 0; } #else - return !sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8); + return !sqlite3Atoi64(z, pResult, length, enc); #endif /* SQLITE_OMIT_FLOATING_POINT */ } #if defined(_MSC_VER) #pragma warning(default : 4756) #endif -/* -** Digit pairs used to convert a U64 or I64 into text, two digits -** at a time. -*/ -static const union { - char a[201]; - short int forceAlignment; -} sqlite3DigitPairs = { - "00010203040506070809" - "10111213141516171819" - "20212223242526272829" - "30313233343536373839" - "40414243444546474849" - "50515253545556575859" - "60616263646566676869" - "70717273747576777879" - "80818283848586878889" - "90919293949596979899" -}; - - /* ** Render an signed 64-bit integer as text. Store the result in zOut[] and ** return the length of the string that was stored, in bytes. The value @@ -36928,35 +36598,23 @@ static const union { SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){ int i; u64 x; - union { - char a[23]; - u16 forceAlignment; - } u; - if( v>0 ){ - x = v; - }else if( v==0 ){ - zOut[0] = '0'; - zOut[1] = 0; - return 1; - }else{ + char zTemp[22]; + if( v<0 ){ x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v; + }else{ + x = v; } - i = sizeof(u.a)-1; - u.a[i] = 0; - while( x>=10 ){ - int kk = (x%100)*2; - assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) ); - assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) ); - *(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk]; - i -= 2; - x /= 100; - } - if( x ){ - u.a[--i] = x + '0'; - } - if( v<0 ) u.a[--i] = '-'; - memcpy(zOut, &u.a[i], sizeof(u.a)-i); - return sizeof(u.a)-1-i; + i = sizeof(zTemp)-2; + zTemp[sizeof(zTemp)-1] = 0; + while( 1 /*exit-by-break*/ ){ + zTemp[i] = (x%10) + '0'; + x = x/10; + if( x==0 ) break; + i--; + }; + if( v<0 ) zTemp[--i] = '-'; + memcpy(zOut, &zTemp[i], sizeof(zTemp)-i); + return sizeof(zTemp)-1-i; } /* @@ -37213,7 +36871,7 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ ** representation. ** ** If iRound<=0 then round to -iRound significant digits to the -** the right of the decimal point, or to a maximum of mxRound total +** 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. @@ -37226,14 +36884,13 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ ** The p->z[] array is *not* zero-terminated. */ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ - int i; /* Index into zBuf[] where to put next character */ - int n; /* Number of digits */ - u64 v; /* mantissa */ - int e, exp = 0; /* Base-2 and base-10 exponent */ - char *zBuf; /* Local alias for p->zBuf */ - char *z; /* Local alias for p->z */ + 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 @@ -37251,94 +36908,78 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou p->sign = '+'; } memcpy(&v,&r,8); - e = (v>>52)&0x7ff; - if( e==0x7ff ){ + e = v>>52; + if( (e&0x7ff)==0x7ff ){ p->isSpecial = 1 + (v!=0x7ff0000000000000LL); p->n = 0; p->iDP = 0; - p->z = p->zBuf; return; } - v &= 0x000fffffffffffffULL; - if( e==0 ){ - int nn = countLeadingZeros(v); - v <<= nn; - e = -1074 - nn; + + /* 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))); + */ + 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{ - v = (v<<11) | U64_BIT(63); - e -= 1086; + 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); + } } - sqlite3Fp2Convert10(v, e, (iRound<=0||iRound>=18)?18:iRound+1, &v, &exp); + v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; - /* Extract significant digits, start at the right-most slot in p->zBuf - ** and working back to the right. "i" keeps track of the next slot in - ** which to store a digit. */ + /* Extract significant digits. */ i = sizeof(p->zBuf)-1; - zBuf = p->zBuf; assert( v>0 ); - while( v>=10 ){ - int kk = (v%100)*2; - assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) ); - assert( TWO_BYTE_ALIGNMENT(&zBuf[i-1]) ); - *(u16*)(&zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk]; - i -= 2; - v /= 100; - } - if( v ){ - assert( v<10 ); - zBuf[i--] = v + '0'; - } + while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; } assert( i>=0 && i<sizeof(p->zBuf)-1 ); - n = sizeof(p->zBuf) - 1 - i; /* Total number of digits extracted */ - assert( n>0 ); - assert( n<sizeof(p->zBuf) ); - testcase( n==sizeof(p->zBuf)-1 ); - p->iDP = n + exp; + p->n = sizeof(p->zBuf) - 1 - i; + assert( p->n>0 ); + assert( p->n<sizeof(p->zBuf) ); + p->iDP = p->n + exp; if( iRound<=0 ){ iRound = p->iDP - iRound; - if( iRound==0 && zBuf[i+1]>='5' ){ + if( iRound==0 && p->zBuf[i+1]>='5' ){ iRound = 1; - zBuf[i--] = '0'; - n++; + p->zBuf[i--] = '0'; + p->n++; p->iDP++; } } - z = &zBuf[i+1]; /* z points to the first digit */ - if( iRound>0 && (iRound<n || n>mxRound) ){ + if( iRound>0 && (iRound<p->n || p->n>mxRound) ){ + char *z = &p->zBuf[i+1]; if( iRound>mxRound ) iRound = mxRound; - if( iRound==17 ){ - /* If the precision is exactly 17, which only happens with the "!" - ** flag (ex: "%!.17g") then try to reduce the precision if that - ** yields text that will round-trip to the original floating-point. - ** value. Thus, for exaple, 49.47 will render as 49.47, rather than - ** as 49.469999999999999. */ - if( z[15]=='9' && z[14]=='9' ){ - int jj, kk; - u64 v2; - for(jj=14; jj>0 && z[jj-1]=='9'; jj--){} - if( jj==0 ){ - v2 = 1; - }else{ - v2 = z[0] - '0'; - for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0'; - v2++; - } - if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){ - iRound = jj+1; - } - }else if( p->iDP>=n || (z[15]=='0' && z[14]=='0' && z[13]=='0') ){ - int jj, kk; - u64 v2; - assert( z[0]!='0' ); - for(jj=14; z[jj-1]=='0'; jj--){} - v2 = z[0] - '0'; - for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0'; - if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){ - iRound = jj+1; - } - } - } - n = iRound; + p->n = iRound; if( z[iRound]>='5' ){ int j = iRound-1; while( 1 /*exit-by-break*/ ){ @@ -37346,9 +36987,8 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou if( z[j]<='9' ) break; z[j] = '0'; if( j==0 ){ - z--; - z[0] = '1'; - n++; + p->z[i--] = '1'; + p->n++; p->iDP++; break; }else{ @@ -37357,13 +36997,13 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou } } } - assert( n>0 ); - while( z[n-1]=='0' ){ - n--; - assert( n>0 ); + p->z = &p->zBuf[i+1]; + assert( i+p->n < sizeof(p->zBuf) ); + assert( p->n>0 ); + while( p->z[p->n-1]=='0' ){ + p->n--; + assert( p->n>0 ); } - p->n = n; - p->z = z; } /* @@ -38602,7 +38242,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ ** Debugging logic */ -/* SQLITE_KV_TRACE() is used for tracing calls to kvrecord routines. */ +/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */ #if 0 #define SQLITE_KV_TRACE(X) printf X #else @@ -38616,6 +38256,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ #define SQLITE_KV_LOG(X) #endif + /* ** Forward declaration of objects used by this VFS implementation */ @@ -38623,11 +38264,6 @@ typedef struct KVVfsFile KVVfsFile; /* A single open file. There are only two files represented by this ** VFS - the database and the rollback journal. -** -** Maintenance reminder: if this struct changes in any way, the JSON -** rendering of its structure must be updated in -** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary -** compatibility concerns, so it does not need an iVersion member. */ struct KVVfsFile { sqlite3_file base; /* IO methods */ @@ -38677,7 +38313,7 @@ static int kvvfsCurrentTime(sqlite3_vfs*, double*); static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); static sqlite3_vfs sqlite3OsKvvfsObject = { - 2, /* iVersion */ + 1, /* iVersion */ sizeof(KVVfsFile), /* szOsFile */ 1024, /* mxPathname */ 0, /* pNext */ @@ -38753,37 +38389,23 @@ static sqlite3_io_methods kvvfs_jrnl_io_methods = { /* Forward declarations for the low-level storage engine */ -#ifndef SQLITE_WASM -/* In WASM builds these are implemented in JS. */ -static int kvrecordWrite(const char*, const char *zKey, const char *zData); -static int kvrecordDelete(const char*, const char *zKey); -static int kvrecordRead(const char*, const char *zKey, char *zBuf, int nBuf); -#endif -#ifndef KVRECORD_KEY_SZ -#define KVRECORD_KEY_SZ 32 -#endif +static int kvstorageWrite(const char*, const char *zKey, const char *zData); +static int kvstorageDelete(const char*, const char *zKey); +static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); +#define KVSTORAGE_KEY_SZ 32 /* Expand the key name with an appropriate prefix and put the result ** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least -** KVRECORD_KEY_SZ bytes. +** KVSTORAGE_KEY_SZ bytes. */ -static void kvrecordMakeKey( +static void kvstorageMakeKey( const char *zClass, const char *zKeyIn, char *zKeyOut ){ - assert( zKeyIn ); - assert( zKeyOut ); - assert( zClass ); - sqlite3_snprintf(KVRECORD_KEY_SZ, zKeyOut, "kvvfs-%s-%s", - zClass, zKeyIn); + sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn); } -#ifndef SQLITE_WASM -/* In WASM builds do not define APIs which use fopen(), fwrite(), -** and the like because those APIs are a portability issue for -** WASM. -*/ /* Write content into a key. zClass is the particular namespace of the ** underlying key/value store to use - either "local" or "session". ** @@ -38791,14 +38413,14 @@ static void kvrecordMakeKey( ** ** Return the number of errors. */ -static int kvrecordWrite( +static int kvstorageWrite( const char *zClass, const char *zKey, const char *zData ){ FILE *fd; - char zXKey[KVRECORD_KEY_SZ]; - kvrecordMakeKey(zClass, zKey, zXKey); + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); fd = fopen(zXKey, "wb"); if( fd ){ SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey, @@ -38816,9 +38438,9 @@ static int kvrecordWrite( ** namespace given by zClass. If the key does not previously exist, ** this routine is a no-op. */ -static int kvrecordDelete(const char *zClass, const char *zKey){ - char zXKey[KVRECORD_KEY_SZ]; - kvrecordMakeKey(zClass, zKey, zXKey); +static int kvstorageDelete(const char *zClass, const char *zKey){ + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); unlink(zXKey); SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey)); return 0; @@ -38839,7 +38461,7 @@ static int kvrecordDelete(const char *zClass, const char *zKey){ ** zero-terminates zBuf at zBuf[0] and returns the size of the data ** without reading it. */ -static int kvrecordRead( +static int kvstorageRead( const char *zClass, const char *zKey, char *zBuf, @@ -38847,8 +38469,8 @@ static int kvrecordRead( ){ FILE *fd; struct stat buf; - char zXKey[KVRECORD_KEY_SZ]; - kvrecordMakeKey(zClass, zKey, zXKey); + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); if( access(zXKey, R_OK)!=0 || stat(zXKey, &buf)!=0 || !S_ISREG(buf.st_mode) @@ -38880,8 +38502,6 @@ static int kvrecordRead( return (int)n; } } -#endif /* #ifndef SQLITE_WASM */ - /* ** An internal level of indirection which enables us to replace the @@ -38889,27 +38509,17 @@ static int kvrecordRead( ** Maintenance reminder: if this struct changes in any way, the JSON ** rendering of its structure must be updated in ** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary -** compatibility concerns, so it does not need an iVersion member. +** compatibility concerns, so it does not need an iVersion +** member. */ typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods; struct sqlite3_kvvfs_methods { - int (*xRcrdRead)(const char*, const char *zKey, char *zBuf, int nBuf); - int (*xRcrdWrite)(const char*, const char *zKey, const char *zData); - int (*xRcrdDelete)(const char*, const char *zKey); + int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf); + int (*xWrite)(const char *zClass, const char *zKey, const char *zData); + int (*xDelete)(const char *zClass, const char *zKey); const int nKeySize; - const int nBufferSize; -#ifndef SQLITE_WASM -# define MAYBE_CONST const -#else -# define MAYBE_CONST -#endif - MAYBE_CONST sqlite3_vfs * pVfs; - MAYBE_CONST sqlite3_io_methods *pIoDb; - MAYBE_CONST sqlite3_io_methods *pIoJrnl; -#undef MAYBE_CONST }; - /* ** This object holds the kvvfs I/O methods which may be swapped out ** for JavaScript-side implementations in WASM builds. In such builds @@ -38924,20 +38534,10 @@ struct sqlite3_kvvfs_methods { const #endif SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { -#ifndef SQLITE_WASM - .xRcrdRead = kvrecordRead, - .xRcrdWrite = kvrecordWrite, - .xRcrdDelete = kvrecordDelete, -#else - .xRcrdRead = 0, - .xRcrdWrite = 0, - .xRcrdDelete = 0, -#endif - .nKeySize = KVRECORD_KEY_SZ, - .nBufferSize = SQLITE_KVOS_SZ, - .pVfs = &sqlite3OsKvvfsObject, - .pIoDb = &kvvfs_db_io_methods, - .pIoJrnl = &kvvfs_jrnl_io_methods +kvstorageRead, +kvstorageWrite, +kvstorageDelete, +KVSTORAGE_KEY_SZ }; /****** Utility subroutines ************************************************/ @@ -38964,10 +38564,7 @@ SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { ** of hexadecimal and base-26 numbers, it is always clear where ** one stops and the next begins. */ -#ifndef SQLITE_WASM -static -#endif -int kvvfsEncode(const char *aData, int nData, char *aOut){ +static int kvvfsEncode(const char *aData, int nData, char *aOut){ int i, j; const unsigned char *a = (const unsigned char*)aData; for(i=j=0; i<nData; i++){ @@ -39018,13 +38615,9 @@ static const signed char kvvfsHexValue[256] = { ** Decode the text encoding back to binary. The binary content is ** written into pOut, which must be at least nOut bytes in length. ** -** The return value is the number of bytes actually written into aOut[], or -** -1 for malformed inputs. +** The return value is the number of bytes actually written into aOut[]. */ -#ifndef SQLITE_WASM -static -#endif -int kvvfsDecode(const char *a, char *aOut, int nOut){ +static int kvvfsDecode(const char *a, char *aOut, int nOut){ int i, j; int c; const unsigned char *aIn = (const unsigned char*)a; @@ -39049,7 +38642,7 @@ int kvvfsDecode(const char *a, char *aOut, int nOut){ }else{ aOut[j] = c<<4; c = kvvfsHexValue[aIn[++i]]; - if( c<0 ) return -1 /* hex bytes are always in pairs */; + if( c<0 ) break; aOut[j++] += c; i++; } @@ -39102,14 +38695,13 @@ static void kvvfsDecodeJournal( static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){ char zData[50]; zData[0] = 0; - sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "sz", zData, - sizeof(zData)-1); + sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1); return strtoll(zData, 0, 0); } static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){ char zData[50]; sqlite3_snprintf(sizeof(zData), zData, "%lld", sz); - return sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "sz", zData); + return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData); } /****** sqlite3_io_methods methods ******************************************/ @@ -39124,9 +38716,6 @@ static int kvvfsClose(sqlite3_file *pProtoFile){ pFile->isJournal ? "journal" : "db")); sqlite3_free(pFile->aJrnl); sqlite3_free(pFile->aData); -#ifdef SQLITE_WASM - memset(pFile, 0, sizeof(*pFile)); -#endif return SQLITE_OK; } @@ -39143,22 +38732,16 @@ static int kvvfsReadJrnl( assert( pFile->isJournal ); SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( pFile->aJrnl==0 ){ - int rc; - int szTxt = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl", - 0, 0); + int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0); char *aTxt; if( szTxt<=4 ){ return SQLITE_IOERR; } aTxt = sqlite3_malloc64( szTxt+1 ); if( aTxt==0 ) return SQLITE_NOMEM; - rc = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl", - aTxt, szTxt+1); - if( rc>=0 ){ - kvvfsDecodeJournal(pFile, aTxt, szTxt); - } + kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1); + kvvfsDecodeJournal(pFile, aTxt, szTxt); sqlite3_free(aTxt); - if( rc ) return rc; if( pFile->aJrnl==0 ) return SQLITE_IOERR; } if( iOfst+iAmt>pFile->nJrnl ){ @@ -39198,8 +38781,8 @@ static int kvvfsReadDb( pgno = 1; } sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - got = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, zKey, - aData, SQLITE_KVOS_SZ-1); + got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey, + aData, SQLITE_KVOS_SZ-1); if( got<0 ){ n = 0; }else{ @@ -39267,7 +38850,6 @@ static int kvvfsWriteDb( unsigned int pgno; char zKey[30]; char *aData = pFile->aData; - int rc; SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); assert( iAmt>=512 && iAmt<=65536 ); assert( (iAmt & (iAmt-1))==0 ); @@ -39276,13 +38858,13 @@ static int kvvfsWriteDb( pgno = 1 + iOfst/iAmt; sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); kvvfsEncode(zBuf, iAmt, aData); - rc = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, zKey, aData); - if( 0==rc ){ - if( iOfst+iAmt > pFile->szDb ){ - pFile->szDb = iOfst + iAmt; - } + if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){ + return SQLITE_IOERR; } - return rc; + if( iOfst+iAmt > pFile->szDb ){ + pFile->szDb = iOfst + iAmt; + } + return SQLITE_OK; } /* @@ -39292,7 +38874,7 @@ static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size)); assert( size==0 ); - sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, "jrnl"); + sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl"); sqlite3_free(pFile->aJrnl); pFile->aJrnl = 0; pFile->nJrnl = 0; @@ -39311,7 +38893,7 @@ static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){ pgnoMax = 2 + pFile->szDb/pFile->szPage; while( pgno<=pgnoMax ){ sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, zKey); + sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey); pgno++; } pFile->szDb = size; @@ -39343,7 +38925,7 @@ static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ }while( n>0 ); zOut[i++] = ' '; kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); - i = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "jrnl", zOut); + i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut); sqlite3_free(zOut); return i ? SQLITE_IOERR : SQLITE_OK; } @@ -39457,32 +39039,33 @@ static int kvvfsOpen( KVVfsFile *pFile = (KVVfsFile*)pProtoFile; if( zName==0 ) zName = ""; SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName)); - assert(!pFile->zClass); - assert(!pFile->aData); - assert(!pFile->aJrnl); - assert(!pFile->nJrnl); - assert(!pFile->base.pMethods); - pFile->szPage = -1; - pFile->szDb = -1; - if( 0==sqlite3_strglob("*-journal", zName) ){ + if( strcmp(zName, "local")==0 + || strcmp(zName, "session")==0 + ){ + pFile->isJournal = 0; + pFile->base.pMethods = &kvvfs_db_io_methods; + }else + if( strcmp(zName, "local-journal")==0 + || strcmp(zName, "session-journal")==0 + ){ pFile->isJournal = 1; pFile->base.pMethods = &kvvfs_jrnl_io_methods; - if( 0==strcmp("session-journal",zName) ){ - pFile->zClass = "session"; - }else if( 0==strcmp("local-journal",zName) ){ - pFile->zClass = "local"; - } }else{ - pFile->isJournal = 0; - pFile->base.pMethods = &kvvfs_db_io_methods; + return SQLITE_CANTOPEN; } - if( !pFile->zClass ){ - pFile->zClass = zName; + if( zName[0]=='s' ){ + pFile->zClass = "session"; + }else{ + pFile->zClass = "local"; } pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ); if( pFile->aData==0 ){ return SQLITE_NOMEM; } + pFile->aJrnl = 0; + pFile->nJrnl = 0; + pFile->szPage = -1; + pFile->szDb = -1; return SQLITE_OK; } @@ -39492,17 +39075,13 @@ static int kvvfsOpen( ** returning. */ static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - int rc /* The JS impl can fail with OOM in argument conversion */; if( strcmp(zPath, "local-journal")==0 ){ - rc = sqlite3KvvfsMethods.xRcrdDelete("local", "jrnl"); + sqlite3KvvfsMethods.xDelete("local", "jrnl"); }else if( strcmp(zPath, "session-journal")==0 ){ - rc = sqlite3KvvfsMethods.xRcrdDelete("session", "jrnl"); + sqlite3KvvfsMethods.xDelete("session", "jrnl"); } - else{ - rc = 0; - } - return rc; + return SQLITE_OK; } /* @@ -39516,42 +39095,21 @@ static int kvvfsAccess( int *pResOut ){ SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath)); -#if 0 && defined(SQLITE_WASM) - /* - ** This is not having the desired effect in the JS bindings. - ** It's ostensibly the same logic as the #else block, but - ** it's not behaving that way. - ** - ** In JS we map all zPaths to Storage objects, and -journal files - ** are mapped to the storage for the main db (which is is exactly - ** what the mapping of "local-journal" -> "local" is doing). - */ - const char *zKey = (0==sqlite3_strglob("*-journal", zPath)) - ? "jrnl" : "sz"; - *pResOut = - sqlite3KvvfsMethods.xRcrdRead(zPath, zKey, 0, 0)>0; -#else if( strcmp(zPath, "local-journal")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("local", "jrnl", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0; }else if( strcmp(zPath, "session-journal")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("session", "jrnl", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0; }else if( strcmp(zPath, "local")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("local", "sz", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0; }else if( strcmp(zPath, "session")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("session", "sz", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0; }else { *pResOut = 0; } - /*all current JS tests avoid triggering: assert( *pResOut == 0 ); */ -#endif SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut)); return SQLITE_OK; } @@ -44835,7 +44393,7 @@ static int unixShmMap( } /* Map the requested memory region into this processes address space. */ - apNew = (char **)sqlite3_realloc64( + apNew = (char **)sqlite3_realloc( pShmNode->apRegion, nReqRegion*sizeof(char *) ); if( !apNew ){ @@ -48280,7 +47838,7 @@ SQLITE_API int sqlite3_os_end(void){ ** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions ** based on the sub-platform)? */ -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_ANSI) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI) # define SQLITE_WIN32_HAS_ANSI #endif @@ -48288,7 +47846,7 @@ SQLITE_API int sqlite3_os_end(void){ ** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions ** based on the sub-platform)? */ -#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT) && \ +#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \ !defined(SQLITE_WIN32_NO_WIDE) # define SQLITE_WIN32_HAS_WIDE #endif @@ -48427,7 +47985,16 @@ SQLITE_API int sqlite3_os_end(void){ */ #if SQLITE_WIN32_FILEMAPPING_API && \ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +/* +** Two of the file mapping APIs are different under WinRT. Figure out which +** set we need. +*/ +#if SQLITE_OS_WINRT +WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \ + LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR); +WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T); +#else #if defined(SQLITE_WIN32_HAS_ANSI) WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \ DWORD, DWORD, DWORD, LPCSTR); @@ -48439,6 +48006,7 @@ WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \ #endif /* defined(SQLITE_WIN32_HAS_WIDE) */ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); +#endif /* SQLITE_OS_WINRT */ /* ** These file mapping APIs are common to both Win32 and WinRT. @@ -48729,7 +48297,7 @@ static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; ** This function is not available on Windows CE or WinRT. */ -#if SQLITE_OS_WINCE +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT # define osAreFileApisANSI() 1 #endif @@ -48744,7 +48312,7 @@ static struct win_syscall { sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ sqlite3_syscall_ptr pDefault; /* Default value */ } aSyscall[] = { -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 }, #else { "AreFileApisANSI", (SYSCALL)0, 0 }, @@ -48783,7 +48351,7 @@ static struct win_syscall { #define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateFileW", (SYSCALL)CreateFileW, 0 }, #else { "CreateFileW", (SYSCALL)0, 0 }, @@ -48792,7 +48360,7 @@ static struct win_syscall { #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) -#if defined(SQLITE_WIN32_HAS_ANSI) && \ +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ SQLITE_WIN32_CREATEFILEMAPPINGA { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, @@ -48803,8 +48371,8 @@ static struct win_syscall { #define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) -#if (SQLITE_OS_WINCE || defined(SQLITE_WIN32_HAS_WIDE)) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, @@ -48813,7 +48381,7 @@ static struct win_syscall { #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateMutexW", (SYSCALL)CreateMutexW, 0 }, #else { "CreateMutexW", (SYSCALL)0, 0 }, @@ -48899,7 +48467,7 @@ static struct win_syscall { #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \ LPDWORD))aSyscall[18].pCurrent) -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 }, #else { "GetDiskFreeSpaceW", (SYSCALL)0, 0 }, @@ -48916,7 +48484,7 @@ static struct win_syscall { #define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 }, #else { "GetFileAttributesW", (SYSCALL)0, 0 }, @@ -48933,7 +48501,11 @@ static struct win_syscall { #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \ LPVOID))aSyscall[22].pCurrent) +#if !SQLITE_OS_WINRT { "GetFileSize", (SYSCALL)GetFileSize, 0 }, +#else + { "GetFileSize", (SYSCALL)0, 0 }, +#endif #define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent) @@ -48946,7 +48518,7 @@ static struct win_syscall { #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \ LPSTR*))aSyscall[24].pCurrent) -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 }, #else { "GetFullPathNameW", (SYSCALL)0, 0 }, @@ -48981,10 +48553,16 @@ static struct win_syscall { #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \ LPCSTR))aSyscall[27].pCurrent) +#if !SQLITE_OS_WINRT { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 }, +#else + { "GetSystemInfo", (SYSCALL)0, 0 }, +#endif + #define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent) { "GetSystemTime", (SYSCALL)GetSystemTime, 0 }, + #define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent) #if !SQLITE_OS_WINCE @@ -49004,7 +48582,7 @@ static struct win_syscall { #define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetTempPathW", (SYSCALL)GetTempPathW, 0 }, #else { "GetTempPathW", (SYSCALL)0, 0 }, @@ -49012,7 +48590,11 @@ static struct win_syscall { #define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent) +#if !SQLITE_OS_WINRT { "GetTickCount", (SYSCALL)GetTickCount, 0 }, +#else + { "GetTickCount", (SYSCALL)0, 0 }, +#endif #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) @@ -49025,7 +48607,7 @@ static struct win_syscall { #define osGetVersionExA ((BOOL(WINAPI*)( \ LPOSVERSIONINFOA))aSyscall[34].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) && \ +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ SQLITE_WIN32_GETVERSIONEX { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, #else @@ -49040,12 +48622,20 @@ static struct win_syscall { #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \ SIZE_T))aSyscall[36].pCurrent) +#if !SQLITE_OS_WINRT { "HeapCreate", (SYSCALL)HeapCreate, 0 }, +#else + { "HeapCreate", (SYSCALL)0, 0 }, +#endif #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \ SIZE_T))aSyscall[37].pCurrent) +#if !SQLITE_OS_WINRT { "HeapDestroy", (SYSCALL)HeapDestroy, 0 }, +#else + { "HeapDestroy", (SYSCALL)0, 0 }, +#endif #define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent) @@ -49063,12 +48653,16 @@ static struct win_syscall { #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \ LPCVOID))aSyscall[41].pCurrent) +#if !SQLITE_OS_WINRT { "HeapValidate", (SYSCALL)HeapValidate, 0 }, +#else + { "HeapValidate", (SYSCALL)0, 0 }, +#endif #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \ LPCVOID))aSyscall[42].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "HeapCompact", (SYSCALL)HeapCompact, 0 }, #else { "HeapCompact", (SYSCALL)0, 0 }, @@ -49084,7 +48678,7 @@ static struct win_syscall { #define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) && \ +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ !defined(SQLITE_OMIT_LOAD_EXTENSION) { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 }, #else @@ -49093,11 +48687,15 @@ static struct win_syscall { #define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent) +#if !SQLITE_OS_WINRT { "LocalFree", (SYSCALL)LocalFree, 0 }, +#else + { "LocalFree", (SYSCALL)0, 0 }, +#endif #define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "LockFile", (SYSCALL)LockFile, 0 }, #else { "LockFile", (SYSCALL)0, 0 }, @@ -49119,7 +48717,8 @@ static struct win_syscall { LPOVERLAPPED))aSyscall[48].pCurrent) #endif -#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, #else { "MapViewOfFile", (SYSCALL)0, 0 }, @@ -49147,12 +48746,20 @@ static struct win_syscall { #define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent) +#if !SQLITE_OS_WINRT { "SetFilePointer", (SYSCALL)SetFilePointer, 0 }, +#else + { "SetFilePointer", (SYSCALL)0, 0 }, +#endif #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \ DWORD))aSyscall[54].pCurrent) +#if !SQLITE_OS_WINRT { "Sleep", (SYSCALL)Sleep, 0 }, +#else + { "Sleep", (SYSCALL)0, 0 }, +#endif #define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent) @@ -49161,7 +48768,7 @@ static struct win_syscall { #define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \ LPFILETIME))aSyscall[56].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "UnlockFile", (SYSCALL)UnlockFile, 0 }, #else { "UnlockFile", (SYSCALL)0, 0 }, @@ -49199,6 +48806,15 @@ static struct win_syscall { #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ LPOVERLAPPED))aSyscall[61].pCurrent) +#if SQLITE_OS_WINRT + { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, +#else + { "CreateEventExW", (SYSCALL)0, 0 }, +#endif + +#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ + DWORD,DWORD))aSyscall[62].pCurrent) + /* ** For WaitForSingleObject(), MSDN says: ** @@ -49208,7 +48824,7 @@ static struct win_syscall { { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ - DWORD))aSyscall[62].pCurrent) + DWORD))aSyscall[63].pCurrent) #if !SQLITE_OS_WINCE { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, @@ -49217,12 +48833,69 @@ static struct win_syscall { #endif #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ - BOOL))aSyscall[63].pCurrent) + BOOL))aSyscall[64].pCurrent) + +#if SQLITE_OS_WINRT + { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, +#else + { "SetFilePointerEx", (SYSCALL)0, 0 }, +#endif + +#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ + PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent) +#if SQLITE_OS_WINRT + { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, +#else + { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, +#endif + +#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ + FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) + +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, +#else + { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, +#endif + +#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ + SIZE_T))aSyscall[67].pCurrent) + +#if SQLITE_OS_WINRT + { "CreateFile2", (SYSCALL)CreateFile2, 0 }, +#else + { "CreateFile2", (SYSCALL)0, 0 }, +#endif + +#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ + LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent) + +#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION) + { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 }, +#else + { "LoadPackagedLibrary", (SYSCALL)0, 0 }, +#endif + +#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \ + DWORD))aSyscall[69].pCurrent) + +#if SQLITE_OS_WINRT + { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, +#else + { "GetTickCount64", (SYSCALL)0, 0 }, +#endif + +#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent) + +#if SQLITE_OS_WINRT { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, +#else + { "GetNativeSystemInfo", (SYSCALL)0, 0 }, +#endif #define osGetNativeSystemInfo ((VOID(WINAPI*)( \ - LPSYSTEM_INFO))aSyscall[64].pCurrent) + LPSYSTEM_INFO))aSyscall[71].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, @@ -49230,7 +48903,7 @@ static struct win_syscall { { "OutputDebugStringA", (SYSCALL)0, 0 }, #endif -#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[65].pCurrent) +#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, @@ -49238,11 +48911,20 @@ static struct win_syscall { { "OutputDebugStringW", (SYSCALL)0, 0 }, #endif -#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[66].pCurrent) +#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, -#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[67].pCurrent) +#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) + +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, +#else + { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ + LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent) /* ** NOTE: On some sub-platforms, the InterlockedCompareExchange "function" @@ -49257,25 +48939,25 @@ static struct win_syscall { { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ - SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[68].pCurrent) + SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) #endif /* defined(InterlockedCompareExchange) */ -#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID { "UuidCreate", (SYSCALL)UuidCreate, 0 }, #else { "UuidCreate", (SYSCALL)0, 0 }, #endif -#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[69].pCurrent) +#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) -#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, #else { "UuidCreateSequential", (SYSCALL)0, 0 }, #endif #define osUuidCreateSequential \ - ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[70].pCurrent) + ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) #if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, @@ -49284,7 +48966,7 @@ static struct win_syscall { #endif #define osFlushViewOfFile \ - ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[71].pCurrent) + ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) /* ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent() @@ -49301,7 +48983,7 @@ static struct win_syscall { #define osCreateEvent ( \ (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \ - aSyscall[72].pCurrent \ + aSyscall[80].pCurrent \ ) /* @@ -49318,7 +49000,7 @@ static struct win_syscall { { "CancelIo", (SYSCALL)0, 0 }, #endif -#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[73].pCurrent) +#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32) { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 }, @@ -49326,7 +49008,7 @@ static struct win_syscall { { "GetModuleHandleW", (SYSCALL)0, 0 }, #endif -#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[74].pCurrent) +#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent) #ifndef _WIN32 { "getenv", (SYSCALL)getenv, 0 }, @@ -49334,7 +49016,7 @@ static struct win_syscall { { "getenv", (SYSCALL)0, 0 }, #endif -#define osGetenv ((const char *(*)(const char *))aSyscall[75].pCurrent) +#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent) #ifndef _WIN32 { "getcwd", (SYSCALL)getcwd, 0 }, @@ -49342,7 +49024,7 @@ static struct win_syscall { { "getcwd", (SYSCALL)0, 0 }, #endif -#define osGetcwd ((char*(*)(char*,size_t))aSyscall[76].pCurrent) +#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent) #ifndef _WIN32 { "readlink", (SYSCALL)readlink, 0 }, @@ -49350,7 +49032,7 @@ static struct win_syscall { { "readlink", (SYSCALL)0, 0 }, #endif -#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[77].pCurrent) +#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent) #ifndef _WIN32 { "lstat", (SYSCALL)lstat, 0 }, @@ -49358,7 +49040,7 @@ static struct win_syscall { { "lstat", (SYSCALL)0, 0 }, #endif -#define osLstat ((int(*)(const char*,struct stat*))aSyscall[78].pCurrent) +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent) #ifndef _WIN32 { "__errno", (SYSCALL)__errno, 0 }, @@ -49366,7 +49048,7 @@ static struct win_syscall { { "__errno", (SYSCALL)0, 0 }, #endif -#define osErrno (*((int*(*)(void))aSyscall[79].pCurrent)()) +#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)()) #ifndef _WIN32 { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 }, @@ -49375,7 +49057,7 @@ static struct win_syscall { #endif #define osCygwin_conv_path ((size_t(*)(unsigned int, \ - const void *, void *, size_t))aSyscall[80].pCurrent) + const void *, void *, size_t))aSyscall[88].pCurrent) }; /* End of the overrideable system calls */ @@ -49479,10 +49161,10 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){ DWORD lastErrno = osGetLastError(); if( lastErrno==NO_ERROR ){ @@ -49595,11 +49277,28 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ } #endif /* _WIN32 */ +/* +** The following routine suspends the current thread for at least ms +** milliseconds. This is equivalent to the Win32 Sleep() interface. +*/ +#if SQLITE_OS_WINRT +static HANDLE sleepObj = NULL; +#endif + SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ +#if SQLITE_OS_WINRT + if ( sleepObj==NULL ){ + sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, + SYNCHRONIZE); + } + assert( sleepObj!=NULL ); + osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE); +#else osSleep(milliseconds); +#endif } -#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && \ +#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ SQLITE_THREADSAFE>0 SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ DWORD rc; @@ -49623,7 +49322,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ #if !SQLITE_WIN32_GETVERSIONEX # define osIsNT() (1) -#elif SQLITE_OS_WINCE || !defined(SQLITE_WIN32_HAS_ANSI) +#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) # define osIsNT() (1) #elif !defined(SQLITE_WIN32_HAS_WIDE) # define osIsNT() (0) @@ -49636,7 +49335,13 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ ** based on the NT kernel. */ SQLITE_API int sqlite3_win32_is_nt(void){ -#if SQLITE_WIN32_GETVERSIONEX +#if SQLITE_OS_WINRT + /* + ** NOTE: The WinRT sub-platform is always assumed to be based on the NT + ** kernel. + */ + return 1; +#elif SQLITE_WIN32_GETVERSIONEX if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ #if defined(SQLITE_WIN32_HAS_ANSI) OSVERSIONINFOA sInfo; @@ -49678,7 +49383,7 @@ static void *winMemMalloc(int nBytes){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif assert( nBytes>=0 ); @@ -49700,7 +49405,7 @@ static void winMemFree(void *pPrior){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ @@ -49721,7 +49426,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif assert( nBytes>=0 ); @@ -49749,7 +49454,7 @@ static int winMemSize(void *p){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) ); #endif if( !p ) return 0; @@ -49779,7 +49484,7 @@ static int winMemInit(void *pAppData){ assert( pWinMemData->magic1==WINMEM_MAGIC1 ); assert( pWinMemData->magic2==WINMEM_MAGIC2 ); -#if SQLITE_WIN32_HEAP_CREATE +#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE if( !pWinMemData->hHeap ){ DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE; DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap; @@ -49812,7 +49517,7 @@ static int winMemInit(void *pAppData){ #endif assert( pWinMemData->hHeap!=0 ); assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif return SQLITE_OK; @@ -49830,7 +49535,7 @@ static void winMemShutdown(void *pAppData){ if( pWinMemData->hHeap ){ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif if( pWinMemData->bOwned ){ @@ -50211,6 +49916,17 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ char *zOut = 0; if( osIsNT() ){ +#if SQLITE_OS_WINRT + WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1]; + dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + lastErrno, + 0, + zTempWide, + SQLITE_WIN32_MAX_ERRMSG_CHARS, + 0); +#else LPWSTR zTempWide = NULL; dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -50221,13 +49937,16 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ (LPWSTR) &zTempWide, 0, 0); +#endif if( dwLen > 0 ){ /* allocate a buffer and convert to UTF8 */ sqlite3BeginBenignMalloc(); zOut = winUnicodeToUtf8(zTempWide); sqlite3EndBenignMalloc(); +#if !SQLITE_OS_WINRT /* free the system buffer allocated by FormatMessage */ osLocalFree(zTempWide); +#endif } } #ifdef SQLITE_WIN32_HAS_ANSI @@ -50888,6 +50607,7 @@ static int winHandleUnlock(HANDLE h, int iOff, int nByte){ static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){ int rc = SQLITE_OK; /* Return value */ +#if !SQLITE_OS_WINRT LONG upperBits; /* Most sig. 32 bits of new offset */ LONG lowerBits; /* Least sig. 32 bits of new offset */ DWORD dwRet; /* Value returned by SetFilePointer() */ @@ -50909,7 +50629,20 @@ static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){ rc = SQLITE_IOERR_SEEK; } } - OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset,sqlite3ErrName(rc))); +#else + /* This implementation works for WinRT. */ + LARGE_INTEGER x; /* The new offset */ + BOOL bRet; /* Value returned by SetFilePointerEx() */ + + x.QuadPart = iOffset; + bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN); + + if(!bRet){ + rc = SQLITE_IOERR_SEEK; + } +#endif + + OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc))); return rc; } @@ -51210,6 +50943,17 @@ static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){ */ static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){ int rc = SQLITE_OK; + +#if SQLITE_OS_WINRT + FILE_STANDARD_INFO info; + BOOL b; + b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info)); + if( b ){ + *pnByte = info.EndOfFile.QuadPart; + }else{ + rc = SQLITE_IOERR_FSTAT; + } +#else DWORD upperBits = 0; DWORD lowerBits = 0; @@ -51219,6 +50963,8 @@ static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){ if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){ rc = SQLITE_IOERR_FSTAT; } +#endif + return rc; } @@ -51417,6 +51163,20 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ assert( pSize!=0 ); SimulateIOError(return SQLITE_IOERR_FSTAT); OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize)); + +#if SQLITE_OS_WINRT + { + FILE_STANDARD_INFO info; + if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo, + &info, sizeof(info)) ){ + *pSize = info.EndOfFile.QuadPart; + }else{ + pFile->lastErrno = osGetLastError(); + rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, + "winFileSize", pFile->zPath); + } + } +#else { DWORD upperBits; DWORD lowerBits; @@ -51431,6 +51191,7 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ "winFileSize", pFile->zPath); } } +#endif OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n", pFile->h, pSize, *pSize, sqlite3ErrName(rc))); return rc; @@ -52392,6 +52153,20 @@ static int winHandleOpen( ** TODO: retry-on-ioerr. */ if( osIsNT() ){ +#if SQLITE_OS_WINRT + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; + memset(&extendedParameters, 0, sizeof(extendedParameters)); + extendedParameters.dwSize = sizeof(extendedParameters); + extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + extendedParameters.dwFileFlags = flag_overlapped; + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; + h = osCreateFile2((LPCWSTR)zConverted, + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ + OPEN_ALWAYS, /* dwCreationDisposition */ + &extendedParameters + ); +#else h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ @@ -52400,6 +52175,7 @@ static int winHandleOpen( FILE_ATTRIBUTE_NORMAL|flag_overlapped, NULL ); +#endif }else{ /* Due to pre-processor directives earlier in this file, ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */ @@ -52867,7 +52643,9 @@ static int winShmMap( HANDLE hMap = NULL; /* file-mapping handle */ void *pMap = 0; /* Mapped memory region */ -#if defined(SQLITE_WIN32_HAS_WIDE) +#if SQLITE_OS_WINRT + hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL); +#elif defined(SQLITE_WIN32_HAS_WIDE) hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL); #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL); @@ -52879,9 +52657,15 @@ static int winShmMap( if( hMap ){ int iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; +#if SQLITE_OS_WINRT + pMap = osMapViewOfFileFromApp(hMap, flags, + iOffset - iOffsetShift, szRegion + iOffsetShift + ); +#else pMap = osMapViewOfFile(hMap, flags, 0, iOffset - iOffsetShift, szRegion + iOffsetShift ); +#endif OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", osGetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion, pMap ? "ok" : "failed")); @@ -53014,7 +52798,9 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ flags |= FILE_MAP_WRITE; } #endif -#if defined(SQLITE_WIN32_HAS_WIDE) +#if SQLITE_OS_WINRT + pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); +#elif defined(SQLITE_WIN32_HAS_WIDE) pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, (DWORD)((nMap>>32) & 0xffffffff), (DWORD)(nMap & 0xffffffff), NULL); @@ -53034,7 +52820,11 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ } assert( (nMap % winSysInfo.dwPageSize)==0 ); assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff ); +#if SQLITE_OS_WINRT + pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap); +#else pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap); +#endif if( pNew==NULL ){ osCloseHandle(pFd->hMap); pFd->hMap = NULL; @@ -53369,6 +53159,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ } #endif +#if !SQLITE_OS_WINRT && defined(_WIN32) else if( osIsNT() ){ char *zMulti; LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) ); @@ -53422,6 +53213,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ } } #endif /* SQLITE_WIN32_HAS_ANSI */ +#endif /* !SQLITE_OS_WINRT */ /* ** Check to make sure the temporary directory ends with an appropriate @@ -53596,6 +53388,13 @@ static int winOpen( memset(pFile, 0, sizeof(winFile)); pFile->h = INVALID_HANDLE_VALUE; +#if SQLITE_OS_WINRT + if( !zUtf8Name && !sqlite3_temp_directory ){ + sqlite3_log(SQLITE_ERROR, + "sqlite3_temp_directory variable should be set for WinRT"); + } +#endif + /* If the second argument to this function is NULL, generate a ** temporary file name to use */ @@ -53678,6 +53477,31 @@ static int winOpen( #endif if( osIsNT() ){ +#if SQLITE_OS_WINRT + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; + extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + extendedParameters.dwFileAttributes = + dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; + extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extendedParameters.lpSecurityAttributes = NULL; + extendedParameters.hTemplateFile = NULL; + do{ + h = osCreateFile2((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + &extendedParameters); + if( h!=INVALID_HANDLE_VALUE ) break; + if( isReadWrite ){ + int rc2; + sqlite3BeginBenignMalloc(); + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); + sqlite3EndBenignMalloc(); + if( rc2==SQLITE_OK && isRO ) break; + } + }while( winRetryIoerr(&cnt, &lastErrno) ); +#else do{ h = osCreateFileW((LPCWSTR)zConverted, dwDesiredAccess, @@ -53694,6 +53518,7 @@ static int winOpen( if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); +#endif } #ifdef SQLITE_WIN32_HAS_ANSI else{ @@ -53830,7 +53655,25 @@ static int winDelete( } if( osIsNT() ){ do { +#if SQLITE_OS_WINRT + WIN32_FILE_ATTRIBUTE_DATA sAttrData; + memset(&sAttrData, 0, sizeof(sAttrData)); + if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, + &sAttrData) ){ + attr = sAttrData.dwFileAttributes; + }else{ + lastErrno = osGetLastError(); + if( lastErrno==ERROR_FILE_NOT_FOUND + || lastErrno==ERROR_PATH_NOT_FOUND ){ + rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ + }else{ + rc = SQLITE_ERROR; + } + break; + } +#else attr = osGetFileAttributesW(zConverted); +#endif if ( attr==INVALID_FILE_ATTRIBUTES ){ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND @@ -53953,7 +53796,6 @@ static int winAccess( attr = sAttrData.dwFileAttributes; } }else{ - if( noRetry ) lastErrno = osGetLastError(); winLogIoerr(cnt, __LINE__); if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ sqlite3_free(zConverted); @@ -54122,7 +53964,7 @@ static int winFullPathnameNoMutex( int nFull, /* Size of output buffer in bytes */ char *zFull /* Output buffer */ ){ -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT int nByte; void *zConverted; char *zOut; @@ -54211,7 +54053,7 @@ static int winFullPathnameNoMutex( } #endif /* __CYGWIN__ */ -#if SQLITE_OS_WINCE && defined(_WIN32) +#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32) SimulateIOError( return SQLITE_ERROR ); /* WinCE has no concept of a relative pathname, or so I am told. */ /* WinRT has no way to convert a relative path to an absolute one. */ @@ -54230,7 +54072,7 @@ static int winFullPathnameNoMutex( return SQLITE_OK; #endif -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT #if defined(_WIN32) /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -54362,7 +54204,11 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ return 0; } if( osIsNT() ){ +#if SQLITE_OS_WINRT + h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); +#else h = osLoadLibraryW((LPCWSTR)zConverted); +#endif } #ifdef SQLITE_WIN32_HAS_ANSI else{ @@ -54444,16 +54290,23 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ DWORD pid = osGetCurrentProcessId(); xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD)); } +#if SQLITE_OS_WINRT + { + ULONGLONG cnt = osGetTickCount64(); + xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG)); + } +#else { DWORD cnt = osGetTickCount(); xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD)); } +#endif /* SQLITE_OS_WINRT */ { LARGE_INTEGER i; osQueryPerformanceCounter(&i); xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER)); } -#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID { UUID id; memset(&id, 0, sizeof(UUID)); @@ -54463,7 +54316,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ osUuidCreateSequential(&id); xorMemory(&e, (unsigned char*)&id, sizeof(UUID)); } -#endif /* !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID */ +#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */ return e.nXor>nBuf ? nBuf : e.nXor; #endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */ } @@ -54694,16 +54547,15 @@ SQLITE_API int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==81 ); - assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 ); - assert( strcmp(aSyscall[20].zName,"GetFileAttributesA")==0 ); - assert( strcmp(aSyscall[40].zName,"HeapReAlloc")==0 ); - assert( strcmp(aSyscall[60].zName,"WideCharToMultiByte")==0 ); - assert( strcmp(aSyscall[80].zName,"cygwin_conv_path")==0 ); + assert( ArraySize(aSyscall)==89 ); /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); +#if SQLITE_OS_WINRT + osGetNativeSystemInfo(&winSysInfo); +#else osGetSystemInfo(&winSysInfo); +#endif assert( winSysInfo.dwAllocationGranularity>0 ); assert( winSysInfo.dwPageSize>0 ); @@ -54727,9 +54579,17 @@ SQLITE_API int sqlite3_os_init(void){ } SQLITE_API int sqlite3_os_end(void){ +#if SQLITE_OS_WINRT + if( sleepObj!=NULL ){ + osCloseHandle(sleepObj); + sleepObj = NULL; + } +#endif + #ifndef SQLITE_OMIT_WAL winBigLock = 0; #endif + return SQLITE_OK; } @@ -59878,8 +59738,6 @@ SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); if( iRead ) return 0; /* Case (4) */ } -#else - UNUSED_PARAMETER(pgno); #endif assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 ); if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd) @@ -60300,17 +60158,17 @@ static int jrnlBufferSize(Pager *pPager){ */ #ifdef SQLITE_CHECK_PAGES /* -** Return a 64-bit hash of the page data for pPage. +** Return a 32-bit hash of the page data for pPage. */ -static u64 pager_datahash(int nByte, unsigned char *pData){ - u64 hash = 0; +static u32 pager_datahash(int nByte, unsigned char *pData){ + u32 hash = 0; int i; for(i=0; i<nByte; i++){ hash = (hash*1039) + pData[i]; } return hash; } -static u64 pager_pagehash(PgHdr *pPage){ +static u32 pager_pagehash(PgHdr *pPage){ return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData); } static void pager_set_pagehash(PgHdr *pPage){ @@ -63259,8 +63117,6 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); pPager->pWal = 0; } -#else - UNUSED_PARAMETER(db); #endif pager_reset(pPager); if( MEMDB ){ @@ -69156,83 +69012,69 @@ static int walCheckpoint( && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK ){ u32 nBackfill = pInfo->nBackfill; - WalIndexHdr *pLive = (WalIndexHdr*)walIndexHdr(pWal); - - /* Now that read-lock slot 0 is locked, check that the wal has not been - ** wrapped since the header was read for this checkpoint. If it was, then - ** there was no work to do anyway. In this case the - ** (pInfo->nBackfill<pWal->hdr.mxFrame) test above only passed because - ** pInfo->nBackfill had already been set to 0 by the writer that wrapped - ** the wal file. It would also be dangerous to proceed, as there may be - ** fewer than pWal->hdr.mxFrame valid frames in the wal file. */ - int bChg = memcmp(pLive->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)); - if( 0==bChg ){ - pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; - - /* Sync the WAL to disk */ - rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); - - /* If the database may grow as a result of this checkpoint, hint - ** about the eventual size of the db file to the VFS layer. - */ - if( rc==SQLITE_OK ){ - i64 nReq = ((i64)mxPage * szPage); - i64 nSize; /* Current size of database file */ - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0); - rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); - if( rc==SQLITE_OK && nSize<nReq ){ - if( (nSize+65536+(i64)pWal->hdr.mxFrame*szPage)<nReq ){ - /* If the size of the final database is larger than the current - ** database plus the amount of data in the wal file, plus the - ** maximum size of the pending-byte page (65536 bytes), then - ** must be corruption somewhere. */ - rc = SQLITE_CORRUPT_BKPT; - }else{ - sqlite3OsFileControlHint( - pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); - } - } + pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; - } + /* Sync the WAL to disk */ + rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); - /* Iterate through the contents of the WAL, copying data to the - ** db file */ - while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ - i64 iOffset; - assert( walFramePgno(pWal, iFrame)==iDbpage ); - SEH_INJECT_FAULT; - if( AtomicLoad(&db->u1.isInterrupted) ){ - rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; - break; - } - if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ - continue; + /* If the database may grow as a result of this checkpoint, hint + ** about the eventual size of the db file to the VFS layer. + */ + if( rc==SQLITE_OK ){ + i64 nReq = ((i64)mxPage * szPage); + i64 nSize; /* Current size of database file */ + sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0); + rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); + if( rc==SQLITE_OK && nSize<nReq ){ + if( (nSize+65536+(i64)pWal->hdr.mxFrame*szPage)<nReq ){ + /* If the size of the final database is larger than the current + ** database plus the amount of data in the wal file, plus the + ** maximum size of the pending-byte page (65536 bytes), then + ** must be corruption somewhere. */ + rc = SQLITE_CORRUPT_BKPT; + }else{ + sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq); } - iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; - /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ - rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - iOffset = (iDbpage-1)*(i64)szPage; - testcase( IS_BIG_INT(iOffset) ); - rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; } - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0); - /* If work was actually accomplished... */ - if( rc==SQLITE_OK ){ - if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ - i64 szDb = pWal->hdr.nPage*(i64)szPage; - testcase( IS_BIG_INT(szDb) ); - rc = sqlite3OsTruncate(pWal->pDbFd, szDb); - if( rc==SQLITE_OK ){ - rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); - } - } + } + + /* Iterate through the contents of the WAL, copying data to the db file */ + while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ + i64 iOffset; + assert( walFramePgno(pWal, iFrame)==iDbpage ); + SEH_INJECT_FAULT; + if( AtomicLoad(&db->u1.isInterrupted) ){ + rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; + break; + } + if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ + continue; + } + iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; + /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ + rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + iOffset = (iDbpage-1)*(i64)szPage; + testcase( IS_BIG_INT(iOffset) ); + rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + } + sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0); + + /* If work was actually accomplished... */ + if( rc==SQLITE_OK ){ + if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ + i64 szDb = pWal->hdr.nPage*(i64)szPage; + testcase( IS_BIG_INT(szDb) ); + rc = sqlite3OsTruncate(pWal->pDbFd, szDb); if( rc==SQLITE_OK ){ - AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; + rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); } } + if( rc==SQLITE_OK ){ + AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; + } } /* Release the reader lock held while backfilling */ @@ -71281,7 +71123,6 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( /* Copy data from the log to the database file. */ if( rc==SQLITE_OK ){ - sqlite3FaultSim(660); if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){ @@ -76270,30 +76111,6 @@ static SQLITE_NOINLINE int btreeBeginTrans( } #endif -#ifdef SQLITE_EXPERIMENTAL_PRAGMA_20251114 - /* If both a read and write transaction will be opened by this call, - ** then issue a file-control as if the following pragma command had - ** been evaluated: - ** - ** PRAGMA experimental_pragma_20251114 = 1|2 - ** - ** where the RHS is "1" if wrflag is 1 (RESERVED lock), or "2" if wrflag - ** is 2 (EXCLUSIVE lock). Ignore any result or error returned by the VFS. - ** - ** WARNING: This code will likely remain part of SQLite only temporarily - - ** it exists to allow users to experiment with certain types of blocking - ** locks in custom VFS implementations. It MAY BE REMOVED AT ANY TIME. */ - if( pBt->pPage1==0 && wrflag ){ - sqlite3_file *fd = sqlite3PagerFile(pPager); - char *aFcntl[3] = {0,0,0}; - aFcntl[1] = "experimental_pragma_20251114"; - assert( wrflag==1 || wrflag==2 ); - aFcntl[2] = (wrflag==1 ? "1" : "2"); - sqlite3OsFileControlHint(fd, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); - sqlite3_free(aFcntl[0]); - } -#endif - /* Call lockBtree() until either pBt->pPage1 is populated or ** lockBtree() returns something other than SQLITE_OK. lockBtree() ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after @@ -77741,7 +77558,7 @@ static int accessPayload( getCellInfo(pCur); aPayload = pCur->info.pPayload; - assert( (u64)offset+(u64)amt <= (u64)pCur->info.nPayload ); + assert( offset+amt <= pCur->info.nPayload ); assert( aPayload > pPage->aData ); if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){ @@ -78298,7 +78115,7 @@ SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){ assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - if( NEVER(pCur->eState==CURSOR_VALID) ){ + if( pCur->eState==CURSOR_VALID ){ *pRes = 0; return SQLITE_OK; } @@ -82379,7 +82196,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 }while( rc==SQLITE_OK && nOut>0 ); if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){ - Pgno pgnoNew = 0; /* Prevent harmless static-analyzer warning */ + Pgno pgnoNew; MemPage *pNew = 0; rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); put4byte(pPgnoOut, pgnoNew); @@ -85045,27 +84862,21 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ StrAccum acc; assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) ); assert( sz>22 ); - if( p->flags & (MEM_Int|MEM_IntReal) ){ -#if GCC_VERSION>=7000000 && GCC_VERSION<15000000 && defined(__i386__) - /* Work-around for GCC bug or bugs: - ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 - ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659 - ** The problem appears to be fixed in GCC 15 */ + if( p->flags & MEM_Int ){ +#if GCC_VERSION>=7000000 + /* Work-around for GCC bug + ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */ i64 x; - assert( (MEM_Str&~p->flags)*4==sizeof(x) ); - memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4); + assert( (p->flags&MEM_Int)*2==sizeof(x) ); + memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2); p->n = sqlite3Int64ToText(x, zBuf); #else p->n = sqlite3Int64ToText(p->u.i, zBuf); #endif - if( p->flags & MEM_IntReal ){ - memcpy(zBuf+p->n,".0", 3); - p->n += 2; - } }else{ sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0); - sqlite3_str_appendf(&acc, "%!.*g", - (p->db ? p->db->nFpDigit : 17), p->u.r); + sqlite3_str_appendf(&acc, "%!.15g", + (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r); assert( acc.zText==zBuf && acc.mxAlloc<=0 ); zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */ p->n = acc.nChar; @@ -85114,9 +84925,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){ assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 ); } if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1; - if( p->db==0 ){ - return 1; /* db->nFpDigit required to validate p->z[] */ - } memcpy(&tmp, p, sizeof(tmp)); vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp); z = p->z; @@ -85267,16 +85075,13 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ ** ** This is an optimization. Correct operation continues even if ** this routine is a no-op. -** -** Return true if the strig is zero-terminated after this routine is -** called and false if it is not. */ -SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ +SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){ /* pMem must be a string, and it cannot be an ephemeral or static string */ - return 0; + return; } - if( pMem->enc!=SQLITE_UTF8 ) return 0; + if( pMem->enc!=SQLITE_UTF8 ) return; assert( pMem->z!=0 ); if( pMem->flags & MEM_Dyn ){ if( pMem->xDel==sqlite3_free @@ -85284,19 +85089,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ ){ pMem->z[pMem->n] = 0; pMem->flags |= MEM_Term; - return 1; + return; } if( pMem->xDel==sqlite3RCStrUnref ){ /* Blindly assume that all RCStr objects are zero-terminated */ pMem->flags |= MEM_Term; - return 1; + return; } }else if( pMem->szMalloc >= pMem->n+1 ){ pMem->z[pMem->n] = 0; pMem->flags |= MEM_Term; - return 1; + return; } - return 0; } /* @@ -85594,70 +85398,18 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ } } -/* -** Invoke sqlite3AtoF() on the text value of pMem and return the -** double result. If sqlite3AtoF() returns an error code, write -** that code into *pRC if (*pRC)!=NULL. -** -** The caller must ensure that pMem->db!=0 and that pMem is in -** mode MEM_Str or MEM_Blob. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem *pMem, int *pRC){ - double val = (double)0; - int rc = 0; - assert( pMem->db!=0 ); - assert( pMem->flags & (MEM_Str|MEM_Blob) ); - if( pMem->z==0 ){ - /* no-op */ - }else if( pMem->enc==SQLITE_UTF8 - && ((pMem->flags & MEM_Term)!=0 || sqlite3VdbeMemZeroTerminateIfAble(pMem)) - ){ - rc = sqlite3AtoF(pMem->z, &val); - }else if( pMem->n==0 ){ - /* no-op */ - }else if( pMem->enc==SQLITE_UTF8 ){ - char *zCopy = sqlite3DbStrNDup(pMem->db, pMem->z, pMem->n); - if( zCopy ){ - rc = sqlite3AtoF(zCopy, &val); - sqlite3DbFree(pMem->db, zCopy); - } - }else{ - int n, i, j; - char *zCopy; - const char *z; - - n = pMem->n & ~1; - zCopy = sqlite3DbMallocRaw(pMem->db, n/2 + 2); - if( zCopy ){ - z = pMem->z; - if( pMem->enc==SQLITE_UTF16LE ){ - for(i=j=0; i<n-1; i+=2, j++){ - zCopy[j] = z[i]; - if( z[i+1]!=0 ) break; - } - }else{ - for(i=j=0; i<n-1; i+=2, j++){ - if( z[i]!=0 ) break; - zCopy[j] = z[i+1]; - } - } - assert( j<=n/2 ); - zCopy[j] = 0; - rc = sqlite3AtoF(zCopy, &val); - if( i<n ) rc = -100; - sqlite3DbFree(pMem->db, zCopy); - } - } - if( pRC ) *pRC = rc; - return val; -} - /* ** Return the best representation of pMem that we can get into a ** double. If pMem is already a double or an integer, return its ** value. If it is a string or blob, try to convert it to a double. ** If it is a NULL, return 0.0. */ +static SQLITE_NOINLINE double memRealValue(Mem *pMem){ + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ + double val = (double)0; + sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc); + return val; +} SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); @@ -85668,7 +85420,7 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ testcase( pMem->flags & MEM_IntReal ); return (double)pMem->u.i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ - return sqlite3MemRealValueRC(pMem, 0); + return memRealValue(pMem); }else{ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ return (double)0; @@ -85792,7 +85544,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ sqlite3_int64 ix; assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - pMem->u.r = sqlite3MemRealValueRC(pMem, &rc); + rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1) || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r))) ){ @@ -86257,84 +86009,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( return SQLITE_OK; } -/* Like sqlite3VdbeMemSetStr() except: -** -** enc is always SQLITE_UTF8 -** pMem->db is always non-NULL -*/ -SQLITE_PRIVATE int sqlite3VdbeMemSetText( - Mem *pMem, /* Memory cell to set to string value */ - const char *z, /* String pointer */ - i64 n, /* Bytes in string, or negative */ - void (*xDel)(void*) /* Destructor function */ -){ - i64 nByte = n; /* New value for pMem->n */ - u16 flags; - - assert( pMem!=0 ); - assert( pMem->db!=0 ); - assert( sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - - /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ - if( !z ){ - sqlite3VdbeMemSetNull(pMem); - return SQLITE_OK; - } - - if( nByte<0 ){ - nByte = strlen(z); - flags = MEM_Str|MEM_Term; - }else{ - flags = MEM_Str; - } - if( nByte>(i64)pMem->db->aLimit[SQLITE_LIMIT_LENGTH] ){ - if( xDel && xDel!=SQLITE_TRANSIENT ){ - if( xDel==SQLITE_DYNAMIC ){ - sqlite3DbFree(pMem->db, (void*)z); - }else{ - xDel((void*)z); - } - } - sqlite3VdbeMemSetNull(pMem); - return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); - } - - /* The following block sets the new values of Mem.z and Mem.xDel. It - ** also sets a flag in local variable "flags" to indicate the memory - ** management (one of MEM_Dyn or MEM_Static). - */ - if( xDel==SQLITE_TRANSIENT ){ - i64 nAlloc = nByte + 1; - testcase( nAlloc==31 ); - testcase( nAlloc==32 ); - if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){ - return SQLITE_NOMEM_BKPT; - } - assert( pMem->z!=0 ); - memcpy(pMem->z, z, nByte); - pMem->z[nByte] = 0; - }else{ - sqlite3VdbeMemRelease(pMem); - pMem->z = (char *)z; - if( xDel==SQLITE_DYNAMIC ){ - pMem->zMalloc = pMem->z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); - pMem->xDel = 0; - }else if( xDel==SQLITE_STATIC ){ - pMem->xDel = xDel; - flags |= MEM_Static; - }else{ - pMem->xDel = xDel; - flags |= MEM_Dyn; - } - } - pMem->flags = flags; - pMem->n = (int)(nByte & 0x7fffffff); - pMem->enc = SQLITE_UTF8; - return SQLITE_OK; -} - /* ** Move data out of a btree key or data field and into a Mem structure. ** The data is payload from the entry that pCur is currently pointing @@ -86358,12 +86032,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( ){ int rc; pMem->flags = MEM_Null; - testcase( amt==SQLITE_MAX_ALLOCATION_SIZE-1 ); - testcase( amt==SQLITE_MAX_ALLOCATION_SIZE ); - if( amt>=SQLITE_MAX_ALLOCATION_SIZE ){ - return SQLITE_NOMEM_BKPT; - } - if( (u64)amt + (u64)offset > (u64)sqlite3BtreeMaxRecordSize(pCur) ){ + if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){ return SQLITE_CORRUPT_BKPT; } if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){ @@ -86763,7 +86432,7 @@ static int valueFromExpr( if( affinity==SQLITE_AFF_BLOB ){ if( op==TK_FLOAT ){ assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) ); - sqlite3AtoF(pVal->z, &pVal->u.r); + sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8); pVal->flags = MEM_Real; }else if( op==TK_INTEGER ){ /* This case is required by -9223372036854775808 and other strings @@ -87031,11 +86700,6 @@ SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr( ** ** If *ppVal is initially NULL then the caller is responsible for ** ensuring that the value written into *ppVal is eventually freed. -** -** If the buffer does not contain a well-formed record, this routine may -** read several bytes past the end of the buffer. Callers must therefore -** ensure that any buffer which may contain a corrupt record is padded -** with at least 8 bytes of addressable memory. */ SQLITE_PRIVATE int sqlite3Stat4Column( sqlite3 *db, /* Database handle */ @@ -90052,7 +89716,7 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName( } assert( p->aColName!=0 ); pColName = &(p->aColName[idx+var*p->nResAlloc]); - rc = sqlite3VdbeMemSetText(pColName, zName, -1, xDel); + rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); return rc; } @@ -93130,23 +92794,7 @@ static void setResultStrOrError( void (*xDel)(void*) /* Destructor function */ ){ Mem *pOut = pCtx->pOut; - int rc; - if( enc==SQLITE_UTF8 ){ - rc = sqlite3VdbeMemSetText(pOut, z, n, xDel); - }else if( enc==SQLITE_UTF8_ZT ){ - /* It is usually considered improper to assert() on an input. However, - ** the following assert() is checking for inputs that are documented - ** to result in undefined behavior. */ - assert( z==0 - || n<0 - || n>pOut->db->aLimit[SQLITE_LIMIT_LENGTH] - || z[n]==0 - ); - rc = sqlite3VdbeMemSetText(pOut, z, n, xDel); - pOut->flags |= MEM_Term; - }else{ - rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); - } + int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); if( rc ){ if( rc==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(pCtx); @@ -93339,7 +92987,7 @@ SQLITE_API void sqlite3_result_text64( #endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){ + if( enc!=SQLITE_UTF8 ){ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; n &= ~(u64)1; } @@ -93490,8 +93138,6 @@ static int doWalCallbacks(sqlite3 *db){ } } } -#else - UNUSED_PARAMETER(db); #endif return rc; } @@ -93799,7 +93445,7 @@ static int valueFromValueList( Mem sMem; /* Raw content of current row */ memset(&sMem, 0, sizeof(sMem)); sz = sqlite3BtreePayloadSize(pRhs->pCsr); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,sz,&sMem); + rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem); if( rc==SQLITE_OK ){ u8 *zBuf = (u8*)sMem.z; u32 iSerial; @@ -94448,25 +94094,13 @@ static int bindText( assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ if( zData!=0 ){ pVar = &p->aVar[i-1]; - if( encoding==SQLITE_UTF8 ){ - rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel); - }else if( encoding==SQLITE_UTF8_ZT ){ - /* It is usually consider improper to assert() on an input. - ** However, the following assert() is checking for inputs - ** that are documented to result in undefined behavior. */ - assert( zData==0 - || nData<0 - || nData>pVar->db->aLimit[SQLITE_LIMIT_LENGTH] - || ((u8*)zData)[nData]==0 - ); - rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel); - pVar->flags |= MEM_Term; - }else{ - rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); - if( encoding==0 ) pVar->enc = ENC(p->db); - } - if( rc==SQLITE_OK && encoding!=0 ){ - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); + if( rc==SQLITE_OK ){ + if( encoding==0 ){ + pVar->enc = ENC(p->db); + }else{ + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + } } if( rc ){ sqlite3Error(p->db, rc); @@ -94578,7 +94212,7 @@ SQLITE_API int sqlite3_bind_text64( unsigned char enc ){ assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){ + if( enc!=SQLITE_UTF8 ){ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; nData &= ~(u64)1; } @@ -95615,26 +95249,35 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( #ifndef SQLITE_HWTIME_H #define SQLITE_HWTIME_H -#if defined(_MSC_VER) && defined(_WIN32) - -/* #include "windows.h" */ - #include <profileapi.h> - - __inline sqlite3_uint64 sqlite3Hwtime(void){ - LARGE_INTEGER tm; - QueryPerformanceCounter(&tm); - return (sqlite3_uint64)tm.QuadPart; - } - -#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \ +/* +** 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){ @@ -95643,14 +95286,6 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( return (sqlite_uint64)hi << 32 | lo; } -#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__aarch64__) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - sqlite3_uint64 cnt; - __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (cnt)); - return cnt; - } - #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__)) __inline__ sqlite_uint64 sqlite3Hwtime(void){ @@ -96009,9 +95644,10 @@ static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){ */ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ double rValue; + u8 enc = pRec->enc; int rc; assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str ); - rValue = sqlite3MemRealValueRC(pRec, &rc); + rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc); if( rc<=0 ) return; if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){ pRec->flags |= MEM_Int; @@ -96093,10 +95729,7 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; - assert( pMem->db!=0 ); - sqlite3_mutex_enter(pMem->db->mutex); applyNumericAffinity(pMem, 0); - sqlite3_mutex_leave(pMem->db->mutex); eType = sqlite3_value_type(pVal); } return eType; @@ -96129,7 +95762,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ pMem->u.i = 0; return MEM_Int; } - pMem->u.r = sqlite3MemRealValueRC(pMem, &rc); + rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); if( rc<=0 ){ if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){ pMem->u.i = ix; @@ -102278,15 +101911,20 @@ case OP_SorterInsert: { /* in2 */ break; } -/* Opcode: IdxDelete P1 P2 P3 * * +/* Opcode: IdxDelete P1 P2 P3 * P5 ** Synopsis: key=r[P2@P3] ** ** The content of P3 registers starting at register P2 form ** an unpacked index key. This opcode removes that entry from the ** index opened by cursor P1. ** -** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found -** and not in writable_schema mode. +** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error +** if no matching index entry is found. This happens when running +** an UPDATE or DELETE statement and the index entry to be updated +** or deleted is not found. For some uses of IdxDelete +** (example: the EXCEPT operator) it does not matter that no matching +** entry is found. For those cases, P5 is zero. Also, do not raise +** this (self-correcting and non-critical) error if in writable_schema mode. */ case OP_IdxDelete: { VdbeCursor *pC; @@ -102312,7 +101950,7 @@ case OP_IdxDelete: { if( res==0 ){ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); if( rc ) goto abort_due_to_error; - }else if( !sqlite3WritableSchema(db) ){ + }else if( pOp->p5 && !sqlite3WritableSchema(db) ){ rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption"); goto abort_due_to_error; } @@ -110406,7 +110044,7 @@ static int exprProbability(Expr *p){ double r = -1.0; if( p->op!=TK_FLOAT ) return -1; assert( !ExprHasProperty(p, EP_IntValue) ); - sqlite3AtoF(p->u.zToken, &r); + sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); assert( r>=0.0 ); if( r>1.0 ) return -1; return (int)(r*134217728.0); @@ -111126,8 +110764,10 @@ static int resolveCompoundOrderBy( /* Convert the ORDER BY term into an integer column number iCol, ** taking care to preserve the COLLATE clause if it exists. */ if( !IN_RENAME_OBJECT ){ - Expr *pNew = sqlite3ExprInt32(db, iCol); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return 1; + pNew->flags |= EP_IntValue; + pNew->u.iValue = iCol; if( pItem->pExpr==pE ){ pItem->pExpr = pNew; }else{ @@ -111481,6 +111121,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ } #endif + /* The ORDER BY and GROUP BY clauses may not refer to terms in + ** outer queries + */ + sNC.pNext = 0; sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; /* If this is a converted compound query, move the ORDER BY clause from @@ -111543,14 +111187,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ return WRC_Abort; } - /* If the SELECT statement contains ON clauses that were moved into - ** the WHERE clause, go through and verify that none of the terms - ** in the ON clauses reference tables to the right of the ON clause. */ - if( (p->selFlags & SF_OnToWhere) ){ - sqlite3SelectCheckOnClauses(pParse, p); - if( pParse->nErr ) return WRC_Abort; - } - /* Advance to the next term of the compound */ p = p->pPrior; @@ -112727,22 +112363,34 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( int dequote /* True to dequote */ ){ Expr *pNew; - int nExtra = pToken ? pToken->n+1 : 0; + int nExtra = 0; + int iValue = 0; assert( db!=0 ); + if( pToken ){ + if( op!=TK_INTEGER || pToken->z==0 + || sqlite3GetInt32(pToken->z, &iValue)==0 ){ + nExtra = pToken->n+1; /* tag-20240227-a */ + assert( iValue>=0 ); + } + } pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); if( pNew ){ memset(pNew, 0, sizeof(Expr)); pNew->op = (u8)op; pNew->iAgg = -1; - if( nExtra ){ - assert( pToken!=0 ); - pNew->u.zToken = (char*)&pNew[1]; - assert( pToken->z!=0 || pToken->n==0 ); - if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); - pNew->u.zToken[pToken->n] = 0; - if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){ - sqlite3DequoteExpr(pNew); + if( pToken ){ + if( nExtra==0 ){ + pNew->flags |= EP_IntValue|EP_Leaf|(iValue?EP_IsTrue:EP_IsFalse); + pNew->u.iValue = iValue; + }else{ + pNew->u.zToken = (char*)&pNew[1]; + assert( pToken->z!=0 || pToken->n==0 ); + if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); + pNew->u.zToken[pToken->n] = 0; + if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){ + sqlite3DequoteExpr(pNew); + } } } #if SQLITE_MAX_EXPR_DEPTH>0 @@ -112767,24 +112415,6 @@ SQLITE_PRIVATE Expr *sqlite3Expr( return sqlite3ExprAlloc(db, op, &x, 0); } -/* -** Allocate an expression for a 32-bit signed integer literal. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3 *db, int iVal){ - Expr *pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)); - if( pNew ){ - memset(pNew, 0, sizeof(Expr)); - pNew->op = TK_INTEGER; - pNew->iAgg = -1; - pNew->flags = EP_IntValue|EP_Leaf|(iVal?EP_IsTrue:EP_IsFalse); - pNew->u.iValue = iVal; -#if SQLITE_MAX_EXPR_DEPTH>0 - pNew->nHeight = 1; -#endif - } - return pNew; -} - /* ** Attach subtrees pLeft and pRight to the Expr node pRoot. ** @@ -112947,7 +112577,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ ){ sqlite3ExprDeferredDelete(pParse, pLeft); sqlite3ExprDeferredDelete(pParse, pRight); - return sqlite3ExprInt32(db, 0); + return sqlite3Expr(db, TK_INTEGER, "0"); }else{ return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); } @@ -113072,9 +112702,7 @@ SQLITE_PRIVATE void sqlite3ExprFunctionUsable( ){ assert( !IN_RENAME_OBJECT ); assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 ); - if( ExprHasProperty(pExpr, EP_FromDDL) - || pParse->prepFlags & SQLITE_PREPARE_FROM_DDL - ){ + if( ExprHasProperty(pExpr, EP_FromDDL) ){ if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 || (pParse->db->flags & SQLITE_TrustedSchema)==0 ){ @@ -113770,7 +113398,9 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); pNew->iLimit = 0; pNew->iOffset = 0; - pNew->selFlags = p->selFlags; + pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; pNew->pWith = sqlite3WithDup(db, p->pWith); #ifndef SQLITE_OMIT_WINDOWFUNC @@ -114422,7 +114052,7 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag){ /* ** Walk an expression tree. Return non-zero if the expression is constant -** or return zero if the expression involves variables or function calls. +** and 0 if it involves variables or function calls. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is @@ -115212,7 +114842,6 @@ SQLITE_PRIVATE int sqlite3FindInIndex( */ u32 savedNQueryLoop = pParse->nQueryLoop; int rMayHaveNull = 0; - int bloomOk = (inFlags & IN_INDEX_MEMBERSHIP)!=0; eType = IN_INDEX_EPH; if( inFlags & IN_INDEX_LOOP ){ pParse->nQueryLoop = 0; @@ -115220,13 +114849,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex( *prRhsHasNull = rMayHaveNull = ++pParse->nMem; } assert( pX->op==TK_IN ); - if( !bloomOk - && ExprUseXSelect(pX) - && (pX->x.pSelect->selFlags & SF_ClonedRhsIn)!=0 - ){ - bloomOk = 1; - } - sqlite3CodeRhsOfIN(pParse, pX, iTab, bloomOk); + sqlite3CodeRhsOfIN(pParse, pX, iTab); if( rMayHaveNull ){ sqlite3SetHasNullFlag(v, iTab, rMayHaveNull); } @@ -115384,8 +115007,7 @@ static int findCompatibleInRhsSubrtn( SQLITE_PRIVATE void sqlite3CodeRhsOfIN( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The IN operator */ - int iTab, /* Use this cursor number */ - int allowBloom /* True to allow the use of a Bloom filter */ + int iTab /* Use this cursor number */ ){ int addrOnce = 0; /* Address of the OP_Once instruction at top */ int addr; /* Address of OP_OpenEphemeral instruction */ @@ -115507,10 +115129,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( sqlite3SelectDestInit(&dest, SRT_Set, iTab); dest.zAffSdst = exprINAffinity(pParse, pExpr); pSelect->iLimit = 0; - if( addrOnce - && allowBloom - && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) - ){ + if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ int regBloom = ++pParse->nMem; addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom); VdbeComment((v, "Bloom filter")); @@ -115731,7 +115350,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ || (pLeft->u.iValue!=1 && pLeft->u.iValue!=0) ){ sqlite3 *db = pParse->db; - pLimit = sqlite3ExprInt32(db, 0); + pLimit = sqlite3Expr(db, TK_INTEGER, "0"); if( pLimit ){ pLimit->affExpr = SQLITE_AFF_NUMERIC; pLimit = sqlite3PExpr(pParse, TK_NE, @@ -115742,7 +115361,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ } }else{ /* If there is no pre-existing limit add a limit of 1 */ - pLimit = sqlite3ExprInt32(pParse->db, 1); + pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); } pSel->iLimit = 0; @@ -116003,9 +115622,8 @@ static void sqlite3ExprCodeIN( if( ExprHasProperty(pExpr, EP_Subrtn) ){ const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr); assert( pOp->opcode==OP_Once || pParse->nErr ); - if( pOp->p3>0 ){ /* tag-202407032019 */ - assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) - || pParse->nErr ); + if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */ + assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ); sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse, rLhs, nVector); VdbeCoverage(v); } @@ -116095,7 +115713,7 @@ static void sqlite3ExprCodeIN( static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ if( ALWAYS(z!=0) ){ double value; - sqlite3AtoF(z, &value); + sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ if( negateFlag ) value = -value; sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL); @@ -119196,10 +118814,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ if( pIEpr==0 ) break; if( NEVER(!ExprUseYTab(pExpr)) ) break; for(i=0; i<pSrcList->nSrc; i++){ - if( pSrcList->a[i].iCursor==pIEpr->iDataCur ){ - testcase( i>0 ); - break; - } + if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break; } if( i>=pSrcList->nSrc ) break; if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */ @@ -119988,7 +119603,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); assert( sqlite3BtreeHoldsAllMutexes(db) ); - if( NEVER(db->mallocFailed) ) goto exit_begin_add_column; + if( db->mallocFailed ) goto exit_begin_add_column; pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_begin_add_column; @@ -120060,7 +119675,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ ** Or, if pTab is not a view or virtual table, zero is returned. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) -static int isRealTable(Parse *pParse, Table *pTab, int iOp){ +static int isRealTable(Parse *pParse, Table *pTab, int bDrop){ const char *zType = 0; #ifndef SQLITE_OMIT_VIEW if( IsView(pTab) ){ @@ -120073,12 +119688,9 @@ static int isRealTable(Parse *pParse, Table *pTab, int iOp){ } #endif if( zType ){ - const char *azMsg[] = { - "rename columns of", "drop column from", "edit constraints of" - }; - assert( iOp>=0 && iOp<ArraySize(azMsg) ); sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"", - azMsg[iOp], zType, pTab->zName + (bDrop ? "drop column from" : "rename columns of"), + zType, pTab->zName ); return 1; } @@ -120549,25 +120161,6 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ return pBest; } -/* -** Set the error message of the context passed as the first argument to -** the result of formatting zFmt using printf() style formatting. -*/ -static void errorMPrintf(sqlite3_context *pCtx, const char *zFmt, ...){ - sqlite3 *db = sqlite3_context_db_handle(pCtx); - char *zErr = 0; - va_list ap; - va_start(ap, zFmt); - zErr = sqlite3VMPrintf(db, zFmt, ap); - va_end(ap); - if( zErr ){ - sqlite3_result_error(pCtx, zErr, -1); - sqlite3DbFree(db, zErr); - }else{ - sqlite3_result_error_nomem(pCtx); - } -} - /* ** An error occurred while parsing or otherwise processing a database ** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an @@ -120865,8 +120458,8 @@ static int renameResolveTrigger(Parse *pParse){ sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); if( pParse->nErr ) rc = pParse->rc; } - if( rc==SQLITE_OK && pStep->pSrc ){ - SrcList *pSrc = sqlite3SrcListDup(db, pStep->pSrc, 0); + if( rc==SQLITE_OK && pStep->zTarget ){ + SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); if( pSrc ){ Select *pSel = sqlite3SelectNew( pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 @@ -120894,10 +120487,10 @@ static int renameResolveTrigger(Parse *pParse){ pSel->pSrc = 0; sqlite3SelectDelete(db, pSel); } - if( ALWAYS(pStep->pSrc) ){ + if( pStep->pFrom ){ int i; - for(i=0; i<pStep->pSrc->nSrc && rc==SQLITE_OK; i++){ - SrcItem *p = &pStep->pSrc->a[i]; + for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){ + SrcItem *p = &pStep->pFrom->a[i]; if( p->fg.isSubquery ){ assert( p->u4.pSubq!=0 ); sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0); @@ -120966,13 +120559,13 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); } - if( pStep->pSrc ){ + if( pStep->pFrom ){ int i; - SrcList *pSrc = pStep->pSrc; - for(i=0; i<pSrc->nSrc; i++){ - if( pSrc->a[i].fg.isSubquery ){ - assert( pSrc->a[i].u4.pSubq!=0 ); - sqlite3WalkSelect(pWalker, pSrc->a[i].u4.pSubq->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); } } } @@ -121143,8 +120736,8 @@ static void renameColumnFunc( if( rc!=SQLITE_OK ) goto renameColumnFunc_done; for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->pSrc ){ - Table *pTarget = sqlite3LocateTableItem(&sParse, 0, &pStep->pSrc->a[0]); + if( pStep->zTarget ){ + Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); if( pTarget==pTab ){ if( pStep->pUpsert ){ ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; @@ -121156,6 +120749,7 @@ static void renameColumnFunc( } } + /* Find tokens to edit in UPDATE OF clause */ if( sParse.pTriggerTab==pTab ){ renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); @@ -121357,10 +120951,13 @@ static void renameTableFunc( if( rc==SQLITE_OK ){ renameWalkTrigger(&sWalker, pTrigger); for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->pSrc ){ + if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ + renameTokenFind(&sParse, &sCtx, pStep->zTarget); + } + if( pStep->pFrom ){ int i; - for(i=0; i<pStep->pSrc->nSrc; i++){ - SrcItem *pItem = &pStep->pSrc->a[i]; + for(i=0; i<pStep->pFrom->nSrc; i++){ + SrcItem *pItem = &pStep->pFrom->a[i]; if( 0==sqlite3_stricmp(pItem->zName, zOld) ){ renameTokenFind(&sParse, &sCtx, pItem->zName); } @@ -121607,57 +121204,6 @@ static void renameTableTest( #endif } - -/* -** Return the number of bytes until the end of the next non-whitespace and -** non-comment token. For the purpose of this function, a "(" token includes -** all of the bytes through and including the matching ")", or until the -** first illegal token, whichever comes first. -** -** Write the token type into *piToken. -** -** The value returned is the number of bytes in the token itself plus -** the number of bytes of leading whitespace and comments skipped plus -** all bytes through the next matching ")" if the token is TK_LP. -** -** Example: (Note: '.' used in place of '*' in the example z[] text) -** -** ,--------- *piToken := TK_RP -** v -** z[] = " /.comment./ --comment\n (two three four) five" -** | | -** |<-------------------------------------->| -** | -** `--- return value -*/ -static int getConstraintToken(const u8 *z, int *piToken){ - int iOff = 0; - int t = 0; - do { - iOff += sqlite3GetToken(&z[iOff], &t); - }while( t==TK_SPACE || t==TK_COMMENT ); - - *piToken = t; - - if( t==TK_LP ){ - int nNest = 1; - while( nNest>0 ){ - iOff += sqlite3GetToken(&z[iOff], &t); - if( t==TK_LP ){ - nNest++; - }else if( t==TK_RP ){ - t = TK_LP; - nNest--; - }else if( t==TK_ILLEGAL ){ - break; - } - } - } - - *piToken = t; - return iOff; -} - /* ** The implementation of internal UDF sqlite_drop_column(). ** @@ -121702,24 +121248,15 @@ static void dropColumnFunc( goto drop_column_done; } + pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName); if( iCol<pTab->nCol-1 ){ RenameToken *pEnd; - pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName); pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName); zEnd = (const char*)pEnd->t.z; }else{ - int eTok; assert( IsOrdinaryTable(pTab) ); - assert( iCol!=0 ); - /* Point pCol->t.z at the "," immediately preceding the definition of - ** the column being dropped. To do this, start at the name of the - ** previous column, and tokenize until the next ",". */ - pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol-1].zCnName); - do { - pCol->t.z += getConstraintToken((const u8*)pCol->t.z, &eTok); - }while( eTok!=TK_COMMA ); - pCol->t.z--; zEnd = (const char*)&zSql[pTab->u.tab.addColOffset]; + while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--; } zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd); @@ -121888,651 +121425,6 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T sqlite3SrcListDelete(db, pSrc); } -/* -** Return the number of bytes of leading whitespace/comments in string z[]. -*/ -static int getWhitespace(const u8 *z){ - int nRet = 0; - while( 1 ){ - int t = 0; - int n = sqlite3GetToken(&z[nRet], &t); - if( t!=TK_SPACE && t!=TK_COMMENT ) break; - nRet += n; - } - return nRet; -} - - -/* -** Argument z points into the body of a constraint - specifically the -** second token of the constraint definition. For a named constraint, -** z points to the first token past the CONSTRAINT keyword. For an -** unnamed NOT NULL constraint, z points to the first byte past the NOT -** keyword. -** -** Return the number of bytes until the end of the constraint. -*/ -static int getConstraint(const u8 *z){ - int iOff = 0; - int t = 0; - - /* Now, the current constraint proceeds until the next occurence of one - ** of the following tokens: - ** - ** CONSTRAINT, PRIMARY, NOT, UNIQUE, CHECK, DEFAULT, - ** COLLATE, REFERENCES, FOREIGN, GENERATED, AS, RP, or COMMA - ** - ** Also exit the loop if ILLEGAL turns up. - */ - while( 1 ){ - int n = getConstraintToken(&z[iOff], &t); - if( t==TK_CONSTRAINT || t==TK_PRIMARY || t==TK_NOT || t==TK_UNIQUE - || t==TK_CHECK || t==TK_DEFAULT || t==TK_COLLATE || t==TK_REFERENCES - || t==TK_FOREIGN || t==TK_RP || t==TK_COMMA || t==TK_ILLEGAL - || t==TK_AS || t==TK_GENERATED - ){ - break; - } - iOff += n; - } - - return iOff; -} - -/* -** Compare two constraint names. -** -** Summary: *pRes := zQuote != zCmp -** -** Details: -** Compare the (possibly quoted) constraint name zQuote[0..nQuote-1] -** against zCmp[]. Write zero into *pRes if they are the same and -** non-zero if they differ. Normally return SQLITE_OK, except if there -** is an OOM, set the OOM error condition on ctx and return SQLITE_NOMEM. -*/ -static int quotedCompare( - sqlite3_context *ctx, /* Function context on which to report errors */ - int t, /* Token type */ - const u8 *zQuote, /* Possibly quoted text. Not zero-terminated. */ - int nQuote, /* Length of zQuote in bytes */ - const u8 *zCmp, /* Zero-terminated, unquoted name to compare against */ - int *pRes /* OUT: Set to 0 if equal, non-zero if unequal */ -){ - char *zCopy = 0; /* De-quoted, zero-terminated copy of zQuote[] */ - - if( t==TK_ILLEGAL ){ - *pRes = 1; - return SQLITE_OK; - } - zCopy = sqlite3MallocZero(nQuote+1); - if( zCopy==0 ){ - sqlite3_result_error_nomem(ctx); - return SQLITE_NOMEM_BKPT; - } - memcpy(zCopy, zQuote, nQuote); - sqlite3Dequote(zCopy); - *pRes = sqlite3_stricmp((const char*)zCopy, (const char*)zCmp); - sqlite3_free(zCopy); - return SQLITE_OK; -} - -/* -** zSql[] is a CREATE TABLE statement, supposedly. Find the offset -** into zSql[] of the first character past the first "(" and write -** that offset into *piOff and return SQLITE_OK. Or, if not found, -** set the SQLITE_CORRUPT error code and return SQLITE_ERROR. -*/ -static int skipCreateTable(sqlite3_context *ctx, const u8 *zSql, int *piOff){ - int iOff = 0; - - if( zSql==0 ) return SQLITE_ERROR; - - /* Jump past the "CREATE TABLE" bit. */ - while( 1 ){ - int t = 0; - iOff += sqlite3GetToken(&zSql[iOff], &t); - if( t==TK_LP ) break; - if( t==TK_ILLEGAL ){ - sqlite3_result_error_code(ctx, SQLITE_CORRUPT_BKPT); - return SQLITE_ERROR; - } - } - - *piOff = iOff; - return SQLITE_OK; -} - -/* -** Internal SQL function sqlite3_drop_constraint(): Given an input -** CREATE TABLE statement, return a revised CREATE TABLE statement -** with a constraint removed. Two forms, depending on the datatype -** of argv[2]: -** -** sqlite_drop_constraint(SQL, INT) -- Omit NOT NULL from the INT-th column -** sqlite_drop_constraint(SQL, TEXT) -- OMIT constraint with name TEXT -** -** In the first case, the left-most column is 0. -*/ -static void dropConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const u8 *zSql = sqlite3_value_text(argv[0]); - const u8 *zCons = 0; - int iNotNull = -1; - int ii; - int iOff = 0; - int iStart = 0; - int iEnd = 0; - char *zNew = 0; - int t = 0; - sqlite3 *db; - UNUSED_PARAMETER(NotUsed); - - if( zSql==0 ) return; - - /* Jump past the "CREATE TABLE" bit. */ - if( skipCreateTable(ctx, zSql, &iOff) ) return; - - if( sqlite3_value_type(argv[1])==SQLITE_INTEGER ){ - iNotNull = sqlite3_value_int(argv[1]); - }else{ - zCons = sqlite3_value_text(argv[1]); - } - - /* Search for the named constraint within column definitions. */ - for(ii=0; iEnd==0; ii++){ - - /* Now parse the column or table constraint definition. Search - ** for the token CONSTRAINT if this is a DROP CONSTRAINT command, or - ** NOT in the right column if this is a DROP NOT NULL. */ - while( 1 ){ - iStart = iOff; - iOff += getConstraintToken(&zSql[iOff], &t); - if( t==TK_CONSTRAINT && (zCons || iNotNull==ii) ){ - /* Check if this is the constraint we are searching for. */ - int nTok = 0; - int cmp = 1; - - /* Skip past any whitespace. */ - iOff += getWhitespace(&zSql[iOff]); - - /* Compare the next token - which may be quoted - with the name of - ** the constraint being dropped. */ - nTok = getConstraintToken(&zSql[iOff], &t); - if( zCons ){ - if( quotedCompare(ctx, t, &zSql[iOff], nTok, zCons, &cmp) ) return; - } - iOff += nTok; - - /* The next token is usually the first token of the constraint - ** definition. This is enough to tell the type of the constraint - - ** TK_NOT means it is a NOT NULL, TK_CHECK a CHECK constraint etc. - ** - ** There is also the chance that the next token is TK_CONSTRAINT - ** (or TK_DEFAULT or TK_COLLATE), for example if a table has been - ** created as follows: - ** - ** CREATE TABLE t1(cols, CONSTRAINT one CONSTRAINT two NOT NULL); - ** - ** In this case, allow the "CONSTRAINT one" bit to be dropped by - ** this command if that is what is requested, or to advance to - ** the next iteration of the loop with &zSql[iOff] still pointing - ** to the CONSTRAINT keyword. */ - nTok = getConstraintToken(&zSql[iOff], &t); - if( t==TK_CONSTRAINT || t==TK_DEFAULT || t==TK_COLLATE - || t==TK_COMMA || t==TK_RP || t==TK_GENERATED || t==TK_AS - ){ - t = TK_CHECK; - }else{ - iOff += nTok; - iOff += getConstraint(&zSql[iOff]); - } - - if( cmp==0 || (iNotNull>=0 && t==TK_NOT) ){ - if( t!=TK_NOT && t!=TK_CHECK ){ - errorMPrintf(ctx, "constraint may not be dropped: %s", zCons); - return; - } - iEnd = iOff; - break; - } - - }else if( t==TK_NOT && iNotNull==ii ){ - iEnd = iOff + getConstraint(&zSql[iOff]); - break; - }else if( t==TK_RP || t==TK_ILLEGAL ){ - iEnd = -1; - break; - }else if( t==TK_COMMA ){ - break; - } - } - } - - /* If the constraint has not been found it is an error. */ - if( iEnd<=0 ){ - if( zCons ){ - errorMPrintf(ctx, "no such constraint: %s", zCons); - }else{ - /* SQLite follows postgres in that a DROP NOT NULL on a column that is - ** not NOT NULL is not an error. So just return the original SQL here. */ - sqlite3_result_text(ctx, (const char*)zSql, -1, SQLITE_TRANSIENT); - } - }else{ - - /* Figure out if an extra space should be inserted after the constraint - ** is removed. And if an additional comma preceding the constraint - ** should be removed. */ - const char *zSpace = " "; - iEnd += getWhitespace(&zSql[iEnd]); - sqlite3GetToken(&zSql[iEnd], &t); - if( t==TK_RP || t==TK_COMMA ){ - zSpace = ""; - if( zSql[iStart-1]==',' ) iStart--; - } - - db = sqlite3_context_db_handle(ctx); - zNew = sqlite3MPrintf(db, "%.*s%s%s", iStart, zSql, zSpace, &zSql[iEnd]); - sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC); - } -} - -/* -** Internal SQL function: -** -** sqlite_add_constraint(SQL, CONSTRAINT-TEXT, ICOL) -** -** SQL is a CREATE TABLE statement. Return a modified version of -** SQL that adds CONSTRAINT-TEXT at the end of the ICOL-th column -** definition. (The left-most column defintion is 0.) -*/ -static void addConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const u8 *zSql = sqlite3_value_text(argv[0]); - const char *zCons = (const char*)sqlite3_value_text(argv[1]); - int iCol = sqlite3_value_int(argv[2]); - int iOff = 0; - int ii; - char *zNew = 0; - int t = 0; - sqlite3 *db; - UNUSED_PARAMETER(NotUsed); - - if( skipCreateTable(ctx, zSql, &iOff) ) return; - - for(ii=0; ii<=iCol || (iCol<0 && t!=TK_RP); ii++){ - iOff += getConstraintToken(&zSql[iOff], &t); - while( 1 ){ - int nTok = getConstraintToken(&zSql[iOff], &t); - if( t==TK_COMMA || t==TK_RP ) break; - if( t==TK_ILLEGAL ){ - sqlite3_result_error_code(ctx, SQLITE_CORRUPT_BKPT); - return; - } - iOff += nTok; - } - } - - iOff += getWhitespace(&zSql[iOff]); - - db = sqlite3_context_db_handle(ctx); - if( iCol<0 ){ - zNew = sqlite3MPrintf(db, "%.*s, %s%s", iOff, zSql, zCons, &zSql[iOff]); - }else{ - zNew = sqlite3MPrintf(db, "%.*s %s%s", iOff, zSql, zCons, &zSql[iOff]); - } - sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC); -} - -/* -** Find a column named pCol in table pTab. If successful, set output -** parameter *piCol to the index of the column in the table and return -** SQLITE_OK. Otherwise, set *piCol to -1 and return an SQLite error -** code. -*/ -static int alterFindCol(Parse *pParse, Table *pTab, Token *pCol, int *piCol){ - sqlite3 *db = pParse->db; - char *zName = sqlite3NameFromToken(db, pCol); - int rc = SQLITE_NOMEM; - int iCol = -1; - - if( zName ){ - iCol = sqlite3ColumnIndex(pTab, zName); - if( iCol<0 ){ - sqlite3ErrorMsg(pParse, "no such column: %s", zName); - rc = SQLITE_ERROR; - }else{ - rc = SQLITE_OK; - } - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - if( rc==SQLITE_OK ){ - const char *zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; - const char *zCol = pTab->aCol[iCol].zCnName; - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){ - pTab = 0; - } - } -#endif - - sqlite3DbFree(db, zName); - *piCol = iCol; - return rc; -} - - -/* -** Find the table named by the first entry in source list pSrc. If successful, -** return a pointer to the Table structure and set output variable (*pzDb) -** to point to the name of the database containin the table (i.e. "main", -** "temp" or the name of an attached database). -** -** If the table cannot be located, return NULL. The value of the two output -** parameters is undefined in this case. -*/ -static Table *alterFindTable( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* Name of the table to look for */ - int *piDb, /* OUT: write the iDb here */ - const char **pzDb, /* OUT: write name of schema here */ - int bAuth /* Do ALTER TABLE authorization checks if true */ -){ - sqlite3 *db = pParse->db; - Table *pTab = 0; - assert( sqlite3BtreeHoldsAllMutexes(db) ); - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( pTab ){ - int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - *pzDb = db->aDb[iDb].zDbSName; - *piDb = iDb; - - if( SQLITE_OK!=isRealTable(pParse, pTab, 2) - || SQLITE_OK!=isAlterableTable(pParse, pTab) - ){ - pTab = 0; - } - } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( pTab && bAuth ){ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, *pzDb, pTab->zName, 0) ){ - pTab = 0; - } - } -#endif - sqlite3SrcListDelete(db, pSrc); - return pTab; -} - -/* -** Generate bytecode for one of: -** -** (1) ALTER TABLE pSrc DROP CONSTRAINT pCons -** (2) ALTER TABLE pSrc ALTER pCol DROP NOT NULL -** -** One of pCons and pCol must be NULL and the other non-null. -*/ -SQLITE_PRIVATE void sqlite3AlterDropConstraint( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* The table being altered */ - Token *pCons, /* Name of the constraint to drop */ - Token *pCol /* Name of the column from which to remove the NOT NULL */ -){ - sqlite3 *db = pParse->db; - Table *pTab = 0; - int iDb = 0; - const char *zDb = 0; - char *zArg = 0; - - assert( (pCol==0)!=(pCons==0) ); - assert( pSrc->nSrc==1 ); - pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, pCons!=0); - if( !pTab ) return; - - if( pCons ){ - zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z); - }else{ - int iCol; - if( alterFindCol(pParse, pTab, pCol, &iCol) ) return; - zArg = sqlite3MPrintf(db, "%d", iCol); - } - - /* Edit the SQL for the named table. */ - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_drop_constraint(sql, %s) " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase" - , zDb, zArg, pTab->zName - ); - sqlite3DbFree(db, zArg); - - /* Finally, reload the database schema. */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons); -} - -/* -** The implementation of SQL function sqlite_fail(MSG). This takes a single -** argument, and returns it as an error message with the error code set to -** SQLITE_CONSTRAINT. -*/ -static void failConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const char *zText = (const char*)sqlite3_value_text(argv[0]); - int err = sqlite3_value_int(argv[1]); - (void)NotUsed; - sqlite3_result_error(ctx, zText, -1); - sqlite3_result_error_code(ctx, err); -} - -/* -** Buffer pCons, which is nCons bytes in size, contains the text of a -** NOT NULL or CHECK constraint that will be inserted into a CREATE TABLE -** statement. If successful, this function returns the size of the buffer in -** bytes not including any trailing whitespace or "--" style comments. Or, -** if an OOM occurs, it returns 0 and sets db->mallocFailed to true. -** -** C-style comments at the end are preserved. "--" style comments are -** removed because the comment terminator might be \000, and we are about -** to insert the pCons[] text into the middle of a larger string, and that -** will have the effect of removing the comment terminator and messing up -** the syntax. -*/ -static int alterRtrimConstraint( - sqlite3 *db, /* used to record OOM error */ - const char *pCons, /* Buffer containing constraint */ - int nCons /* Size of pCons in bytes */ -){ - u8 *zTmp = (u8*)sqlite3MPrintf(db, "%.*s", nCons, pCons); - int iOff = 0; - int iEnd = 0; - - if( zTmp==0 ) return 0; - - while( 1 ){ - int t = 0; - int nToken = sqlite3GetToken(&zTmp[iOff], &t); - if( t==TK_ILLEGAL ) break; - if( t!=TK_SPACE && (t!=TK_COMMENT || zTmp[iOff]!='-') ){ - iEnd = iOff+nToken; - } - iOff += nToken; - } - - sqlite3DbFree(db, zTmp); - return iEnd; -} - -/* -** Prepare a statement of the form: -** -** ALTER TABLE pSrc ALTER pCol SET NOT NULL -*/ -SQLITE_PRIVATE void sqlite3AlterSetNotNull( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* Name of the table being altered */ - Token *pCol, /* Name of the column to add a NOT NULL constraint to */ - Token *pFirst /* The NOT token of the NOT NULL constraint text */ -){ - Table *pTab = 0; - int iCol = 0; - int iDb = 0; - const char *zDb = 0; - const char *pCons = 0; - int nCons = 0; - - /* Look up the table being altered. */ - assert( pSrc->nSrc==1 ); - pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 0); - if( !pTab ) return; - - /* Find the column being altered. */ - if( alterFindCol(pParse, pTab, pCol, &iCol) ){ - return; - } - - /* Find the length in bytes of the constraint definition */ - pCons = pFirst->z; - nCons = alterRtrimConstraint(pParse->db, pCons, pParse->sLastToken.z - pCons); - - /* Search for a constraint violation. Throw an exception if one is found. */ - sqlite3NestedParse(pParse, - "SELECT sqlite_fail('constraint failed', %d) " - "FROM %Q.%Q AS x WHERE x.%.*s IS NULL", - SQLITE_CONSTRAINT, zDb, pTab->zName, (int)pCol->n, pCol->z - ); - - /* Edit the SQL for the named table. */ - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_add_constraint(sqlite_drop_constraint(sql, %d), %.*Q, %d) " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase" - , zDb, iCol, nCons, pCons, iCol, pTab->zName - ); - - /* Finally, reload the database schema. */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons); -} - -/* -** Implementation of internal SQL function: -** -** sqlite_find_constraint(SQL, CONSTRAINT-NAME) -** -** This function returns true if the SQL passed as the first argument is a -** CREATE TABLE that contains a constraint with the name CONSTRAINT-NAME, -** or false otherwise. -*/ -static void findConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const u8 *zSql = 0; - const u8 *zCons = 0; - int iOff = 0; - int t = 0; - - (void)NotUsed; - zSql = sqlite3_value_text(argv[0]); - zCons = sqlite3_value_text(argv[1]); - - if( zSql==0 || zCons==0 ) return; - while( t!=TK_LP && t!=TK_ILLEGAL ){ - iOff += sqlite3GetToken(&zSql[iOff], &t); - } - - while( 1 ){ - iOff += getConstraintToken(&zSql[iOff], &t); - if( t==TK_CONSTRAINT ){ - int nTok = 0; - int cmp = 0; - iOff += getWhitespace(&zSql[iOff]); - nTok = getConstraintToken(&zSql[iOff], &t); - if( quotedCompare(ctx, t, &zSql[iOff], nTok, zCons, &cmp) ) return; - if( cmp==0 ){ - sqlite3_result_int(ctx, 1); - return; - } - }else if( t==TK_ILLEGAL ){ - break; - } - } - - sqlite3_result_int(ctx, 0); -} - -/* -** Generate bytecode to implement: -** -** ALTER TABLE pSrc ADD [CONSTRAINT pName] CHECK(pExpr) -** -** Any "ON CONFLICT" text that occurs after the "CHECK(...)", up -** until pParse->sLastToken, is included as part of the new constraint. -*/ -SQLITE_PRIVATE void sqlite3AlterAddConstraint( - Parse *pParse, /* Parse context */ - SrcList *pSrc, /* Table to add constraint to */ - Token *pFirst, /* First token of new constraint */ - Token *pName, /* Name of new constraint. NULL if name omitted. */ - const char *pExpr, /* Text of CHECK expression */ - int nExpr /* Size of pExpr in bytes */ -){ - Table *pTab = 0; /* Table identified by pSrc */ - int iDb = 0; /* Which schema does pTab live in */ - const char *zDb = 0; /* Name of the schema in which pTab lives */ - const char *pCons = 0; /* Text of the constraint */ - int nCons; /* Bytes of text to use from pCons[] */ - - /* Look up the table being altered. */ - assert( pSrc->nSrc==1 ); - pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1); - if( !pTab ) return; - - /* If this new constraint has a name, check that it is not a duplicate of - ** an existing constraint. It is an error if it is. */ - if( pName ){ - char *zName = sqlite3NameFromToken(pParse->db, pName); - - sqlite3NestedParse(pParse, - "SELECT sqlite_fail('constraint %q already exists', %d) " - "FROM \"%w\"." LEGACY_SCHEMA_TABLE " " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase " - "AND sqlite_find_constraint(sql, %Q)", - zName, SQLITE_ERROR, zDb, pTab->zName, zName - ); - sqlite3DbFree(pParse->db, zName); - } - - /* Search for a constraint violation. Throw an exception if one is found. */ - sqlite3NestedParse(pParse, - "SELECT sqlite_fail('constraint failed', %d) " - "FROM %Q.%Q WHERE (%.*s) IS NOT TRUE", - SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr - ); - - /* Edit the SQL for the named table. */ - pCons = pFirst->z; - nCons = alterRtrimConstraint(pParse->db, pCons, pParse->sLastToken.z - pCons); - - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_add_constraint(sql, %.*Q, -1) " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase" - , zDb, nCons, pCons, pTab->zName - ); - - /* Finally, reload the database schema. */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons); -} - /* ** Register built-in functions used to help implement ALTER TABLE */ @@ -122543,10 +121435,6 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void){ INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest), INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc), INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc), - INTERNAL_FUNCTION(sqlite_drop_constraint,2, dropConstraintFunc), - INTERNAL_FUNCTION(sqlite_fail, 2, failConstraintFunc), - INTERNAL_FUNCTION(sqlite_add_constraint, 3, addConstraintFunc), - INTERNAL_FUNCTION(sqlite_find_constraint,2, findConstraintFunc), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } @@ -125167,7 +124055,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( if( sqlite3WalkSelect(&pFix->w, pStep->pSelect) || sqlite3WalkExpr(&pFix->w, pStep->pWhere) || sqlite3WalkExprList(&pFix->w, pStep->pExprList) - || sqlite3FixSrcList(pFix, pStep->pSrc) + || sqlite3FixSrcList(pFix, pStep->pFrom) ){ return 1; } @@ -125274,7 +124162,7 @@ SQLITE_API int sqlite3_set_authorizer( sqlite3_mutex_enter(db->mutex); db->xAuth = (sqlite3_xauth)xAuth; db->pAuthArg = pArg; - sqlite3ExpirePreparedStatements(db, 1); + if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } @@ -125945,7 +124833,6 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem( const char *zDb; if( p->fg.fixedSchema ){ int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema); - assert( iDb>=0 && iDb<pParse->db->nDb ); zDb = pParse->db->aDb[iDb].zDbSName; }else{ assert( !p->fg.isSubquery ); @@ -127519,8 +126406,8 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ ** The estimate is conservative. It might be larger that what is ** really needed. */ -static i64 identLength(const char *z){ - i64 n; +static int identLength(const char *z){ + int n; for(n=0; *z; n++, z++){ if( *z=='"' ){ n++; } } @@ -128030,14 +126917,13 @@ SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){ ** restored to its original value prior to this routine returning. */ SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ - const char *zTail; /* Pointer to the last "_" in zName */ + char *zTail; /* Pointer to the last "_" in zName */ Table *pTab; /* Table that zName is a shadow of */ - char *zCopy; zTail = strrchr(zName, '_'); if( zTail==0 ) return 0; - zCopy = sqlite3DbStrNDup(db, zName, (int)(zTail-zName)); - pTab = zCopy ? sqlite3FindTable(db, zCopy, 0) : 0; - sqlite3DbFree(db, zCopy); + *zTail = 0; + pTab = sqlite3FindTable(db, zName, 0); + *zTail = '_'; if( pTab==0 ) return 0; if( !IsVirtual(pTab) ) return 0; return sqlite3IsShadowTableOf(db, pTab, zName); @@ -128190,7 +127076,6 @@ SQLITE_PRIVATE void sqlite3EndTable( convertToWithoutRowidTable(pParse, p); } iDb = sqlite3SchemaToIndex(db, p->pSchema); - assert( iDb>=0 && iDb<=db->nDb ); #ifndef SQLITE_OMIT_CHECK /* Resolve names in all CHECK constraint expressions. @@ -128486,7 +127371,6 @@ SQLITE_PRIVATE void sqlite3CreateView( sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); - assert( iDb>=0 && iDb<db->nDb ); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; @@ -130083,7 +128967,6 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists goto exit_drop_index; } iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); - assert( iDb>=0 && iDb<db->nDb ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; @@ -131918,7 +130801,7 @@ static int vtabIsReadOnly(Parse *pParse, Table *pTab){ ** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS ** virtual tables if PRAGMA trusted_schema=ON. */ - if( (pParse->pToplevel!=0 || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL)) + if( pParse->pToplevel!=0 && pTab->u.vtab.p->eVtabRisk > ((pParse->db->flags & SQLITE_TrustedSchema)!=0) ){ @@ -132756,6 +131639,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( &iPartIdxLabel, pPrior, r1); sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); + sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */ sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); pPrior = pIdx; } @@ -133330,7 +132214,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3_result_error_nomem(context); return; } - sqlite3AtoF(zBuf, &r); + sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8); sqlite3_free(zBuf); } sqlite3_result_double(context, r); @@ -133968,7 +132852,7 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int sqlite3_str_appendf(pStr, "%!0.15g", r1); zVal = sqlite3_str_value(pStr); if( zVal ){ - sqlite3AtoF(zVal, &r2); + sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8); if( r1!=r2 ){ sqlite3_str_reset(pStr); sqlite3_str_appendf(pStr, "%!0.20e", r1); @@ -134065,7 +132949,7 @@ static void unistrFunc( } i = j = 0; while( i<nIn ){ - const char *z = strchr(&zIn[i],'\\'); + char *z = strchr(&zIn[i],'\\'); if( z==0 ){ n = nIn - i; memmove(&zOut[j], &zIn[i], n); @@ -134102,7 +132986,7 @@ static void unistrFunc( } } zOut[j] = 0; - sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8_ZT); + sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8); return; unistr_error: @@ -134195,7 +133079,7 @@ static void charFunc( } \ } *zOut = 0; - sqlite3_result_text64(context, (char*)z, zOut-z,sqlite3_free,SQLITE_UTF8_ZT); + sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); } /* @@ -134224,7 +133108,7 @@ static void hexFunc( } *z = 0; sqlite3_result_text64(context, zHex, (u64)(z-zHex), - sqlite3_free, SQLITE_UTF8_ZT); + sqlite3_free, SQLITE_UTF8); } } @@ -134562,7 +133446,7 @@ static void concatFuncCore( } z[j] = 0; assert( j<=n ); - sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8_ZT); + sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8); } /* @@ -135228,8 +134112,6 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0); - assert( pDef!=0 ); /* The sqlite3CreateFunc() call above cannot fail - ** because the "like" SQL-function already exists */ pDef->funcFlags |= flags; pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE; } @@ -137018,7 +135900,6 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ if( p ){ TriggerStep *pStep = p->step_list; - sqlite3SrcListDelete(dbMem, pStep->pSrc); sqlite3ExprDelete(dbMem, pStep->pWhere); sqlite3ExprListDelete(dbMem, pStep->pExprList); sqlite3SelectDelete(dbMem, pStep->pSelect); @@ -137238,7 +136119,6 @@ SQLITE_PRIVATE void sqlite3FkCheck( if( !IsOrdinaryTable(pTab) ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=00 && iDb<db->nDb ); zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the @@ -137686,14 +136566,14 @@ static Trigger *fkActionTrigger( pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ - sizeof(TriggerStep) /* Single step in trigger program */ + sizeof(TriggerStep) + /* Single step in trigger program */ + nFrom + 1 /* Space for pStep->zTarget */ ); if( pTrigger ){ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; - pStep->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - if( pStep->pSrc ){ - pStep->pSrc->a[0].zName = sqlite3DbStrNDup(db, zFrom, nFrom); - } + pStep->zTarget = (char *)&pStep[1]; + memcpy((char *)pStep->zTarget, zFrom, nFrom); + pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); @@ -141750,11 +140630,7 @@ struct sqlite3_api_routines { /* Version 3.51.0 and later */ int (*set_errmsg)(sqlite3*,int,const char*); int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); - /* Version 3.52.0 and later */ - void (*str_truncate)(sqlite3_str*,int); - void (*str_free)(sqlite3_str*); - int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*)); - int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*); + }; /* @@ -142093,11 +140969,6 @@ typedef int (*sqlite3_loadext_entry)( /* Version 3.51.0 and later */ #define sqlite3_set_errmsg sqlite3_api->set_errmsg #define sqlite3_db_status64 sqlite3_api->db_status64 -/* Version 3.52.0 and later */ -#define sqlite3_str_truncate sqlite3_api->str_truncate -#define sqlite3_str_free sqlite3_api->str_free -#define sqlite3_carray_bind sqlite3_api->carray_bind -#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -142624,17 +141495,7 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_setlk_timeout, /* Version 3.51.0 and later */ sqlite3_set_errmsg, - sqlite3_db_status64, - /* Version 3.52.0 and later */ - sqlite3_str_truncate, - sqlite3_str_free, -#ifdef SQLITE_ENABLE_CARRAY - sqlite3_carray_bind, - sqlite3_carray_bind_v2 -#else - 0, - 0 -#endif + sqlite3_db_status64 }; /* True if x is the directory separator character @@ -142736,42 +141597,33 @@ static int sqlite3LoadExtension( ** entry point name "sqlite3_extension_init" was not found, then ** construct an entry point name "sqlite3_X_init" where the X is ** replaced by the lowercase value of every ASCII alphabetic - ** character in the filename after the last "/" up to the first ".", - ** and skipping the first three characters if they are "lib". + ** character in the filename after the last "/" upto the first ".", + ** and eliding the first three characters if they are "lib". ** Examples: ** ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init - ** - ** If that still finds no entry point, repeat a second time but this - ** time include both alphabetic and numeric characters up to the first - ** ".". Example: - ** - ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example5_init */ if( xInit==0 && zProc==0 ){ int iFile, iEntry, c; int ncFile = sqlite3Strlen30(zFile); - int cnt = 0; zAltEntry = sqlite3_malloc64(ncFile+30); if( zAltEntry==0 ){ sqlite3OsDlClose(pVfs, handle); return SQLITE_NOMEM_BKPT; } - do{ - memcpy(zAltEntry, "sqlite3_", 8); - for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} - iFile++; - if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; - for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ - if( sqlite3Isalpha(c) || (cnt && sqlite3Isdigit(c)) ){ - zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; - } + memcpy(zAltEntry, "sqlite3_", 8); + for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} + iFile++; + if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; + for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ + if( sqlite3Isalpha(c) ){ + zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; } - memcpy(zAltEntry+iEntry, "_init", 6); - zEntry = zAltEntry; - xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); - }while( xInit==0 && (++cnt)<2 ); + } + memcpy(zAltEntry+iEntry, "_init", 6); + zEntry = zAltEntry; + xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); } if( xInit==0 ){ if( pzErrMsg ){ @@ -146843,8 +145695,7 @@ static void corruptSchema( static const char *azAlterType[] = { "rename", "drop column", - "add column", - "drop constraint" + "add column" }; *pData->pzErrMsg = sqlite3MPrintf(db, "error in %s %s after %s: %s", azObj[0], azObj[1], @@ -147927,7 +146778,7 @@ SQLITE_API int sqlite3_prepare16_v3( */ typedef struct DistinctCtx DistinctCtx; struct DistinctCtx { - u8 isTnct; /* 0: Not distinct. 1: DISTINCT 2: DISTINCT and ORDER BY */ + u8 isTnct; /* 0: Not distinct. 1: DISTICT 2: DISTINCT and ORDER BY */ u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */ int tabTnct; /* Ephemeral table used for DISTINCT processing */ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ @@ -148057,6 +146908,8 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew->iLimit = 0; pNew->iOffset = 0; pNew->selId = ++pParse->nSelect; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = 0; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1); pNew->pSrc = pSrc; @@ -148565,10 +147418,6 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){ pRight->fg.isOn = 1; p->selFlags |= SF_OnToWhere; } - - if( IsVirtual(pRightTab) && joinType==EP_OuterON && pRight->u1.pFuncArg ){ - p->selFlags |= SF_OnToWhere; - } } return 0; } @@ -149208,6 +148057,29 @@ static void selectInnerLoop( } switch( eDest ){ + /* In this mode, write each query result to the key of the temporary + ** table iParm. + */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT + case SRT_Union: { + int r1; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); + sqlite3ReleaseTempReg(pParse, r1); + break; + } + + /* Construct a record from the query result, but instead of + ** saving that record, use it as a key to delete elements from + ** the temporary table iParm. + */ + case SRT_Except: { + sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol); + break; + } +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + /* Store the result as data using a unique key. */ case SRT_Fifo: @@ -150320,8 +149192,8 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( } } if( zType ){ - const i64 k = strlen(zType); - n = strlen(pCol->zCnName); + const i64 k = sqlite3Strlen30(zType); + n = sqlite3Strlen30(pCol->zCnName); pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2); pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); if( pCol->zCnName ){ @@ -150494,9 +149366,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ ** function is responsible for ensuring that this structure is eventually ** freed. */ -static KeyInfo *multiSelectByMergeKeyInfo(Parse *pParse, Select *p, int nExtra){ +static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ ExprList *pOrderBy = p->pOrderBy; - int nOrderBy = (pOrderBy!=0) ? pOrderBy->nExpr : 0; + int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0; sqlite3 *db = pParse->db; KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); if( pRet ){ @@ -150629,7 +149501,7 @@ static void generateWithRecursiveQuery( regCurrent = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol); if( pOrderBy ){ - KeyInfo *pKeyInfo = multiSelectByMergeKeyInfo(pParse, p, 1); + KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1); sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0, (char*)pKeyInfo, P4_KEYINFO); destQueue.pOrderBy = pOrderBy; @@ -150638,28 +149510,8 @@ static void generateWithRecursiveQuery( } VdbeComment((v, "Queue table")); if( iDistinct ){ - /* Generate an ephemeral table used to enforce distinctness on the - ** output of the recursive part of the CTE. - */ - KeyInfo *pKeyInfo; /* Collating sequence for the result set */ - CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ - - assert( p->pNext==0 ); - assert( p->pEList!=0 ); - nCol = p->pEList->nExpr; - pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nCol, 1); - if( pKeyInfo ){ - for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ - *apColl = multiSelectCollSeq(pParse, p, i); - if( 0==*apColl ){ - *apColl = pParse->db->pDfltColl; - } - } - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iDistinct, nCol, 0, - (void*)pKeyInfo, P4_KEYINFO); - }else{ - assert( pParse->nErr>0 ); - } + p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0); + p->selFlags |= SF_UsesEphemeral; } /* Detach the ORDER BY clause from the compound SELECT */ @@ -150734,7 +149586,7 @@ static void generateWithRecursiveQuery( #endif /* SQLITE_OMIT_CTE */ /* Forward references */ -static int multiSelectByMerge( +static int multiSelectOrderBy( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ @@ -150883,26 +149735,12 @@ static int multiSelect( generateWithRecursiveQuery(pParse, p, &dest); }else #endif + + /* Compound SELECTs that have an ORDER BY clause are handled separately. + */ if( p->pOrderBy ){ - /* If the compound has an ORDER BY clause, then always use the merge - ** algorithm. */ - return multiSelectByMerge(pParse, p, pDest); - }else if( p->op!=TK_ALL ){ - /* If the compound is EXCEPT, INTERSECT, or UNION (anything other than - ** UNION ALL) then also always use the merge algorithm. However, the - ** multiSelectByMerge() routine requires that the compound have an - ** ORDER BY clause, and it doesn't right now. So invent one first. */ - Expr *pOne = sqlite3ExprInt32(db, 1); - p->pOrderBy = sqlite3ExprListAppend(pParse, 0, pOne); - if( pParse->nErr ) goto multi_select_end; - assert( p->pOrderBy!=0 ); - p->pOrderBy->a[0].u.x.iOrderByCol = 1; - return multiSelectByMerge(pParse, p, pDest); - }else{ - /* For a UNION ALL compound without ORDER BY, simply run the left - ** query, then run the right query */ - int addr = 0; - int nLimit = 0; /* Initialize to suppress harmless compiler warning */ + return multiSelectOrderBy(pParse, p, pDest); + }else{ #ifndef SQLITE_OMIT_EXPLAIN if( pPrior->pPrior==0 ){ @@ -150910,49 +149748,300 @@ static int multiSelect( ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); } #endif - assert( !pPrior->pLimit ); - pPrior->iLimit = p->iLimit; - pPrior->iOffset = p->iOffset; - pPrior->pLimit = sqlite3ExprDup(db, p->pLimit, 0); - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); - rc = sqlite3Select(pParse, pPrior, &dest); - sqlite3ExprDelete(db, pPrior->pLimit); - pPrior->pLimit = 0; - if( rc ){ - goto multi_select_end; - } - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); - VdbeComment((v, "Jump ahead if LIMIT reached")); - if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_OffsetLimit, - p->iLimit, p->iOffset+1, p->iOffset); - } - } - ExplainQueryPlan((pParse, 1, "UNION ALL")); - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); - rc = sqlite3Select(pParse, p, &dest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - if( p->pLimit - && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) - && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) - ){ - p->nSelectRow = sqlite3LogEst((u64)nLimit); - } - if( addr ){ - sqlite3VdbeJumpHere(v, addr); + + /* Generate code for the left and right SELECT statements. + */ + switch( p->op ){ + case TK_ALL: { + int addr = 0; + int nLimit = 0; /* Initialize to suppress harmless compiler warning */ + assert( !pPrior->pLimit ); + pPrior->iLimit = p->iLimit; + pPrior->iOffset = p->iOffset; + pPrior->pLimit = p->pLimit; + TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); + rc = sqlite3Select(pParse, pPrior, &dest); + pPrior->pLimit = 0; + if( rc ){ + goto multi_select_end; + } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit ){ + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); + VdbeComment((v, "Jump ahead if LIMIT reached")); + if( p->iOffset ){ + sqlite3VdbeAddOp3(v, OP_OffsetLimit, + p->iLimit, p->iOffset+1, p->iOffset); + } + } + ExplainQueryPlan((pParse, 1, "UNION ALL")); + TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); + rc = sqlite3Select(pParse, p, &dest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + if( p->pLimit + && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) + && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) + ){ + p->nSelectRow = sqlite3LogEst((u64)nLimit); + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; + } + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temp table holding result */ + u8 op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit; /* Saved values of p->nLimit */ + int addr; + int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */ + SelectDest uniondest; + + + testcase( p->op==TK_EXCEPT ); + testcase( p->op==TK_UNION ); + priorOp = SRT_Union; + if( dest.eDest==priorOp ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + assert( p->pLimit==0 ); /* Not allowed on leftward elements */ + unionTab = dest.iSDParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + assert( p->pOrderBy==0 ); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + } + + + /* Code the SELECT statements to our left + */ + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); + TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n")); + rc = sqlite3Select(pParse, pPrior, &uniondest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement + */ + if( p->op==TK_EXCEPT ){ + op = SRT_Except; + emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab); + VdbeCoverage(v); + }else{ + assert( p->op==TK_UNION ); + op = SRT_Union; + } + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + uniondest.eDest = op; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + sqlite3SelectOpName(p->op))); + TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n")); + rc = sqlite3Select(pParse, p, &uniondest); + testcase( rc!=SQLITE_OK ); + assert( p->pOrderBy==0 ); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->pOrderBy = 0; + if( p->op==TK_UNION ){ + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + } + if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass); + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->iLimit = 0; + p->iOffset = 0; + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); + assert( p->pEList || db->mallocFailed ); + if( dest.eDest!=priorOp && db->mallocFailed==0 ){ + int iCont, iBreak, iStart; + iBreak = sqlite3VdbeMakeLabel(pParse); + iCont = sqlite3VdbeMakeLabel(pParse); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); + iStart = sqlite3VdbeCurrentAddr(v); + selectInnerLoop(pParse, p, unionTab, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + } + break; + } + default: assert( p->op==TK_INTERSECT ); { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit; + int addr, iLimit, iOffset; + SelectDest intersectdest; + int r1; + int emptyBypass; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; + assert( p->pOrderBy==0 ); + + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); + TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n")); + rc = sqlite3Select(pParse, pPrior, &intersectdest); + if( rc ){ + goto multi_select_end; + } + + /* Initialize LIMIT counters before checking to see if the LHS + ** is empty, in case the jump is taken */ + iBreak = sqlite3VdbeMakeLabel(pParse); + computeLimitRegisters(pParse, p, iBreak); + emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v); + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + + /* Disable prior SELECTs and the LIMIT counters during the computation + ** of the RHS select */ + pLimit = p->pLimit; + iLimit = p->iLimit; + iOffset = p->iOffset; + p->pPrior = 0; + p->pLimit = 0; + p->iLimit = 0; + p->iOffset = 0; + + intersectdest.iSDParm = tab2; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + sqlite3SelectOpName(p->op))); + TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n")); + rc = sqlite3Select(pParse, p, &intersectdest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + if( p->nSelectRow>pPrior->nSelectRow ){ + p->nSelectRow = pPrior->nSelectRow; + } + sqlite3ExprDelete(db, p->pLimit); + + /* Reinstate the LIMIT counters prior to running the final intersect */ + p->pLimit = pLimit; + p->iLimit = iLimit; + p->iOffset = iOffset; + + /* Generate code to take the intersection of the two temporary + ** tables. + */ + if( rc ) break; + assert( p->pEList ); + sqlite3VdbeAddOp1(v, OP_Rewind, tab1); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); + iCont = sqlite3VdbeMakeLabel(pParse); + sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); + VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, r1); + selectInnerLoop(pParse, p, tab1, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); + sqlite3VdbeJumpHere(v, emptyBypass); + sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); + break; + } } -#ifndef SQLITE_OMIT_EXPLAIN + + #ifndef SQLITE_OMIT_EXPLAIN if( p->pNext==0 ){ ExplainQueryPlanPop(pParse); } -#endif + #endif + } + if( pParse->nErr ) goto multi_select_end; + + /* Compute collating sequences used by + ** temporary tables needed to implement the compound select. + ** Attach the KeyInfo structure to all temporary tables. + ** + ** This section is run by the right-most SELECT statement only. + ** SELECT statements to the left always skip this part. The right-most + ** SELECT might also skip this part if it has no ORDER BY clause and + ** no temp tables are required. + */ + if( p->selFlags & SF_UsesEphemeral ){ + int i; /* Loop counter */ + KeyInfo *pKeyInfo; /* Collating sequence for the result set */ + Select *pLoop; /* For looping through SELECT statements */ + CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ + int nCol; /* Number of columns in result set */ + + assert( p->pNext==0 ); + assert( p->pEList!=0 ); + nCol = p->pEList->nExpr; + pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); + if( !pKeyInfo ){ + rc = SQLITE_NOMEM_BKPT; + goto multi_select_end; + } + for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ + *apColl = multiSelectCollSeq(pParse, p, i); + if( 0==*apColl ){ + *apColl = db->pDfltColl; + } + } + + for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ + for(i=0; i<2; i++){ + int addr = pLoop->addrOpenEphm[i]; + if( addr<0 ){ + /* If [0] is unused then [1] is also unused. So we can + ** always safely abort as soon as the first unused slot is found */ + assert( pLoop->addrOpenEphm[1]<0 ); + break; + } + sqlite3VdbeChangeP2(v, addr, nCol); + sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo), + P4_KEYINFO); + pLoop->addrOpenEphm[i] = -1; + } + } + sqlite3KeyInfoUnref(pKeyInfo); } multi_select_end: @@ -150984,8 +150073,8 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ ** Code an output subroutine for a coroutine implementation of a ** SELECT statement. ** -** The data to be output is contained in an array of pIn->nSdst registers -** starting at register pIn->iSdst. pDest is where the output should +** The data to be output is contained in pIn->iSdst. There are +** pIn->nSdst columns to be output. pDest is where the output should ** be sent. ** ** regReturn is the number of the register holding the subroutine @@ -151014,8 +150103,6 @@ static int generateOutputSubroutine( int iContinue; int addr; - assert( pIn->eDest==SRT_Coroutine ); - addr = sqlite3VdbeCurrentAddr(v); iContinue = sqlite3VdbeMakeLabel(pParse); @@ -151037,60 +150124,23 @@ static int generateOutputSubroutine( */ codeOffset(v, p->iOffset, iContinue); + assert( pDest->eDest!=SRT_Exists ); + assert( pDest->eDest!=SRT_Table ); switch( pDest->eDest ){ /* Store the result as data using a unique key. */ - case SRT_Fifo: - case SRT_DistFifo: - case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); - int iParm = pDest->iSDParm; - testcase( pDest->eDest==SRT_Table ); - testcase( pDest->eDest==SRT_EphemTab ); - testcase( pDest->eDest==SRT_Fifo ); - testcase( pDest->eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); -#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) - /* A destination of SRT_Table and a non-zero iSDParm2 parameter means - ** that this is an "UPDATE ... FROM" on a virtual table or view. In this - ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. - ** This does not affect operation in any way - it just allows MakeRecord - ** to process OPFLAG_NOCHANGE values without an assert() failing. */ - if( pDest->eDest==SRT_Table && pDest->iSDParm2 ){ - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); - } -#endif -#ifndef SQLITE_OMIT_CTE - if( pDest->eDest==SRT_DistFifo ){ - /* If the destination is DistFifo, then cursor (iParm+1) is open - ** on an ephemeral index that is used to enforce uniqueness on the - ** total result. At this point, we are processing the setup portion - ** of the recursive CTE using the merge algorithm, so the results are - ** guaranteed to be unique anyhow. But we still need to populate the - ** (iParm+1) cursor for use by the subsequent recursive phase. - */ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1, - pIn->iSdst, pIn->nSdst); - } -#endif - sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); + sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); + sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); sqlite3ReleaseTempReg(pParse, r1); break; } - /* If any row exist in the result set, record that fact and abort. - */ - case SRT_Exists: { - sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm); - /* The LIMIT clause will terminate the loop for us */ - break; - } - #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)". */ @@ -151137,51 +150187,9 @@ static int generateOutputSubroutine( break; } -#ifndef SQLITE_OMIT_CTE - /* Write the results into a priority queue that is order according to - ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an - ** index with pSO->nExpr+2 columns. Build a key using pSO for the first - ** pSO->nExpr columns, then make sure all keys are unique by adding a - ** final OP_Sequence column. The last column is the record as a blob. - */ - case SRT_DistQueue: - case SRT_Queue: { - int nKey; - int r1, r2, r3, ii; - ExprList *pSO; - int iParm = pDest->iSDParm; - pSO = pDest->pOrderBy; - assert( pSO ); - nKey = pSO->nExpr; - r1 = sqlite3GetTempReg(pParse); - r2 = sqlite3GetTempRange(pParse, nKey+2); - r3 = r2+nKey+1; - - sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r3); - if( pDest->eDest==SRT_DistQueue ){ - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); - } - for(ii=0; ii<nKey; ii++){ - sqlite3VdbeAddOp2(v, OP_SCopy, - pIn->iSdst + pSO->a[ii].u.x.iOrderByCol - 1, - r2+ii); - } - sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); - sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempRange(pParse, r2, nKey+2); - break; - } -#endif /* SQLITE_OMIT_CTE */ - - /* Ignore the output */ - case SRT_Discard: { - break; - } - /* If none of the above, then the result destination must be - ** SRT_Output. + ** SRT_Output. This routine is never called with any other + ** destination other than the ones handled above or SRT_Output. ** ** For SRT_Output, results are stored in a sequence of registers. ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to @@ -151209,9 +150217,8 @@ static int generateOutputSubroutine( } /* -** Generate code for a compound SELECT statement using a merge -** algorithm. The compound must have an ORDER BY clause for this -** to work. +** Alternative compound select code generator for cases when there +** is an ORDER BY clause. ** ** We assume a query of the following form: ** @@ -151228,7 +150235,7 @@ static int generateOutputSubroutine( ** ** outB: Move the output of the selectB coroutine into the output ** of the compound query. (Only generated for UNION and -** UNION ALL. EXCEPT and INTERSECT never output a row that +** UNION ALL. EXCEPT and INSERTSECT never output a row that ** appears only in B.) ** ** AltB: Called when there is data from both coroutines and A<B. @@ -151281,8 +150288,10 @@ static int generateOutputSubroutine( ** AeqB: ... ** AgtB: ... ** Init: initialize coroutine registers -** yield coA, on eof goto EofA -** yield coB, on eof goto EofB +** yield coA +** if eof(A) goto EofA +** yield coB +** if eof(B) goto EofB ** Cmpr: Compare A, B ** Jump AltB, AeqB, AgtB ** End: ... @@ -151290,10 +150299,10 @@ static int generateOutputSubroutine( ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not ** actually called using Gosub and they do not Return. EofA and EofB loop ** until all data is exhausted then jump to the "end" label. AltB, AeqB, -** and AgtB jump to either Cmpr or to one of EofA or EofB. +** and AgtB jump to either L2 or to one of EofA or EofB. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT -static int multiSelectByMerge( +static int multiSelectOrderBy( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ @@ -151365,8 +150374,10 @@ static int multiSelectByMerge( if( pItem->u.x.iOrderByCol==i ) break; } if( j==nOrderBy ){ - Expr *pNew = sqlite3ExprInt32(db, i); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return SQLITE_NOMEM_BKPT; + pNew->flags |= EP_IntValue; + pNew->u.iValue = i; p->pOrderBy = pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i; } @@ -151374,29 +150385,26 @@ static int multiSelectByMerge( } /* Compute the comparison permutation and keyinfo that is used with - ** the permutation to determine if the next row of results comes - ** from selectA or selectB. Also add literal collations to the - ** ORDER BY clause terms so that when selectA and selectB are - ** evaluated, they use the correct collation. + ** the permutation used to determine if the next + ** row of results comes from selectA or selectB. Also add explicit + ** collations to the ORDER BY clause terms so that when the subqueries + ** to the right and the left are evaluated, they use the correct + ** collation. */ aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1)); if( aPermute ){ struct ExprList_item *pItem; - int bKeep = 0; aPermute[0] = nOrderBy; for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ assert( pItem!=0 ); assert( pItem->u.x.iOrderByCol>0 ); assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; - if( aPermute[i]!=(u32)i-1 ) bKeep = 1; - } - if( bKeep==0 ){ - sqlite3DbFreeNN(db, aPermute); - aPermute = 0; } + pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); + }else{ + pKeyMerge = 0; } - pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1); /* Allocate a range of temporary registers and the KeyInfo needed ** for the logic that removes duplicate result rows when the @@ -151475,7 +150483,7 @@ static int multiSelectByMerge( */ addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); - VdbeComment((v, "SUBR: next-A")); + VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; ExplainQueryPlan((pParse, 1, "LEFT")); sqlite3Select(pParse, pPrior, &destA); @@ -151487,7 +150495,7 @@ static int multiSelectByMerge( */ addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); - VdbeComment((v, "SUBR: next-B")); + VdbeComment((v, "right SELECT")); savedLimit = p->iLimit; savedOffset = p->iOffset; p->iLimit = regLimitB; @@ -151501,7 +150509,7 @@ static int multiSelectByMerge( /* Generate a subroutine that outputs the current row of the A ** select as the next output row of the compound select. */ - VdbeNoopComment((v, "SUBR: out-A")); + VdbeNoopComment((v, "Output routine for A")); addrOutA = generateOutputSubroutine(pParse, p, &destA, pDest, regOutA, regPrev, pKeyDup, labelEnd); @@ -151510,7 +150518,7 @@ static int multiSelectByMerge( ** select as the next output row of the compound select. */ if( op==TK_ALL || op==TK_UNION ){ - VdbeNoopComment((v, "SUBR: out-B")); + VdbeNoopComment((v, "Output routine for B")); addrOutB = generateOutputSubroutine(pParse, p, &destB, pDest, regOutB, regPrev, pKeyDup, labelEnd); @@ -151523,12 +150531,10 @@ static int multiSelectByMerge( if( op==TK_EXCEPT || op==TK_INTERSECT ){ addrEofA_noB = addrEofA = labelEnd; }else{ - VdbeNoopComment((v, "SUBR: eof-A")); + VdbeNoopComment((v, "eof-A subroutine")); addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - VdbeComment((v, "out-B")); addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); VdbeCoverage(v); - VdbeComment((v, "next-B")); sqlite3VdbeGoto(v, addrEofA); p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); } @@ -151540,20 +150546,17 @@ static int multiSelectByMerge( addrEofB = addrEofA; if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; }else{ - VdbeNoopComment((v, "SUBR: eof-B")); + VdbeNoopComment((v, "eof-B subroutine")); addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - VdbeComment((v, "out-A")); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); - VdbeComment((v, "next-A")); sqlite3VdbeGoto(v, addrEofB); } /* Generate code to handle the case of A<B */ + VdbeNoopComment((v, "A-lt-B subroutine")); addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - VdbeComment((v, "out-A")); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); - VdbeComment((v, "next-A")); sqlite3VdbeGoto(v, labelCmpr); /* Generate code to handle the case of A==B @@ -151564,48 +150567,36 @@ static int multiSelectByMerge( addrAeqB = addrAltB; addrAltB++; }else{ - addrAeqB = addrAltB + 1; + VdbeNoopComment((v, "A-eq-B subroutine")); + addrAeqB = + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); + sqlite3VdbeGoto(v, labelCmpr); } /* Generate code to handle the case of A>B */ + VdbeNoopComment((v, "A-gt-B subroutine")); addrAgtB = sqlite3VdbeCurrentAddr(v); if( op==TK_ALL || op==TK_UNION ){ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - VdbeComment((v, "out-B")); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - VdbeComment((v, "next-B")); - sqlite3VdbeGoto(v, labelCmpr); - }else{ - addrAgtB++; /* Just do next-B. Might as well use the next-B call - ** in the next code block */ } + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); + sqlite3VdbeGoto(v, labelCmpr); /* This code runs once to initialize everything. */ sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); - VdbeComment((v, "next-A")); - /* v--- Also the A>B case for EXCEPT and INTERSECT */ sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - VdbeComment((v, "next-B")); /* Implement the main merge loop */ - if( aPermute!=0 ){ - sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); - } sqlite3VdbeResolveLabel(v, labelCmpr); + sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO); - if( aPermute!=0 ){ - sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); - } - sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); - VdbeCoverageIf(v, op==TK_ALL); - VdbeCoverageIf(v, op==TK_UNION); - VdbeCoverageIf(v, op==TK_EXCEPT); - VdbeCoverageIf(v, op==TK_INTERSECT); + sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); + sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v); /* Jump to the this point in order to terminate the query. */ @@ -152522,7 +151513,7 @@ static int flattenSubquery( } pSubitem->fg.jointype |= jointype; - /* Begin substituting subquery result set expressions for + /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. ** ** Example: @@ -152534,7 +151525,7 @@ static int flattenSubquery( ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ - if( pSub->pOrderBy ){ + if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){ /* At this point, any non-zero iOrderByCol values indicate that the ** ORDER BY column expression is identical to the iOrderByCol'th ** expression returned by SELECT statement pSub. Since these values @@ -152542,9 +151533,9 @@ static int flattenSubquery( ** zero them before transferring the ORDER BY clause. ** ** Not doing this may cause an error if a subsequent call to this - ** function attempts to flatten a compound sub-query into pParent. - ** See ticket [d11a6e908f]. - */ + ** function attempts to flatten a compound sub-query into pParent + ** (the only way this can happen is if the compound sub-query is + ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ ExprList *pOrderBy = pSub->pOrderBy; for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].u.x.iOrderByCol = 0; @@ -153162,16 +152153,6 @@ static int pushDownWhereTerms( x.pEList = pSubq->pEList; x.pCList = findLeftmostExprlist(pSubq); pNew = substExpr(&x, pNew); - assert( pNew!=0 || pParse->nErr!=0 ); - if( pParse->nErr==0 && pNew->op==TK_IN && ExprUseXSelect(pNew) ){ - assert( pNew->x.pSelect!=0 ); - pNew->x.pSelect->selFlags |= SF_ClonedRhsIn; - assert( pWhere!=0 ); - assert( pWhere->op==TK_IN ); - assert( ExprUseXSelect(pWhere) ); - assert( pWhere->x.pSelect!=0 ); - pWhere->x.pSelect->selFlags |= SF_ClonedRhsIn; - } #ifndef SQLITE_OMIT_WINDOWFUNC if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){ /* Restriction 6c has prevented push-down in this case */ @@ -153406,14 +152387,14 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){ ** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2) ** ORDER BY ... COLLATE ... ** -** This transformation is necessary because the multiSelectByMerge() routine +** This transformation is necessary because the multiSelectOrderBy() routine ** above that generates the code for a compound SELECT with an ORDER BY clause ** uses a merge algorithm that requires the same collating sequence on the ** result columns as on the ORDER BY clause. See ticket ** http://sqlite.org/src/info/6709574d2a ** ** This transformation is only needed for EXCEPT, INTERSECT, and UNION. -** The UNION ALL operator works fine with multiSelectByMerge() even when +** The UNION ALL operator works fine with multiSelectOrderBy() even when ** there are COLLATE terms in the ORDER BY. */ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ @@ -153959,7 +152940,7 @@ static int selectExpander(Walker *pWalker, Select *p){ } #ifndef SQLITE_OMIT_VIRTUALTABLE else if( ALWAYS(IsVirtual(pTab)) - && (pFrom->fg.fromDDL || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL)) + && pFrom->fg.fromDDL && ALWAYS(pTab->u.vtab.p!=0) && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) ){ @@ -154912,7 +153893,7 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ && pExpr->pAggInfo==0 ){ sqlite3 *db = pWalker->pParse->db; - Expr *pNew = sqlite3ExprInt32(db, 1); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1"); if( pNew ){ Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); @@ -155263,6 +154244,7 @@ static SQLITE_NOINLINE void existsToJoin( ExprSetProperty(pWhere, EP_IntValue); assert( p->pWhere!=0 ); pSub->pSrc->a[0].fg.fromExists = 1; + pSub->pSrc->a[0].fg.jointype |= JT_CROSS; p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc); if( pSubWhere ){ p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere); @@ -155290,7 +154272,6 @@ typedef struct CheckOnCtx CheckOnCtx; struct CheckOnCtx { SrcList *pSrc; /* SrcList for this context */ int iJoin; /* Cursor numbers must be =< than this */ - int bFuncArg; /* True for table-function arg */ CheckOnCtx *pParent; /* Parent context */ }; @@ -155342,9 +154323,7 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){ if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){ if( pCtx->iJoin && iTab>pCtx->iJoin ){ sqlite3ErrorMsg(pWalker->pParse, - "%s references tables to its right", - (pCtx->bFuncArg ? "table-function argument" : "ON clause") - ); + "ON clause references tables to its right"); return WRC_Abort; } break; @@ -155379,10 +154358,9 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){ ** Check all ON clauses in pSelect to verify that they do not reference ** columns to the right. */ -SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect){ +static void selectCheckOnClauses(Parse *pParse, Select *pSelect){ Walker w; CheckOnCtx sCtx; - int ii; assert( pSelect->selFlags & SF_OnToWhere ); assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 ); memset(&w, 0, sizeof(w)); @@ -155392,46 +154370,8 @@ SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect){ w.u.pCheckOnCtx = &sCtx; memset(&sCtx, 0, sizeof(sCtx)); sCtx.pSrc = pSelect->pSrc; - sqlite3WalkExpr(&w, pSelect->pWhere); + sqlite3WalkExprNN(&w, pSelect->pWhere); pSelect->selFlags &= ~SF_OnToWhere; - - /* Check for any table-function args that are attached to virtual tables - ** on the RHS of an outer join. They are subject to the same constraints - ** as ON clauses. */ - sCtx.bFuncArg = 1; - for(ii=0; ii<pSelect->pSrc->nSrc; ii++){ - SrcItem *pItem = &pSelect->pSrc->a[ii]; - if( pItem->fg.isTabFunc - && (pItem->fg.jointype & JT_OUTER) - ){ - sCtx.iJoin = pItem->iCursor; - sqlite3WalkExprList(&w, pItem->u1.pFuncArg); - } - } -} - -/* -** If p2 exists and p1 and p2 have the same number of terms, then change -** every term of p1 to have the same sort order as p2 and return true. -** -** If p2 is NULL or p1 and p2 are different lengths, then make no changes -** and return false. -** -** p1 must be non-NULL. -*/ -static int sqlite3CopySortOrder(ExprList *p1, ExprList *p2){ - assert( p1 ); - if( p2 && p1->nExpr==p2->nExpr ){ - int ii; - for(ii=0; ii<p1->nExpr; ii++){ - u8 sortFlags; - sortFlags = p2->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC; - p1->a[ii].fg.sortFlags = sortFlags; - } - return 1; - }else{ - return 0; - } } /* @@ -155529,7 +154469,8 @@ SQLITE_PRIVATE int sqlite3Select( assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue ); assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue ); if( IgnorableDistinct(pDest) ){ - assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Discard || + assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || + pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard || pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo ); /* All of these destinations are also able to ignore the ORDER BY clause */ if( p->pOrderBy ){ @@ -155545,6 +154486,7 @@ SQLITE_PRIVATE int sqlite3Select( p->pOrderBy = 0; } p->selFlags &= ~(u32)SF_Distinct; + p->selFlags |= SF_NoopOrderBy; } sqlite3SelectPrep(pParse, p, 0); if( pParse->nErr ){ @@ -155559,6 +154501,18 @@ SQLITE_PRIVATE int sqlite3Select( } #endif + /* If the SELECT statement contains ON clauses that were moved into + ** the WHERE clause, go through and verify that none of the terms + ** in the ON clauses reference tables to the right of the ON clause. + ** Do this now, after name resolution, but before query flattening + */ + if( p->selFlags & SF_OnToWhere ){ + selectCheckOnClauses(pParse, p); + if( pParse->nErr ){ + goto select_end; + } + } + /* If the SF_UFSrcCheck flag is set, then this function is being called ** as part of populating the temp table for an UPDATE...FROM statement. ** In this case, it is an error if the target object (pSrc->a[0]) name @@ -156072,8 +155026,7 @@ SQLITE_PRIVATE int sqlite3Select( ** BY and DISTINCT, and an index or separate temp-table for the other. */ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct - && sqlite3CopySortOrder(pEList, sSort.pOrderBy) - && sqlite3ExprListCompare(pEList, sSort.pOrderBy, -1)==0 + && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 && OptimizationEnabled(db, SQLITE_GroupByOrder) #ifndef SQLITE_OMIT_WINDOWFUNC && p->pWin==0 @@ -156287,10 +155240,21 @@ SQLITE_PRIVATE int sqlite3Select( ** but not actually sorted. Either way, record the fact that the ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp ** variable. */ - if( sqlite3CopySortOrder(pGroupBy, sSort.pOrderBy) - && sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 - ){ - orderByGrp = 1; + if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){ + int ii; + /* The GROUP BY processing doesn't care whether rows are delivered in + ** ASC or DESC order - only that each group is returned contiguously. + ** So set the ASC/DESC flags in the GROUP BY to match those in the + ** ORDER BY to maximize the chances of rows being delivered in an + ** order that makes the ORDER BY redundant. */ + for(ii=0; ii<pGroupBy->nExpr; ii++){ + u8 sortFlags; + sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC; + pGroupBy->a[ii].fg.sortFlags = sortFlags; + } + if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ + orderByGrp = 1; + } } }else{ assert( 0==sqlite3LogEst(1) ); @@ -157100,7 +156064,7 @@ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerS sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); sqlite3UpsertDelete(db, pTmp->pUpsert); - sqlite3SrcListDelete(db, pTmp->pSrc); + sqlite3SrcListDelete(db, pTmp->pFrom); sqlite3DbFree(db, pTmp->zSpan); sqlite3DbFree(db, pTmp); @@ -157289,16 +156253,11 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( } } - /* NB: The SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES compile-time option is - ** experimental and unsupported. Do not use it unless understand the - ** implications and you cannot get by without this capability. */ -#if !defined(SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES) /* Experimental */ /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); goto trigger_cleanup; } -#endif /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. @@ -157410,7 +156369,6 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); - assert( iDb>=00 && iDb<db->nDb ); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; @@ -157445,12 +156403,12 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( if( sqlite3ReadOnlyShadowTables(db) ){ TriggerStep *pStep; for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){ - if( pStep->pSrc!=0 - && sqlite3ShadowTableName(db, pStep->pSrc->a[0].zName) + if( pStep->zTarget!=0 + && sqlite3ShadowTableName(db, pStep->zTarget) ){ sqlite3ErrorMsg(pParse, "trigger \"%s\" may not write to shadow table \"%s\"", - pTrig->zName, pStep->pSrc->a[0].zName); + pTrig->zName, pStep->zTarget); goto triggerfinish_cleanup; } } @@ -157541,39 +156499,26 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep( static TriggerStep *triggerStepAllocate( Parse *pParse, /* Parser context */ u8 op, /* Trigger opcode */ - SrcList *pTabList, /* Target table */ + Token *pName, /* The target name */ const char *zStart, /* Start of SQL text */ const char *zEnd /* End of SQL text */ ){ - Trigger *pNew = pParse->pNewTrigger; sqlite3 *db = pParse->db; - TriggerStep *pTriggerStep = 0; + TriggerStep *pTriggerStep; - if( pParse->nErr==0 ){ - if( pNew - && pNew->pSchema!=db->aDb[1].pSchema - && pTabList->a[0].u4.zDatabase - ){ - sqlite3ErrorMsg(pParse, - "qualified table names are not allowed on INSERT, UPDATE, and DELETE " - "statements within triggers"); - }else{ - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); - if( pTriggerStep ){ - pTriggerStep->pSrc = sqlite3SrcListDup(db, pTabList, EXPRDUP_REDUCE); - pTriggerStep->op = op; - pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); - if( pTriggerStep->pSrc && IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, - pTriggerStep->pSrc->a[0].zName, - pTabList->a[0].zName - ); - } - } + if( pParse->nErr ) return 0; + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); + if( pTriggerStep ){ + char *z = (char*)&pTriggerStep[1]; + memcpy(z, pName->z, pName->n); + sqlite3Dequote(z); + pTriggerStep->zTarget = z; + pTriggerStep->op = op; + pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); + if( IN_RENAME_OBJECT ){ + sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName); } } - - sqlite3SrcListDelete(db, pTabList); return pTriggerStep; } @@ -157586,7 +156531,7 @@ static TriggerStep *triggerStepAllocate( */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( Parse *pParse, /* Parser */ - SrcList *pTabList, /* Table to INSERT into */ + Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ Select *pSelect, /* A SELECT statement that supplies values */ u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ @@ -157599,7 +156544,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( assert(pSelect != 0 || db->mallocFailed); - pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTabList, zStart, zEnd); + pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd); if( pTriggerStep ){ if( IN_RENAME_OBJECT ){ pTriggerStep->pSelect = pSelect; @@ -157631,7 +156576,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( Parse *pParse, /* Parser */ - SrcList *pTabList, /* Name of the table to be updated */ + Token *pTableName, /* Name of the table to be updated */ SrcList *pFrom, /* FROM clause for an UPDATE-FROM, or NULL */ ExprList *pEList, /* The SET clause: list of column and new values */ Expr *pWhere, /* The WHERE clause */ @@ -157642,36 +156587,21 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTabList, zStart, zEnd); + pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd); if( pTriggerStep ){ - SrcList *pFromDup = 0; if( IN_RENAME_OBJECT ){ pTriggerStep->pExprList = pEList; pTriggerStep->pWhere = pWhere; - pFromDup = pFrom; + pTriggerStep->pFrom = pFrom; pEList = 0; pWhere = 0; pFrom = 0; }else{ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pFromDup = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE); + pTriggerStep->pFrom = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE); } pTriggerStep->orconf = orconf; - - if( pFromDup && !IN_RENAME_OBJECT){ - Select *pSub; - Token as = {0, 0}; - pSub = sqlite3SelectNew(pParse, 0, pFromDup, 0,0,0,0, SF_NestedFrom, 0); - pFromDup = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &as, pSub ,0); - } - if( pFromDup && pTriggerStep->pSrc ){ - pTriggerStep->pSrc = sqlite3SrcListAppendList( - pParse, pTriggerStep->pSrc, pFromDup - ); - }else{ - sqlite3SrcListDelete(db, pFromDup); - } } sqlite3ExprListDelete(db, pEList); sqlite3ExprDelete(db, pWhere); @@ -157686,7 +156616,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( Parse *pParse, /* Parser */ - SrcList *pTabList, /* The table from which rows are deleted */ + Token *pTableName, /* The table from which rows are deleted */ Expr *pWhere, /* The WHERE clause */ const char *zStart, /* Start of SQL text */ const char *zEnd /* End of SQL text */ @@ -157694,7 +156624,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTabList, zStart, zEnd); + pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd); if( pTriggerStep ){ if( IN_RENAME_OBJECT ){ pTriggerStep->pWhere = pWhere; @@ -157894,7 +156824,6 @@ static SQLITE_NOINLINE Trigger *triggersReallyExist( p = pList; if( (pParse->db->flags & SQLITE_EnableTrigger)==0 && pTab->pTrigger!=0 - && sqlite3SchemaToIndex(pParse->db, pTab->pTrigger->pSchema)!=1 ){ /* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that ** only TEMP triggers are allowed. Truncate the pList so that it @@ -157957,6 +156886,52 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist( return triggersReallyExist(pParse,pTab,op,pChanges,pMask); } +/* +** Convert the pStep->zTarget string into a SrcList and return a pointer +** to that SrcList. +** +** This routine adds a specific database name, if needed, to the target when +** forming the SrcList. This prevents a trigger in one database from +** referring to a target in another database. An exception is when the +** trigger is in TEMP in which case it can refer to any other database it +** wants. +*/ +SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc( + Parse *pParse, /* The parsing context */ + TriggerStep *pStep /* The trigger containing the target token */ +){ + sqlite3 *db = pParse->db; + SrcList *pSrc; /* SrcList to be returned */ + char *zName = sqlite3DbStrDup(db, pStep->zTarget); + pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); + assert( pSrc==0 || pSrc->nSrc==1 ); + assert( zName || pSrc==0 ); + if( pSrc ){ + Schema *pSchema = pStep->pTrig->pSchema; + pSrc->a[0].zName = zName; + if( pSchema!=db->aDb[1].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); + if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){ + Select *pSubquery; + Token as; + pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0); + as.n = 0; + as.z = 0; + pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); + } + pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup); + } + }else{ + sqlite3DbFree(db, zName); + } + return pSrc; +} + /* ** Return true if the pExpr term from the RETURNING clause argument ** list is of the form "*". Raise an error if the terms if of the @@ -158222,7 +157197,7 @@ static int codeTriggerProgram( switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, - sqlite3SrcListDup(db, pStep->pSrc, 0), + sqlite3TriggerStepSrc(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), pParse->eOrconf, 0, 0, 0 @@ -158232,7 +157207,7 @@ static int codeTriggerProgram( } case TK_INSERT: { sqlite3Insert(pParse, - sqlite3SrcListDup(db, pStep->pSrc, 0), + sqlite3TriggerStepSrc(pParse, pStep), sqlite3SelectDup(db, pStep->pSelect, 0), sqlite3IdListDup(db, pStep->pIdList), pParse->eOrconf, @@ -158243,7 +157218,7 @@ static int codeTriggerProgram( } case TK_DELETE: { sqlite3DeleteFrom(pParse, - sqlite3SrcListDup(db, pStep->pSrc, 0), + sqlite3TriggerStepSrc(pParse, pStep), sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 ); sqlite3VdbeAddOp0(v, OP_ResetCount); @@ -160565,11 +159540,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( pDb = &db->aDb[nDb]; assert( strcmp(pDb->zDbSName,zDbVacuum)==0 ); pTemp = pDb->pBt; - nRes = sqlite3BtreeGetRequestedReserve(pMain); if( pOut ){ sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp)); i64 sz = 0; - const char *zFilename; if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){ rc = SQLITE_ERROR; sqlite3SetString(pzErrMsg, db, "output file already exists"); @@ -160581,16 +159554,8 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( ** they are for the database being vacuumed, except that PAGER_CACHESPILL ** is always set. */ pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK); - - /* If the VACUUM INTO target file is a URI filename and if the - ** "reserve=N" query parameter is present, reset the reserve to the - ** amount specified, if the amount is within range */ - zFilename = sqlite3BtreeGetFilename(pTemp); - if( ALWAYS(zFilename) ){ - int nNew = (int)sqlite3_uri_int64(zFilename, "reserve", nRes); - if( nNew>=0 && nNew<=255 ) nRes = nNew; - } } + nRes = sqlite3BtreeGetRequestedReserve(pMain); sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); @@ -164395,7 +163360,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){ int iTab = pParse->nTab++; int iCache = ++pParse->nMem; - sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab, 0); + sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab); sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache); }else{ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); @@ -166054,14 +165019,13 @@ static int isLikeOrGlob( ){ int isNum; double rDummy; - assert( zNew[iTo]==0 ); - isNum = sqlite3AtoF(zNew, &rDummy); + isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); if( isNum<=0 ){ if( iTo==1 && zNew[0]=='-' ){ isNum = +1; }else{ zNew[iTo-1]++; - isNum = sqlite3AtoF(zNew, &rDummy); + isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); zNew[iTo-1]--; } } @@ -166104,34 +165068,6 @@ static int isLikeOrGlob( } #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ -/* -** If pExpr is one of "like", "glob", "match", or "regexp", then -** return the corresponding SQLITE_INDEX_CONSTRAINT_xxxx value. -** If not, return 0. -** -** pExpr is guaranteed to be a TK_FUNCTION. -*/ -SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr *pExpr){ - static const struct { - const char *zOp; - unsigned char eOp; - } aOp[] = { - { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, - { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, - { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, - { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } - }; - int i; - assert( pExpr->op==TK_FUNCTION ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - for(i=0; i<ArraySize(aOp); i++){ - if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ - return aOp[i].eOp; - } - } - return 0; -} - #ifndef SQLITE_OMIT_VIRTUALTABLE /* @@ -166168,6 +165104,15 @@ static int isAuxiliaryVtabOperator( Expr **ppRight /* Expression to left of MATCH/op2 */ ){ if( pExpr->op==TK_FUNCTION ){ + static const struct Op2 { + const char *zOp; + unsigned char eOp2; + } aOp[] = { + { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, + { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, + { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, + { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } + }; ExprList *pList; Expr *pCol; /* Column reference */ int i; @@ -166187,11 +165132,16 @@ static int isAuxiliaryVtabOperator( */ pCol = pList->a[1].pExpr; assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) ); - if( ExprIsVtab(pCol) && (i = sqlite3ExprIsLikeOperator(pExpr))!=0 ){ - *peOp2 = i; - *ppRight = pList->a[0].pExpr; - *ppLeft = pCol; - return 1; + if( ExprIsVtab(pCol) ){ + for(i=0; i<ArraySize(aOp); i++){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ + *peOp2 = aOp[i].eOp2; + *ppRight = pList->a[0].pExpr; + *ppLeft = pCol; + return 1; + } + } } /* We can also match against the first column of overloaded @@ -166325,22 +165275,16 @@ static void whereCombineDisjuncts( Expr *pNew; /* New virtual expression */ int op; /* Operator for the combined expression */ int idxNew; /* Index in pWC of the next virtual term */ - Expr *pA, *pB; /* Expressions associated with pOne and pTwo */ if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return; if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; - pA = pOne->pExpr; - pB = pTwo->pExpr; - assert( pA->pLeft!=0 && pA->pRight!=0 ); - assert( pB->pLeft!=0 && pB->pRight!=0 ); - if( sqlite3ExprCompare(0,pA->pLeft, pB->pLeft, -1) ) return; - if( sqlite3ExprCompare(0,pA->pRight, pB->pRight,-1) ) return; - if( ExprHasProperty(pA,EP_Commuted)!=ExprHasProperty(pB,EP_Commuted) ){ - return; - } + assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); + assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); + if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; + if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return; /* If we reach this point, it means the two subterms can be combined */ if( (eOp & (eOp-1))!=0 ){ if( eOp & (WO_LT|WO_LE) ){ @@ -166351,7 +165295,7 @@ static void whereCombineDisjuncts( } } db = pWC->pWInfo->pParse->db; - pNew = sqlite3ExprDup(db, pA, 0); + pNew = sqlite3ExprDup(db, pOne->pExpr, 0); if( pNew==0 ) return; for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); } pNew->op = op; @@ -167391,11 +166335,13 @@ static void whereAddLimitExpr( int iVal = 0; if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){ - Expr *pVal = sqlite3ExprInt32(db, iVal); + Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0); if( pVal==0 ) return; + ExprSetProperty(pVal, EP_IntValue); + pVal->u.iValue = iVal; pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); }else{ - Expr *pVal = sqlite3ExprAlloc(db, TK_REGISTER, 0, 0); + Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0); if( pVal==0 ) return; pVal->iTable = iReg; pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); @@ -169222,14 +168168,11 @@ static sqlite3_index_info *allocateIndexInfo( break; } if( i==n ){ - int bSortByGroup = (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0; nOrderBy = n; if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){ - eDistinct = 2 + bSortByGroup; + eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ - eDistinct = 1 - bSortByGroup; - }else if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ - eDistinct = 3; + eDistinct = 1; } } } @@ -170640,67 +169583,6 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ return rc; } -/* -** Callback for estLikePatternLength(). -** -** If this node is a string literal that is longer pWalker->sz, then set -** pWalker->sz to the byte length of that string literal. -** -** pWalker->eCode indicates how to count characters: -** -** eCode==0 Count as a GLOB pattern -** eCode==1 Count as a LIKE pattern -*/ -static int exprNodePatternLengthEst(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_STRING ){ - int sz = 0; /* Pattern size in bytes */ - u8 *z = (u8*)pExpr->u.zToken; /* The pattern */ - u8 c; /* Next character of the pattern */ - u8 c1, c2, c3; /* Wildcards */ - if( pWalker->eCode ){ - c1 = '%'; - c2 = '_'; - c3 = 0; - }else{ - c1 = '*'; - c2 = '?'; - c3 = '['; - } - while( (c = *(z++))!=0 ){ - if( c==c3 ){ - if( *z ) z++; - while( *z && *z!=']' ) z++; - }else if( c!=c1 && c!=c2 ){ - sz++; - } - } - if( sz>pWalker->u.sz ) pWalker->u.sz = sz; - } - return WRC_Continue; -} - -/* -** Return the length of the longest string literal in the given -** expression. -** -** eCode indicates how to count characters: -** -** eCode==0 Count as a GLOB pattern -** eCode==1 Count as a LIKE pattern -*/ -static int estLikePatternLength(Expr *p, u16 eCode){ - Walker w; - w.u.sz = 0; - w.eCode = eCode; - w.xExprCallback = exprNodePatternLengthEst; - w.xSelectCallback = sqlite3SelectWalkFail; -#ifdef SQLITE_DEBUG - w.xSelectCallback2 = sqlite3SelectWalkAssert2; -#endif - sqlite3WalkExpr(&w, p); - return w.u.sz; -} - /* ** Adjust the WhereLoop.nOut value downward to account for terms of the ** WHERE clause that reference the loop but which are not used by an @@ -170729,13 +169611,6 @@ static int estLikePatternLength(Expr *p, u16 eCode){ ** "x" column is boolean or else -1 or 0 or 1 is a common default value ** on the "x" column and so in that case only cap the output row estimate ** at 1/2 instead of 1/4. -** -** Heuristic 3: If there is a LIKE or GLOB (or REGEXP or MATCH) operator -** with a large constant pattern, then reduce the size of the search -** space according to the length of the pattern, under the theory that -** longer patterns are less likely to match. This heuristic was added -** to give better output-row count estimates when preparing queries for -** the Join-Order Benchmarks. See forum thread 2026-01-30T09:57:54z */ static void whereLoopOutputAdjust( WhereClause *pWC, /* The WHERE clause */ @@ -170785,14 +169660,13 @@ static void whereLoopOutputAdjust( }else{ /* In the absence of explicit truth probabilities, use heuristics to ** guess a reasonable truth probability. */ - Expr *pOpExpr = pTerm->pExpr; pLoop->nOut--; if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */ ){ - Expr *pRight = pOpExpr->pRight; + Expr *pRight = pTerm->pExpr->pRight; int k = 0; - testcase( pOpExpr->op==TK_IS ); + testcase( pTerm->pExpr->op==TK_IS ); if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){ k = 10; }else{ @@ -170802,23 +169676,6 @@ static void whereLoopOutputAdjust( pTerm->wtFlags |= TERM_HEURTRUTH; iReduce = k; } - }else - if( ExprHasProperty(pOpExpr, EP_InfixFunc) - && pOpExpr->op==TK_FUNCTION - ){ - int eOp; - assert( ExprUseXList(pOpExpr) ); - assert( pOpExpr->x.pList->nExpr>=2 ); - eOp = sqlite3ExprIsLikeOperator(pOpExpr); - if( ALWAYS(eOp>0) ){ - int szPattern; - Expr *pRHS = pOpExpr->x.pList->a[0].pExpr; - eOp = eOp==SQLITE_INDEX_CONSTRAINT_LIKE; - szPattern = estLikePatternLength(pRHS, eOp); - if( szPattern>0 ){ - pLoop->nOut -= szPattern*2; - } - } } } } @@ -170890,7 +169747,7 @@ static int whereRangeVectorLen( idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); if( aff!=idxaff ) break; - pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr); + pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); if( pColl==0 ) break; if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break; } @@ -171279,7 +170136,6 @@ static int whereLoopAddBtreeIndex( pNew->rRun += nInMul + nIn; pNew->nOut += nInMul + nIn; whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize); - if( pSrc->fg.fromExists ) pNew->nOut = 0; rc = whereLoopInsert(pBuilder, pNew); if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ @@ -171876,8 +170732,6 @@ static int whereLoopAddBtree( if( pSrc->fg.isSubquery ){ if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE; pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy; - }else if( pSrc->fg.fromExists ){ - pNew->nOut = 0; } rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; @@ -171980,7 +170834,6 @@ static int whereLoopAddBtree( ** positioned to the correct row during the right-join no-match ** loop. */ }else{ - if( pSrc->fg.fromExists ) pNew->nOut = 0; rc = whereLoopInsert(pBuilder, pNew); } pNew->nOut = rSize; @@ -172643,7 +171496,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ sqlite3 *db = pWInfo->pParse->db; int rc = SQLITE_OK; int bFirstPastRJ = 0; - int hasRightCrossJoin = 0; + int hasRightJoin = 0; WhereLoop *pNew; @@ -172670,34 +171523,15 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ ** prevents the right operand of a RIGHT JOIN from being swapped with ** other elements even further to the right. ** - ** The hasRightCrossJoin flag prevent FROM-clause terms from moving - ** from the right side of a LEFT JOIN or CROSS JOIN over to the - ** left side of that same join. This is a required restriction in - ** the case of LEFT JOIN - an incorrect answer may results if it is - ** not enforced. This restriction is not required for CROSS JOIN. - ** It is provided merely as a means of controlling join order, under - ** the theory that no real-world queries that care about performance - ** actually use the CROSS JOIN syntax. + ** The JT_LTORJ case and the hasRightJoin flag work together to + ** prevent FROM-clause terms from moving from the right side of + ** a LEFT JOIN over to the left side of that join if the LEFT JOIN + ** is itself on the left side of a RIGHT JOIN. */ - if( pItem->fg.jointype & (JT_LTORJ|JT_CROSS) ){ - testcase( pItem->fg.jointype & JT_LTORJ ); - testcase( pItem->fg.jointype & JT_CROSS ); - hasRightCrossJoin = 1; - } + if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1; mPrereq |= mPrior; bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0; - }else if( pItem->fg.fromExists ){ - /* joins that result from the EXISTS-to-JOIN optimization should not - ** be moved to the left of any of their dependencies */ - WhereClause *pWC = &pWInfo->sWC; - WhereTerm *pTerm; - int i; - for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){ - if( (pNew->maskSelf & pTerm->prereqAll)!=0 ){ - mPrereq |= (pTerm->prereqAll & (pNew->maskSelf-1)); - } - } - }else if( !hasRightCrossJoin ){ + }else if( !hasRightJoin ){ mPrereq = 0; } #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -172920,7 +171754,9 @@ static i8 wherePathSatisfiesOrderBy( pLoop = pLast; } if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ - if( pLoop->u.vtab.isOrdered && pWInfo->pOrderBy==pOrderBy ){ + if( pLoop->u.vtab.isOrdered + && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) + ){ obSat = obDone; }else{ /* No further ORDER BY terms may be matched. So this call should @@ -173296,21 +172132,12 @@ static LogEst whereSortingCost( ** 12 otherwise ** ** For the purposes of this heuristic, a star-query is defined as a query -** with a central "fact" table that is joined against multiple -** "dimension" tables, subject to the following constraints: -** -** (aa) Only a five-way or larger join is considered for this -** optimization. If there are fewer than four terms in the FROM -** clause, this heuristic does not apply. -** -** (bb) The join between the fact table and the dimension tables must -** be an INNER join. CROSS and OUTER JOINs do not qualify. -** -** (cc) A table must have 3 or more dimension tables in order to be -** considered a fact table. (Was 4 prior to 2026-02-10.) -** -** (dd) A table that is a self-join cannot be a dimension table. -** Dimension tables are joined against fact tables. +** with a large central table that is joined using an INNER JOIN, +** not CROSS or OUTER JOINs, against four or more smaller tables. +** The central table is called the "fact" table. The smaller tables +** that get joined are "dimension tables". Also, any table that is +** self-joined cannot be a dimension table; we assume that dimension +** tables may only be joined against fact tables. ** ** SIDE EFFECT: (and really the whole point of this subroutine) ** @@ -173363,7 +172190,7 @@ static int computeMxChoice(WhereInfo *pWInfo){ } #endif /* SQLITE_DEBUG */ - if( nLoop>=4 /* Constraint (aa) */ + if( nLoop>=5 && !pWInfo->bStarDone && OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery) ){ @@ -173375,7 +172202,7 @@ static int computeMxChoice(WhereInfo *pWInfo){ pWInfo->bStarDone = 1; /* Only do this computation once */ - /* Look for fact tables with three or more dimensions where the + /* Look for fact tables with four or more dimensions where the ** dimension tables are not separately from the fact tables by an outer ** or cross join. Adjust cost weights if found. */ @@ -173392,17 +172219,18 @@ static int computeMxChoice(WhereInfo *pWInfo){ if( (pFactTab->fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ /* If the candidate fact-table is the right table of an outer join ** restrict the search for dimension-tables to be tables to the right - ** of the fact-table. Constraint (bb) */ - if( iFromIdx+3 > nLoop ){ - break; /* ^-- Impossible to reach nDep>=2 - Constraint (cc) */ - } + ** of the fact-table. */ + if( iFromIdx+4 > nLoop ) break; /* Impossible to reach nDep>=4 */ while( pStart && pStart->iTab<=iFromIdx ){ pStart = pStart->pNextLoop; } } for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ if( (aFromTabs[pWLoop->iTab].fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ - break; /* Constraint (bb) */ + /* Fact-tables and dimension-tables cannot be separated by an + ** outer join (at least for the definition of fact- and dimension- + ** used by this heuristic). */ + break; } if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */ && (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */ @@ -173416,9 +172244,7 @@ static int computeMxChoice(WhereInfo *pWInfo){ } } } - if( nDep<=2 ){ - continue; /* Constraint (cc) */ - } + if( nDep<=3 ) continue; /* If we reach this point, it means that pFactTab is a fact table ** with four or more dimensions connected by inner joins. Proceed @@ -173431,23 +172257,6 @@ static int computeMxChoice(WhereInfo *pWInfo){ pWLoop->rStarDelta = 0; } } -#endif -#ifdef WHERETRACE_ENABLED /* 0x80000 */ - if( sqlite3WhereTrace & 0x80000 ){ - Bitmask mShow = mSeen; - sqlite3DebugPrintf("Fact table %s(%d), dimensions:", - pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName, - iFromIdx); - for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( mShow & pWLoop->maskSelf ){ - SrcItem *pDim = aFromTabs + pWLoop->iTab; - mShow &= ~pWLoop->maskSelf; - sqlite3DebugPrintf(" %s(%d)", - pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab); - } - } - sqlite3DebugPrintf("\n"); - } #endif pWInfo->bStarUsed = 1; @@ -173471,8 +172280,10 @@ static int computeMxChoice(WhereInfo *pWInfo){ if( sqlite3WhereTrace & 0x80000 ){ SrcItem *pDim = aFromTabs + pWLoop->iTab; sqlite3DebugPrintf( - "Increase SCAN cost of %s to %d\n", - pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, mxRun + "Increase SCAN cost of dimension %s(%d) of fact %s(%d) to %d\n", + pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab, + pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName, + iFromIdx, mxRun ); } pWLoop->rStarDelta = mxRun - pWLoop->rRun; @@ -174286,7 +173097,6 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){ pTerm->wtFlags |= TERM_CODED; - pTerm->prereqAll = 0; } } if( i!=pWInfo->nLevel-1 ){ @@ -175274,15 +174084,14 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ } - if( pTabList->a[pLevel->iFrom].fg.fromExists - && (i==pWInfo->nLevel-1 - || pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0) - ){ - /* This is an EXISTS-to-JOIN optimization which is either the - ** inner-most loop, or the inner-most of a group of nested - ** EXISTS-to-JOIN optimization loops. If this loop sees a successful - ** row, it should break out of itself as well as other EXISTS-to-JOIN - ** loops in which is is directly nested. */ + if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){ + /* If the EXISTS-to-JOIN optimization was applied, then the EXISTS + ** loop(s) will be the inner-most loops of the join. There might be + ** multiple EXISTS loops, but they will all be nested, and the join + ** order will not have been changed by the query planner. If the + ** inner-most EXISTS loop sees a single successful row, it should + ** break out of *all* EXISTS loops. But only the inner-most of the + ** nested EXISTS loops should do this breakout. */ int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */ while( nOuter<i ){ if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break; @@ -175290,11 +174099,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } testcase( nOuter>0 ); sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk); - if( nOuter ){ - VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i)); - }else{ - VdbeComment((v, "EXISTS break %d", i)); - } + VdbeComment((v, "EXISTS break")); } sqlite3VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ @@ -176311,7 +175116,7 @@ SQLITE_PRIVATE void sqlite3WindowUpdate( pWin->eEnd = aUp[i].eEnd; pWin->eExclude = 0; if( pWin->eStart==TK_FOLLOWING ){ - pWin->pStart = sqlite3ExprInt32(db, 1); + pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1"); } break; } @@ -176656,7 +175461,9 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** keep everything legal in this case. */ if( pSublist==0 ){ - pSublist = sqlite3ExprListAppend(pParse, 0, sqlite3ExprInt32(db, 0)); + pSublist = sqlite3ExprListAppend(pParse, 0, + sqlite3Expr(db, TK_INTEGER, "0") + ); } pSub = sqlite3SelectNew( @@ -178880,23 +177687,8 @@ static void updateDeleteLimitError( ** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate ** testing. */ - static void *parserStackRealloc( - void *pOld, /* Prior allocation */ - sqlite3_uint64 newSize, /* Requested new alloation size */ - Parse *pParse /* Parsing context */ - ){ - void *p = sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); - if( p==0 ) sqlite3OomFault(pParse->db); - return p; - } - static void parserStackFree(void *pOld, Parse *pParse){ - (void)pParse; - sqlite3_free(pOld); - } - - /* Return an integer that is the maximum allowed stack size */ - static int parserStackSizeLimit(Parse *pParse){ - return pParse->db->aLimit[SQLITE_LIMIT_PARSER_DEPTH]; + static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){ + return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); } @@ -178935,46 +177727,15 @@ static void updateDeleteLimitError( } - /* Create a TK_ISNULL or TK_NOTNULL expression, perhaps optimized to - ** to TK_TRUEFALSE, if possible */ - static Expr *sqlite3PExprIsNull( - Parse *pParse, /* Parsing context */ - int op, /* TK_ISNULL or TK_NOTNULL */ - Expr *pLeft /* Operand */ - ){ - Expr *p = pLeft; - assert( op==TK_ISNULL || op==TK_NOTNULL ); - assert( pLeft!=0 ); - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ - p = p->pLeft; - assert( p!=0 ); - } - switch( p->op ){ - case TK_INTEGER: - case TK_STRING: - case TK_FLOAT: - case TK_BLOB: - sqlite3ExprDeferredDelete(pParse, pLeft); - return sqlite3ExprInt32(pParse->db, op==TK_NOTNULL); - default: - break; - } - return sqlite3PExpr(pParse, op, pLeft, 0); - } - - /* Create a TK_IS or TK_ISNOT operator, perhaps optimized to - ** TK_ISNULL or TK_NOTNULL or TK_TRUEFALSE. */ - static Expr *sqlite3PExprIs( - Parse *pParse, /* Parsing context */ - int op, /* TK_IS or TK_ISNOT */ - Expr *pLeft, /* Left operand */ - Expr *pRight /* Right operand */ - ){ - if( pRight && pRight->op==TK_NULL ){ - sqlite3ExprDeferredDelete(pParse, pRight); - return sqlite3PExprIsNull(pParse, op==TK_IS ? TK_ISNULL : TK_NOTNULL, pLeft); + /* A routine to convert a binary TK_IS or TK_ISNOT expression into a + ** unary TK_ISNULL or TK_NOTNULL expression. */ + static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ + sqlite3 *db = pParse->db; + if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){ + pA->op = (u8)op; + sqlite3ExprDelete(db, pA->pRight); + pA->pRight = 0; } - return sqlite3PExpr(pParse, op, pLeft, pRight); } /* Add a single new term to an ExprList that is used to store a @@ -179257,72 +178018,63 @@ static void updateDeleteLimitError( #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 322 +#define YYNOCODE 323 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 102 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - ExprList* yy14; - With* yy59; - Cte* yy67; - Upsert* yy122; - IdList* yy132; - int yy144; - const char* yy168; - SrcList* yy203; - Window* yy211; - OnOrUsing yy269; - struct TrigEvent yy286; - struct {int value; int mask;} yy383; - u32 yy391; - TriggerStep* yy427; - Expr* yy454; - u8 yy462; - struct FrameBound yy509; - Select* yy555; + u32 yy9; + struct TrigEvent yy28; + With* yy125; + IdList* yy204; + struct FrameBound yy205; + TriggerStep* yy319; + const char* yy342; + Cte* yy361; + ExprList* yy402; + Upsert* yy403; + OnOrUsing yy421; + u8 yy444; + struct {int value; int mask;} yy481; + Window* yy483; + int yy502; + SrcList* yy563; + Expr* yy590; + Select* yy637; } YYMINORTYPE; #ifndef YYSTACKDEPTH -#define YYSTACKDEPTH 50 +#define YYSTACKDEPTH 100 #endif #define sqlite3ParserARG_SDECL #define sqlite3ParserARG_PDECL #define sqlite3ParserARG_PARAM #define sqlite3ParserARG_FETCH #define sqlite3ParserARG_STORE -#undef YYREALLOC #define YYREALLOC parserStackRealloc -#undef YYFREE -#define YYFREE parserStackFree -#undef YYDYNSTACK +#define YYFREE sqlite3_free #define YYDYNSTACK 1 -#undef YYSIZELIMIT -#define YYSIZELIMIT parserStackSizeLimit -#define sqlite3ParserCTX(P) ((P)->pParse) #define sqlite3ParserCTX_SDECL Parse *pParse; #define sqlite3ParserCTX_PDECL ,Parse *pParse #define sqlite3ParserCTX_PARAM ,pParse #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; -#undef YYERRORSYMBOL -#undef YYERRSYMDT -#undef YYFALLBACK #define YYFALLBACK 1 -#define YYNSTATE 600 -#define YYNRULE 412 -#define YYNRULE_WITH_ACTION 348 +#define YYNSTATE 583 +#define YYNRULE 409 +#define YYNRULE_WITH_ACTION 344 #define YYNTOKEN 187 -#define YY_MAX_SHIFT 599 -#define YY_MIN_SHIFTREDUCE 867 -#define YY_MAX_SHIFTREDUCE 1278 -#define YY_ERROR_ACTION 1279 -#define YY_ACCEPT_ACTION 1280 -#define YY_NO_ACTION 1281 -#define YY_MIN_REDUCE 1282 -#define YY_MAX_REDUCE 1693 +#define YY_MAX_SHIFT 582 +#define YY_MIN_SHIFTREDUCE 845 +#define YY_MAX_SHIFTREDUCE 1253 +#define YY_ERROR_ACTION 1254 +#define YY_ACCEPT_ACTION 1255 +#define YY_NO_ACTION 1256 +#define YY_MIN_REDUCE 1257 +#define YY_MAX_REDUCE 1665 #define YY_MIN_DSTRCTR 206 -#define YY_MAX_DSTRCTR 319 +#define YY_MAX_DSTRCTR 320 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -179405,680 +178157,643 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2379) +#define YY_ACTTAB_COUNT (2207) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 134, 131, 238, 290, 290, 1353, 593, 1332, 478, 1606, - /* 10 */ 593, 1315, 593, 7, 593, 1353, 590, 593, 579, 424, - /* 20 */ 1566, 134, 131, 238, 1318, 541, 478, 477, 575, 84, - /* 30 */ 84, 1005, 303, 84, 84, 51, 51, 63, 63, 1006, - /* 40 */ 84, 84, 498, 141, 142, 93, 442, 1254, 1254, 1085, - /* 50 */ 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, 424, - /* 60 */ 296, 296, 498, 296, 296, 567, 553, 296, 296, 1306, - /* 70 */ 574, 1358, 1358, 590, 542, 579, 590, 574, 579, 548, - /* 80 */ 590, 1304, 579, 141, 142, 93, 576, 1254, 1254, 1085, - /* 90 */ 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, 399, - /* 100 */ 478, 395, 6, 138, 138, 138, 138, 137, 137, 136, - /* 110 */ 136, 136, 135, 132, 463, 44, 342, 593, 305, 1127, - /* 120 */ 1280, 1, 1, 599, 2, 1284, 598, 1200, 1284, 1200, - /* 130 */ 330, 424, 158, 330, 1613, 158, 390, 116, 308, 1366, - /* 140 */ 51, 51, 1366, 138, 138, 138, 138, 137, 137, 136, - /* 150 */ 136, 136, 135, 132, 463, 141, 142, 93, 515, 1254, - /* 160 */ 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, - /* 170 */ 140, 1230, 329, 584, 296, 296, 212, 296, 296, 568, - /* 180 */ 568, 488, 143, 1072, 1072, 1086, 1089, 590, 1195, 579, - /* 190 */ 590, 340, 579, 140, 140, 140, 140, 133, 392, 564, - /* 200 */ 536, 1195, 250, 425, 1195, 250, 137, 137, 136, 136, - /* 210 */ 136, 135, 132, 463, 291, 138, 138, 138, 138, 137, - /* 220 */ 137, 136, 136, 136, 135, 132, 463, 966, 1230, 1231, - /* 230 */ 1230, 412, 965, 467, 412, 424, 467, 489, 357, 1611, - /* 240 */ 391, 138, 138, 138, 138, 137, 137, 136, 136, 136, - /* 250 */ 135, 132, 463, 463, 134, 131, 238, 555, 1076, 141, - /* 260 */ 142, 93, 593, 1254, 1254, 1085, 1088, 1075, 1075, 139, - /* 270 */ 139, 140, 140, 140, 140, 1317, 134, 131, 238, 424, - /* 280 */ 549, 1597, 1531, 333, 97, 83, 83, 140, 140, 140, - /* 290 */ 140, 138, 138, 138, 138, 137, 137, 136, 136, 136, - /* 300 */ 135, 132, 463, 141, 142, 93, 1657, 1254, 1254, 1085, - /* 310 */ 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, 138, - /* 320 */ 138, 138, 138, 137, 137, 136, 136, 136, 135, 132, - /* 330 */ 463, 591, 1230, 958, 958, 138, 138, 138, 138, 137, - /* 340 */ 137, 136, 136, 136, 135, 132, 463, 44, 398, 547, - /* 350 */ 1306, 136, 136, 136, 135, 132, 463, 386, 593, 442, - /* 360 */ 595, 145, 595, 138, 138, 138, 138, 137, 137, 136, - /* 370 */ 136, 136, 135, 132, 463, 500, 1230, 112, 550, 460, - /* 380 */ 459, 51, 51, 424, 296, 296, 479, 334, 1259, 1230, - /* 390 */ 1231, 1230, 1599, 1261, 388, 312, 444, 590, 246, 579, - /* 400 */ 546, 1260, 271, 235, 329, 584, 551, 141, 142, 93, - /* 410 */ 429, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, - /* 420 */ 140, 140, 140, 22, 22, 1230, 1262, 424, 1262, 216, - /* 430 */ 296, 296, 98, 1230, 1231, 1230, 264, 884, 45, 528, - /* 440 */ 525, 524, 1041, 590, 1269, 579, 421, 420, 393, 523, - /* 450 */ 44, 141, 142, 93, 498, 1254, 1254, 1085, 1088, 1075, - /* 460 */ 1075, 139, 139, 140, 140, 140, 140, 138, 138, 138, - /* 470 */ 138, 137, 137, 136, 136, 136, 135, 132, 463, 593, - /* 480 */ 1611, 561, 1230, 1231, 1230, 23, 264, 515, 200, 528, - /* 490 */ 525, 524, 127, 585, 509, 4, 355, 487, 506, 523, - /* 500 */ 593, 498, 84, 84, 134, 131, 238, 329, 584, 588, - /* 510 */ 1627, 138, 138, 138, 138, 137, 137, 136, 136, 136, - /* 520 */ 135, 132, 463, 19, 19, 435, 1230, 1460, 297, 297, - /* 530 */ 311, 424, 1565, 464, 1631, 599, 2, 1284, 437, 574, - /* 540 */ 1107, 590, 330, 579, 158, 582, 489, 357, 573, 593, - /* 550 */ 592, 1366, 409, 1274, 1230, 141, 142, 93, 1364, 1254, - /* 560 */ 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, - /* 570 */ 140, 389, 84, 84, 1062, 567, 1230, 313, 1523, 593, - /* 580 */ 125, 125, 970, 1230, 1231, 1230, 296, 296, 126, 46, - /* 590 */ 464, 594, 464, 296, 296, 1050, 1230, 218, 439, 590, - /* 600 */ 1604, 579, 84, 84, 7, 403, 590, 515, 579, 325, - /* 610 */ 417, 1230, 1231, 1230, 250, 138, 138, 138, 138, 137, - /* 620 */ 137, 136, 136, 136, 135, 132, 463, 1050, 1050, 1052, - /* 630 */ 1053, 35, 1275, 1230, 1231, 1230, 424, 1370, 993, 574, - /* 640 */ 371, 414, 274, 412, 1597, 467, 1302, 552, 451, 590, - /* 650 */ 543, 579, 1530, 1230, 1231, 1230, 1214, 201, 409, 1174, - /* 660 */ 141, 142, 93, 223, 1254, 1254, 1085, 1088, 1075, 1075, - /* 670 */ 139, 139, 140, 140, 140, 140, 296, 296, 1250, 593, - /* 680 */ 424, 296, 296, 236, 529, 296, 296, 515, 100, 590, - /* 690 */ 1600, 579, 48, 1605, 590, 1230, 579, 7, 590, 577, - /* 700 */ 579, 904, 84, 84, 141, 142, 93, 496, 1254, 1254, - /* 710 */ 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, - /* 720 */ 138, 138, 138, 138, 137, 137, 136, 136, 136, 135, - /* 730 */ 132, 463, 1365, 1230, 296, 296, 1250, 115, 1275, 326, - /* 740 */ 233, 539, 1062, 40, 282, 127, 585, 590, 4, 579, - /* 750 */ 329, 584, 1230, 1231, 1230, 1598, 593, 388, 904, 1051, - /* 760 */ 1356, 1356, 588, 1050, 138, 138, 138, 138, 137, 137, - /* 770 */ 136, 136, 136, 135, 132, 463, 185, 593, 1230, 19, - /* 780 */ 19, 1230, 971, 1597, 424, 1651, 464, 129, 908, 1195, - /* 790 */ 1230, 1231, 1230, 1325, 443, 1050, 1050, 1052, 582, 1603, - /* 800 */ 149, 149, 1195, 7, 5, 1195, 1687, 410, 141, 142, - /* 810 */ 93, 1536, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, - /* 820 */ 140, 140, 140, 140, 1214, 397, 593, 1062, 424, 1536, - /* 830 */ 1538, 50, 901, 125, 125, 1230, 1231, 1230, 1230, 1231, - /* 840 */ 1230, 126, 1230, 464, 594, 464, 515, 1230, 1050, 84, - /* 850 */ 84, 3, 141, 142, 93, 924, 1254, 1254, 1085, 1088, - /* 860 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 138, 138, - /* 870 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 463, - /* 880 */ 1050, 1050, 1052, 1053, 35, 442, 457, 532, 433, 1230, - /* 890 */ 1062, 1361, 540, 540, 1598, 925, 388, 7, 1129, 1230, - /* 900 */ 1231, 1230, 1129, 1536, 1230, 1231, 1230, 1051, 570, 1214, - /* 910 */ 593, 1050, 138, 138, 138, 138, 137, 137, 136, 136, - /* 920 */ 136, 135, 132, 463, 6, 185, 1195, 1230, 231, 593, - /* 930 */ 382, 992, 424, 151, 151, 510, 1213, 557, 482, 1195, - /* 940 */ 381, 160, 1195, 1050, 1050, 1052, 1230, 1231, 1230, 422, - /* 950 */ 593, 447, 84, 84, 593, 217, 141, 142, 93, 593, - /* 960 */ 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, - /* 970 */ 140, 140, 1214, 19, 19, 593, 424, 19, 19, 442, - /* 980 */ 1063, 442, 19, 19, 1230, 1231, 1230, 515, 445, 458, - /* 990 */ 1597, 386, 315, 1175, 1685, 556, 1685, 450, 84, 84, - /* 1000 */ 141, 142, 93, 505, 1254, 1254, 1085, 1088, 1075, 1075, - /* 1010 */ 139, 139, 140, 140, 140, 140, 138, 138, 138, 138, - /* 1020 */ 137, 137, 136, 136, 136, 135, 132, 463, 442, 1147, - /* 1030 */ 454, 1597, 362, 1041, 593, 462, 1460, 1233, 47, 1393, - /* 1040 */ 324, 565, 565, 115, 1148, 449, 7, 460, 459, 307, - /* 1050 */ 375, 354, 593, 113, 593, 329, 584, 19, 19, 1149, - /* 1060 */ 138, 138, 138, 138, 137, 137, 136, 136, 136, 135, - /* 1070 */ 132, 463, 209, 1173, 563, 19, 19, 19, 19, 49, - /* 1080 */ 424, 944, 1175, 1686, 1046, 1686, 218, 355, 484, 343, - /* 1090 */ 210, 945, 569, 562, 1262, 1233, 1262, 490, 314, 423, - /* 1100 */ 424, 1598, 1206, 388, 141, 142, 93, 440, 1254, 1254, - /* 1110 */ 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, - /* 1120 */ 352, 316, 531, 316, 141, 142, 93, 549, 1254, 1254, - /* 1130 */ 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, - /* 1140 */ 446, 10, 1598, 274, 388, 915, 281, 299, 383, 534, - /* 1150 */ 378, 533, 269, 593, 1206, 587, 587, 587, 374, 293, - /* 1160 */ 1579, 991, 1173, 302, 138, 138, 138, 138, 137, 137, - /* 1170 */ 136, 136, 136, 135, 132, 463, 53, 53, 520, 1250, - /* 1180 */ 593, 1147, 1576, 431, 138, 138, 138, 138, 137, 137, - /* 1190 */ 136, 136, 136, 135, 132, 463, 1148, 301, 593, 1577, - /* 1200 */ 593, 1307, 431, 54, 54, 593, 268, 593, 461, 461, - /* 1210 */ 461, 1149, 347, 492, 424, 135, 132, 463, 1146, 1195, - /* 1220 */ 474, 68, 68, 69, 69, 550, 332, 287, 21, 21, - /* 1230 */ 55, 55, 1195, 581, 424, 1195, 309, 1250, 141, 142, - /* 1240 */ 93, 119, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, - /* 1250 */ 140, 140, 140, 140, 593, 237, 480, 1476, 141, 142, - /* 1260 */ 93, 593, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, - /* 1270 */ 140, 140, 140, 140, 344, 430, 346, 70, 70, 494, - /* 1280 */ 991, 1132, 1132, 512, 56, 56, 1269, 593, 268, 593, - /* 1290 */ 369, 374, 593, 481, 215, 384, 1624, 481, 138, 138, - /* 1300 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 463, - /* 1310 */ 71, 71, 72, 72, 225, 73, 73, 593, 138, 138, - /* 1320 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 463, - /* 1330 */ 586, 431, 593, 872, 873, 874, 593, 911, 593, 1602, - /* 1340 */ 74, 74, 593, 7, 1460, 242, 593, 306, 424, 1578, - /* 1350 */ 472, 306, 364, 219, 367, 75, 75, 430, 345, 57, - /* 1360 */ 57, 58, 58, 432, 187, 59, 59, 593, 424, 61, - /* 1370 */ 61, 1475, 141, 142, 93, 123, 1254, 1254, 1085, 1088, - /* 1380 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 424, 570, - /* 1390 */ 62, 62, 141, 142, 93, 911, 1254, 1254, 1085, 1088, - /* 1400 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 161, 384, - /* 1410 */ 1624, 1474, 141, 130, 93, 441, 1254, 1254, 1085, 1088, - /* 1420 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 267, 266, - /* 1430 */ 265, 1460, 138, 138, 138, 138, 137, 137, 136, 136, - /* 1440 */ 136, 135, 132, 463, 593, 1336, 593, 1269, 1460, 384, - /* 1450 */ 1624, 231, 138, 138, 138, 138, 137, 137, 136, 136, - /* 1460 */ 136, 135, 132, 463, 593, 163, 593, 76, 76, 77, - /* 1470 */ 77, 593, 138, 138, 138, 138, 137, 137, 136, 136, - /* 1480 */ 136, 135, 132, 463, 475, 593, 483, 78, 78, 20, - /* 1490 */ 20, 1249, 424, 491, 79, 79, 495, 422, 295, 235, - /* 1500 */ 1574, 38, 511, 896, 422, 335, 240, 422, 147, 147, - /* 1510 */ 112, 593, 424, 593, 101, 222, 991, 142, 93, 455, - /* 1520 */ 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, - /* 1530 */ 140, 140, 593, 39, 148, 148, 80, 80, 93, 551, - /* 1540 */ 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, - /* 1550 */ 140, 140, 328, 923, 922, 64, 64, 502, 1656, 1005, - /* 1560 */ 933, 896, 124, 422, 121, 254, 593, 1006, 593, 226, - /* 1570 */ 593, 127, 585, 164, 4, 16, 138, 138, 138, 138, - /* 1580 */ 137, 137, 136, 136, 136, 135, 132, 463, 588, 81, - /* 1590 */ 81, 65, 65, 82, 82, 593, 138, 138, 138, 138, - /* 1600 */ 137, 137, 136, 136, 136, 135, 132, 463, 593, 226, - /* 1610 */ 237, 966, 464, 593, 298, 593, 965, 593, 66, 66, - /* 1620 */ 593, 1170, 593, 411, 582, 353, 469, 115, 593, 471, - /* 1630 */ 169, 173, 173, 593, 44, 991, 174, 174, 89, 89, - /* 1640 */ 67, 67, 593, 85, 85, 150, 150, 1114, 1043, 593, - /* 1650 */ 273, 86, 86, 1062, 593, 503, 171, 171, 593, 125, - /* 1660 */ 125, 497, 593, 273, 336, 152, 152, 126, 1335, 464, - /* 1670 */ 594, 464, 146, 146, 1050, 593, 545, 172, 172, 593, - /* 1680 */ 1054, 165, 165, 256, 339, 156, 156, 127, 585, 1586, - /* 1690 */ 4, 329, 584, 499, 358, 273, 115, 348, 155, 155, - /* 1700 */ 930, 931, 153, 153, 588, 1114, 1050, 1050, 1052, 1053, - /* 1710 */ 35, 1554, 521, 593, 270, 1008, 1009, 9, 593, 372, - /* 1720 */ 593, 115, 593, 168, 593, 115, 593, 1110, 464, 270, - /* 1730 */ 996, 964, 273, 129, 1645, 1214, 154, 154, 1054, 1404, - /* 1740 */ 582, 88, 88, 90, 90, 87, 87, 52, 52, 60, - /* 1750 */ 60, 1405, 504, 537, 559, 1179, 961, 507, 129, 558, - /* 1760 */ 127, 585, 1126, 4, 1126, 1125, 894, 1125, 162, 1062, - /* 1770 */ 963, 359, 129, 1401, 363, 125, 125, 588, 366, 368, - /* 1780 */ 370, 1349, 1334, 126, 1333, 464, 594, 464, 377, 387, - /* 1790 */ 1050, 1391, 1414, 1618, 1459, 1387, 1399, 208, 580, 1464, - /* 1800 */ 1314, 464, 243, 516, 1305, 1293, 1384, 1292, 1294, 1638, - /* 1810 */ 288, 170, 228, 582, 12, 408, 321, 322, 241, 323, - /* 1820 */ 245, 1446, 1050, 1050, 1052, 1053, 35, 559, 304, 350, - /* 1830 */ 351, 501, 560, 127, 585, 1441, 4, 1451, 1434, 310, - /* 1840 */ 1450, 526, 1062, 1332, 415, 380, 232, 1527, 125, 125, - /* 1850 */ 588, 1214, 1396, 356, 1526, 583, 126, 1397, 464, 594, - /* 1860 */ 464, 1641, 535, 1050, 1581, 1395, 1269, 1583, 1582, 213, - /* 1870 */ 402, 277, 214, 227, 464, 1573, 239, 1571, 1266, 1394, - /* 1880 */ 434, 198, 100, 224, 96, 183, 582, 191, 485, 193, - /* 1890 */ 486, 194, 195, 196, 519, 1050, 1050, 1052, 1053, 35, - /* 1900 */ 559, 113, 252, 413, 1447, 558, 493, 13, 1455, 416, - /* 1910 */ 1453, 1452, 14, 202, 1521, 1062, 1532, 508, 258, 106, - /* 1920 */ 514, 125, 125, 99, 1214, 1543, 289, 260, 206, 126, - /* 1930 */ 365, 464, 594, 464, 361, 517, 1050, 261, 448, 1295, - /* 1940 */ 262, 418, 1352, 1351, 108, 1350, 1655, 1654, 1343, 915, - /* 1950 */ 419, 1322, 233, 452, 319, 379, 1321, 453, 1623, 320, - /* 1960 */ 1320, 275, 1653, 544, 276, 1609, 1608, 1342, 1050, 1050, - /* 1970 */ 1052, 1053, 35, 1630, 1218, 466, 385, 456, 300, 1419, - /* 1980 */ 144, 1418, 570, 407, 407, 406, 284, 404, 11, 1508, - /* 1990 */ 881, 396, 120, 127, 585, 394, 4, 1214, 327, 114, - /* 2000 */ 1375, 1374, 220, 247, 400, 338, 401, 554, 42, 1224, - /* 2010 */ 588, 596, 283, 337, 285, 286, 188, 597, 1290, 1285, - /* 2020 */ 175, 1558, 176, 1559, 1557, 1556, 159, 317, 229, 177, - /* 2030 */ 868, 230, 91, 465, 464, 221, 331, 468, 1165, 470, - /* 2040 */ 473, 94, 244, 95, 249, 189, 582, 1124, 1122, 341, - /* 2050 */ 427, 190, 178, 1249, 179, 43, 192, 947, 349, 428, - /* 2060 */ 1138, 197, 251, 180, 181, 436, 102, 182, 438, 103, - /* 2070 */ 104, 199, 248, 1140, 253, 1062, 105, 255, 1137, 166, - /* 2080 */ 24, 125, 125, 257, 1264, 273, 360, 513, 259, 126, - /* 2090 */ 15, 464, 594, 464, 204, 883, 1050, 518, 263, 373, - /* 2100 */ 381, 92, 585, 1130, 4, 203, 205, 426, 107, 522, - /* 2110 */ 25, 26, 329, 584, 913, 572, 527, 376, 588, 926, - /* 2120 */ 530, 109, 184, 318, 167, 110, 27, 538, 1050, 1050, - /* 2130 */ 1052, 1053, 35, 1211, 1091, 17, 476, 111, 1181, 234, - /* 2140 */ 292, 1180, 464, 294, 207, 994, 129, 1201, 272, 1000, - /* 2150 */ 28, 1197, 29, 30, 582, 1199, 1205, 1214, 31, 1204, - /* 2160 */ 32, 1186, 41, 566, 33, 1105, 211, 8, 115, 1092, - /* 2170 */ 1090, 1094, 34, 278, 578, 1095, 117, 122, 118, 1145, - /* 2180 */ 36, 18, 128, 1062, 1055, 895, 957, 37, 589, 125, - /* 2190 */ 125, 279, 186, 280, 1646, 157, 405, 126, 1220, 464, - /* 2200 */ 594, 464, 1218, 466, 1050, 1219, 300, 1281, 1281, 1281, - /* 2210 */ 1281, 407, 407, 406, 284, 404, 1281, 1281, 881, 1281, - /* 2220 */ 300, 1281, 1281, 571, 1281, 407, 407, 406, 284, 404, - /* 2230 */ 1281, 247, 881, 338, 1281, 1281, 1050, 1050, 1052, 1053, - /* 2240 */ 35, 337, 1281, 1281, 1281, 247, 1281, 338, 1281, 1281, - /* 2250 */ 1281, 1281, 1281, 1281, 1281, 337, 1281, 1281, 1281, 1281, - /* 2260 */ 1281, 1281, 1281, 1281, 1281, 1214, 1281, 1281, 1281, 1281, - /* 2270 */ 1281, 1281, 249, 1281, 1281, 1281, 1281, 1281, 1281, 1281, - /* 2280 */ 178, 1281, 1281, 43, 1281, 1281, 249, 1281, 1281, 1281, - /* 2290 */ 1281, 1281, 1281, 1281, 178, 1281, 1281, 43, 1281, 1281, - /* 2300 */ 248, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, - /* 2310 */ 1281, 1281, 1281, 1281, 248, 1281, 1281, 1281, 1281, 1281, - /* 2320 */ 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, - /* 2330 */ 1281, 1281, 1281, 1281, 1281, 426, 1281, 1281, 1281, 1281, - /* 2340 */ 329, 584, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 426, - /* 2350 */ 1281, 1281, 1281, 1281, 329, 584, 1281, 1281, 1281, 1281, - /* 2360 */ 1281, 1281, 1281, 1281, 476, 1281, 1281, 1281, 1281, 1281, - /* 2370 */ 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 476, + /* 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, 451, 1050, 1050, 1064, 1067, + /* 120 */ 1255, 1, 1, 582, 2, 1259, 581, 1174, 1259, 1174, + /* 130 */ 321, 413, 155, 321, 1584, 155, 379, 112, 481, 1341, + /* 140 */ 456, 299, 1341, 134, 134, 134, 134, 133, 133, 132, + /* 150 */ 132, 132, 131, 128, 451, 137, 138, 91, 498, 1228, + /* 160 */ 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, + /* 170 */ 136, 1204, 862, 1281, 288, 288, 283, 288, 288, 523, + /* 180 */ 523, 1250, 139, 578, 7, 578, 1345, 573, 1169, 562, + /* 190 */ 573, 1054, 562, 136, 136, 136, 136, 129, 573, 547, + /* 200 */ 562, 1169, 245, 1541, 1169, 245, 133, 133, 132, 132, + /* 210 */ 132, 131, 128, 451, 302, 134, 134, 134, 134, 133, + /* 220 */ 133, 132, 132, 132, 131, 128, 451, 1575, 1204, 1205, + /* 230 */ 1204, 7, 470, 550, 455, 413, 550, 455, 130, 127, + /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132, + /* 250 */ 131, 128, 451, 136, 136, 136, 136, 538, 483, 137, + /* 260 */ 138, 91, 1019, 1228, 1228, 1063, 1066, 1053, 1053, 135, + /* 270 */ 135, 136, 136, 136, 136, 1085, 576, 1204, 132, 132, + /* 280 */ 132, 131, 128, 451, 93, 214, 134, 134, 134, 134, + /* 290 */ 133, 133, 132, 132, 132, 131, 128, 451, 401, 19, + /* 300 */ 19, 134, 134, 134, 134, 133, 133, 132, 132, 132, + /* 310 */ 131, 128, 451, 1498, 426, 267, 344, 467, 332, 134, + /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128, + /* 330 */ 451, 1281, 576, 6, 1204, 1205, 1204, 257, 576, 413, + /* 340 */ 511, 508, 507, 1279, 94, 1019, 464, 1204, 551, 551, + /* 350 */ 506, 1224, 1571, 44, 38, 51, 51, 411, 576, 413, + /* 360 */ 45, 51, 51, 137, 138, 91, 530, 1228, 1228, 1063, + /* 370 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 398, + /* 380 */ 1148, 82, 82, 137, 138, 91, 39, 1228, 1228, 1063, + /* 390 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 344, + /* 400 */ 44, 288, 288, 375, 1204, 1205, 1204, 209, 1204, 1224, + /* 410 */ 320, 567, 471, 576, 573, 576, 562, 576, 316, 264, + /* 420 */ 231, 46, 160, 134, 134, 134, 134, 133, 133, 132, + /* 430 */ 132, 132, 131, 128, 451, 303, 82, 82, 82, 82, + /* 440 */ 82, 82, 442, 134, 134, 134, 134, 133, 133, 132, + /* 450 */ 132, 132, 131, 128, 451, 1582, 544, 320, 567, 1250, + /* 460 */ 874, 1582, 380, 382, 413, 1204, 1205, 1204, 360, 182, + /* 470 */ 288, 288, 1576, 557, 1339, 557, 7, 557, 1277, 472, + /* 480 */ 346, 526, 531, 573, 556, 562, 439, 1511, 137, 138, + /* 490 */ 91, 219, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, + /* 500 */ 136, 136, 136, 136, 465, 1511, 1513, 532, 413, 288, + /* 510 */ 288, 423, 512, 288, 288, 411, 288, 288, 874, 130, + /* 520 */ 127, 234, 573, 1107, 562, 1204, 573, 1107, 562, 573, + /* 530 */ 560, 562, 137, 138, 91, 1293, 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 */ 493, 503, 1292, 1204, 257, 288, 288, 511, 508, 507, + /* 570 */ 1204, 1628, 1169, 123, 568, 275, 4, 506, 573, 1511, + /* 580 */ 562, 331, 1204, 1205, 1204, 1169, 548, 548, 1169, 261, + /* 590 */ 571, 7, 134, 134, 134, 134, 133, 133, 132, 132, + /* 600 */ 132, 131, 128, 451, 108, 533, 130, 127, 234, 1204, + /* 610 */ 448, 447, 413, 1451, 452, 983, 886, 96, 1598, 1233, + /* 620 */ 1204, 1205, 1204, 984, 1235, 1450, 565, 1204, 1205, 1204, + /* 630 */ 229, 522, 1234, 534, 1333, 1333, 137, 138, 91, 1449, + /* 640 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, + /* 650 */ 136, 136, 373, 1595, 971, 1040, 413, 1236, 418, 1236, + /* 660 */ 879, 121, 121, 948, 373, 1595, 1204, 1205, 1204, 122, + /* 670 */ 1204, 452, 577, 452, 363, 417, 1028, 882, 373, 1595, + /* 680 */ 137, 138, 91, 462, 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, 570, 570, 570, 197, 423, 1040, 198, + /* 720 */ 1204, 123, 568, 1204, 4, 320, 567, 1204, 1205, 1204, + /* 730 */ 40, 388, 576, 384, 882, 1029, 423, 1188, 571, 1028, + /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 750 */ 128, 451, 529, 1568, 1204, 19, 19, 1204, 575, 492, + /* 760 */ 413, 157, 452, 489, 1187, 1331, 1331, 5, 1204, 949, + /* 770 */ 431, 1028, 1028, 1030, 565, 22, 22, 1204, 1205, 1204, + /* 780 */ 1204, 1205, 1204, 477, 137, 138, 91, 212, 1228, 1228, + /* 790 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, + /* 800 */ 1188, 48, 111, 1040, 413, 1204, 213, 970, 1041, 121, + /* 810 */ 121, 1204, 1205, 1204, 1204, 1205, 1204, 122, 221, 452, + /* 820 */ 577, 452, 44, 487, 1028, 1204, 1205, 1204, 137, 138, + /* 830 */ 91, 378, 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, 461, 1204, 1205, 1204, 1569, 1040, 377, 214, 1149, + /* 870 */ 1657, 535, 1657, 437, 902, 320, 567, 1568, 364, 320, + /* 880 */ 567, 412, 329, 1029, 519, 1188, 3, 1028, 134, 134, + /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451, + /* 900 */ 1659, 399, 1169, 307, 893, 307, 515, 576, 413, 214, + /* 910 */ 498, 944, 1024, 540, 903, 1169, 943, 392, 1169, 1028, + /* 920 */ 1028, 1030, 406, 298, 1204, 50, 1149, 1658, 413, 1658, + /* 930 */ 145, 145, 137, 138, 91, 293, 1228, 1228, 1063, 1066, + /* 940 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 1188, 1147, + /* 950 */ 514, 1568, 137, 138, 91, 1505, 1228, 1228, 1063, 1066, + /* 960 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 434, 323, + /* 970 */ 435, 539, 111, 1506, 274, 291, 372, 517, 367, 516, + /* 980 */ 262, 1204, 1205, 1204, 1574, 481, 363, 576, 7, 1569, + /* 990 */ 1568, 377, 134, 134, 134, 134, 133, 133, 132, 132, + /* 1000 */ 132, 131, 128, 451, 1568, 576, 1147, 576, 232, 576, + /* 1010 */ 19, 19, 134, 134, 134, 134, 133, 133, 132, 132, + /* 1020 */ 132, 131, 128, 451, 1169, 433, 576, 1207, 19, 19, + /* 1030 */ 19, 19, 19, 19, 1627, 576, 911, 1169, 47, 120, + /* 1040 */ 1169, 117, 413, 306, 498, 438, 1125, 206, 336, 19, + /* 1050 */ 19, 1435, 49, 449, 449, 449, 1368, 315, 81, 81, + /* 1060 */ 576, 304, 413, 1570, 207, 377, 137, 138, 91, 115, + /* 1070 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, + /* 1080 */ 136, 136, 576, 82, 82, 1207, 137, 138, 91, 1340, + /* 1090 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, + /* 1100 */ 136, 136, 1569, 386, 377, 82, 82, 463, 1126, 1552, + /* 1110 */ 333, 463, 335, 131, 128, 451, 1569, 161, 377, 16, + /* 1120 */ 317, 387, 428, 1127, 448, 447, 134, 134, 134, 134, + /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 451, 1128, 576, + /* 1140 */ 1105, 10, 445, 267, 576, 1554, 134, 134, 134, 134, + /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 451, 532, 576, + /* 1160 */ 922, 576, 19, 19, 576, 1573, 576, 147, 147, 7, + /* 1170 */ 923, 1236, 498, 1236, 576, 487, 413, 552, 285, 1224, + /* 1180 */ 969, 215, 82, 82, 66, 66, 1435, 67, 67, 21, + /* 1190 */ 21, 1110, 1110, 495, 334, 297, 413, 53, 53, 297, + /* 1200 */ 137, 138, 91, 119, 1228, 1228, 1063, 1066, 1053, 1053, + /* 1210 */ 135, 135, 136, 136, 136, 136, 413, 1336, 1311, 446, + /* 1220 */ 137, 138, 91, 227, 1228, 1228, 1063, 1066, 1053, 1053, + /* 1230 */ 135, 135, 136, 136, 136, 136, 574, 1224, 936, 936, + /* 1240 */ 137, 126, 91, 141, 1228, 1228, 1063, 1066, 1053, 1053, + /* 1250 */ 135, 135, 136, 136, 136, 136, 533, 429, 472, 346, + /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 1270 */ 128, 451, 576, 457, 233, 343, 1435, 403, 498, 1550, + /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 1290 */ 128, 451, 576, 324, 576, 82, 82, 487, 576, 969, + /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 1310 */ 128, 451, 288, 288, 546, 68, 68, 54, 54, 553, + /* 1320 */ 413, 69, 69, 351, 6, 573, 944, 562, 410, 409, + /* 1330 */ 1435, 943, 450, 545, 260, 259, 258, 576, 158, 576, + /* 1340 */ 413, 222, 1180, 479, 969, 138, 91, 430, 1228, 1228, + /* 1350 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, + /* 1360 */ 70, 70, 71, 71, 576, 1126, 91, 576, 1228, 1228, + /* 1370 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, + /* 1380 */ 1127, 166, 850, 851, 852, 1282, 419, 72, 72, 108, + /* 1390 */ 73, 73, 1310, 358, 1180, 1128, 576, 305, 576, 123, + /* 1400 */ 568, 494, 4, 488, 134, 134, 134, 134, 133, 133, + /* 1410 */ 132, 132, 132, 131, 128, 451, 571, 564, 534, 55, + /* 1420 */ 55, 56, 56, 576, 134, 134, 134, 134, 133, 133, + /* 1430 */ 132, 132, 132, 131, 128, 451, 576, 1104, 233, 1104, + /* 1440 */ 452, 1602, 582, 2, 1259, 576, 57, 57, 576, 321, + /* 1450 */ 576, 155, 565, 1435, 485, 353, 576, 356, 1341, 59, + /* 1460 */ 59, 576, 44, 969, 569, 419, 576, 238, 60, 60, + /* 1470 */ 261, 74, 74, 75, 75, 287, 231, 576, 1366, 76, + /* 1480 */ 76, 1040, 420, 184, 20, 20, 576, 121, 121, 77, + /* 1490 */ 77, 97, 218, 288, 288, 122, 125, 452, 577, 452, + /* 1500 */ 143, 143, 1028, 576, 520, 576, 573, 576, 562, 144, + /* 1510 */ 144, 474, 227, 1244, 478, 123, 568, 576, 4, 320, + /* 1520 */ 567, 245, 411, 576, 443, 411, 78, 78, 62, 62, + /* 1530 */ 79, 79, 571, 319, 1028, 1028, 1030, 1031, 35, 418, + /* 1540 */ 63, 63, 576, 290, 411, 9, 80, 80, 1144, 576, + /* 1550 */ 400, 576, 486, 455, 576, 1223, 452, 576, 325, 342, + /* 1560 */ 576, 111, 576, 1188, 242, 64, 64, 473, 565, 576, + /* 1570 */ 23, 576, 170, 170, 171, 171, 576, 87, 87, 328, + /* 1580 */ 65, 65, 542, 83, 83, 146, 146, 541, 123, 568, + /* 1590 */ 341, 4, 84, 84, 168, 168, 576, 1040, 576, 148, + /* 1600 */ 148, 576, 1380, 121, 121, 571, 1021, 576, 266, 576, + /* 1610 */ 424, 122, 576, 452, 577, 452, 576, 553, 1028, 142, + /* 1620 */ 142, 169, 169, 576, 162, 162, 528, 889, 371, 452, + /* 1630 */ 152, 152, 151, 151, 1379, 149, 149, 109, 370, 150, + /* 1640 */ 150, 565, 576, 480, 576, 266, 86, 86, 576, 1092, + /* 1650 */ 1028, 1028, 1030, 1031, 35, 542, 482, 576, 266, 466, + /* 1660 */ 543, 123, 568, 1616, 4, 88, 88, 85, 85, 475, + /* 1670 */ 1040, 52, 52, 222, 901, 900, 121, 121, 571, 1188, + /* 1680 */ 58, 58, 244, 1032, 122, 889, 452, 577, 452, 908, + /* 1690 */ 909, 1028, 300, 347, 504, 111, 263, 361, 165, 111, + /* 1700 */ 111, 1088, 452, 263, 974, 1153, 266, 1092, 986, 987, + /* 1710 */ 942, 939, 125, 125, 565, 1103, 872, 1103, 159, 941, + /* 1720 */ 1309, 125, 1557, 1028, 1028, 1030, 1031, 35, 542, 337, + /* 1730 */ 1530, 205, 1529, 541, 499, 1589, 490, 348, 1376, 352, + /* 1740 */ 355, 1032, 357, 1040, 359, 1324, 1308, 366, 563, 121, + /* 1750 */ 121, 376, 1188, 1389, 1434, 1362, 280, 122, 1374, 452, + /* 1760 */ 577, 452, 167, 1439, 1028, 1289, 1280, 1268, 1267, 1269, + /* 1770 */ 1609, 1359, 312, 313, 314, 397, 12, 237, 224, 1421, + /* 1780 */ 295, 1416, 1409, 1426, 339, 484, 340, 509, 1371, 1612, + /* 1790 */ 1372, 1425, 1244, 404, 301, 228, 1028, 1028, 1030, 1031, + /* 1800 */ 35, 1601, 1192, 454, 345, 1307, 292, 369, 1502, 1501, + /* 1810 */ 270, 396, 396, 395, 277, 393, 1370, 1369, 859, 1549, + /* 1820 */ 186, 123, 568, 235, 4, 1188, 391, 210, 211, 223, + /* 1830 */ 1547, 239, 1241, 327, 422, 96, 220, 195, 571, 180, + /* 1840 */ 188, 326, 468, 469, 190, 191, 502, 192, 193, 566, + /* 1850 */ 247, 109, 1430, 491, 199, 251, 102, 281, 402, 476, + /* 1860 */ 405, 1496, 452, 497, 253, 1422, 13, 1428, 14, 1427, + /* 1870 */ 203, 1507, 241, 500, 565, 354, 407, 92, 95, 1270, + /* 1880 */ 175, 254, 518, 43, 1327, 255, 1326, 1325, 436, 1518, + /* 1890 */ 350, 1318, 104, 229, 893, 1626, 440, 441, 1625, 408, + /* 1900 */ 240, 1296, 268, 1040, 310, 269, 1297, 527, 444, 121, + /* 1910 */ 121, 368, 1295, 1594, 1624, 311, 1394, 122, 1317, 452, + /* 1920 */ 577, 452, 374, 1580, 1028, 1393, 140, 553, 11, 90, + /* 1930 */ 568, 385, 4, 116, 318, 414, 1579, 110, 1483, 537, + /* 1940 */ 320, 567, 1350, 555, 42, 579, 571, 1349, 1198, 383, + /* 1950 */ 276, 390, 216, 389, 278, 279, 1028, 1028, 1030, 1031, + /* 1960 */ 35, 172, 580, 1265, 458, 1260, 415, 416, 185, 156, + /* 1970 */ 452, 1534, 1535, 173, 1533, 1532, 89, 308, 225, 226, + /* 1980 */ 846, 174, 565, 453, 217, 1188, 322, 236, 1102, 154, + /* 1990 */ 1100, 330, 187, 176, 1223, 243, 189, 925, 338, 246, + /* 2000 */ 1116, 194, 177, 425, 178, 427, 98, 196, 99, 100, + /* 2010 */ 101, 1040, 179, 1119, 1115, 248, 249, 121, 121, 163, + /* 2020 */ 24, 250, 349, 1238, 496, 122, 1108, 452, 577, 452, + /* 2030 */ 1192, 454, 1028, 266, 292, 200, 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, 230, 1188, 284, 286, 265, 204, 125, 1171, + /* 2100 */ 241, 28, 978, 972, 29, 41, 1175, 1179, 175, 1173, + /* 2110 */ 30, 43, 31, 8, 241, 1178, 32, 1160, 208, 549, + /* 2120 */ 33, 111, 175, 1083, 1070, 43, 1068, 1072, 240, 113, + /* 2130 */ 114, 34, 561, 118, 1124, 271, 1073, 36, 18, 572, + /* 2140 */ 1033, 873, 240, 124, 37, 935, 272, 273, 1617, 183, + /* 2150 */ 153, 394, 1194, 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 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 312, - /* 10 */ 195, 218, 195, 316, 195, 235, 254, 195, 256, 19, - /* 20 */ 297, 277, 278, 279, 218, 206, 213, 214, 206, 218, - /* 30 */ 219, 31, 206, 218, 219, 218, 219, 218, 219, 39, - /* 40 */ 218, 219, 195, 43, 44, 45, 195, 47, 48, 49, + /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 241, + /* 10 */ 242, 195, 217, 221, 195, 235, 254, 195, 256, 19, + /* 20 */ 225, 298, 254, 195, 256, 206, 213, 214, 206, 218, + /* 30 */ 219, 31, 206, 195, 218, 219, 195, 218, 219, 39, + /* 40 */ 218, 219, 313, 43, 44, 45, 317, 47, 48, 49, /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19, - /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 195, - /* 70 */ 255, 237, 238, 254, 255, 256, 254, 255, 256, 264, - /* 80 */ 254, 207, 256, 43, 44, 45, 264, 47, 48, 49, - /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 251, - /* 100 */ 287, 253, 215, 103, 104, 105, 106, 107, 108, 109, - /* 110 */ 110, 111, 112, 113, 114, 82, 265, 195, 271, 11, + /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 277, + /* 70 */ 278, 279, 234, 254, 255, 256, 254, 255, 256, 218, + /* 80 */ 254, 240, 256, 43, 44, 45, 264, 47, 48, 49, + /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 271, + /* 100 */ 287, 22, 23, 103, 104, 105, 106, 107, 108, 109, + /* 110 */ 110, 111, 112, 113, 114, 114, 47, 48, 49, 50, /* 120 */ 187, 188, 189, 190, 191, 192, 190, 87, 192, 89, - /* 130 */ 197, 19, 199, 197, 317, 199, 319, 25, 271, 206, - /* 140 */ 218, 219, 206, 103, 104, 105, 106, 107, 108, 109, + /* 130 */ 197, 19, 199, 197, 318, 199, 320, 25, 195, 206, + /* 140 */ 299, 271, 206, 103, 104, 105, 106, 107, 108, 109, /* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 195, 47, /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 170 */ 58, 60, 139, 140, 241, 242, 289, 241, 242, 309, - /* 180 */ 310, 294, 70, 47, 48, 49, 50, 254, 77, 256, - /* 190 */ 254, 195, 256, 55, 56, 57, 58, 59, 221, 88, - /* 200 */ 109, 90, 269, 240, 93, 269, 107, 108, 109, 110, - /* 210 */ 111, 112, 113, 114, 215, 103, 104, 105, 106, 107, - /* 220 */ 108, 109, 110, 111, 112, 113, 114, 136, 117, 118, - /* 230 */ 119, 298, 141, 300, 298, 19, 300, 129, 130, 317, - /* 240 */ 318, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 250 */ 112, 113, 114, 114, 277, 278, 279, 146, 122, 43, - /* 260 */ 44, 45, 195, 47, 48, 49, 50, 51, 52, 53, - /* 270 */ 54, 55, 56, 57, 58, 218, 277, 278, 279, 19, - /* 280 */ 19, 195, 286, 23, 68, 218, 219, 55, 56, 57, - /* 290 */ 58, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 300 */ 112, 113, 114, 43, 44, 45, 232, 47, 48, 49, - /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 103, + /* 170 */ 58, 60, 21, 195, 241, 242, 215, 241, 242, 312, + /* 180 */ 313, 102, 70, 205, 317, 207, 242, 254, 77, 256, + /* 190 */ 254, 122, 256, 55, 56, 57, 58, 59, 254, 88, + /* 200 */ 256, 90, 269, 240, 93, 269, 107, 108, 109, 110, + /* 210 */ 111, 112, 113, 114, 271, 103, 104, 105, 106, 107, + /* 220 */ 108, 109, 110, 111, 112, 113, 114, 313, 117, 118, + /* 230 */ 119, 317, 81, 195, 301, 19, 195, 301, 277, 278, + /* 240 */ 279, 103, 104, 105, 106, 107, 108, 109, 110, 111, + /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 195, 43, + /* 260 */ 44, 45, 74, 47, 48, 49, 50, 51, 52, 53, + /* 270 */ 54, 55, 56, 57, 58, 124, 195, 60, 109, 110, + /* 280 */ 111, 112, 113, 114, 68, 195, 103, 104, 105, 106, + /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 208, 218, + /* 300 */ 219, 103, 104, 105, 106, 107, 108, 109, 110, 111, + /* 310 */ 112, 113, 114, 162, 233, 24, 128, 129, 130, 103, /* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 330 */ 114, 135, 60, 137, 138, 103, 104, 105, 106, 107, - /* 340 */ 108, 109, 110, 111, 112, 113, 114, 82, 281, 206, - /* 350 */ 195, 109, 110, 111, 112, 113, 114, 195, 195, 195, - /* 360 */ 205, 22, 207, 103, 104, 105, 106, 107, 108, 109, - /* 370 */ 110, 111, 112, 113, 114, 195, 60, 116, 117, 107, - /* 380 */ 108, 218, 219, 19, 241, 242, 121, 23, 116, 117, - /* 390 */ 118, 119, 306, 121, 308, 206, 234, 254, 15, 256, - /* 400 */ 195, 129, 259, 260, 139, 140, 145, 43, 44, 45, - /* 410 */ 200, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 420 */ 56, 57, 58, 218, 219, 60, 154, 19, 156, 265, - /* 430 */ 241, 242, 24, 117, 118, 119, 120, 21, 73, 123, - /* 440 */ 124, 125, 74, 254, 61, 256, 107, 108, 221, 133, - /* 450 */ 82, 43, 44, 45, 195, 47, 48, 49, 50, 51, - /* 460 */ 52, 53, 54, 55, 56, 57, 58, 103, 104, 105, - /* 470 */ 106, 107, 108, 109, 110, 111, 112, 113, 114, 195, - /* 480 */ 317, 318, 117, 118, 119, 22, 120, 195, 22, 123, - /* 490 */ 124, 125, 19, 20, 284, 22, 128, 81, 288, 133, - /* 500 */ 195, 195, 218, 219, 277, 278, 279, 139, 140, 36, - /* 510 */ 195, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 520 */ 112, 113, 114, 218, 219, 62, 60, 195, 241, 242, - /* 530 */ 271, 19, 240, 60, 189, 190, 191, 192, 233, 255, - /* 540 */ 124, 254, 197, 256, 199, 72, 129, 130, 264, 195, - /* 550 */ 195, 206, 22, 23, 60, 43, 44, 45, 206, 47, - /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 570 */ 58, 195, 218, 219, 101, 195, 60, 271, 162, 195, - /* 580 */ 107, 108, 109, 117, 118, 119, 241, 242, 115, 73, - /* 590 */ 117, 118, 119, 241, 242, 122, 60, 195, 266, 254, - /* 600 */ 312, 256, 218, 219, 316, 203, 254, 195, 256, 255, - /* 610 */ 208, 117, 118, 119, 269, 103, 104, 105, 106, 107, - /* 620 */ 108, 109, 110, 111, 112, 113, 114, 154, 155, 156, - /* 630 */ 157, 158, 102, 117, 118, 119, 19, 242, 144, 255, - /* 640 */ 23, 206, 24, 298, 195, 300, 206, 195, 264, 254, - /* 650 */ 206, 256, 240, 117, 118, 119, 183, 22, 22, 23, - /* 660 */ 43, 44, 45, 151, 47, 48, 49, 50, 51, 52, - /* 670 */ 53, 54, 55, 56, 57, 58, 241, 242, 60, 195, - /* 680 */ 19, 241, 242, 195, 23, 241, 242, 195, 152, 254, - /* 690 */ 310, 256, 243, 312, 254, 60, 256, 316, 254, 206, - /* 700 */ 256, 60, 218, 219, 43, 44, 45, 272, 47, 48, - /* 710 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 720 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 730 */ 113, 114, 240, 60, 241, 242, 118, 25, 102, 255, - /* 740 */ 166, 167, 101, 22, 26, 19, 20, 254, 22, 256, - /* 750 */ 139, 140, 117, 118, 119, 306, 195, 308, 117, 118, - /* 760 */ 237, 238, 36, 122, 103, 104, 105, 106, 107, 108, - /* 770 */ 109, 110, 111, 112, 113, 114, 195, 195, 60, 218, - /* 780 */ 219, 60, 109, 195, 19, 217, 60, 25, 23, 77, - /* 790 */ 117, 118, 119, 225, 233, 154, 155, 156, 72, 312, - /* 800 */ 218, 219, 90, 316, 22, 93, 303, 304, 43, 44, - /* 810 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54, - /* 820 */ 55, 56, 57, 58, 183, 195, 195, 101, 19, 213, - /* 830 */ 214, 243, 23, 107, 108, 117, 118, 119, 117, 118, - /* 840 */ 119, 115, 60, 117, 118, 119, 195, 60, 122, 218, - /* 850 */ 219, 22, 43, 44, 45, 35, 47, 48, 49, 50, - /* 860 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104, - /* 870 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 880 */ 154, 155, 156, 157, 158, 195, 255, 67, 195, 60, - /* 890 */ 101, 240, 311, 312, 306, 75, 308, 316, 29, 117, - /* 900 */ 118, 119, 33, 287, 117, 118, 119, 118, 146, 183, - /* 910 */ 195, 122, 103, 104, 105, 106, 107, 108, 109, 110, - /* 920 */ 111, 112, 113, 114, 215, 195, 77, 60, 25, 195, - /* 930 */ 122, 144, 19, 218, 219, 66, 23, 88, 246, 90, - /* 940 */ 132, 25, 93, 154, 155, 156, 117, 118, 119, 257, - /* 950 */ 195, 131, 218, 219, 195, 265, 43, 44, 45, 195, - /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 970 */ 57, 58, 183, 218, 219, 195, 19, 218, 219, 195, - /* 980 */ 23, 195, 218, 219, 117, 118, 119, 195, 233, 255, - /* 990 */ 195, 195, 233, 22, 23, 146, 25, 233, 218, 219, - /* 1000 */ 43, 44, 45, 294, 47, 48, 49, 50, 51, 52, - /* 1010 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106, - /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 114, 195, 12, - /* 1030 */ 234, 195, 240, 74, 195, 255, 195, 60, 243, 262, - /* 1040 */ 263, 311, 312, 25, 27, 19, 316, 107, 108, 265, - /* 1050 */ 24, 265, 195, 150, 195, 139, 140, 218, 219, 42, - /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1070 */ 113, 114, 233, 102, 67, 218, 219, 218, 219, 243, - /* 1080 */ 19, 64, 22, 23, 23, 25, 195, 128, 129, 130, - /* 1090 */ 233, 74, 233, 86, 154, 118, 156, 130, 265, 208, - /* 1100 */ 19, 306, 95, 308, 43, 44, 45, 266, 47, 48, - /* 1110 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1120 */ 153, 230, 96, 232, 43, 44, 45, 19, 47, 48, - /* 1130 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1140 */ 114, 22, 306, 24, 308, 127, 120, 121, 122, 123, - /* 1150 */ 124, 125, 126, 195, 147, 212, 213, 214, 132, 23, - /* 1160 */ 195, 25, 102, 100, 103, 104, 105, 106, 107, 108, - /* 1170 */ 109, 110, 111, 112, 113, 114, 218, 219, 19, 60, - /* 1180 */ 195, 12, 210, 211, 103, 104, 105, 106, 107, 108, - /* 1190 */ 109, 110, 111, 112, 113, 114, 27, 134, 195, 195, - /* 1200 */ 195, 210, 211, 218, 219, 195, 47, 195, 212, 213, - /* 1210 */ 214, 42, 16, 130, 19, 112, 113, 114, 23, 77, - /* 1220 */ 195, 218, 219, 218, 219, 117, 163, 164, 218, 219, - /* 1230 */ 218, 219, 90, 64, 19, 93, 153, 118, 43, 44, - /* 1240 */ 45, 160, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1250 */ 55, 56, 57, 58, 195, 119, 272, 276, 43, 44, - /* 1260 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1270 */ 55, 56, 57, 58, 78, 116, 80, 218, 219, 116, - /* 1280 */ 144, 128, 129, 130, 218, 219, 61, 195, 47, 195, - /* 1290 */ 16, 132, 195, 263, 195, 314, 315, 267, 103, 104, - /* 1300 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 1310 */ 218, 219, 218, 219, 151, 218, 219, 195, 103, 104, - /* 1320 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 1330 */ 210, 211, 195, 7, 8, 9, 195, 60, 195, 312, - /* 1340 */ 218, 219, 195, 316, 195, 120, 195, 263, 19, 195, - /* 1350 */ 125, 267, 78, 24, 80, 218, 219, 116, 162, 218, - /* 1360 */ 219, 218, 219, 301, 302, 218, 219, 195, 19, 218, - /* 1370 */ 219, 276, 43, 44, 45, 160, 47, 48, 49, 50, - /* 1380 */ 51, 52, 53, 54, 55, 56, 57, 58, 19, 146, - /* 1390 */ 218, 219, 43, 44, 45, 118, 47, 48, 49, 50, - /* 1400 */ 51, 52, 53, 54, 55, 56, 57, 58, 165, 314, - /* 1410 */ 315, 276, 43, 44, 45, 266, 47, 48, 49, 50, - /* 1420 */ 51, 52, 53, 54, 55, 56, 57, 58, 128, 129, - /* 1430 */ 130, 195, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1440 */ 111, 112, 113, 114, 195, 228, 195, 61, 195, 314, - /* 1450 */ 315, 25, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1460 */ 111, 112, 113, 114, 195, 22, 195, 218, 219, 218, - /* 1470 */ 219, 195, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1480 */ 111, 112, 113, 114, 195, 195, 246, 218, 219, 218, - /* 1490 */ 219, 25, 19, 246, 218, 219, 246, 257, 259, 260, - /* 1500 */ 195, 22, 266, 60, 257, 195, 120, 257, 218, 219, - /* 1510 */ 116, 195, 19, 195, 150, 151, 25, 44, 45, 266, - /* 1520 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1530 */ 57, 58, 195, 54, 218, 219, 218, 219, 45, 145, - /* 1540 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1550 */ 57, 58, 246, 121, 122, 218, 219, 19, 23, 31, - /* 1560 */ 25, 118, 159, 257, 161, 24, 195, 39, 195, 143, - /* 1570 */ 195, 19, 20, 22, 22, 24, 103, 104, 105, 106, - /* 1580 */ 107, 108, 109, 110, 111, 112, 113, 114, 36, 218, - /* 1590 */ 219, 218, 219, 218, 219, 195, 103, 104, 105, 106, - /* 1600 */ 107, 108, 109, 110, 111, 112, 113, 114, 195, 143, - /* 1610 */ 119, 136, 60, 195, 22, 195, 141, 195, 218, 219, - /* 1620 */ 195, 23, 195, 25, 72, 23, 131, 25, 195, 134, - /* 1630 */ 23, 218, 219, 195, 82, 144, 218, 219, 218, 219, - /* 1640 */ 218, 219, 195, 218, 219, 218, 219, 60, 23, 195, - /* 1650 */ 25, 218, 219, 101, 195, 117, 218, 219, 195, 107, - /* 1660 */ 108, 23, 195, 25, 195, 218, 219, 115, 228, 117, - /* 1670 */ 118, 119, 218, 219, 122, 195, 19, 218, 219, 195, - /* 1680 */ 60, 218, 219, 142, 195, 218, 219, 19, 20, 195, - /* 1690 */ 22, 139, 140, 23, 23, 25, 25, 195, 218, 219, - /* 1700 */ 7, 8, 218, 219, 36, 118, 154, 155, 156, 157, - /* 1710 */ 158, 195, 23, 195, 25, 84, 85, 49, 195, 23, - /* 1720 */ 195, 25, 195, 23, 195, 25, 195, 23, 60, 25, - /* 1730 */ 23, 23, 25, 25, 142, 183, 218, 219, 118, 195, - /* 1740 */ 72, 218, 219, 218, 219, 218, 219, 218, 219, 218, - /* 1750 */ 219, 195, 195, 146, 86, 98, 23, 195, 25, 91, - /* 1760 */ 19, 20, 154, 22, 156, 154, 23, 156, 25, 101, - /* 1770 */ 23, 195, 25, 195, 195, 107, 108, 36, 195, 195, - /* 1780 */ 195, 195, 228, 115, 195, 117, 118, 119, 195, 195, - /* 1790 */ 122, 261, 195, 321, 195, 195, 195, 258, 238, 195, - /* 1800 */ 195, 60, 299, 291, 195, 195, 258, 195, 195, 195, - /* 1810 */ 290, 244, 216, 72, 245, 193, 258, 258, 299, 258, - /* 1820 */ 299, 274, 154, 155, 156, 157, 158, 86, 247, 295, - /* 1830 */ 248, 295, 91, 19, 20, 270, 22, 274, 270, 248, - /* 1840 */ 274, 222, 101, 227, 274, 221, 231, 221, 107, 108, - /* 1850 */ 36, 183, 262, 247, 221, 283, 115, 262, 117, 118, - /* 1860 */ 119, 198, 116, 122, 220, 262, 61, 220, 220, 251, - /* 1870 */ 247, 142, 251, 245, 60, 202, 299, 202, 38, 262, - /* 1880 */ 202, 22, 152, 151, 296, 43, 72, 236, 18, 239, - /* 1890 */ 202, 239, 239, 239, 18, 154, 155, 156, 157, 158, - /* 1900 */ 86, 150, 201, 248, 275, 91, 248, 273, 236, 248, - /* 1910 */ 275, 275, 273, 236, 248, 101, 286, 202, 201, 159, - /* 1920 */ 63, 107, 108, 296, 183, 293, 202, 201, 22, 115, - /* 1930 */ 202, 117, 118, 119, 292, 223, 122, 201, 65, 202, - /* 1940 */ 201, 223, 220, 220, 22, 220, 226, 226, 229, 127, - /* 1950 */ 223, 220, 166, 24, 285, 220, 222, 114, 315, 285, - /* 1960 */ 220, 202, 220, 307, 92, 320, 320, 229, 154, 155, - /* 1970 */ 156, 157, 158, 0, 1, 2, 223, 83, 5, 268, - /* 1980 */ 149, 268, 146, 10, 11, 12, 13, 14, 22, 280, - /* 1990 */ 17, 202, 159, 19, 20, 251, 22, 183, 282, 148, - /* 2000 */ 252, 252, 250, 30, 249, 32, 248, 147, 25, 13, - /* 2010 */ 36, 204, 196, 40, 196, 6, 302, 194, 194, 194, - /* 2020 */ 209, 215, 209, 215, 215, 215, 224, 224, 216, 209, - /* 2030 */ 4, 216, 215, 3, 60, 22, 122, 19, 122, 19, - /* 2040 */ 125, 22, 15, 22, 71, 16, 72, 23, 23, 140, - /* 2050 */ 305, 152, 79, 25, 131, 82, 143, 20, 16, 305, - /* 2060 */ 1, 143, 145, 131, 131, 62, 54, 131, 37, 54, - /* 2070 */ 54, 152, 99, 117, 34, 101, 54, 24, 1, 5, - /* 2080 */ 22, 107, 108, 116, 76, 25, 162, 41, 142, 115, - /* 2090 */ 24, 117, 118, 119, 116, 20, 122, 19, 126, 23, - /* 2100 */ 132, 19, 20, 69, 22, 69, 22, 134, 22, 68, - /* 2110 */ 22, 22, 139, 140, 60, 141, 68, 24, 36, 28, - /* 2120 */ 97, 22, 37, 68, 23, 150, 34, 22, 154, 155, - /* 2130 */ 156, 157, 158, 23, 23, 22, 163, 25, 23, 142, - /* 2140 */ 23, 98, 60, 23, 22, 144, 25, 76, 34, 117, - /* 2150 */ 34, 89, 34, 34, 72, 87, 76, 183, 34, 94, - /* 2160 */ 34, 23, 22, 24, 34, 23, 25, 44, 25, 23, - /* 2170 */ 23, 23, 22, 22, 25, 11, 143, 25, 143, 23, - /* 2180 */ 22, 22, 22, 101, 23, 23, 136, 22, 25, 107, - /* 2190 */ 108, 142, 25, 142, 142, 23, 15, 115, 1, 117, - /* 2200 */ 118, 119, 1, 2, 122, 1, 5, 322, 322, 322, - /* 2210 */ 322, 10, 11, 12, 13, 14, 322, 322, 17, 322, - /* 2220 */ 5, 322, 322, 141, 322, 10, 11, 12, 13, 14, - /* 2230 */ 322, 30, 17, 32, 322, 322, 154, 155, 156, 157, - /* 2240 */ 158, 40, 322, 322, 322, 30, 322, 32, 322, 322, - /* 2250 */ 322, 322, 322, 322, 322, 40, 322, 322, 322, 322, - /* 2260 */ 322, 322, 322, 322, 322, 183, 322, 322, 322, 322, - /* 2270 */ 322, 322, 71, 322, 322, 322, 322, 322, 322, 322, - /* 2280 */ 79, 322, 322, 82, 322, 322, 71, 322, 322, 322, - /* 2290 */ 322, 322, 322, 322, 79, 322, 322, 82, 322, 322, - /* 2300 */ 99, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2310 */ 322, 322, 322, 322, 99, 322, 322, 322, 322, 322, - /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2330 */ 322, 322, 322, 322, 322, 134, 322, 322, 322, 322, - /* 2340 */ 139, 140, 322, 322, 322, 322, 322, 322, 322, 134, - /* 2350 */ 322, 322, 322, 322, 139, 140, 322, 322, 322, 322, - /* 2360 */ 322, 322, 322, 322, 163, 322, 322, 322, 322, 322, - /* 2370 */ 322, 322, 322, 322, 322, 322, 322, 322, 163, 322, - /* 2380 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2390 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2400 */ 322, 322, 322, 322, 322, 322, 322, 322, 187, 187, - /* 2410 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2420 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2430 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2440 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2450 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2460 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2470 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2480 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2490 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2500 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2510 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2520 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2530 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2540 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2550 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2560 */ 187, 187, 187, 187, 187, 187, + /* 330 */ 114, 195, 195, 215, 117, 118, 119, 120, 195, 19, + /* 340 */ 123, 124, 125, 207, 24, 74, 246, 60, 310, 311, + /* 350 */ 133, 60, 311, 82, 22, 218, 219, 257, 195, 19, + /* 360 */ 73, 218, 219, 43, 44, 45, 206, 47, 48, 49, + /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 22, + /* 380 */ 23, 218, 219, 43, 44, 45, 54, 47, 48, 49, + /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 128, + /* 400 */ 82, 241, 242, 195, 117, 118, 119, 289, 60, 118, + /* 410 */ 139, 140, 294, 195, 254, 195, 256, 195, 255, 259, + /* 420 */ 260, 73, 22, 103, 104, 105, 106, 107, 108, 109, + /* 430 */ 110, 111, 112, 113, 114, 206, 218, 219, 218, 219, + /* 440 */ 218, 219, 234, 103, 104, 105, 106, 107, 108, 109, + /* 450 */ 110, 111, 112, 113, 114, 318, 319, 139, 140, 102, + /* 460 */ 60, 318, 319, 221, 19, 117, 118, 119, 23, 195, + /* 470 */ 241, 242, 313, 255, 206, 255, 317, 255, 206, 129, + /* 480 */ 130, 206, 264, 254, 264, 256, 264, 195, 43, 44, + /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54, + /* 500 */ 55, 56, 57, 58, 246, 213, 214, 19, 19, 241, + /* 510 */ 242, 195, 23, 241, 242, 257, 241, 242, 118, 277, + /* 520 */ 278, 279, 254, 29, 256, 60, 254, 33, 256, 254, + /* 530 */ 206, 256, 43, 44, 45, 218, 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 */ 66, 19, 218, 60, 120, 241, 242, 123, 124, 125, + /* 570 */ 60, 232, 77, 19, 20, 26, 22, 133, 254, 287, + /* 580 */ 256, 265, 117, 118, 119, 90, 312, 313, 93, 47, + /* 590 */ 36, 317, 103, 104, 105, 106, 107, 108, 109, 110, + /* 600 */ 111, 112, 113, 114, 116, 117, 277, 278, 279, 60, + /* 610 */ 107, 108, 19, 276, 60, 31, 23, 152, 195, 116, + /* 620 */ 117, 118, 119, 39, 121, 276, 72, 117, 118, 119, + /* 630 */ 166, 167, 129, 145, 237, 238, 43, 44, 45, 276, + /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 650 */ 57, 58, 315, 316, 144, 101, 19, 154, 116, 156, + /* 660 */ 23, 107, 108, 109, 315, 316, 117, 118, 119, 115, + /* 670 */ 60, 117, 118, 119, 132, 200, 122, 60, 315, 316, + /* 680 */ 43, 44, 45, 272, 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, 212, 213, 214, 22, 195, 101, 22, + /* 720 */ 60, 19, 20, 60, 22, 139, 140, 117, 118, 119, + /* 730 */ 22, 251, 195, 253, 117, 118, 195, 183, 36, 122, + /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 750 */ 113, 114, 195, 195, 60, 218, 219, 60, 195, 284, + /* 760 */ 19, 25, 60, 288, 23, 237, 238, 22, 60, 109, + /* 770 */ 233, 154, 155, 156, 72, 218, 219, 117, 118, 119, + /* 780 */ 117, 118, 119, 116, 43, 44, 45, 265, 47, 48, + /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* 800 */ 183, 243, 25, 101, 19, 60, 265, 144, 23, 107, + /* 810 */ 108, 117, 118, 119, 117, 118, 119, 115, 151, 117, + /* 820 */ 118, 119, 82, 195, 122, 117, 118, 119, 43, 44, + /* 830 */ 45, 195, 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, 121, 117, 118, 119, 307, 101, 309, 195, 22, + /* 870 */ 23, 195, 25, 19, 35, 139, 140, 195, 24, 139, + /* 880 */ 140, 208, 195, 118, 109, 183, 22, 122, 103, 104, + /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + /* 900 */ 304, 305, 77, 230, 127, 232, 67, 195, 19, 195, + /* 910 */ 195, 136, 23, 88, 75, 90, 141, 203, 93, 154, + /* 920 */ 155, 156, 208, 295, 60, 243, 22, 23, 19, 25, + /* 930 */ 218, 219, 43, 44, 45, 100, 47, 48, 49, 50, + /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 183, 102, + /* 950 */ 96, 195, 43, 44, 45, 240, 47, 48, 49, 50, + /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 134, + /* 970 */ 131, 146, 25, 286, 120, 121, 122, 123, 124, 125, + /* 980 */ 126, 117, 118, 119, 313, 195, 132, 195, 317, 307, + /* 990 */ 195, 309, 103, 104, 105, 106, 107, 108, 109, 110, + /* 1000 */ 111, 112, 113, 114, 195, 195, 102, 195, 195, 195, + /* 1010 */ 218, 219, 103, 104, 105, 106, 107, 108, 109, 110, + /* 1020 */ 111, 112, 113, 114, 77, 233, 195, 60, 218, 219, + /* 1030 */ 218, 219, 218, 219, 23, 195, 25, 90, 243, 159, + /* 1040 */ 93, 161, 19, 233, 195, 233, 23, 233, 16, 218, + /* 1050 */ 219, 195, 243, 212, 213, 214, 262, 263, 218, 219, + /* 1060 */ 195, 271, 19, 307, 233, 309, 43, 44, 45, 160, + /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 1080 */ 57, 58, 195, 218, 219, 118, 43, 44, 45, 240, + /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 1100 */ 57, 58, 307, 195, 309, 218, 219, 263, 12, 195, + /* 1110 */ 78, 267, 80, 112, 113, 114, 307, 22, 309, 24, + /* 1120 */ 255, 281, 266, 27, 107, 108, 103, 104, 105, 106, + /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 195, + /* 1140 */ 11, 22, 255, 24, 195, 195, 103, 104, 105, 106, + /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 19, 195, + /* 1160 */ 64, 195, 218, 219, 195, 313, 195, 218, 219, 317, + /* 1170 */ 74, 154, 195, 156, 195, 195, 19, 233, 23, 60, + /* 1180 */ 25, 24, 218, 219, 218, 219, 195, 218, 219, 218, + /* 1190 */ 219, 128, 129, 130, 162, 263, 19, 218, 219, 267, + /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52, + /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 240, 228, 255, + /* 1220 */ 43, 44, 45, 25, 47, 48, 49, 50, 51, 52, + /* 1230 */ 53, 54, 55, 56, 57, 58, 135, 118, 137, 138, + /* 1240 */ 43, 44, 45, 22, 47, 48, 49, 50, 51, 52, + /* 1250 */ 53, 54, 55, 56, 57, 58, 117, 266, 129, 130, + /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 1270 */ 113, 114, 195, 195, 119, 295, 195, 206, 195, 195, + /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 1290 */ 113, 114, 195, 195, 195, 218, 219, 195, 195, 144, + /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 1310 */ 113, 114, 241, 242, 67, 218, 219, 218, 219, 146, + /* 1320 */ 19, 218, 219, 240, 215, 254, 136, 256, 107, 108, + /* 1330 */ 195, 141, 255, 86, 128, 129, 130, 195, 165, 195, + /* 1340 */ 19, 143, 95, 272, 25, 44, 45, 266, 47, 48, + /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* 1360 */ 218, 219, 218, 219, 195, 12, 45, 195, 47, 48, + /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* 1380 */ 27, 23, 7, 8, 9, 210, 211, 218, 219, 116, + /* 1390 */ 218, 219, 228, 16, 147, 42, 195, 295, 195, 19, + /* 1400 */ 20, 266, 22, 294, 103, 104, 105, 106, 107, 108, + /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 218, + /* 1420 */ 219, 218, 219, 195, 103, 104, 105, 106, 107, 108, + /* 1430 */ 109, 110, 111, 112, 113, 114, 195, 154, 119, 156, + /* 1440 */ 60, 189, 190, 191, 192, 195, 218, 219, 195, 197, + /* 1450 */ 195, 199, 72, 195, 19, 78, 195, 80, 206, 218, + /* 1460 */ 219, 195, 82, 144, 210, 211, 195, 15, 218, 219, + /* 1470 */ 47, 218, 219, 218, 219, 259, 260, 195, 261, 218, + /* 1480 */ 219, 101, 302, 303, 218, 219, 195, 107, 108, 218, + /* 1490 */ 219, 150, 151, 241, 242, 115, 25, 117, 118, 119, + /* 1500 */ 218, 219, 122, 195, 146, 195, 254, 195, 256, 218, + /* 1510 */ 219, 246, 25, 61, 246, 19, 20, 195, 22, 139, + /* 1520 */ 140, 269, 257, 195, 266, 257, 218, 219, 218, 219, + /* 1530 */ 218, 219, 36, 246, 154, 155, 156, 157, 158, 116, + /* 1540 */ 218, 219, 195, 22, 257, 49, 218, 219, 23, 195, + /* 1550 */ 25, 195, 117, 301, 195, 25, 60, 195, 195, 23, + /* 1560 */ 195, 25, 195, 183, 24, 218, 219, 130, 72, 195, + /* 1570 */ 22, 195, 218, 219, 218, 219, 195, 218, 219, 195, + /* 1580 */ 218, 219, 86, 218, 219, 218, 219, 91, 19, 20, + /* 1590 */ 153, 22, 218, 219, 218, 219, 195, 101, 195, 218, + /* 1600 */ 219, 195, 195, 107, 108, 36, 23, 195, 25, 195, + /* 1610 */ 62, 115, 195, 117, 118, 119, 195, 146, 122, 218, + /* 1620 */ 219, 218, 219, 195, 218, 219, 19, 60, 122, 60, + /* 1630 */ 218, 219, 218, 219, 195, 218, 219, 150, 132, 218, + /* 1640 */ 219, 72, 195, 23, 195, 25, 218, 219, 195, 60, + /* 1650 */ 154, 155, 156, 157, 158, 86, 23, 195, 25, 195, + /* 1660 */ 91, 19, 20, 142, 22, 218, 219, 218, 219, 130, + /* 1670 */ 101, 218, 219, 143, 121, 122, 107, 108, 36, 183, + /* 1680 */ 218, 219, 142, 60, 115, 118, 117, 118, 119, 7, + /* 1690 */ 8, 122, 153, 23, 23, 25, 25, 23, 23, 25, + /* 1700 */ 25, 23, 60, 25, 23, 98, 25, 118, 84, 85, + /* 1710 */ 23, 23, 25, 25, 72, 154, 23, 156, 25, 23, + /* 1720 */ 228, 25, 195, 154, 155, 156, 157, 158, 86, 195, + /* 1730 */ 195, 258, 195, 91, 291, 322, 195, 195, 195, 195, + /* 1740 */ 195, 118, 195, 101, 195, 195, 195, 195, 238, 107, + /* 1750 */ 108, 195, 183, 195, 195, 195, 290, 115, 195, 117, + /* 1760 */ 118, 119, 244, 195, 122, 195, 195, 195, 195, 195, + /* 1770 */ 195, 258, 258, 258, 258, 193, 245, 300, 216, 274, + /* 1780 */ 247, 270, 270, 274, 296, 296, 248, 222, 262, 198, + /* 1790 */ 262, 274, 61, 274, 248, 231, 154, 155, 156, 157, + /* 1800 */ 158, 0, 1, 2, 247, 227, 5, 221, 221, 221, + /* 1810 */ 142, 10, 11, 12, 13, 14, 262, 262, 17, 202, + /* 1820 */ 300, 19, 20, 300, 22, 183, 247, 251, 251, 245, + /* 1830 */ 202, 30, 38, 32, 202, 152, 151, 22, 36, 43, + /* 1840 */ 236, 40, 18, 202, 239, 239, 18, 239, 239, 283, + /* 1850 */ 201, 150, 236, 202, 236, 201, 159, 202, 248, 248, + /* 1860 */ 248, 248, 60, 63, 201, 275, 273, 275, 273, 275, + /* 1870 */ 22, 286, 71, 223, 72, 202, 223, 297, 297, 202, + /* 1880 */ 79, 201, 116, 82, 220, 201, 220, 220, 65, 293, + /* 1890 */ 292, 229, 22, 166, 127, 226, 24, 114, 226, 223, + /* 1900 */ 99, 222, 202, 101, 285, 92, 220, 308, 83, 107, + /* 1910 */ 108, 220, 220, 316, 220, 285, 268, 115, 229, 117, + /* 1920 */ 118, 119, 223, 321, 122, 268, 149, 146, 22, 19, + /* 1930 */ 20, 202, 22, 159, 282, 134, 321, 148, 280, 147, + /* 1940 */ 139, 140, 252, 141, 25, 204, 36, 252, 13, 251, + /* 1950 */ 196, 248, 250, 249, 196, 6, 154, 155, 156, 157, + /* 1960 */ 158, 209, 194, 194, 163, 194, 306, 306, 303, 224, + /* 1970 */ 60, 215, 215, 209, 215, 215, 215, 224, 216, 216, + /* 1980 */ 4, 209, 72, 3, 22, 183, 164, 15, 23, 16, + /* 1990 */ 23, 140, 152, 131, 25, 24, 143, 20, 16, 145, + /* 2000 */ 1, 143, 131, 62, 131, 37, 54, 152, 54, 54, + /* 2010 */ 54, 101, 131, 117, 1, 34, 142, 107, 108, 5, + /* 2020 */ 22, 116, 162, 76, 41, 115, 69, 117, 118, 119, + /* 2030 */ 1, 2, 122, 25, 5, 69, 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, 142, 183, 23, 23, 34, 22, 25, 89, + /* 2100 */ 71, 34, 117, 144, 34, 22, 76, 76, 79, 87, + /* 2110 */ 34, 82, 34, 44, 71, 94, 34, 23, 25, 24, + /* 2120 */ 34, 25, 79, 23, 23, 82, 23, 23, 99, 143, + /* 2130 */ 143, 22, 25, 25, 23, 22, 11, 22, 22, 25, + /* 2140 */ 23, 23, 99, 22, 22, 136, 142, 142, 142, 25, + /* 2150 */ 23, 15, 1, 1, 323, 323, 323, 323, 323, 323, + /* 2160 */ 323, 323, 323, 134, 323, 323, 323, 323, 139, 140, + /* 2170 */ 323, 323, 323, 323, 323, 323, 323, 134, 323, 323, + /* 2180 */ 323, 323, 139, 140, 323, 323, 323, 323, 323, 323, + /* 2190 */ 323, 323, 163, 323, 323, 323, 323, 323, 323, 323, + /* 2200 */ 323, 323, 323, 323, 323, 323, 163, 323, 323, 323, + /* 2210 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2220 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2230 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2240 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2250 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2260 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2270 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2280 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2290 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2300 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2310 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2320 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2330 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2340 */ 323, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2350 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2360 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2370 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2380 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2390 */ 187, 187, 187, 187, }; -#define YY_SHIFT_COUNT (599) +#define YY_SHIFT_COUNT (582) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2215) +#define YY_SHIFT_MAX (2152) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 2201, 1973, 2215, 1552, 1552, 33, 368, 1668, 1741, 1814, - /* 10 */ 726, 726, 726, 265, 33, 33, 33, 33, 33, 0, - /* 20 */ 0, 216, 1349, 726, 726, 726, 726, 726, 726, 726, - /* 30 */ 726, 726, 726, 726, 726, 726, 726, 726, 272, 272, - /* 40 */ 111, 111, 316, 365, 516, 867, 867, 916, 916, 916, - /* 50 */ 916, 40, 112, 260, 364, 408, 512, 617, 661, 765, - /* 60 */ 809, 913, 957, 1061, 1081, 1195, 1215, 1329, 1349, 1349, - /* 70 */ 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, - /* 80 */ 1349, 1349, 1349, 1349, 1349, 1349, 1369, 1349, 1473, 1493, - /* 90 */ 1493, 473, 1974, 2082, 726, 726, 726, 726, 726, 726, - /* 100 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 110 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 120 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 130 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 140 */ 726, 726, 726, 726, 726, 726, 138, 232, 232, 232, - /* 150 */ 232, 232, 232, 232, 188, 99, 242, 718, 416, 1159, - /* 160 */ 867, 867, 940, 940, 867, 1103, 417, 574, 574, 574, - /* 170 */ 611, 139, 139, 2379, 2379, 1026, 1026, 1026, 536, 466, - /* 180 */ 466, 466, 466, 1017, 1017, 849, 718, 971, 1060, 867, - /* 190 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, - /* 200 */ 867, 867, 867, 867, 867, 867, 867, 867, 261, 712, - /* 210 */ 712, 867, 108, 1142, 1142, 977, 1108, 1108, 977, 977, - /* 220 */ 1243, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 641, 789, - /* 230 */ 789, 635, 366, 721, 673, 782, 494, 787, 829, 867, - /* 240 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, - /* 250 */ 959, 867, 867, 867, 867, 867, 867, 867, 867, 867, - /* 260 */ 867, 867, 867, 867, 867, 820, 820, 820, 867, 867, - /* 270 */ 867, 1136, 867, 867, 867, 1119, 1007, 867, 1169, 867, - /* 280 */ 867, 867, 867, 867, 867, 867, 867, 1225, 1153, 869, - /* 290 */ 196, 618, 618, 618, 618, 1491, 196, 196, 91, 339, - /* 300 */ 1326, 1386, 383, 1163, 1364, 1426, 1364, 1538, 903, 1163, - /* 310 */ 1163, 903, 1163, 1426, 1538, 1018, 1535, 1241, 1528, 1528, - /* 320 */ 1528, 1394, 1394, 1394, 1394, 762, 762, 1403, 1466, 1475, - /* 330 */ 1551, 1746, 1805, 1746, 1746, 1729, 1729, 1840, 1840, 1729, - /* 340 */ 1730, 1732, 1859, 1842, 1870, 1870, 1870, 1870, 1729, 1876, - /* 350 */ 1751, 1732, 1732, 1751, 1859, 1842, 1751, 1842, 1751, 1729, - /* 360 */ 1876, 1760, 1857, 1729, 1876, 1906, 1729, 1876, 1729, 1876, - /* 370 */ 1906, 1746, 1746, 1746, 1873, 1922, 1922, 1906, 1746, 1822, - /* 380 */ 1746, 1873, 1746, 1746, 1786, 1929, 1843, 1843, 1906, 1729, - /* 390 */ 1872, 1872, 1894, 1894, 1831, 1836, 1966, 1729, 1833, 1831, - /* 400 */ 1851, 1860, 1751, 1983, 1996, 1996, 2009, 2009, 2009, 2379, - /* 410 */ 2379, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 2379, - /* 420 */ 2379, 2379, 2379, 2379, 136, 1063, 1196, 530, 636, 1274, - /* 430 */ 1300, 1443, 1598, 1495, 1479, 967, 1083, 1602, 463, 1625, - /* 440 */ 1638, 1670, 1541, 1671, 1689, 1696, 1277, 1432, 1693, 808, - /* 450 */ 1700, 1607, 1657, 1587, 1704, 1707, 1631, 1708, 1733, 1608, - /* 460 */ 1611, 1743, 1747, 1620, 1592, 2026, 2030, 2013, 1914, 2018, - /* 470 */ 1916, 2020, 2019, 2021, 1915, 2027, 2029, 2024, 2025, 1909, - /* 480 */ 1899, 1923, 2028, 2028, 1913, 2037, 1917, 2042, 2059, 1918, - /* 490 */ 1932, 2028, 1933, 2003, 2031, 2028, 1919, 2012, 2015, 2016, - /* 500 */ 2022, 1936, 1956, 2040, 2053, 2077, 2074, 2058, 1967, 1924, - /* 510 */ 2034, 2060, 2036, 2008, 2046, 1946, 1978, 2066, 2075, 2078, - /* 520 */ 1968, 1972, 2084, 2041, 2086, 2088, 2076, 2089, 2048, 2054, - /* 530 */ 2093, 2023, 2091, 2099, 2055, 2085, 2101, 2092, 1975, 2105, - /* 540 */ 2110, 2111, 2112, 2115, 2113, 2043, 1997, 2117, 2120, 2032, - /* 550 */ 2114, 2122, 2001, 2121, 2116, 2118, 2119, 2124, 2062, 2071, - /* 560 */ 2068, 2123, 2080, 2065, 2126, 2138, 2140, 2139, 2141, 2143, - /* 570 */ 2130, 2033, 2035, 2142, 2121, 2146, 2147, 2148, 2150, 2149, - /* 580 */ 2152, 2156, 2151, 2164, 2158, 2159, 2161, 2162, 2160, 2165, - /* 590 */ 2163, 2050, 2049, 2051, 2052, 2167, 2172, 2181, 2197, 2204, + /* 0 */ 2029, 1801, 2043, 1380, 1380, 318, 271, 1496, 1569, 1642, + /* 10 */ 702, 702, 702, 740, 318, 318, 318, 318, 318, 0, + /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702, + /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 503, 503, + /* 40 */ 111, 111, 217, 287, 348, 610, 610, 736, 736, 736, + /* 50 */ 736, 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, 169, 549, 610, 151, 542, 610, 610, 1017, + /* 160 */ 1017, 610, 1001, 350, 464, 464, 464, 586, 1, 1, + /* 170 */ 2207, 2207, 854, 854, 854, 465, 694, 694, 694, 694, + /* 180 */ 1096, 1096, 825, 549, 847, 904, 610, 610, 610, 610, + /* 190 */ 610, 610, 610, 610, 610, 610, 610, 610, 610, 610, + /* 200 */ 610, 610, 610, 610, 610, 488, 947, 947, 610, 1129, + /* 210 */ 495, 495, 1139, 1139, 967, 967, 1173, 2207, 2207, 2207, + /* 220 */ 2207, 2207, 2207, 2207, 617, 765, 765, 697, 444, 708, + /* 230 */ 660, 745, 510, 663, 864, 610, 610, 610, 610, 610, + /* 240 */ 610, 610, 610, 610, 610, 188, 610, 610, 610, 610, + /* 250 */ 610, 610, 610, 610, 610, 610, 610, 610, 839, 839, + /* 260 */ 839, 610, 610, 610, 1155, 610, 610, 610, 1119, 1247, + /* 270 */ 610, 1353, 610, 610, 610, 610, 610, 610, 610, 610, + /* 280 */ 1063, 494, 1101, 291, 291, 291, 291, 1319, 1101, 1101, + /* 290 */ 775, 1221, 1375, 1452, 667, 1341, 1198, 1341, 1435, 1487, + /* 300 */ 667, 667, 1487, 667, 1198, 1435, 777, 1011, 1423, 584, + /* 310 */ 584, 584, 1273, 1273, 1273, 1273, 1471, 1471, 880, 1530, + /* 320 */ 1190, 1095, 1731, 1731, 1668, 1668, 1794, 1794, 1668, 1683, + /* 330 */ 1685, 1815, 1796, 1824, 1824, 1824, 1824, 1668, 1828, 1701, + /* 340 */ 1685, 1685, 1701, 1815, 1796, 1701, 1796, 1701, 1668, 1828, + /* 350 */ 1697, 1800, 1668, 1828, 1848, 1668, 1828, 1668, 1828, 1848, + /* 360 */ 1766, 1766, 1766, 1823, 1870, 1870, 1848, 1766, 1767, 1766, + /* 370 */ 1823, 1766, 1766, 1727, 1872, 1783, 1783, 1848, 1668, 1813, + /* 380 */ 1813, 1825, 1825, 1777, 1781, 1906, 1668, 1774, 1777, 1789, + /* 390 */ 1792, 1701, 1919, 1935, 1935, 1949, 1949, 1949, 2207, 2207, + /* 400 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, + /* 410 */ 2207, 2207, 2207, 69, 1032, 79, 357, 1377, 1206, 400, + /* 420 */ 1525, 835, 332, 1540, 1437, 1539, 1536, 1548, 1583, 1620, + /* 430 */ 1633, 1670, 1671, 1674, 1567, 1553, 1682, 1506, 1675, 1358, + /* 440 */ 1607, 1589, 1678, 1681, 1624, 1687, 1688, 1283, 1561, 1693, + /* 450 */ 1696, 1623, 1521, 1976, 1980, 1962, 1822, 1972, 1973, 1965, + /* 460 */ 1967, 1851, 1840, 1862, 1969, 1969, 1971, 1853, 1977, 1854, + /* 470 */ 1982, 1999, 1858, 1871, 1969, 1873, 1941, 1968, 1969, 1855, + /* 480 */ 1952, 1954, 1955, 1956, 1881, 1896, 1981, 1874, 2013, 2014, + /* 490 */ 1998, 1905, 1860, 1957, 2008, 1966, 1947, 1983, 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, 1950, + /* 530 */ 2071, 2072, 1985, 2062, 2075, 1959, 2073, 2067, 2070, 2076, + /* 540 */ 2078, 2010, 2030, 2022, 2069, 2031, 2021, 2082, 2094, 2083, + /* 550 */ 2095, 2093, 2096, 2086, 1986, 1987, 2100, 2073, 2101, 2103, + /* 560 */ 2104, 2109, 2107, 2108, 2111, 2113, 2125, 2115, 2116, 2117, + /* 570 */ 2118, 2121, 2122, 2114, 2009, 2004, 2005, 2006, 2124, 2127, + /* 580 */ 2136, 2151, 2152, }; -#define YY_REDUCE_COUNT (423) -#define YY_REDUCE_MIN (-303) -#define YY_REDUCE_MAX (1825) +#define YY_REDUCE_COUNT (412) +#define YY_REDUCE_MIN (-277) +#define YY_REDUCE_MAX (1772) static const short yy_reduce_ofst[] = { - /* 0 */ -67, 345, -64, -178, -181, 143, 435, -78, -183, 163, - /* 10 */ -185, 284, 384, -174, 189, 352, 440, 444, 493, -23, - /* 20 */ 227, -277, -1, 305, 561, 755, 759, 764, -189, 839, - /* 30 */ 857, 354, 484, 859, 631, 67, 734, 780, -187, 616, - /* 40 */ 581, 730, 891, 449, 588, 795, 836, -238, 287, -238, - /* 50 */ 287, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 60 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 70 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 80 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 90 */ -256, 205, 582, 715, 958, 985, 1003, 1005, 1010, 1012, - /* 100 */ 1059, 1066, 1092, 1094, 1097, 1122, 1137, 1141, 1143, 1147, - /* 110 */ 1151, 1172, 1249, 1251, 1269, 1271, 1276, 1290, 1316, 1318, - /* 120 */ 1337, 1371, 1373, 1375, 1400, 1413, 1418, 1420, 1422, 1425, - /* 130 */ 1427, 1433, 1438, 1447, 1454, 1459, 1463, 1467, 1480, 1484, - /* 140 */ 1518, 1523, 1525, 1527, 1529, 1531, -256, -256, -256, -256, - /* 150 */ -256, -256, -256, -256, -256, -256, -256, 155, 210, -220, - /* 160 */ 86, -130, 943, 996, 402, -256, -113, 981, 1095, 1135, - /* 170 */ 395, -256, -256, -256, -256, 568, 568, 568, -4, -153, - /* 180 */ -133, 259, 306, -166, 523, -303, -126, 503, 503, -37, - /* 190 */ -149, 164, 690, 292, 412, 492, 651, 784, 332, 786, - /* 200 */ 841, 1149, 833, 1236, 792, 162, 796, 1253, 777, 288, - /* 210 */ 381, 380, 709, 487, 1027, 972, 1030, 1084, 991, 1120, - /* 220 */ -152, 1062, 692, 1240, 1247, 1250, 1239, 1306, -207, -194, - /* 230 */ 57, 180, 74, 315, 355, 376, 452, 488, 630, 693, - /* 240 */ 965, 1004, 1025, 1099, 1154, 1289, 1305, 1310, 1469, 1489, - /* 250 */ 984, 1494, 1502, 1516, 1544, 1556, 1557, 1562, 1576, 1578, - /* 260 */ 1579, 1583, 1584, 1585, 1586, 1217, 1440, 1554, 1589, 1593, - /* 270 */ 1594, 1530, 1597, 1599, 1600, 1539, 1472, 1601, 1560, 1604, - /* 280 */ 355, 1605, 1609, 1610, 1612, 1613, 1614, 1503, 1512, 1520, - /* 290 */ 1567, 1548, 1558, 1559, 1561, 1530, 1567, 1567, 1569, 1596, - /* 300 */ 1622, 1519, 1521, 1547, 1565, 1581, 1568, 1534, 1582, 1563, - /* 310 */ 1566, 1591, 1570, 1606, 1536, 1619, 1615, 1616, 1624, 1626, - /* 320 */ 1633, 1590, 1595, 1603, 1617, 1618, 1621, 1572, 1623, 1628, - /* 330 */ 1663, 1644, 1577, 1647, 1648, 1673, 1675, 1588, 1627, 1678, - /* 340 */ 1630, 1629, 1634, 1651, 1650, 1652, 1653, 1654, 1688, 1701, - /* 350 */ 1655, 1635, 1636, 1658, 1639, 1672, 1661, 1677, 1666, 1715, - /* 360 */ 1717, 1632, 1642, 1724, 1726, 1712, 1728, 1736, 1737, 1739, - /* 370 */ 1718, 1722, 1723, 1725, 1719, 1720, 1721, 1727, 1731, 1734, - /* 380 */ 1735, 1738, 1740, 1742, 1643, 1656, 1669, 1674, 1753, 1759, - /* 390 */ 1645, 1646, 1711, 1713, 1748, 1744, 1709, 1789, 1716, 1749, - /* 400 */ 1752, 1755, 1758, 1807, 1816, 1818, 1823, 1824, 1825, 1745, - /* 410 */ 1754, 1714, 1811, 1806, 1808, 1809, 1810, 1813, 1802, 1803, - /* 420 */ 1812, 1815, 1817, 1820, + /* 0 */ -67, 1252, -64, -178, -181, 160, 1071, 143, -184, 137, + /* 10 */ 218, 220, 222, -174, 229, 268, 272, 275, 324, -208, + /* 20 */ 242, -277, -39, 81, 537, 792, 810, 812, -189, 814, + /* 30 */ 831, 163, 865, 944, 887, 840, 964, 1077, -187, 292, + /* 40 */ -133, 274, 673, 558, 682, 795, 809, -238, -232, -238, + /* 50 */ -232, 329, 329, 329, 329, 329, 329, 329, 329, 329, + /* 60 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + /* 70 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + /* 80 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 557, + /* 90 */ 712, 949, 966, 969, 971, 979, 1097, 1099, 1103, 1142, + /* 100 */ 1144, 1169, 1172, 1201, 1203, 1228, 1241, 1250, 1253, 1255, + /* 110 */ 1261, 1266, 1271, 1282, 1291, 1308, 1310, 1312, 1322, 1328, + /* 120 */ 1347, 1354, 1356, 1359, 1362, 1365, 1367, 1374, 1376, 1381, + /* 130 */ 1401, 1403, 1406, 1412, 1414, 1417, 1421, 1428, 1447, 1449, + /* 140 */ 1453, 1462, 329, 329, 329, 329, 329, 329, 329, 329, + /* 150 */ 329, 329, 329, -22, -159, 475, -220, 756, 38, 501, + /* 160 */ 841, 714, 329, 118, 337, 349, 363, -56, 329, 329, + /* 170 */ 329, 329, -205, -205, -205, 687, -172, -130, -57, 790, + /* 180 */ 397, 528, -271, 136, 596, 596, 90, 316, 522, 541, + /* 190 */ -37, 715, 849, 977, 628, 856, 980, 991, 1081, 1102, + /* 200 */ 1135, 1083, -162, 208, 1258, 794, -86, 159, 41, 1109, + /* 210 */ 671, 852, 844, 932, 1175, 1254, 480, 1180, 100, 258, + /* 220 */ 1265, 1268, 1216, 1287, -139, 317, 344, 63, 339, 423, + /* 230 */ 563, 636, 676, 813, 908, 914, 950, 1078, 1084, 1098, + /* 240 */ 1363, 1384, 1407, 1439, 1464, 411, 1527, 1534, 1535, 1537, + /* 250 */ 1541, 1542, 1543, 1544, 1545, 1547, 1549, 1550, 990, 1164, + /* 260 */ 1492, 1551, 1552, 1556, 1217, 1558, 1559, 1560, 1473, 1413, + /* 270 */ 1563, 1510, 1568, 563, 1570, 1571, 1572, 1573, 1574, 1575, + /* 280 */ 1443, 1466, 1518, 1513, 1514, 1515, 1516, 1217, 1518, 1518, + /* 290 */ 1531, 1562, 1582, 1477, 1505, 1511, 1533, 1512, 1488, 1538, + /* 300 */ 1509, 1517, 1546, 1519, 1557, 1489, 1565, 1564, 1578, 1586, + /* 310 */ 1587, 1588, 1526, 1528, 1554, 1555, 1576, 1577, 1566, 1579, + /* 320 */ 1584, 1591, 1520, 1523, 1617, 1628, 1580, 1581, 1632, 1585, + /* 330 */ 1590, 1593, 1604, 1605, 1606, 1608, 1609, 1641, 1649, 1610, + /* 340 */ 1592, 1594, 1611, 1595, 1616, 1612, 1618, 1613, 1651, 1654, + /* 350 */ 1596, 1598, 1655, 1663, 1650, 1673, 1680, 1677, 1684, 1653, + /* 360 */ 1664, 1666, 1667, 1662, 1669, 1672, 1676, 1686, 1679, 1691, + /* 370 */ 1689, 1692, 1694, 1597, 1599, 1619, 1630, 1699, 1700, 1602, + /* 380 */ 1615, 1648, 1657, 1690, 1698, 1658, 1729, 1652, 1695, 1702, + /* 390 */ 1704, 1703, 1741, 1754, 1758, 1768, 1769, 1771, 1660, 1661, + /* 400 */ 1665, 1752, 1756, 1757, 1759, 1760, 1764, 1745, 1753, 1762, + /* 410 */ 1763, 1761, 1772, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1691, 1691, 1691, 1516, 1279, 1392, 1279, 1279, 1279, 1279, - /* 10 */ 1516, 1516, 1516, 1279, 1279, 1279, 1279, 1279, 1279, 1422, - /* 20 */ 1422, 1568, 1312, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 30 */ 1279, 1279, 1279, 1279, 1279, 1515, 1279, 1279, 1279, 1279, - /* 40 */ 1607, 1607, 1279, 1279, 1279, 1279, 1279, 1592, 1591, 1279, - /* 50 */ 1279, 1279, 1431, 1279, 1279, 1279, 1438, 1279, 1279, 1279, - /* 60 */ 1279, 1279, 1517, 1518, 1279, 1279, 1279, 1279, 1567, 1569, - /* 70 */ 1533, 1445, 1444, 1443, 1442, 1551, 1410, 1436, 1429, 1433, - /* 80 */ 1512, 1513, 1511, 1670, 1518, 1517, 1279, 1432, 1480, 1496, - /* 90 */ 1479, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 100 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 110 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 120 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 130 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 140 */ 1279, 1279, 1279, 1279, 1279, 1279, 1488, 1495, 1494, 1493, - /* 150 */ 1502, 1492, 1489, 1482, 1481, 1483, 1484, 1303, 1300, 1354, - /* 160 */ 1279, 1279, 1279, 1279, 1279, 1485, 1312, 1473, 1472, 1471, - /* 170 */ 1279, 1499, 1486, 1498, 1497, 1575, 1644, 1643, 1534, 1279, - /* 180 */ 1279, 1279, 1279, 1279, 1279, 1607, 1279, 1279, 1279, 1279, - /* 190 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 200 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1412, 1607, - /* 210 */ 1607, 1279, 1312, 1607, 1607, 1308, 1413, 1413, 1308, 1308, - /* 220 */ 1416, 1587, 1383, 1383, 1383, 1383, 1392, 1383, 1279, 1279, - /* 230 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 240 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1572, 1570, 1279, - /* 250 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 260 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 270 */ 1279, 1279, 1279, 1279, 1279, 1388, 1279, 1279, 1279, 1279, - /* 280 */ 1279, 1279, 1279, 1279, 1279, 1279, 1637, 1683, 1279, 1546, - /* 290 */ 1368, 1388, 1388, 1388, 1388, 1390, 1369, 1367, 1382, 1313, - /* 300 */ 1286, 1683, 1683, 1448, 1437, 1389, 1437, 1680, 1435, 1448, - /* 310 */ 1448, 1435, 1448, 1389, 1680, 1329, 1659, 1324, 1422, 1422, - /* 320 */ 1422, 1412, 1412, 1412, 1412, 1416, 1416, 1514, 1389, 1382, - /* 330 */ 1279, 1355, 1683, 1355, 1355, 1398, 1398, 1682, 1682, 1398, - /* 340 */ 1534, 1667, 1457, 1357, 1363, 1363, 1363, 1363, 1398, 1297, - /* 350 */ 1435, 1667, 1667, 1435, 1457, 1357, 1435, 1357, 1435, 1398, - /* 360 */ 1297, 1550, 1678, 1398, 1297, 1524, 1398, 1297, 1398, 1297, - /* 370 */ 1524, 1355, 1355, 1355, 1344, 1279, 1279, 1524, 1355, 1329, - /* 380 */ 1355, 1344, 1355, 1355, 1625, 1279, 1528, 1528, 1524, 1398, - /* 390 */ 1617, 1617, 1425, 1425, 1430, 1416, 1519, 1398, 1279, 1430, - /* 400 */ 1428, 1426, 1435, 1347, 1640, 1640, 1636, 1636, 1636, 1688, - /* 410 */ 1688, 1587, 1652, 1312, 1312, 1312, 1312, 1652, 1331, 1331, - /* 420 */ 1313, 1313, 1312, 1652, 1279, 1279, 1279, 1279, 1279, 1279, - /* 430 */ 1279, 1647, 1279, 1279, 1535, 1279, 1279, 1279, 1279, 1279, - /* 440 */ 1279, 1279, 1402, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 450 */ 1279, 1279, 1593, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 460 */ 1279, 1279, 1279, 1279, 1462, 1279, 1282, 1584, 1279, 1279, - /* 470 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 480 */ 1279, 1279, 1439, 1440, 1279, 1279, 1279, 1279, 1279, 1279, - /* 490 */ 1279, 1454, 1279, 1279, 1279, 1449, 1279, 1279, 1279, 1279, - /* 500 */ 1279, 1279, 1279, 1279, 1403, 1279, 1279, 1279, 1279, 1279, - /* 510 */ 1279, 1549, 1548, 1279, 1279, 1400, 1279, 1279, 1279, 1279, - /* 520 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1327, - /* 530 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 540 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 550 */ 1279, 1279, 1279, 1427, 1279, 1279, 1279, 1279, 1279, 1279, - /* 560 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1622, 1417, - /* 570 */ 1279, 1279, 1279, 1279, 1671, 1279, 1279, 1279, 1279, 1377, - /* 580 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 590 */ 1663, 1371, 1463, 1279, 1466, 1301, 1279, 1291, 1279, 1279, + /* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254, + /* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397, + /* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 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, 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 */ 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, 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, 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, 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, 1254, 1402, 1254, 1254, 1254, + /* 540 */ 1254, 1254, 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, }; /********** End of lemon-generated parsing tables *****************************/ @@ -180663,33 +179378,34 @@ static const char *const yyTokenName[] = { /* 292 */ "foreach_clause", /* 293 */ "when_clause", /* 294 */ "trigger_cmd", - /* 295 */ "tridxby", - /* 296 */ "database_kw_opt", - /* 297 */ "key_opt", - /* 298 */ "alter_add", - /* 299 */ "kwcolumn_opt", - /* 300 */ "create_vtab", - /* 301 */ "vtabarglist", - /* 302 */ "vtabarg", - /* 303 */ "vtabargtoken", - /* 304 */ "lp", - /* 305 */ "anylist", - /* 306 */ "wqitem", - /* 307 */ "wqas", - /* 308 */ "withnm", - /* 309 */ "windowdefn_list", - /* 310 */ "windowdefn", - /* 311 */ "window", - /* 312 */ "frame_opt", - /* 313 */ "part_opt", - /* 314 */ "filter_clause", - /* 315 */ "over_clause", - /* 316 */ "range_or_rows", - /* 317 */ "frame_bound", - /* 318 */ "frame_bound_s", - /* 319 */ "frame_bound_e", - /* 320 */ "frame_exclude_opt", - /* 321 */ "frame_exclude", + /* 295 */ "trnm", + /* 296 */ "tridxby", + /* 297 */ "database_kw_opt", + /* 298 */ "key_opt", + /* 299 */ "add_column_fullname", + /* 300 */ "kwcolumn_opt", + /* 301 */ "create_vtab", + /* 302 */ "vtabarglist", + /* 303 */ "vtabarg", + /* 304 */ "vtabargtoken", + /* 305 */ "lp", + /* 306 */ "anylist", + /* 307 */ "wqitem", + /* 308 */ "wqas", + /* 309 */ "withnm", + /* 310 */ "windowdefn_list", + /* 311 */ "windowdefn", + /* 312 */ "window", + /* 313 */ "frame_opt", + /* 314 */ "part_opt", + /* 315 */ "filter_clause", + /* 316 */ "over_clause", + /* 317 */ "range_or_rows", + /* 318 */ "frame_bound", + /* 319 */ "frame_bound_s", + /* 320 */ "frame_bound_e", + /* 321 */ "frame_exclude_opt", + /* 322 */ "frame_exclude", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -180819,8 +179535,8 @@ static const char *const yyRuleName[] = { /* 119 */ "fullname ::= nm DOT nm", /* 120 */ "xfullname ::= nm", /* 121 */ "xfullname ::= nm DOT nm", - /* 122 */ "xfullname ::= nm AS nm", - /* 123 */ "xfullname ::= nm DOT nm AS nm", + /* 122 */ "xfullname ::= nm DOT nm AS nm", + /* 123 */ "xfullname ::= nm AS nm", /* 124 */ "joinop ::= COMMA|JOIN", /* 125 */ "joinop ::= JOIN_KW JOIN", /* 126 */ "joinop ::= JOIN_KW nm JOIN", @@ -180969,146 +179685,143 @@ static const char *const yyRuleName[] = { /* 269 */ "when_clause ::= WHEN expr", /* 270 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", /* 271 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 272 */ "tridxby ::= INDEXED BY nm", - /* 273 */ "tridxby ::= NOT INDEXED", - /* 274 */ "trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt", - /* 275 */ "trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt", - /* 276 */ "trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt", - /* 277 */ "trigger_cmd ::= scanpt select scanpt", - /* 278 */ "expr ::= RAISE LP IGNORE RP", - /* 279 */ "expr ::= RAISE LP raisetype COMMA expr RP", - /* 280 */ "raisetype ::= ROLLBACK", - /* 281 */ "raisetype ::= ABORT", - /* 282 */ "raisetype ::= FAIL", - /* 283 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 284 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 285 */ "cmd ::= DETACH database_kw_opt expr", - /* 286 */ "key_opt ::=", - /* 287 */ "key_opt ::= KEY expr", - /* 288 */ "cmd ::= REINDEX", - /* 289 */ "cmd ::= REINDEX nm dbnm", - /* 290 */ "cmd ::= ANALYZE", - /* 291 */ "cmd ::= ANALYZE nm dbnm", - /* 292 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 293 */ "cmd ::= alter_add carglist", - /* 294 */ "alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken", + /* 272 */ "trnm ::= nm DOT nm", + /* 273 */ "tridxby ::= INDEXED BY nm", + /* 274 */ "tridxby ::= NOT INDEXED", + /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", + /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", + /* 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 expr RP", + /* 281 */ "raisetype ::= ROLLBACK", + /* 282 */ "raisetype ::= ABORT", + /* 283 */ "raisetype ::= FAIL", + /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 286 */ "cmd ::= DETACH database_kw_opt expr", + /* 287 */ "key_opt ::=", + /* 288 */ "key_opt ::= KEY expr", + /* 289 */ "cmd ::= REINDEX", + /* 290 */ "cmd ::= REINDEX nm dbnm", + /* 291 */ "cmd ::= ANALYZE", + /* 292 */ "cmd ::= ANALYZE nm dbnm", + /* 293 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 294 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", /* 295 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", - /* 296 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", - /* 297 */ "cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm", - /* 298 */ "cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL", - /* 299 */ "cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf", - /* 300 */ "cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf", - /* 301 */ "cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf", - /* 302 */ "cmd ::= create_vtab", - /* 303 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 304 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 305 */ "vtabarg ::=", - /* 306 */ "vtabargtoken ::= ANY", - /* 307 */ "vtabargtoken ::= lp anylist RP", - /* 308 */ "lp ::= LP", - /* 309 */ "with ::= WITH wqlist", - /* 310 */ "with ::= WITH RECURSIVE wqlist", - /* 311 */ "wqas ::= AS", - /* 312 */ "wqas ::= AS MATERIALIZED", - /* 313 */ "wqas ::= AS NOT MATERIALIZED", - /* 314 */ "wqitem ::= withnm eidlist_opt wqas LP select RP", - /* 315 */ "withnm ::= nm", - /* 316 */ "wqlist ::= wqitem", - /* 317 */ "wqlist ::= wqlist COMMA wqitem", - /* 318 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 319 */ "windowdefn ::= nm AS LP window RP", - /* 320 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 321 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 322 */ "window ::= ORDER BY sortlist frame_opt", - /* 323 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 324 */ "window ::= nm frame_opt", - /* 325 */ "frame_opt ::=", - /* 326 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", - /* 327 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", - /* 328 */ "range_or_rows ::= RANGE|ROWS|GROUPS", - /* 329 */ "frame_bound_s ::= frame_bound", - /* 330 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 331 */ "frame_bound_e ::= frame_bound", - /* 332 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 333 */ "frame_bound ::= expr PRECEDING|FOLLOWING", - /* 334 */ "frame_bound ::= CURRENT ROW", - /* 335 */ "frame_exclude_opt ::=", - /* 336 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", - /* 337 */ "frame_exclude ::= NO OTHERS", - /* 338 */ "frame_exclude ::= CURRENT ROW", - /* 339 */ "frame_exclude ::= GROUP|TIES", - /* 340 */ "window_clause ::= WINDOW windowdefn_list", - /* 341 */ "filter_over ::= filter_clause over_clause", - /* 342 */ "filter_over ::= over_clause", - /* 343 */ "filter_over ::= filter_clause", - /* 344 */ "over_clause ::= OVER LP window RP", - /* 345 */ "over_clause ::= OVER nm", - /* 346 */ "filter_clause ::= FILTER LP WHERE expr RP", - /* 347 */ "term ::= QNUMBER", - /* 348 */ "input ::= cmdlist", - /* 349 */ "cmdlist ::= cmdlist ecmd", - /* 350 */ "cmdlist ::= ecmd", - /* 351 */ "ecmd ::= SEMI", - /* 352 */ "ecmd ::= cmdx SEMI", - /* 353 */ "ecmd ::= explain cmdx SEMI", - /* 354 */ "trans_opt ::=", - /* 355 */ "trans_opt ::= TRANSACTION", - /* 356 */ "trans_opt ::= TRANSACTION nm", - /* 357 */ "savepoint_opt ::= SAVEPOINT", - /* 358 */ "savepoint_opt ::=", - /* 359 */ "cmd ::= create_table create_table_args", - /* 360 */ "table_option_set ::= table_option", - /* 361 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 362 */ "columnlist ::= columnname carglist", - /* 363 */ "nm ::= ID|INDEXED|JOIN_KW", - /* 364 */ "nm ::= STRING", - /* 365 */ "typetoken ::= typename", - /* 366 */ "typename ::= ID|STRING", - /* 367 */ "signed ::= plus_num", - /* 368 */ "signed ::= minus_num", - /* 369 */ "carglist ::= carglist ccons", - /* 370 */ "carglist ::=", - /* 371 */ "ccons ::= NULL onconf", - /* 372 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 373 */ "ccons ::= AS generated", - /* 374 */ "conslist_opt ::= COMMA conslist", - /* 375 */ "conslist ::= conslist tconscomma tcons", - /* 376 */ "conslist ::= tcons", - /* 377 */ "tconscomma ::=", - /* 378 */ "defer_subclause_opt ::= defer_subclause", - /* 379 */ "resolvetype ::= raisetype", - /* 380 */ "selectnowith ::= oneselect", - /* 381 */ "oneselect ::= values", - /* 382 */ "sclp ::= selcollist COMMA", - /* 383 */ "as ::= ID|STRING", - /* 384 */ "indexed_opt ::= indexed_by", - /* 385 */ "returning ::=", - /* 386 */ "expr ::= term", - /* 387 */ "likeop ::= LIKE_KW|MATCH", - /* 388 */ "case_operand ::= expr", - /* 389 */ "exprlist ::= nexprlist", - /* 390 */ "nmnum ::= plus_num", - /* 391 */ "nmnum ::= nm", - /* 392 */ "nmnum ::= ON", - /* 393 */ "nmnum ::= DELETE", - /* 394 */ "nmnum ::= DEFAULT", - /* 395 */ "plus_num ::= INTEGER|FLOAT", - /* 396 */ "foreach_clause ::=", - /* 397 */ "foreach_clause ::= FOR EACH ROW", - /* 398 */ "tridxby ::=", - /* 399 */ "database_kw_opt ::= DATABASE", - /* 400 */ "database_kw_opt ::=", - /* 401 */ "kwcolumn_opt ::=", - /* 402 */ "kwcolumn_opt ::= COLUMNKW", - /* 403 */ "vtabarglist ::= vtabarg", - /* 404 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 405 */ "vtabarg ::= vtabarg vtabargtoken", - /* 406 */ "anylist ::=", - /* 407 */ "anylist ::= anylist LP anylist RP", - /* 408 */ "anylist ::= anylist ANY", - /* 409 */ "with ::=", - /* 410 */ "windowdefn_list ::= windowdefn", - /* 411 */ "window ::= frame_opt", + /* 296 */ "add_column_fullname ::= fullname", + /* 297 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", + /* 298 */ "cmd ::= create_vtab", + /* 299 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 300 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 301 */ "vtabarg ::=", + /* 302 */ "vtabargtoken ::= ANY", + /* 303 */ "vtabargtoken ::= lp anylist RP", + /* 304 */ "lp ::= LP", + /* 305 */ "with ::= WITH wqlist", + /* 306 */ "with ::= WITH RECURSIVE wqlist", + /* 307 */ "wqas ::= AS", + /* 308 */ "wqas ::= AS MATERIALIZED", + /* 309 */ "wqas ::= AS NOT MATERIALIZED", + /* 310 */ "wqitem ::= withnm eidlist_opt wqas LP select RP", + /* 311 */ "withnm ::= nm", + /* 312 */ "wqlist ::= wqitem", + /* 313 */ "wqlist ::= wqlist COMMA wqitem", + /* 314 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", + /* 315 */ "windowdefn ::= nm AS LP window RP", + /* 316 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", + /* 317 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", + /* 318 */ "window ::= ORDER BY sortlist frame_opt", + /* 319 */ "window ::= nm ORDER BY sortlist frame_opt", + /* 320 */ "window ::= nm frame_opt", + /* 321 */ "frame_opt ::=", + /* 322 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", + /* 323 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", + /* 324 */ "range_or_rows ::= RANGE|ROWS|GROUPS", + /* 325 */ "frame_bound_s ::= frame_bound", + /* 326 */ "frame_bound_s ::= UNBOUNDED PRECEDING", + /* 327 */ "frame_bound_e ::= frame_bound", + /* 328 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", + /* 329 */ "frame_bound ::= expr PRECEDING|FOLLOWING", + /* 330 */ "frame_bound ::= CURRENT ROW", + /* 331 */ "frame_exclude_opt ::=", + /* 332 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", + /* 333 */ "frame_exclude ::= NO OTHERS", + /* 334 */ "frame_exclude ::= CURRENT ROW", + /* 335 */ "frame_exclude ::= GROUP|TIES", + /* 336 */ "window_clause ::= WINDOW windowdefn_list", + /* 337 */ "filter_over ::= filter_clause over_clause", + /* 338 */ "filter_over ::= over_clause", + /* 339 */ "filter_over ::= filter_clause", + /* 340 */ "over_clause ::= OVER LP window RP", + /* 341 */ "over_clause ::= OVER nm", + /* 342 */ "filter_clause ::= FILTER LP WHERE expr RP", + /* 343 */ "term ::= QNUMBER", + /* 344 */ "input ::= cmdlist", + /* 345 */ "cmdlist ::= cmdlist ecmd", + /* 346 */ "cmdlist ::= ecmd", + /* 347 */ "ecmd ::= SEMI", + /* 348 */ "ecmd ::= cmdx SEMI", + /* 349 */ "ecmd ::= explain cmdx SEMI", + /* 350 */ "trans_opt ::=", + /* 351 */ "trans_opt ::= TRANSACTION", + /* 352 */ "trans_opt ::= TRANSACTION nm", + /* 353 */ "savepoint_opt ::= SAVEPOINT", + /* 354 */ "savepoint_opt ::=", + /* 355 */ "cmd ::= create_table create_table_args", + /* 356 */ "table_option_set ::= table_option", + /* 357 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 358 */ "columnlist ::= columnname carglist", + /* 359 */ "nm ::= ID|INDEXED|JOIN_KW", + /* 360 */ "nm ::= STRING", + /* 361 */ "typetoken ::= typename", + /* 362 */ "typename ::= ID|STRING", + /* 363 */ "signed ::= plus_num", + /* 364 */ "signed ::= minus_num", + /* 365 */ "carglist ::= carglist ccons", + /* 366 */ "carglist ::=", + /* 367 */ "ccons ::= NULL onconf", + /* 368 */ "ccons ::= GENERATED ALWAYS AS generated", + /* 369 */ "ccons ::= AS generated", + /* 370 */ "conslist_opt ::= COMMA conslist", + /* 371 */ "conslist ::= conslist tconscomma tcons", + /* 372 */ "conslist ::= tcons", + /* 373 */ "tconscomma ::=", + /* 374 */ "defer_subclause_opt ::= defer_subclause", + /* 375 */ "resolvetype ::= raisetype", + /* 376 */ "selectnowith ::= oneselect", + /* 377 */ "oneselect ::= values", + /* 378 */ "sclp ::= selcollist COMMA", + /* 379 */ "as ::= ID|STRING", + /* 380 */ "indexed_opt ::= indexed_by", + /* 381 */ "returning ::=", + /* 382 */ "expr ::= term", + /* 383 */ "likeop ::= LIKE_KW|MATCH", + /* 384 */ "case_operand ::= expr", + /* 385 */ "exprlist ::= nexprlist", + /* 386 */ "nmnum ::= plus_num", + /* 387 */ "nmnum ::= nm", + /* 388 */ "nmnum ::= ON", + /* 389 */ "nmnum ::= DELETE", + /* 390 */ "nmnum ::= DEFAULT", + /* 391 */ "plus_num ::= INTEGER|FLOAT", + /* 392 */ "foreach_clause ::=", + /* 393 */ "foreach_clause ::= FOR EACH ROW", + /* 394 */ "trnm ::= nm", + /* 395 */ "tridxby ::=", + /* 396 */ "database_kw_opt ::= DATABASE", + /* 397 */ "database_kw_opt ::=", + /* 398 */ "kwcolumn_opt ::=", + /* 399 */ "kwcolumn_opt ::= COLUMNKW", + /* 400 */ "vtabarglist ::= vtabarg", + /* 401 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 402 */ "vtabarg ::= vtabarg vtabargtoken", + /* 403 */ "anylist ::=", + /* 404 */ "anylist ::= anylist LP anylist RP", + /* 405 */ "anylist ::= anylist ANY", + /* 406 */ "with ::=", + /* 407 */ "windowdefn_list ::= windowdefn", + /* 408 */ "window ::= frame_opt", }; #endif /* NDEBUG */ @@ -181123,24 +179836,15 @@ static int yyGrowStack(yyParser *p){ int newSize; int idx; yyStackEntry *pNew; -#ifdef YYSIZELIMIT - int nLimit = YYSIZELIMIT(sqlite3ParserCTX(p)); -#endif newSize = oldSize*2 + 100; -#ifdef YYSIZELIMIT - if( newSize>nLimit ){ - newSize = nLimit; - if( newSize<=oldSize ) return 1; - } -#endif idx = (int)(p->yytos - p->yystack); if( p->yystack==p->yystk0 ){ - pNew = YYREALLOC(0, newSize*sizeof(pNew[0]), sqlite3ParserCTX(p)); + pNew = YYREALLOC(0, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0])); }else{ - pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]), sqlite3ParserCTX(p)); + pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; } p->yystack = pNew; @@ -181247,7 +179951,7 @@ static void yy_destructor( case 254: /* values */ case 256: /* mvalues */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy555)); +sqlite3SelectDelete(pParse->db, (yypminor->yy637)); } break; case 218: /* term */ @@ -181259,10 +179963,10 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy555)); case 283: /* case_else */ case 286: /* vinto */ case 293: /* when_clause */ - case 297: /* key_opt */ - case 314: /* filter_clause */ + case 298: /* key_opt */ + case 315: /* filter_clause */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy454)); +sqlite3ExprDelete(pParse->db, (yypminor->yy590)); } break; case 223: /* eidlist_opt */ @@ -181277,9 +179981,9 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy454)); case 271: /* setlist */ case 280: /* paren_exprlist */ case 282: /* case_exprlist */ - case 313: /* part_opt */ + case 314: /* part_opt */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy402)); } break; case 240: /* fullname */ @@ -181288,51 +179992,51 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); case 260: /* stl_prefix */ case 265: /* xfullname */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy203)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy563)); } break; case 243: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy59)); +sqlite3WithDelete(pParse->db, (yypminor->yy125)); } break; case 253: /* window_clause */ - case 309: /* windowdefn_list */ + case 310: /* windowdefn_list */ { -sqlite3WindowListDelete(pParse->db, (yypminor->yy211)); +sqlite3WindowListDelete(pParse->db, (yypminor->yy483)); } break; case 266: /* idlist */ case 273: /* idlist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy132)); +sqlite3IdListDelete(pParse->db, (yypminor->yy204)); } break; case 276: /* filter_over */ - case 310: /* windowdefn */ - case 311: /* window */ - case 312: /* frame_opt */ - case 315: /* over_clause */ + case 311: /* windowdefn */ + case 312: /* window */ + case 313: /* frame_opt */ + case 316: /* over_clause */ { -sqlite3WindowDelete(pParse->db, (yypminor->yy211)); +sqlite3WindowDelete(pParse->db, (yypminor->yy483)); } break; case 289: /* trigger_cmd_list */ case 294: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy319)); } break; case 291: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy286).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy28).b); } break; - case 317: /* frame_bound */ - case 318: /* frame_bound_s */ - case 319: /* frame_bound_e */ + case 318: /* frame_bound */ + case 319: /* frame_bound_s */ + case 320: /* frame_bound_e */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy509).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy205).pExpr); } break; /********* End destructor definitions *****************************************/ @@ -181385,9 +180089,7 @@ SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){ } #if YYGROWABLESTACK - if( pParser->yystack!=pParser->yystk0 ){ - YYFREE(pParser->yystack, sqlite3ParserCTX(pParser)); - } + if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack); #endif } @@ -181570,7 +180272,7 @@ static void yyStackOverflow(yyParser *yypParser){ ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ - if( pParse->nErr==0 ) sqlite3ErrorMsg(pParse, "Recursion limit"); + sqlite3OomFault(pParse->db); /******** End %stack_overflow code ********************************************/ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */ sqlite3ParserCTX_STORE @@ -181758,8 +180460,8 @@ static const YYCODETYPE yyRuleInfoLhs[] = { 240, /* (119) fullname ::= nm DOT nm */ 265, /* (120) xfullname ::= nm */ 265, /* (121) xfullname ::= nm DOT nm */ - 265, /* (122) xfullname ::= nm AS nm */ - 265, /* (123) xfullname ::= nm DOT nm AS nm */ + 265, /* (122) xfullname ::= nm DOT nm AS nm */ + 265, /* (123) xfullname ::= nm AS nm */ 261, /* (124) joinop ::= COMMA|JOIN */ 261, /* (125) joinop ::= JOIN_KW JOIN */ 261, /* (126) joinop ::= JOIN_KW nm JOIN */ @@ -181908,146 +180610,143 @@ static const YYCODETYPE yyRuleInfoLhs[] = { 293, /* (269) when_clause ::= WHEN expr */ 289, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ 289, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - 295, /* (272) tridxby ::= INDEXED BY nm */ - 295, /* (273) tridxby ::= NOT INDEXED */ - 294, /* (274) trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */ - 294, /* (275) trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */ - 294, /* (276) trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */ - 294, /* (277) trigger_cmd ::= scanpt select scanpt */ - 219, /* (278) expr ::= RAISE LP IGNORE RP */ - 219, /* (279) expr ::= RAISE LP raisetype COMMA expr RP */ - 238, /* (280) raisetype ::= ROLLBACK */ - 238, /* (281) raisetype ::= ABORT */ - 238, /* (282) raisetype ::= FAIL */ - 192, /* (283) cmd ::= DROP TRIGGER ifexists fullname */ - 192, /* (284) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 192, /* (285) cmd ::= DETACH database_kw_opt expr */ - 297, /* (286) key_opt ::= */ - 297, /* (287) key_opt ::= KEY expr */ - 192, /* (288) cmd ::= REINDEX */ - 192, /* (289) cmd ::= REINDEX nm dbnm */ - 192, /* (290) cmd ::= ANALYZE */ - 192, /* (291) cmd ::= ANALYZE nm dbnm */ - 192, /* (292) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 192, /* (293) cmd ::= alter_add carglist */ - 298, /* (294) alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */ + 295, /* (272) trnm ::= nm DOT nm */ + 296, /* (273) tridxby ::= INDEXED BY nm */ + 296, /* (274) tridxby ::= NOT INDEXED */ + 294, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + 294, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + 294, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + 294, /* (278) trigger_cmd ::= scanpt select scanpt */ + 219, /* (279) expr ::= RAISE LP IGNORE RP */ + 219, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */ + 238, /* (281) raisetype ::= ROLLBACK */ + 238, /* (282) raisetype ::= ABORT */ + 238, /* (283) raisetype ::= FAIL */ + 192, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ + 192, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + 192, /* (286) cmd ::= DETACH database_kw_opt expr */ + 298, /* (287) key_opt ::= */ + 298, /* (288) key_opt ::= KEY expr */ + 192, /* (289) cmd ::= REINDEX */ + 192, /* (290) cmd ::= REINDEX nm dbnm */ + 192, /* (291) cmd ::= ANALYZE */ + 192, /* (292) cmd ::= ANALYZE nm dbnm */ + 192, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ + 192, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ 192, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - 192, /* (296) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 192, /* (297) cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */ - 192, /* (298) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */ - 192, /* (299) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */ - 192, /* (300) cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */ - 192, /* (301) cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */ - 192, /* (302) cmd ::= create_vtab */ - 192, /* (303) cmd ::= create_vtab LP vtabarglist RP */ - 300, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 302, /* (305) vtabarg ::= */ - 303, /* (306) vtabargtoken ::= ANY */ - 303, /* (307) vtabargtoken ::= lp anylist RP */ - 304, /* (308) lp ::= LP */ - 269, /* (309) with ::= WITH wqlist */ - 269, /* (310) with ::= WITH RECURSIVE wqlist */ - 307, /* (311) wqas ::= AS */ - 307, /* (312) wqas ::= AS MATERIALIZED */ - 307, /* (313) wqas ::= AS NOT MATERIALIZED */ - 306, /* (314) wqitem ::= withnm eidlist_opt wqas LP select RP */ - 308, /* (315) withnm ::= nm */ - 243, /* (316) wqlist ::= wqitem */ - 243, /* (317) wqlist ::= wqlist COMMA wqitem */ - 309, /* (318) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 310, /* (319) windowdefn ::= nm AS LP window RP */ - 311, /* (320) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 311, /* (321) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 311, /* (322) window ::= ORDER BY sortlist frame_opt */ - 311, /* (323) window ::= nm ORDER BY sortlist frame_opt */ - 311, /* (324) window ::= nm frame_opt */ - 312, /* (325) frame_opt ::= */ - 312, /* (326) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 312, /* (327) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 316, /* (328) range_or_rows ::= RANGE|ROWS|GROUPS */ - 318, /* (329) frame_bound_s ::= frame_bound */ - 318, /* (330) frame_bound_s ::= UNBOUNDED PRECEDING */ - 319, /* (331) frame_bound_e ::= frame_bound */ - 319, /* (332) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 317, /* (333) frame_bound ::= expr PRECEDING|FOLLOWING */ - 317, /* (334) frame_bound ::= CURRENT ROW */ - 320, /* (335) frame_exclude_opt ::= */ - 320, /* (336) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 321, /* (337) frame_exclude ::= NO OTHERS */ - 321, /* (338) frame_exclude ::= CURRENT ROW */ - 321, /* (339) frame_exclude ::= GROUP|TIES */ - 253, /* (340) window_clause ::= WINDOW windowdefn_list */ - 276, /* (341) filter_over ::= filter_clause over_clause */ - 276, /* (342) filter_over ::= over_clause */ - 276, /* (343) filter_over ::= filter_clause */ - 315, /* (344) over_clause ::= OVER LP window RP */ - 315, /* (345) over_clause ::= OVER nm */ - 314, /* (346) filter_clause ::= FILTER LP WHERE expr RP */ - 218, /* (347) term ::= QNUMBER */ - 187, /* (348) input ::= cmdlist */ - 188, /* (349) cmdlist ::= cmdlist ecmd */ - 188, /* (350) cmdlist ::= ecmd */ - 189, /* (351) ecmd ::= SEMI */ - 189, /* (352) ecmd ::= cmdx SEMI */ - 189, /* (353) ecmd ::= explain cmdx SEMI */ - 194, /* (354) trans_opt ::= */ - 194, /* (355) trans_opt ::= TRANSACTION */ - 194, /* (356) trans_opt ::= TRANSACTION nm */ - 196, /* (357) savepoint_opt ::= SAVEPOINT */ - 196, /* (358) savepoint_opt ::= */ - 192, /* (359) cmd ::= create_table create_table_args */ - 205, /* (360) table_option_set ::= table_option */ - 203, /* (361) columnlist ::= columnlist COMMA columnname carglist */ - 203, /* (362) columnlist ::= columnname carglist */ - 195, /* (363) nm ::= ID|INDEXED|JOIN_KW */ - 195, /* (364) nm ::= STRING */ - 210, /* (365) typetoken ::= typename */ - 211, /* (366) typename ::= ID|STRING */ - 212, /* (367) signed ::= plus_num */ - 212, /* (368) signed ::= minus_num */ - 209, /* (369) carglist ::= carglist ccons */ - 209, /* (370) carglist ::= */ - 217, /* (371) ccons ::= NULL onconf */ - 217, /* (372) ccons ::= GENERATED ALWAYS AS generated */ - 217, /* (373) ccons ::= AS generated */ - 204, /* (374) conslist_opt ::= COMMA conslist */ - 230, /* (375) conslist ::= conslist tconscomma tcons */ - 230, /* (376) conslist ::= tcons */ - 231, /* (377) tconscomma ::= */ - 235, /* (378) defer_subclause_opt ::= defer_subclause */ - 237, /* (379) resolvetype ::= raisetype */ - 241, /* (380) selectnowith ::= oneselect */ - 242, /* (381) oneselect ::= values */ - 257, /* (382) sclp ::= selcollist COMMA */ - 258, /* (383) as ::= ID|STRING */ - 267, /* (384) indexed_opt ::= indexed_by */ - 275, /* (385) returning ::= */ - 219, /* (386) expr ::= term */ - 277, /* (387) likeop ::= LIKE_KW|MATCH */ - 281, /* (388) case_operand ::= expr */ - 264, /* (389) exprlist ::= nexprlist */ - 287, /* (390) nmnum ::= plus_num */ - 287, /* (391) nmnum ::= nm */ - 287, /* (392) nmnum ::= ON */ - 287, /* (393) nmnum ::= DELETE */ - 287, /* (394) nmnum ::= DEFAULT */ - 213, /* (395) plus_num ::= INTEGER|FLOAT */ - 292, /* (396) foreach_clause ::= */ - 292, /* (397) foreach_clause ::= FOR EACH ROW */ - 295, /* (398) tridxby ::= */ - 296, /* (399) database_kw_opt ::= DATABASE */ - 296, /* (400) database_kw_opt ::= */ - 299, /* (401) kwcolumn_opt ::= */ - 299, /* (402) kwcolumn_opt ::= COLUMNKW */ - 301, /* (403) vtabarglist ::= vtabarg */ - 301, /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */ - 302, /* (405) vtabarg ::= vtabarg vtabargtoken */ - 305, /* (406) anylist ::= */ - 305, /* (407) anylist ::= anylist LP anylist RP */ - 305, /* (408) anylist ::= anylist ANY */ - 269, /* (409) with ::= */ - 309, /* (410) windowdefn_list ::= windowdefn */ - 311, /* (411) window ::= frame_opt */ + 299, /* (296) add_column_fullname ::= fullname */ + 192, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + 192, /* (298) cmd ::= create_vtab */ + 192, /* (299) cmd ::= create_vtab LP vtabarglist RP */ + 301, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 303, /* (301) vtabarg ::= */ + 304, /* (302) vtabargtoken ::= ANY */ + 304, /* (303) vtabargtoken ::= lp anylist RP */ + 305, /* (304) lp ::= LP */ + 269, /* (305) with ::= WITH wqlist */ + 269, /* (306) with ::= WITH RECURSIVE wqlist */ + 308, /* (307) wqas ::= AS */ + 308, /* (308) wqas ::= AS MATERIALIZED */ + 308, /* (309) wqas ::= AS NOT MATERIALIZED */ + 307, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ + 309, /* (311) withnm ::= nm */ + 243, /* (312) wqlist ::= wqitem */ + 243, /* (313) wqlist ::= wqlist COMMA wqitem */ + 310, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + 311, /* (315) windowdefn ::= nm AS LP window RP */ + 312, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + 312, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + 312, /* (318) window ::= ORDER BY sortlist frame_opt */ + 312, /* (319) window ::= nm ORDER BY sortlist frame_opt */ + 312, /* (320) window ::= nm frame_opt */ + 313, /* (321) frame_opt ::= */ + 313, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + 313, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + 317, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ + 319, /* (325) frame_bound_s ::= frame_bound */ + 319, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ + 320, /* (327) frame_bound_e ::= frame_bound */ + 320, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ + 318, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ + 318, /* (330) frame_bound ::= CURRENT ROW */ + 321, /* (331) frame_exclude_opt ::= */ + 321, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ + 322, /* (333) frame_exclude ::= NO OTHERS */ + 322, /* (334) frame_exclude ::= CURRENT ROW */ + 322, /* (335) frame_exclude ::= GROUP|TIES */ + 253, /* (336) window_clause ::= WINDOW windowdefn_list */ + 276, /* (337) filter_over ::= filter_clause over_clause */ + 276, /* (338) filter_over ::= over_clause */ + 276, /* (339) filter_over ::= filter_clause */ + 316, /* (340) over_clause ::= OVER LP window RP */ + 316, /* (341) over_clause ::= OVER nm */ + 315, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ + 218, /* (343) term ::= QNUMBER */ + 187, /* (344) input ::= cmdlist */ + 188, /* (345) cmdlist ::= cmdlist ecmd */ + 188, /* (346) cmdlist ::= ecmd */ + 189, /* (347) ecmd ::= SEMI */ + 189, /* (348) ecmd ::= cmdx SEMI */ + 189, /* (349) ecmd ::= explain cmdx SEMI */ + 194, /* (350) trans_opt ::= */ + 194, /* (351) trans_opt ::= TRANSACTION */ + 194, /* (352) trans_opt ::= TRANSACTION nm */ + 196, /* (353) savepoint_opt ::= SAVEPOINT */ + 196, /* (354) savepoint_opt ::= */ + 192, /* (355) cmd ::= create_table create_table_args */ + 205, /* (356) table_option_set ::= table_option */ + 203, /* (357) columnlist ::= columnlist COMMA columnname carglist */ + 203, /* (358) columnlist ::= columnname carglist */ + 195, /* (359) nm ::= ID|INDEXED|JOIN_KW */ + 195, /* (360) nm ::= STRING */ + 210, /* (361) typetoken ::= typename */ + 211, /* (362) typename ::= ID|STRING */ + 212, /* (363) signed ::= plus_num */ + 212, /* (364) signed ::= minus_num */ + 209, /* (365) carglist ::= carglist ccons */ + 209, /* (366) carglist ::= */ + 217, /* (367) ccons ::= NULL onconf */ + 217, /* (368) ccons ::= GENERATED ALWAYS AS generated */ + 217, /* (369) ccons ::= AS generated */ + 204, /* (370) conslist_opt ::= COMMA conslist */ + 230, /* (371) conslist ::= conslist tconscomma tcons */ + 230, /* (372) conslist ::= tcons */ + 231, /* (373) tconscomma ::= */ + 235, /* (374) defer_subclause_opt ::= defer_subclause */ + 237, /* (375) resolvetype ::= raisetype */ + 241, /* (376) selectnowith ::= oneselect */ + 242, /* (377) oneselect ::= values */ + 257, /* (378) sclp ::= selcollist COMMA */ + 258, /* (379) as ::= ID|STRING */ + 267, /* (380) indexed_opt ::= indexed_by */ + 275, /* (381) returning ::= */ + 219, /* (382) expr ::= term */ + 277, /* (383) likeop ::= LIKE_KW|MATCH */ + 281, /* (384) case_operand ::= expr */ + 264, /* (385) exprlist ::= nexprlist */ + 287, /* (386) nmnum ::= plus_num */ + 287, /* (387) nmnum ::= nm */ + 287, /* (388) nmnum ::= ON */ + 287, /* (389) nmnum ::= DELETE */ + 287, /* (390) nmnum ::= DEFAULT */ + 213, /* (391) plus_num ::= INTEGER|FLOAT */ + 292, /* (392) foreach_clause ::= */ + 292, /* (393) foreach_clause ::= FOR EACH ROW */ + 295, /* (394) trnm ::= nm */ + 296, /* (395) tridxby ::= */ + 297, /* (396) database_kw_opt ::= DATABASE */ + 297, /* (397) database_kw_opt ::= */ + 300, /* (398) kwcolumn_opt ::= */ + 300, /* (399) kwcolumn_opt ::= COLUMNKW */ + 302, /* (400) vtabarglist ::= vtabarg */ + 302, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ + 303, /* (402) vtabarg ::= vtabarg vtabargtoken */ + 306, /* (403) anylist ::= */ + 306, /* (404) anylist ::= anylist LP anylist RP */ + 306, /* (405) anylist ::= anylist ANY */ + 269, /* (406) with ::= */ + 310, /* (407) windowdefn_list ::= windowdefn */ + 312, /* (408) window ::= frame_opt */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -182175,8 +180874,8 @@ static const signed char yyRuleInfoNRhs[] = { -3, /* (119) fullname ::= nm DOT nm */ -1, /* (120) xfullname ::= nm */ -3, /* (121) xfullname ::= nm DOT nm */ - -3, /* (122) xfullname ::= nm AS nm */ - -5, /* (123) xfullname ::= nm DOT nm AS nm */ + -5, /* (122) xfullname ::= nm DOT nm AS nm */ + -3, /* (123) xfullname ::= nm AS nm */ -1, /* (124) joinop ::= COMMA|JOIN */ -2, /* (125) joinop ::= JOIN_KW JOIN */ -3, /* (126) joinop ::= JOIN_KW nm JOIN */ @@ -182325,146 +181024,143 @@ static const signed char yyRuleInfoNRhs[] = { -2, /* (269) when_clause ::= WHEN expr */ -3, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ -2, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - -3, /* (272) tridxby ::= INDEXED BY nm */ - -2, /* (273) tridxby ::= NOT INDEXED */ - -9, /* (274) trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */ - -8, /* (275) trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */ - -6, /* (276) trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */ - -3, /* (277) trigger_cmd ::= scanpt select scanpt */ - -4, /* (278) expr ::= RAISE LP IGNORE RP */ - -6, /* (279) expr ::= RAISE LP raisetype COMMA expr RP */ - -1, /* (280) raisetype ::= ROLLBACK */ - -1, /* (281) raisetype ::= ABORT */ - -1, /* (282) raisetype ::= FAIL */ - -4, /* (283) cmd ::= DROP TRIGGER ifexists fullname */ - -6, /* (284) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - -3, /* (285) cmd ::= DETACH database_kw_opt expr */ - 0, /* (286) key_opt ::= */ - -2, /* (287) key_opt ::= KEY expr */ - -1, /* (288) cmd ::= REINDEX */ - -3, /* (289) cmd ::= REINDEX nm dbnm */ - -1, /* (290) cmd ::= ANALYZE */ - -3, /* (291) cmd ::= ANALYZE nm dbnm */ - -6, /* (292) cmd ::= ALTER TABLE fullname RENAME TO nm */ - -2, /* (293) cmd ::= alter_add carglist */ - -7, /* (294) alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */ + -3, /* (272) trnm ::= nm DOT nm */ + -3, /* (273) tridxby ::= INDEXED BY nm */ + -2, /* (274) tridxby ::= NOT INDEXED */ + -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + -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 expr RP */ + -1, /* (281) raisetype ::= ROLLBACK */ + -1, /* (282) raisetype ::= ABORT */ + -1, /* (283) raisetype ::= FAIL */ + -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ + -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + -3, /* (286) cmd ::= DETACH database_kw_opt expr */ + 0, /* (287) key_opt ::= */ + -2, /* (288) key_opt ::= KEY expr */ + -1, /* (289) cmd ::= REINDEX */ + -3, /* (290) cmd ::= REINDEX nm dbnm */ + -1, /* (291) cmd ::= ANALYZE */ + -3, /* (292) cmd ::= ANALYZE nm dbnm */ + -6, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ + -7, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ -6, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - -8, /* (296) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - -6, /* (297) cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */ - -9, /* (298) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */ - -10, /* (299) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */ - -11, /* (300) cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */ - -9, /* (301) cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */ - -1, /* (302) cmd ::= create_vtab */ - -4, /* (303) cmd ::= create_vtab LP vtabarglist RP */ - -8, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 0, /* (305) vtabarg ::= */ - -1, /* (306) vtabargtoken ::= ANY */ - -3, /* (307) vtabargtoken ::= lp anylist RP */ - -1, /* (308) lp ::= LP */ - -2, /* (309) with ::= WITH wqlist */ - -3, /* (310) with ::= WITH RECURSIVE wqlist */ - -1, /* (311) wqas ::= AS */ - -2, /* (312) wqas ::= AS MATERIALIZED */ - -3, /* (313) wqas ::= AS NOT MATERIALIZED */ - -6, /* (314) wqitem ::= withnm eidlist_opt wqas LP select RP */ - -1, /* (315) withnm ::= nm */ - -1, /* (316) wqlist ::= wqitem */ - -3, /* (317) wqlist ::= wqlist COMMA wqitem */ - -3, /* (318) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (319) windowdefn ::= nm AS LP window RP */ - -5, /* (320) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (321) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (322) window ::= ORDER BY sortlist frame_opt */ - -5, /* (323) window ::= nm ORDER BY sortlist frame_opt */ - -2, /* (324) window ::= nm frame_opt */ - 0, /* (325) frame_opt ::= */ - -3, /* (326) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - -6, /* (327) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - -1, /* (328) range_or_rows ::= RANGE|ROWS|GROUPS */ - -1, /* (329) frame_bound_s ::= frame_bound */ - -2, /* (330) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (331) frame_bound_e ::= frame_bound */ - -2, /* (332) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (333) frame_bound ::= expr PRECEDING|FOLLOWING */ - -2, /* (334) frame_bound ::= CURRENT ROW */ - 0, /* (335) frame_exclude_opt ::= */ - -2, /* (336) frame_exclude_opt ::= EXCLUDE frame_exclude */ - -2, /* (337) frame_exclude ::= NO OTHERS */ - -2, /* (338) frame_exclude ::= CURRENT ROW */ - -1, /* (339) frame_exclude ::= GROUP|TIES */ - -2, /* (340) window_clause ::= WINDOW windowdefn_list */ - -2, /* (341) filter_over ::= filter_clause over_clause */ - -1, /* (342) filter_over ::= over_clause */ - -1, /* (343) filter_over ::= filter_clause */ - -4, /* (344) over_clause ::= OVER LP window RP */ - -2, /* (345) over_clause ::= OVER nm */ - -5, /* (346) filter_clause ::= FILTER LP WHERE expr RP */ - -1, /* (347) term ::= QNUMBER */ - -1, /* (348) input ::= cmdlist */ - -2, /* (349) cmdlist ::= cmdlist ecmd */ - -1, /* (350) cmdlist ::= ecmd */ - -1, /* (351) ecmd ::= SEMI */ - -2, /* (352) ecmd ::= cmdx SEMI */ - -3, /* (353) ecmd ::= explain cmdx SEMI */ - 0, /* (354) trans_opt ::= */ - -1, /* (355) trans_opt ::= TRANSACTION */ - -2, /* (356) trans_opt ::= TRANSACTION nm */ - -1, /* (357) savepoint_opt ::= SAVEPOINT */ - 0, /* (358) savepoint_opt ::= */ - -2, /* (359) cmd ::= create_table create_table_args */ - -1, /* (360) table_option_set ::= table_option */ - -4, /* (361) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (362) columnlist ::= columnname carglist */ - -1, /* (363) nm ::= ID|INDEXED|JOIN_KW */ - -1, /* (364) nm ::= STRING */ - -1, /* (365) typetoken ::= typename */ - -1, /* (366) typename ::= ID|STRING */ - -1, /* (367) signed ::= plus_num */ - -1, /* (368) signed ::= minus_num */ - -2, /* (369) carglist ::= carglist ccons */ - 0, /* (370) carglist ::= */ - -2, /* (371) ccons ::= NULL onconf */ - -4, /* (372) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (373) ccons ::= AS generated */ - -2, /* (374) conslist_opt ::= COMMA conslist */ - -3, /* (375) conslist ::= conslist tconscomma tcons */ - -1, /* (376) conslist ::= tcons */ - 0, /* (377) tconscomma ::= */ - -1, /* (378) defer_subclause_opt ::= defer_subclause */ - -1, /* (379) resolvetype ::= raisetype */ - -1, /* (380) selectnowith ::= oneselect */ - -1, /* (381) oneselect ::= values */ - -2, /* (382) sclp ::= selcollist COMMA */ - -1, /* (383) as ::= ID|STRING */ - -1, /* (384) indexed_opt ::= indexed_by */ - 0, /* (385) returning ::= */ - -1, /* (386) expr ::= term */ - -1, /* (387) likeop ::= LIKE_KW|MATCH */ - -1, /* (388) case_operand ::= expr */ - -1, /* (389) exprlist ::= nexprlist */ - -1, /* (390) nmnum ::= plus_num */ - -1, /* (391) nmnum ::= nm */ - -1, /* (392) nmnum ::= ON */ - -1, /* (393) nmnum ::= DELETE */ - -1, /* (394) nmnum ::= DEFAULT */ - -1, /* (395) plus_num ::= INTEGER|FLOAT */ - 0, /* (396) foreach_clause ::= */ - -3, /* (397) foreach_clause ::= FOR EACH ROW */ - 0, /* (398) tridxby ::= */ - -1, /* (399) database_kw_opt ::= DATABASE */ - 0, /* (400) database_kw_opt ::= */ - 0, /* (401) kwcolumn_opt ::= */ - -1, /* (402) kwcolumn_opt ::= COLUMNKW */ - -1, /* (403) vtabarglist ::= vtabarg */ - -3, /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (405) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (406) anylist ::= */ - -4, /* (407) anylist ::= anylist LP anylist RP */ - -2, /* (408) anylist ::= anylist ANY */ - 0, /* (409) with ::= */ - -1, /* (410) windowdefn_list ::= windowdefn */ - -1, /* (411) window ::= frame_opt */ + -1, /* (296) add_column_fullname ::= fullname */ + -8, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + -1, /* (298) cmd ::= create_vtab */ + -4, /* (299) cmd ::= create_vtab LP vtabarglist RP */ + -8, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 0, /* (301) vtabarg ::= */ + -1, /* (302) vtabargtoken ::= ANY */ + -3, /* (303) vtabargtoken ::= lp anylist RP */ + -1, /* (304) lp ::= LP */ + -2, /* (305) with ::= WITH wqlist */ + -3, /* (306) with ::= WITH RECURSIVE wqlist */ + -1, /* (307) wqas ::= AS */ + -2, /* (308) wqas ::= AS MATERIALIZED */ + -3, /* (309) wqas ::= AS NOT MATERIALIZED */ + -6, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ + -1, /* (311) withnm ::= nm */ + -1, /* (312) wqlist ::= wqitem */ + -3, /* (313) wqlist ::= wqlist COMMA wqitem */ + -3, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + -5, /* (315) windowdefn ::= nm AS LP window RP */ + -5, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + -6, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + -4, /* (318) window ::= ORDER BY sortlist frame_opt */ + -5, /* (319) window ::= nm ORDER BY sortlist frame_opt */ + -2, /* (320) window ::= nm frame_opt */ + 0, /* (321) frame_opt ::= */ + -3, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + -6, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + -1, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ + -1, /* (325) frame_bound_s ::= frame_bound */ + -2, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ + -1, /* (327) frame_bound_e ::= frame_bound */ + -2, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ + -2, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ + -2, /* (330) frame_bound ::= CURRENT ROW */ + 0, /* (331) frame_exclude_opt ::= */ + -2, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ + -2, /* (333) frame_exclude ::= NO OTHERS */ + -2, /* (334) frame_exclude ::= CURRENT ROW */ + -1, /* (335) frame_exclude ::= GROUP|TIES */ + -2, /* (336) window_clause ::= WINDOW windowdefn_list */ + -2, /* (337) filter_over ::= filter_clause over_clause */ + -1, /* (338) filter_over ::= over_clause */ + -1, /* (339) filter_over ::= filter_clause */ + -4, /* (340) over_clause ::= OVER LP window RP */ + -2, /* (341) over_clause ::= OVER nm */ + -5, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ + -1, /* (343) term ::= QNUMBER */ + -1, /* (344) input ::= cmdlist */ + -2, /* (345) cmdlist ::= cmdlist ecmd */ + -1, /* (346) cmdlist ::= ecmd */ + -1, /* (347) ecmd ::= SEMI */ + -2, /* (348) ecmd ::= cmdx SEMI */ + -3, /* (349) ecmd ::= explain cmdx SEMI */ + 0, /* (350) trans_opt ::= */ + -1, /* (351) trans_opt ::= TRANSACTION */ + -2, /* (352) trans_opt ::= TRANSACTION nm */ + -1, /* (353) savepoint_opt ::= SAVEPOINT */ + 0, /* (354) savepoint_opt ::= */ + -2, /* (355) cmd ::= create_table create_table_args */ + -1, /* (356) table_option_set ::= table_option */ + -4, /* (357) columnlist ::= columnlist COMMA columnname carglist */ + -2, /* (358) columnlist ::= columnname carglist */ + -1, /* (359) nm ::= ID|INDEXED|JOIN_KW */ + -1, /* (360) nm ::= STRING */ + -1, /* (361) typetoken ::= typename */ + -1, /* (362) typename ::= ID|STRING */ + -1, /* (363) signed ::= plus_num */ + -1, /* (364) signed ::= minus_num */ + -2, /* (365) carglist ::= carglist ccons */ + 0, /* (366) carglist ::= */ + -2, /* (367) ccons ::= NULL onconf */ + -4, /* (368) ccons ::= GENERATED ALWAYS AS generated */ + -2, /* (369) ccons ::= AS generated */ + -2, /* (370) conslist_opt ::= COMMA conslist */ + -3, /* (371) conslist ::= conslist tconscomma tcons */ + -1, /* (372) conslist ::= tcons */ + 0, /* (373) tconscomma ::= */ + -1, /* (374) defer_subclause_opt ::= defer_subclause */ + -1, /* (375) resolvetype ::= raisetype */ + -1, /* (376) selectnowith ::= oneselect */ + -1, /* (377) oneselect ::= values */ + -2, /* (378) sclp ::= selcollist COMMA */ + -1, /* (379) as ::= ID|STRING */ + -1, /* (380) indexed_opt ::= indexed_by */ + 0, /* (381) returning ::= */ + -1, /* (382) expr ::= term */ + -1, /* (383) likeop ::= LIKE_KW|MATCH */ + -1, /* (384) case_operand ::= expr */ + -1, /* (385) exprlist ::= nexprlist */ + -1, /* (386) nmnum ::= plus_num */ + -1, /* (387) nmnum ::= nm */ + -1, /* (388) nmnum ::= ON */ + -1, /* (389) nmnum ::= DELETE */ + -1, /* (390) nmnum ::= DEFAULT */ + -1, /* (391) plus_num ::= INTEGER|FLOAT */ + 0, /* (392) foreach_clause ::= */ + -3, /* (393) foreach_clause ::= FOR EACH ROW */ + -1, /* (394) trnm ::= nm */ + 0, /* (395) tridxby ::= */ + -1, /* (396) database_kw_opt ::= DATABASE */ + 0, /* (397) database_kw_opt ::= */ + 0, /* (398) kwcolumn_opt ::= */ + -1, /* (399) kwcolumn_opt ::= COLUMNKW */ + -1, /* (400) vtabarglist ::= vtabarg */ + -3, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ + -2, /* (402) vtabarg ::= vtabarg vtabargtoken */ + 0, /* (403) anylist ::= */ + -4, /* (404) anylist ::= anylist LP anylist RP */ + -2, /* (405) anylist ::= anylist ANY */ + 0, /* (406) with ::= */ + -1, /* (407) windowdefn_list ::= windowdefn */ + -1, /* (408) window ::= frame_opt */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -182516,16 +181212,16 @@ static YYACTIONTYPE yy_reduce( { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy144);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy144 = TK_DEFERRED;} +{yymsp[1].minor.yy502 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); - case 328: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==328); -{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/} + case 324: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==324); +{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); @@ -182548,7 +181244,7 @@ static YYACTIONTYPE yy_reduce( break; case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy144,0,0,yymsp[-2].minor.yy144); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502); } break; case 14: /* createkw ::= CREATE */ @@ -182564,38 +181260,38 @@ static YYACTIONTYPE yy_reduce( case 81: /* ifexists ::= */ yytestcase(yyruleno==81); case 100: /* distinct ::= */ yytestcase(yyruleno==100); case 246: /* collate ::= */ yytestcase(yyruleno==246); -{yymsp[1].minor.yy144 = 0;} +{yymsp[1].minor.yy502 = 0;} break; case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy144 = 1;} +{yymsp[-2].minor.yy502 = 1;} break; case 17: /* temp ::= TEMP */ -{yymsp[0].minor.yy144 = pParse->db->init.busy==0;} +{yymsp[0].minor.yy502 = pParse->db->init.busy==0;} break; case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy391,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy9,0); } break; case 20: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy555); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy637); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); } break; case 21: /* table_option_set ::= */ -{yymsp[1].minor.yy391 = 0;} +{yymsp[1].minor.yy9 = 0;} break; case 22: /* table_option_set ::= table_option_set COMMA table_option */ -{yylhsminor.yy391 = yymsp[-2].minor.yy391|yymsp[0].minor.yy391;} - yymsp[-2].minor.yy391 = yylhsminor.yy391; +{yylhsminor.yy9 = yymsp[-2].minor.yy9|yymsp[0].minor.yy9;} + yymsp[-2].minor.yy9 = yylhsminor.yy9; break; case 23: /* table_option ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy391 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy9 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy391 = 0; + yymsp[-1].minor.yy9 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -182603,13 +181299,13 @@ static YYACTIONTYPE yy_reduce( case 24: /* table_option ::= nm */ { if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){ - yylhsminor.yy391 = TF_Strict; + yylhsminor.yy9 = TF_Strict; }else{ - yylhsminor.yy391 = 0; + yylhsminor.yy9 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } - yymsp[0].minor.yy391 = yylhsminor.yy391; + yymsp[0].minor.yy9 = yylhsminor.yy9; break; case 25: /* columnname ::= nm typetoken */ {sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} @@ -182635,7 +181331,7 @@ static YYACTIONTYPE yy_reduce( case 30: /* scanpt ::= */ { assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy168 = yyLookaheadToken.z; + yymsp[1].minor.yy342 = yyLookaheadToken.z; } break; case 31: /* scantok ::= */ @@ -182649,17 +181345,17 @@ static YYACTIONTYPE yy_reduce( {ASSERT_IS_CREATE; pParse->u1.cr.constraintName = yymsp[0].minor.yy0;} break; case 33: /* ccons ::= DEFAULT scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 34: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} break; case 35: /* ccons ::= DEFAULT PLUS scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 36: /* ccons ::= DEFAULT MINUS scantok term */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy454, 0); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy590, 0); sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]); } break; @@ -182674,133 +181370,133 @@ static YYACTIONTYPE yy_reduce( } break; case 38: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy144);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);} break; case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy144,yymsp[0].minor.yy144,yymsp[-2].minor.yy144);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);} break; case 40: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy144,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 41: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} break; case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy144);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy402,yymsp[0].minor.yy502);} break; case 43: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy144);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);} break; case 44: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 45: /* generated ::= LP expr RP */ -{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy454,0);} +{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy590,0);} break; case 46: /* generated ::= LP expr RP ID */ -{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy454,&yymsp[0].minor.yy0);} +{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy590,&yymsp[0].minor.yy0);} break; case 48: /* autoinc ::= AUTOINCR */ -{yymsp[0].minor.yy144 = 1;} +{yymsp[0].minor.yy502 = 1;} break; case 49: /* refargs ::= */ -{ yymsp[1].minor.yy144 = OE_None*0x0101; /* EV: R-19803-45884 */} +{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */} break; case 50: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy144 = (yymsp[-1].minor.yy144 & ~yymsp[0].minor.yy383.mask) | yymsp[0].minor.yy383.value; } +{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy481.mask) | yymsp[0].minor.yy481.value; } break; case 51: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy383.value = 0; yymsp[-1].minor.yy383.mask = 0x000000; } +{ yymsp[-1].minor.yy481.value = 0; yymsp[-1].minor.yy481.mask = 0x000000; } break; case 52: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy383.value = 0; yymsp[-2].minor.yy383.mask = 0x000000; } +{ yymsp[-2].minor.yy481.value = 0; yymsp[-2].minor.yy481.mask = 0x000000; } break; case 53: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144; yymsp[-2].minor.yy383.mask = 0x0000ff; } +{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy481.mask = 0x0000ff; } break; case 54: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144<<8; yymsp[-2].minor.yy383.mask = 0x00ff00; } +{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy481.mask = 0x00ff00; } break; case 55: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy144 = OE_SetNull; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */} break; case 56: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy144 = OE_SetDflt; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */} break; case 57: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy144 = OE_Cascade; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */} break; case 58: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy144 = OE_Restrict; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */} break; case 59: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy144 = OE_None; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */} break; case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy144 = 0;} +{yymsp[-2].minor.yy502 = 0;} break; case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76); case 173: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==173); -{yymsp[-1].minor.yy144 = yymsp[0].minor.yy144;} +{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;} break; case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80); case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219); case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222); case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247); -{yymsp[-1].minor.yy144 = 1;} +{yymsp[-1].minor.yy502 = 1;} break; case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy144 = 0;} +{yymsp[-1].minor.yy502 = 0;} break; case 66: /* tconscomma ::= COMMA */ {ASSERT_IS_CREATE; pParse->u1.cr.constraintName.n = 0;} break; case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy144,yymsp[-2].minor.yy144,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);} break; case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy144,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy402,yymsp[0].minor.yy502,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 70: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy454,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy590,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} break; case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy144); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy144); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy402, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy502); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502); } break; case 73: /* onconf ::= */ case 75: /* orconf ::= */ yytestcase(yyruleno==75); -{yymsp[1].minor.yy144 = OE_Default;} +{yymsp[1].minor.yy502 = OE_Default;} break; case 74: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy144 = yymsp[0].minor.yy144;} +{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;} break; case 77: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy144 = OE_Ignore;} +{yymsp[0].minor.yy502 = OE_Ignore;} break; case 78: /* resolvetype ::= REPLACE */ case 174: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==174); -{yymsp[0].minor.yy144 = OE_Replace;} +{yymsp[0].minor.yy502 = OE_Replace;} break; case 79: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy203, 0, yymsp[-1].minor.yy144); + sqlite3DropTable(pParse, yymsp[0].minor.yy563, 0, yymsp[-1].minor.yy502); } break; case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[0].minor.yy555, yymsp[-7].minor.yy144, yymsp[-5].minor.yy144); + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[0].minor.yy637, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502); } break; case 83: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy203, 1, yymsp[-1].minor.yy144); + sqlite3DropTable(pParse, yymsp[0].minor.yy563, 1, yymsp[-1].minor.yy502); } break; case 84: /* cmd ::= select */ @@ -182809,20 +181505,20 @@ static YYACTIONTYPE yy_reduce( if( (pParse->db->mDbFlags & DBFLAG_EncodingFixed)!=0 || sqlite3ReadSchema(pParse)==SQLITE_OK ){ - sqlite3Select(pParse, yymsp[0].minor.yy555, &dest); + sqlite3Select(pParse, yymsp[0].minor.yy637, &dest); } - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); } break; case 85: /* select ::= WITH wqlist selectnowith */ -{yymsp[-2].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} +{yymsp[-2].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} break; case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */ -{yymsp[-3].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} +{yymsp[-3].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} break; case 87: /* select ::= selectnowith */ { - Select *p = yymsp[0].minor.yy555; + Select *p = yymsp[0].minor.yy637; if( p ){ parserDoubleLinkSelect(pParse, p); } @@ -182830,8 +181526,8 @@ static YYACTIONTYPE yy_reduce( break; case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy555; - Select *pLhs = yymsp[-2].minor.yy555; + Select *pRhs = yymsp[0].minor.yy637; + Select *pLhs = yymsp[-2].minor.yy637; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; @@ -182841,60 +181537,60 @@ static YYACTIONTYPE yy_reduce( pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy144; + pRhs->op = (u8)yymsp[-1].minor.yy502; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue; pRhs->selFlags &= ~(u32)SF_MultiValue; - if( yymsp[-1].minor.yy144!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy555 = pRhs; + yymsp[-2].minor.yy637 = pRhs; } break; case 89: /* multiselect_op ::= UNION */ case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91); -{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-OP*/} +{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/} break; case 90: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy144 = TK_ALL;} +{yymsp[-1].minor.yy502 = TK_ALL;} break; case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yymsp[-8].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy203,yymsp[-4].minor.yy454,yymsp[-3].minor.yy14,yymsp[-2].minor.yy454,yymsp[-1].minor.yy14,yymsp[-7].minor.yy144,yymsp[0].minor.yy454); + yymsp[-8].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy402,yymsp[-5].minor.yy563,yymsp[-4].minor.yy590,yymsp[-3].minor.yy402,yymsp[-2].minor.yy590,yymsp[-1].minor.yy402,yymsp[-7].minor.yy502,yymsp[0].minor.yy590); } break; case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ { - yymsp[-9].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy14,yymsp[-6].minor.yy203,yymsp[-5].minor.yy454,yymsp[-4].minor.yy14,yymsp[-3].minor.yy454,yymsp[-1].minor.yy14,yymsp[-8].minor.yy144,yymsp[0].minor.yy454); - if( yymsp[-9].minor.yy555 ){ - yymsp[-9].minor.yy555->pWinDefn = yymsp[-2].minor.yy211; + yymsp[-9].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy402,yymsp[-6].minor.yy563,yymsp[-5].minor.yy590,yymsp[-4].minor.yy402,yymsp[-3].minor.yy590,yymsp[-1].minor.yy402,yymsp[-8].minor.yy502,yymsp[0].minor.yy590); + if( yymsp[-9].minor.yy637 ){ + yymsp[-9].minor.yy637->pWinDefn = yymsp[-2].minor.yy483; }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy211); + sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy483); } } break; case 94: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0); + yymsp[-3].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values,0); } break; case 95: /* oneselect ::= mvalues */ { - sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy555); + sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy637); } break; case 96: /* mvalues ::= values COMMA LP nexprlist RP */ case 97: /* mvalues ::= mvalues COMMA LP nexprlist RP */ yytestcase(yyruleno==97); { - yymsp[-4].minor.yy555 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy555, yymsp[-1].minor.yy14); + yymsp[-4].minor.yy637 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy637, yymsp[-1].minor.yy402); } break; case 98: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy144 = SF_Distinct;} +{yymsp[0].minor.yy502 = SF_Distinct;} break; case 99: /* distinct ::= ALL */ -{yymsp[0].minor.yy144 = SF_All;} +{yymsp[0].minor.yy502 = SF_All;} break; case 101: /* sclp ::= */ case 134: /* orderby_opt ::= */ yytestcase(yyruleno==134); @@ -182902,20 +181598,20 @@ static YYACTIONTYPE yy_reduce( case 234: /* exprlist ::= */ yytestcase(yyruleno==234); case 237: /* paren_exprlist ::= */ yytestcase(yyruleno==237); case 242: /* eidlist_opt ::= */ yytestcase(yyruleno==242); -{yymsp[1].minor.yy14 = 0;} +{yymsp[1].minor.yy402 = 0;} break; case 102: /* selcollist ::= sclp scanpt expr scanpt as */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy14,yymsp[-3].minor.yy168,yymsp[-1].minor.yy168); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy402,yymsp[-3].minor.yy342,yymsp[-1].minor.yy342); } break; case 103: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); - yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, p); + yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy402, p); } break; case 104: /* selcollist ::= sclp scanpt nm DOT STAR */ @@ -182925,7 +181621,7 @@ static YYACTIONTYPE yy_reduce( sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, pDot); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, pDot); } break; case 105: /* as ::= AS nm */ @@ -182936,50 +181632,50 @@ static YYACTIONTYPE yy_reduce( break; case 107: /* from ::= */ case 110: /* stl_prefix ::= */ yytestcase(yyruleno==110); -{yymsp[1].minor.yy203 = 0;} +{yymsp[1].minor.yy563 = 0;} break; case 108: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy203 = yymsp[0].minor.yy203; - sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy203); + yymsp[-1].minor.yy563 = yymsp[0].minor.yy563; + sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy563); } break; case 109: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy203 && yymsp[-1].minor.yy203->nSrc>0) ) yymsp[-1].minor.yy203->a[yymsp[-1].minor.yy203->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy144; + if( ALWAYS(yymsp[-1].minor.yy563 && yymsp[-1].minor.yy563->nSrc>0) ) yymsp[-1].minor.yy563->a[yymsp[-1].minor.yy563->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502; } break; case 111: /* seltablist ::= stl_prefix nm dbnm as on_using */ { - yymsp[-4].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy203,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); + yymsp[-4].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy563,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); } break; case 112: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ { - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy269); - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-1].minor.yy0); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy421); + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-1].minor.yy0); } break; case 113: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ { - yymsp[-7].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy203,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); - sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy203, yymsp[-3].minor.yy14); + yymsp[-7].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy563,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); + sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy563, yymsp[-3].minor.yy402); } break; case 114: /* seltablist ::= stl_prefix LP select RP as on_using */ { - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy555,&yymsp[0].minor.yy269); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy637,&yymsp[0].minor.yy421); } break; case 115: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ { - if( yymsp[-5].minor.yy203==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy269.pOn==0 && yymsp[0].minor.yy269.pUsing==0 ){ - yymsp[-5].minor.yy203 = yymsp[-3].minor.yy203; - }else if( ALWAYS(yymsp[-3].minor.yy203!=0) && yymsp[-3].minor.yy203->nSrc==1 ){ - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); - 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; + if( yymsp[-5].minor.yy563==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy421.pOn==0 && yymsp[0].minor.yy421.pUsing==0 ){ + yymsp[-5].minor.yy563 = yymsp[-3].minor.yy563; + }else if( ALWAYS(yymsp[-3].minor.yy563!=0) && yymsp[-3].minor.yy563->nSrc==1 ){ + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); + if( yymsp[-5].minor.yy563 ){ + SrcItem *pNew = &yymsp[-5].minor.yy563->a[yymsp[-5].minor.yy563->nSrc-1]; + SrcItem *pOld = yymsp[-3].minor.yy563->a; assert( pOld->fg.fixedSchema==0 ); pNew->zName = pOld->zName; assert( pOld->fg.fixedSchema==0 ); @@ -183004,12 +181700,12 @@ static YYACTIONTYPE yy_reduce( } pOld->zName = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy203); + sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy563); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy203); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy203,0,0,0,0,SF_NestedFrom,0); - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy269); + sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy563); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy563,0,0,0,0,SF_NestedFrom,0); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy421); } } break; @@ -183018,67 +181714,57 @@ static YYACTIONTYPE yy_reduce( {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; case 118: /* fullname ::= nm */ - case 120: /* xfullname ::= nm */ yytestcase(yyruleno==120); { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); + if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy203 = yylhsminor.yy203; + yymsp[0].minor.yy563 = yylhsminor.yy563; break; case 119: /* fullname ::= nm DOT nm */ - case 121: /* xfullname ::= nm DOT nm */ yytestcase(yyruleno==121); { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy203 = yylhsminor.yy203; + yymsp[-2].minor.yy563 = yylhsminor.yy563; + break; + case 120: /* xfullname ::= nm */ +{yymsp[0].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} break; - case 122: /* xfullname ::= nm AS nm */ + case 121: /* xfullname ::= nm DOT nm */ +{yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 122: /* xfullname ::= nm DOT nm AS nm */ { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); - if( yylhsminor.yy203 ){ - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[-2].minor.yy0); - }else{ - yylhsminor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); - } - } + yymsp[-4].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ + if( yymsp[-4].minor.yy563 ) yymsp[-4].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy203 = yylhsminor.yy203; break; - case 123: /* xfullname ::= nm DOT nm AS nm */ + case 123: /* xfullname ::= nm AS nm */ { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); - if( yylhsminor.yy203 ){ - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[-2].minor.yy0); - }else{ - yylhsminor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); - } - } + yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ + if( yymsp[-2].minor.yy563 ) yymsp[-2].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } - yymsp[-4].minor.yy203 = yylhsminor.yy203; break; case 124: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy144 = JT_INNER; } +{ yymsp[0].minor.yy502 = JT_INNER; } break; case 125: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} +{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; case 126: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} +{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; case 127: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} +{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; case 128: /* on_using ::= ON expr */ -{yymsp[-1].minor.yy269.pOn = yymsp[0].minor.yy454; yymsp[-1].minor.yy269.pUsing = 0;} +{yymsp[-1].minor.yy421.pOn = yymsp[0].minor.yy590; yymsp[-1].minor.yy421.pUsing = 0;} break; case 129: /* on_using ::= USING LP idlist RP */ -{yymsp[-3].minor.yy269.pOn = 0; yymsp[-3].minor.yy269.pUsing = yymsp[-1].minor.yy132;} +{yymsp[-3].minor.yy421.pOn = 0; yymsp[-3].minor.yy421.pUsing = yymsp[-1].minor.yy204;} break; case 130: /* on_using ::= */ -{yymsp[1].minor.yy269.pOn = 0; yymsp[1].minor.yy269.pUsing = 0;} +{yymsp[1].minor.yy421.pOn = 0; yymsp[1].minor.yy421.pUsing = 0;} break; case 132: /* indexed_by ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} @@ -183088,35 +181774,35 @@ static YYACTIONTYPE yy_reduce( break; case 135: /* orderby_opt ::= ORDER BY sortlist */ case 145: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==145); -{yymsp[-2].minor.yy14 = yymsp[0].minor.yy14;} +{yymsp[-2].minor.yy402 = yymsp[0].minor.yy402;} break; case 136: /* sortlist ::= sortlist COMMA expr sortorder nulls */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14,yymsp[-2].minor.yy454); - sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402,yymsp[-2].minor.yy590); + sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); } break; case 137: /* sortlist ::= expr sortorder nulls */ { - yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy454); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); + yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy590); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); } break; case 138: /* sortorder ::= ASC */ -{yymsp[0].minor.yy144 = SQLITE_SO_ASC;} +{yymsp[0].minor.yy502 = SQLITE_SO_ASC;} break; case 139: /* sortorder ::= DESC */ -{yymsp[0].minor.yy144 = SQLITE_SO_DESC;} +{yymsp[0].minor.yy502 = SQLITE_SO_DESC;} break; case 140: /* sortorder ::= */ case 143: /* nulls ::= */ yytestcase(yyruleno==143); -{yymsp[1].minor.yy144 = SQLITE_SO_UNDEFINED;} +{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;} break; case 141: /* nulls ::= NULLS FIRST */ -{yymsp[-1].minor.yy144 = SQLITE_SO_ASC;} +{yymsp[-1].minor.yy502 = SQLITE_SO_ASC;} break; case 142: /* nulls ::= NULLS LAST */ -{yymsp[-1].minor.yy144 = SQLITE_SO_DESC;} +{yymsp[-1].minor.yy502 = SQLITE_SO_DESC;} break; case 146: /* having_opt ::= */ case 148: /* limit_opt ::= */ yytestcase(yyruleno==148); @@ -183125,42 +181811,42 @@ static YYACTIONTYPE yy_reduce( case 232: /* case_else ::= */ yytestcase(yyruleno==232); case 233: /* case_operand ::= */ yytestcase(yyruleno==233); case 252: /* vinto ::= */ yytestcase(yyruleno==252); -{yymsp[1].minor.yy454 = 0;} +{yymsp[1].minor.yy590 = 0;} break; case 147: /* having_opt ::= HAVING expr */ case 154: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==154); case 156: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==156); case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231); case 251: /* vinto ::= INTO expr */ yytestcase(yyruleno==251); -{yymsp[-1].minor.yy454 = yymsp[0].minor.yy454;} +{yymsp[-1].minor.yy590 = yymsp[0].minor.yy590;} break; case 149: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,0);} +{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,0);} break; case 150: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} +{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} break; case 151: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,yymsp[-2].minor.yy454);} +{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,yymsp[-2].minor.yy590);} break; case 152: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy203, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy203,yymsp[0].minor.yy454,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy563, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy563,yymsp[0].minor.yy590,0,0); } break; case 157: /* where_opt_ret ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-1].minor.yy454 = 0;} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-1].minor.yy590 = 0;} break; case 158: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-3].minor.yy454 = yymsp[-2].minor.yy454;} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-3].minor.yy590 = yymsp[-2].minor.yy590;} break; case 159: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-4].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy14,"set list"); - if( yymsp[-1].minor.yy203 ){ - SrcList *pFromClause = yymsp[-1].minor.yy203; + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-4].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy402,"set list"); + if( yymsp[-1].minor.yy563 ){ + SrcList *pFromClause = yymsp[-1].minor.yy563; if( pFromClause->nSrc>1 ){ Select *pSubquery; Token as; @@ -183169,90 +181855,90 @@ static YYACTIONTYPE yy_reduce( as.z = 0; pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); } - yymsp[-5].minor.yy203 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy203, pFromClause); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy563, pFromClause); } - sqlite3Update(pParse,yymsp[-5].minor.yy203,yymsp[-2].minor.yy14,yymsp[0].minor.yy454,yymsp[-6].minor.yy144,0,0,0); + sqlite3Update(pParse,yymsp[-5].minor.yy563,yymsp[-2].minor.yy402,yymsp[0].minor.yy590,yymsp[-6].minor.yy502,0,0,0); } break; case 160: /* setlist ::= setlist COMMA nm EQ expr */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy454); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, 1); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[0].minor.yy590); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, 1); } break; case 161: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yymsp[-6].minor.yy14 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy14, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); + yymsp[-6].minor.yy402 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy402, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); } break; case 162: /* setlist ::= nm EQ expr */ { - yylhsminor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy454); - sqlite3ExprListSetName(pParse, yylhsminor.yy14, &yymsp[-2].minor.yy0, 1); + yylhsminor.yy402 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy590); + sqlite3ExprListSetName(pParse, yylhsminor.yy402, &yymsp[-2].minor.yy0, 1); } - yymsp[-2].minor.yy14 = yylhsminor.yy14; + yymsp[-2].minor.yy402 = yylhsminor.yy402; break; case 163: /* setlist ::= LP idlist RP EQ expr */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); + yymsp[-4].minor.yy402 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); } break; case 164: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ { - sqlite3Insert(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy555, yymsp[-2].minor.yy132, yymsp[-5].minor.yy144, yymsp[0].minor.yy122); + sqlite3Insert(pParse, yymsp[-3].minor.yy563, yymsp[-1].minor.yy637, yymsp[-2].minor.yy204, yymsp[-5].minor.yy502, yymsp[0].minor.yy403); } break; case 165: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ { - sqlite3Insert(pParse, yymsp[-4].minor.yy203, 0, yymsp[-3].minor.yy132, yymsp[-6].minor.yy144, 0); + sqlite3Insert(pParse, yymsp[-4].minor.yy563, 0, yymsp[-3].minor.yy204, yymsp[-6].minor.yy502, 0); } break; case 166: /* upsert ::= */ -{ yymsp[1].minor.yy122 = 0; } +{ yymsp[1].minor.yy403 = 0; } break; case 167: /* upsert ::= RETURNING selcollist */ -{ yymsp[-1].minor.yy122 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy14); } +{ yymsp[-1].minor.yy403 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy402); } break; case 168: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ -{ yymsp[-11].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy14,yymsp[-6].minor.yy454,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,yymsp[0].minor.yy122);} +{ yymsp[-11].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy402,yymsp[-6].minor.yy590,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,yymsp[0].minor.yy403);} break; case 169: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ -{ yymsp[-8].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy14,yymsp[-3].minor.yy454,0,0,yymsp[0].minor.yy122); } +{ yymsp[-8].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy402,yymsp[-3].minor.yy590,0,0,yymsp[0].minor.yy403); } break; case 170: /* upsert ::= ON CONFLICT DO NOTHING returning */ -{ yymsp[-4].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } +{ yymsp[-4].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } break; case 171: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ -{ yymsp[-7].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,0);} +{ yymsp[-7].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,0);} break; case 172: /* returning ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy14);} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy402);} break; case 175: /* idlist_opt ::= */ -{yymsp[1].minor.yy132 = 0;} +{yymsp[1].minor.yy204 = 0;} break; case 176: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy132 = yymsp[-1].minor.yy132;} +{yymsp[-2].minor.yy204 = yymsp[-1].minor.yy204;} break; case 177: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy132 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy132,&yymsp[0].minor.yy0);} +{yymsp[-2].minor.yy204 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy204,&yymsp[0].minor.yy0);} break; case 178: /* idlist ::= nm */ -{yymsp[0].minor.yy132 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} +{yymsp[0].minor.yy204 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; case 179: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy454 = yymsp[-1].minor.yy454;} +{yymsp[-2].minor.yy590 = yymsp[-1].minor.yy590;} break; case 180: /* expr ::= ID|INDEXED|JOIN_KW */ -{yymsp[0].minor.yy454=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy590=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 181: /* expr ::= nm DOT nm */ { Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); - yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } - yymsp[-2].minor.yy454 = yylhsminor.yy454; + yymsp[-2].minor.yy590 = yylhsminor.yy590; break; case 182: /* expr ::= nm DOT nm DOT nm */ { @@ -183263,32 +181949,27 @@ static YYACTIONTYPE yy_reduce( if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, 0, temp1); } - yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } - yymsp[-4].minor.yy454 = yylhsminor.yy454; + yymsp[-4].minor.yy590 = yylhsminor.yy590; break; case 183: /* term ::= NULL|FLOAT|BLOB */ case 184: /* term ::= STRING */ yytestcase(yyruleno==184); -{yymsp[0].minor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 185: /* term ::= INTEGER */ { - int iValue; - if( sqlite3GetInt32(yymsp[0].minor.yy0.z, &iValue)==0 ){ - yylhsminor.yy454 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 0); - }else{ - yylhsminor.yy454 = sqlite3ExprInt32(pParse->db, iValue); - } - if( yylhsminor.yy454 ) yylhsminor.yy454->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); + yylhsminor.yy590 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + if( yylhsminor.yy590 ) yylhsminor.yy590->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); } - yymsp[0].minor.yy454 = yylhsminor.yy454; + yymsp[0].minor.yy590 = yylhsminor.yy590; break; case 186: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; - yymsp[0].minor.yy454 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy454, n); + yymsp[0].minor.yy590 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy590, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers @@ -183297,80 +181978,80 @@ static YYACTIONTYPE yy_reduce( assert( t.n>=2 ); if( pParse->nested==0 ){ parserSyntaxError(pParse, &t); - yymsp[0].minor.yy454 = 0; + yymsp[0].minor.yy590 = 0; }else{ - yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable); + yymsp[0].minor.yy590 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy590 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy590->iTable); } } } break; case 187: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy454 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy454, &yymsp[0].minor.yy0, 1); + yymsp[-2].minor.yy590 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy590, &yymsp[0].minor.yy0, 1); } break; case 188: /* expr ::= CAST LP expr AS typetoken RP */ { - yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy454, yymsp[-3].minor.yy454, 0); + yymsp[-5].minor.yy590 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy590, yymsp[-3].minor.yy590, 0); } break; case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy144); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy502); } - yymsp[-4].minor.yy454 = yylhsminor.yy454; + yymsp[-4].minor.yy590 = yylhsminor.yy590; break; case 190: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy14, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy144); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-1].minor.yy14); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy402, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy502); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-1].minor.yy402); } - yymsp[-7].minor.yy454 = yylhsminor.yy454; + yymsp[-7].minor.yy590 = yylhsminor.yy590; break; case 191: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); } - yymsp[-3].minor.yy454 = yylhsminor.yy454; + yymsp[-3].minor.yy590 = yylhsminor.yy590; break; case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy14, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy144); - sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy402, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy502); + sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); } - yymsp[-5].minor.yy454 = yylhsminor.yy454; + yymsp[-5].minor.yy590 = yylhsminor.yy590; break; case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy14, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy144); - sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-2].minor.yy14); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy402, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy502); + sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-2].minor.yy402); } - yymsp[-8].minor.yy454 = yylhsminor.yy454; + yymsp[-8].minor.yy590 = yylhsminor.yy590; break; case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); + sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); } - yymsp[-4].minor.yy454 = yylhsminor.yy454; + yymsp[-4].minor.yy590 = yylhsminor.yy590; break; case 195: /* term ::= CTIME_KW */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); } - yymsp[0].minor.yy454 = yylhsminor.yy454; + yymsp[0].minor.yy590 = yylhsminor.yy590; break; case 196: /* expr ::= LP nexprlist COMMA expr RP */ { - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy454 ){ - yymsp[-4].minor.yy454->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yymsp[-4].minor.yy590 ){ + yymsp[-4].minor.yy590->x.pList = pList; if( ALWAYS(pList->nExpr) ){ - yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate; + yymsp[-4].minor.yy590->flags |= pList->a[0].pExpr->flags & EP_Propagate; } }else{ sqlite3ExprListDelete(pParse->db, pList); @@ -183378,7 +182059,7 @@ static YYACTIONTYPE yy_reduce( } break; case 197: /* expr ::= expr AND expr */ -{yymsp[-2].minor.yy454=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} +{yymsp[-2].minor.yy590=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} break; case 198: /* expr ::= expr OR expr */ case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199); @@ -183387,7 +182068,7 @@ static YYACTIONTYPE yy_reduce( case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202); case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203); case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204); -{yymsp[-2].minor.yy454=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} +{yymsp[-2].minor.yy590=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} break; case 205: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} @@ -183397,11 +182078,11 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy454); - yymsp[-2].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy454, 0); - if( yymsp[-2].minor.yy454 ) yymsp[-2].minor.yy454->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy590); + yymsp[-2].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + if( bNot ) yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy590, 0); + if( yymsp[-2].minor.yy590 ) yymsp[-2].minor.yy590->flags |= EP_InfixFunc; } break; case 207: /* expr ::= expr likeop expr ESCAPE expr */ @@ -183409,87 +182090,91 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); - yymsp[-4].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); - if( yymsp[-4].minor.yy454 ) yymsp[-4].minor.yy454->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); + yymsp[-4].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); + if( bNot ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); + if( yymsp[-4].minor.yy590 ) yymsp[-4].minor.yy590->flags |= EP_InfixFunc; } break; case 208: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy454 = sqlite3PExprIsNull(pParse,yymsp[0].major,yymsp[-1].minor.yy454);} +{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy590,0);} break; case 209: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy454 = sqlite3PExprIsNull(pParse,TK_NOTNULL,yymsp[-2].minor.yy454);} +{yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy590,0);} break; case 210: /* expr ::= expr IS expr */ { - yymsp[-2].minor.yy454 = sqlite3PExprIs(pParse, TK_IS, yymsp[-2].minor.yy454, yymsp[0].minor.yy454); + yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-2].minor.yy590, TK_ISNULL); } break; case 211: /* expr ::= expr IS NOT expr */ { - yymsp[-3].minor.yy454 = sqlite3PExprIs(pParse, TK_ISNOT, yymsp[-3].minor.yy454, yymsp[0].minor.yy454); + yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-3].minor.yy590, TK_NOTNULL); } break; case 212: /* expr ::= expr IS NOT DISTINCT FROM expr */ { - yymsp[-5].minor.yy454 = sqlite3PExprIs(pParse, TK_IS, yymsp[-5].minor.yy454, yymsp[0].minor.yy454); + yymsp[-5].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-5].minor.yy590, TK_ISNULL); } break; case 213: /* expr ::= expr IS DISTINCT FROM expr */ { - yymsp[-4].minor.yy454 = sqlite3PExprIs(pParse, TK_ISNOT, yymsp[-4].minor.yy454, yymsp[0].minor.yy454); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-4].minor.yy590, TK_NOTNULL); } break; case 214: /* expr ::= NOT expr */ case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215); -{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/} +{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy590, 0);/*A-overwrites-B*/} break; case 216: /* expr ::= PLUS|MINUS expr */ { - Expr *p = yymsp[0].minor.yy454; + Expr *p = yymsp[0].minor.yy590; u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS); assert( TK_UPLUS>TK_PLUS ); assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) ); if( p && p->op==TK_UPLUS ){ p->op = op; - yymsp[-1].minor.yy454 = p; + yymsp[-1].minor.yy590 = p; }else{ - yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, op, p, 0); + yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, op, p, 0); /*A-overwrites-B*/ } } break; case 217: /* expr ::= expr PTR expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454); - pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy454); - yylhsminor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy590); + pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy590); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); } - yymsp[-2].minor.yy454 = yylhsminor.yy454; + yymsp[-2].minor.yy590 = yylhsminor.yy590; break; case 218: /* between_op ::= BETWEEN */ case 221: /* in_op ::= IN */ yytestcase(yyruleno==221); -{yymsp[0].minor.yy144 = 0;} +{yymsp[0].minor.yy502 = 0;} break; case 220: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0); - if( yymsp[-4].minor.yy454 ){ - yymsp[-4].minor.yy454->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy590, 0); + if( yymsp[-4].minor.yy590 ){ + yymsp[-4].minor.yy590->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } break; case 223: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy14==0 ){ + if( yymsp[-1].minor.yy402==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -183502,145 +182187,145 @@ static YYACTIONTYPE yy_reduce( ** it is or not) and if it is an aggregate, that could change the meaning ** of the whole query. */ - Expr *pB = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy144 ? "true" : "false"); + Expr *pB = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy502 ? "true" : "false"); if( pB ) sqlite3ExprIdToTrueFalse(pB); - if( !ExprHasProperty(yymsp[-4].minor.yy454, EP_HasFunc) ){ - sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy454); - yymsp[-4].minor.yy454 = pB; + if( !ExprHasProperty(yymsp[-4].minor.yy590, EP_HasFunc) ){ + sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy590); + yymsp[-4].minor.yy590 = pB; }else{ - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, yymsp[-3].minor.yy144 ? TK_OR : TK_AND, pB, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, yymsp[-3].minor.yy502 ? TK_OR : TK_AND, pB, yymsp[-4].minor.yy590); } }else{ - Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr; - if( yymsp[-1].minor.yy14->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy454->op!=TK_VECTOR ){ - yymsp[-1].minor.yy14->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + Expr *pRHS = yymsp[-1].minor.yy402->a[0].pExpr; + if( yymsp[-1].minor.yy402->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy590->op!=TK_VECTOR ){ + yymsp[-1].minor.yy402->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy454, pRHS); - }else if( yymsp[-1].minor.yy14->nExpr==1 && pRHS->op==TK_SELECT ){ - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pRHS->x.pSelect); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy590, pRHS); + }else if( yymsp[-1].minor.yy402->nExpr==1 && pRHS->op==TK_SELECT ){ + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pRHS->x.pSelect); pRHS->x.pSelect = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); }else{ - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - if( yymsp[-4].minor.yy454==0 ){ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); - }else if( yymsp[-4].minor.yy454->pLeft->op==TK_VECTOR ){ - int nExpr = yymsp[-4].minor.yy454->pLeft->x.pList->nExpr; - Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy14); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + if( yymsp[-4].minor.yy590==0 ){ + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); + }else if( yymsp[-4].minor.yy590->pLeft->op==TK_VECTOR ){ + int nExpr = yymsp[-4].minor.yy590->pLeft->x.pList->nExpr; + Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy402); if( pSelectRHS ){ parserDoubleLinkSelect(pParse, pSelectRHS); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelectRHS); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelectRHS); } }else{ - yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy14; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy402; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); } } - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } } break; case 224: /* expr ::= LP select RP */ { - yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy454, yymsp[-1].minor.yy555); + yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy590, yymsp[-1].minor.yy637); } break; case 225: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, yymsp[-1].minor.yy555); - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, yymsp[-1].minor.yy637); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } break; case 226: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); - if( yymsp[0].minor.yy14 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy14); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelect); - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[0].minor.yy402 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy402); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelect); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } break; case 227: /* expr ::= EXISTS LP select RP */ { Expr *p; - p = yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy555); + p = yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy637); } break; case 228: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy454, 0); - if( yymsp[-4].minor.yy454 ){ - yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy454 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454) : yymsp[-2].minor.yy14; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy590, 0); + if( yymsp[-4].minor.yy590 ){ + yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy590 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590) : yymsp[-2].minor.yy402; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy402); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); } } break; case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[0].minor.yy454); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[0].minor.yy590); } break; case 230: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); - yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, yymsp[0].minor.yy454); + yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); + yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402, yymsp[0].minor.yy590); } break; case 235: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy454);} +{yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[0].minor.yy590);} break; case 236: /* nexprlist ::= expr */ -{yymsp[0].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy454); /*A-overwrites-Y*/} +{yymsp[0].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy590); /*A-overwrites-Y*/} break; case 238: /* paren_exprlist ::= LP exprlist RP */ case 243: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==243); -{yymsp[-2].minor.yy14 = yymsp[-1].minor.yy14;} +{yymsp[-2].minor.yy402 = yymsp[-1].minor.yy402;} break; case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy144, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy454, SQLITE_SO_ASC, yymsp[-8].minor.yy144, SQLITE_IDXTYPE_APPDEF); + sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy402, yymsp[-10].minor.yy502, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy590, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF); if( IN_RENAME_OBJECT && pParse->pNewIndex ){ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); } } break; case 240: /* uniqueflag ::= UNIQUE */ - case 281: /* raisetype ::= ABORT */ yytestcase(yyruleno==281); -{yymsp[0].minor.yy144 = OE_Abort;} + case 282: /* raisetype ::= ABORT */ yytestcase(yyruleno==282); +{yymsp[0].minor.yy502 = OE_Abort;} break; case 241: /* uniqueflag ::= */ -{yymsp[1].minor.yy144 = OE_None;} +{yymsp[1].minor.yy502 = OE_None;} break; case 244: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy14 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); + yymsp[-4].minor.yy402 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); } break; case 245: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy14 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); /*A-overwrites-Y*/ + yymsp[-2].minor.yy402 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/ } break; case 248: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy203, yymsp[-1].minor.yy144);} +{sqlite3DropIndex(pParse, yymsp[0].minor.yy563, yymsp[-1].minor.yy502);} break; case 249: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy454);} +{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy590);} break; case 250: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy454);} +{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy590);} break; case 253: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} @@ -183662,12 +182347,12 @@ static YYACTIONTYPE yy_reduce( Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy319, &all); } break; case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy144, yymsp[-4].minor.yy286.a, yymsp[-4].minor.yy286.b, yymsp[-2].minor.yy203, yymsp[0].minor.yy454, yymsp[-10].minor.yy144, yymsp[-8].minor.yy144); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy28.a, yymsp[-4].minor.yy28.b, yymsp[-2].minor.yy563, yymsp[0].minor.yy590, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ #ifdef SQLITE_DEBUG assert( pParse->isCreate ); /* Set by createkw reduce action */ @@ -183676,439 +182361,421 @@ static YYACTIONTYPE yy_reduce( } break; case 262: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/ } +{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ } break; case 263: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy144 = TK_INSTEAD;} +{ yymsp[-1].minor.yy502 = TK_INSTEAD;} break; case 264: /* trigger_time ::= */ -{ yymsp[1].minor.yy144 = TK_BEFORE; } +{ yymsp[1].minor.yy502 = TK_BEFORE; } break; case 265: /* trigger_event ::= DELETE|INSERT */ case 266: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==266); -{yymsp[0].minor.yy286.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy286.b = 0;} +{yymsp[0].minor.yy28.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy28.b = 0;} break; case 267: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy286.a = TK_UPDATE; yymsp[-2].minor.yy286.b = yymsp[0].minor.yy132;} +{yymsp[-2].minor.yy28.a = TK_UPDATE; yymsp[-2].minor.yy28.b = yymsp[0].minor.yy204;} break; case 268: /* when_clause ::= */ - case 286: /* key_opt ::= */ yytestcase(yyruleno==286); -{ yymsp[1].minor.yy454 = 0; } + case 287: /* key_opt ::= */ yytestcase(yyruleno==287); +{ yymsp[1].minor.yy590 = 0; } break; case 269: /* when_clause ::= WHEN expr */ - case 287: /* key_opt ::= KEY expr */ yytestcase(yyruleno==287); -{ yymsp[-1].minor.yy454 = yymsp[0].minor.yy454; } + case 288: /* key_opt ::= KEY expr */ yytestcase(yyruleno==288); +{ yymsp[-1].minor.yy590 = yymsp[0].minor.yy590; } break; case 270: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427; - yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427; + assert( yymsp[-2].minor.yy319!=0 ); + yymsp[-2].minor.yy319->pLast->pNext = yymsp[-1].minor.yy319; + yymsp[-2].minor.yy319->pLast = yymsp[-1].minor.yy319; } break; case 271: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427; + assert( yymsp[-1].minor.yy319!=0 ); + yymsp[-1].minor.yy319->pLast = yymsp[-1].minor.yy319; } break; - case 272: /* tridxby ::= INDEXED BY nm */ + case 272: /* trnm ::= nm DOT nm */ +{ + yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; + sqlite3ErrorMsg(pParse, + "qualified table names are not allowed on INSERT, UPDATE, and DELETE " + "statements within triggers"); +} + break; + case 273: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 273: /* tridxby ::= NOT INDEXED */ + case 274: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 274: /* trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */ -{yylhsminor.yy427 = sqlite3TriggerUpdateStep(pParse, yymsp[-6].minor.yy203, yymsp[-2].minor.yy203, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454, yymsp[-7].minor.yy144, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy168);} - yymsp[-8].minor.yy427 = yylhsminor.yy427; + case 275: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ +{yylhsminor.yy319 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy563, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590, yymsp[-7].minor.yy502, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy342);} + yymsp[-8].minor.yy319 = yylhsminor.yy319; break; - case 275: /* trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */ + case 276: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ { - yylhsminor.yy427 = sqlite3TriggerInsertStep(pParse,yymsp[-4].minor.yy203,yymsp[-3].minor.yy132,yymsp[-2].minor.yy555,yymsp[-6].minor.yy144,yymsp[-1].minor.yy122,yymsp[-7].minor.yy168,yymsp[0].minor.yy168);/*yylhsminor.yy427-overwrites-yymsp[-6].minor.yy144*/ + yylhsminor.yy319 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy204,yymsp[-2].minor.yy637,yymsp[-6].minor.yy502,yymsp[-1].minor.yy403,yymsp[-7].minor.yy342,yymsp[0].minor.yy342);/*yylhsminor.yy319-overwrites-yymsp[-6].minor.yy502*/ } - yymsp[-7].minor.yy427 = yylhsminor.yy427; + yymsp[-7].minor.yy319 = yylhsminor.yy319; break; - case 276: /* trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */ -{yylhsminor.yy427 = sqlite3TriggerDeleteStep(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy454, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy168);} - yymsp[-5].minor.yy427 = yylhsminor.yy427; + case 277: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +{yylhsminor.yy319 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy590, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy342);} + yymsp[-5].minor.yy319 = yylhsminor.yy319; break; - case 277: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy555, yymsp[-2].minor.yy168, yymsp[0].minor.yy168); /*yylhsminor.yy427-overwrites-yymsp[-1].minor.yy555*/} - yymsp[-2].minor.yy427 = yylhsminor.yy427; + case 278: /* trigger_cmd ::= scanpt select scanpt */ +{yylhsminor.yy319 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy637, yymsp[-2].minor.yy342, yymsp[0].minor.yy342); /*yylhsminor.yy319-overwrites-yymsp[-1].minor.yy637*/} + yymsp[-2].minor.yy319 = yylhsminor.yy319; break; - case 278: /* expr ::= RAISE LP IGNORE RP */ + case 279: /* expr ::= RAISE LP IGNORE RP */ { - yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy454 ){ - yymsp[-3].minor.yy454->affExpr = OE_Ignore; + yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy590 ){ + yymsp[-3].minor.yy590->affExpr = OE_Ignore; } } break; - case 279: /* expr ::= RAISE LP raisetype COMMA expr RP */ + case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */ { - 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; + yymsp[-5].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy590, 0); + if( yymsp[-5].minor.yy590 ) { + yymsp[-5].minor.yy590->affExpr = (char)yymsp[-3].minor.yy502; } } break; - case 280: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy144 = OE_Rollback;} + case 281: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy502 = OE_Rollback;} break; - case 282: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy144 = OE_Fail;} + case 283: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy502 = OE_Fail;} break; - case 283: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 284: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy203,yymsp[-1].minor.yy144); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy563,yymsp[-1].minor.yy502); } break; - case 284: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, yymsp[0].minor.yy454); + sqlite3Attach(pParse, yymsp[-3].minor.yy590, yymsp[-1].minor.yy590, yymsp[0].minor.yy590); } break; - case 285: /* cmd ::= DETACH database_kw_opt expr */ + case 286: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy454); + sqlite3Detach(pParse, yymsp[0].minor.yy590); } break; - case 288: /* cmd ::= REINDEX */ + case 289: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 289: /* cmd ::= REINDEX nm dbnm */ + case 290: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 290: /* cmd ::= ANALYZE */ + case 291: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 291: /* cmd ::= ANALYZE nm dbnm */ + case 292: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 292: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 293: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy203,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy563,&yymsp[0].minor.yy0); } break; - case 293: /* cmd ::= alter_add carglist */ + case 294: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); -} - break; - case 294: /* alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */ -{ - disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[-4].minor.yy203); - sqlite3AddColumn(pParse, yymsp[-1].minor.yy0, yymsp[0].minor.yy0); - yymsp[-6].minor.yy0 = yymsp[-1].minor.yy0; } break; case 295: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ { - sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0); -} - break; - case 296: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ -{ - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy203, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); -} - break; - case 297: /* cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */ -{ - sqlite3AlterDropConstraint(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0, 0); + sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy563, &yymsp[0].minor.yy0); } break; - case 298: /* cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */ + case 296: /* add_column_fullname ::= fullname */ { - sqlite3AlterDropConstraint(pParse, yymsp[-6].minor.yy203, 0, &yymsp[-3].minor.yy0); -} - break; - case 299: /* cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */ -{ - sqlite3AlterSetNotNull(pParse, yymsp[-7].minor.yy203, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0); -} - break; - case 300: /* cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */ -{ - sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1)); + disableLookaside(pParse); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy563); } - yy_destructor(yypParser,219,&yymsp[-2].minor); break; - case 301: /* cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */ + case 297: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ { - sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1)); + sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy563, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } - yy_destructor(yypParser,219,&yymsp[-2].minor); break; - case 302: /* cmd ::= create_vtab */ + case 298: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 303: /* cmd ::= create_vtab LP vtabarglist RP */ + case 299: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 304: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 300: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy144); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502); } break; - case 305: /* vtabarg ::= */ + case 301: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 306: /* vtabargtoken ::= ANY */ - case 307: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==307); - case 308: /* lp ::= LP */ yytestcase(yyruleno==308); + case 302: /* vtabargtoken ::= ANY */ + case 303: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==303); + case 304: /* lp ::= LP */ yytestcase(yyruleno==304); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 309: /* with ::= WITH wqlist */ - case 310: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==310); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy59, 1); } + case 305: /* with ::= WITH wqlist */ + case 306: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==306); +{ sqlite3WithPush(pParse, yymsp[0].minor.yy125, 1); } break; - case 311: /* wqas ::= AS */ -{yymsp[0].minor.yy462 = M10d_Any;} + case 307: /* wqas ::= AS */ +{yymsp[0].minor.yy444 = M10d_Any;} break; - case 312: /* wqas ::= AS MATERIALIZED */ -{yymsp[-1].minor.yy462 = M10d_Yes;} + case 308: /* wqas ::= AS MATERIALIZED */ +{yymsp[-1].minor.yy444 = M10d_Yes;} break; - case 313: /* wqas ::= AS NOT MATERIALIZED */ -{yymsp[-2].minor.yy462 = M10d_No;} + case 309: /* wqas ::= AS NOT MATERIALIZED */ +{yymsp[-2].minor.yy444 = M10d_No;} break; - case 314: /* wqitem ::= withnm eidlist_opt wqas LP select RP */ + case 310: /* wqitem ::= withnm eidlist_opt wqas LP select RP */ { - yymsp[-5].minor.yy67 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy555, yymsp[-3].minor.yy462); /*A-overwrites-X*/ + yymsp[-5].minor.yy361 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy637, yymsp[-3].minor.yy444); /*A-overwrites-X*/ } break; - case 315: /* withnm ::= nm */ + case 311: /* withnm ::= nm */ {pParse->bHasWith = 1;} break; - case 316: /* wqlist ::= wqitem */ + case 312: /* wqlist ::= wqitem */ { - yymsp[0].minor.yy59 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy67); /*A-overwrites-X*/ + yymsp[0].minor.yy125 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy361); /*A-overwrites-X*/ } break; - case 317: /* wqlist ::= wqlist COMMA wqitem */ + case 313: /* wqlist ::= wqlist COMMA wqitem */ { - yymsp[-2].minor.yy59 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy59, yymsp[0].minor.yy67); + yymsp[-2].minor.yy125 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy125, yymsp[0].minor.yy361); } break; - case 318: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ + case 314: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ { - assert( yymsp[0].minor.yy211!=0 ); - sqlite3WindowChain(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy211); - yymsp[0].minor.yy211->pNextWin = yymsp[-2].minor.yy211; - yylhsminor.yy211 = yymsp[0].minor.yy211; + assert( yymsp[0].minor.yy483!=0 ); + sqlite3WindowChain(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy483); + yymsp[0].minor.yy483->pNextWin = yymsp[-2].minor.yy483; + yylhsminor.yy483 = yymsp[0].minor.yy483; } - yymsp[-2].minor.yy211 = yylhsminor.yy211; + yymsp[-2].minor.yy483 = yylhsminor.yy483; break; - case 319: /* windowdefn ::= nm AS LP window RP */ + case 315: /* windowdefn ::= nm AS LP window RP */ { - if( ALWAYS(yymsp[-1].minor.yy211) ){ - yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); + if( ALWAYS(yymsp[-1].minor.yy483) ){ + yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); } - yylhsminor.yy211 = yymsp[-1].minor.yy211; + yylhsminor.yy483 = yymsp[-1].minor.yy483; } - yymsp[-4].minor.yy211 = yylhsminor.yy211; + yymsp[-4].minor.yy483 = yylhsminor.yy483; break; - case 320: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + case 316: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ { - yymsp[-4].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, 0); + yymsp[-4].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, 0); } break; - case 321: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + case 317: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ { - yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, &yymsp[-5].minor.yy0); + yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, &yymsp[-5].minor.yy0); } - yymsp[-5].minor.yy211 = yylhsminor.yy211; + yymsp[-5].minor.yy483 = yylhsminor.yy483; break; - case 322: /* window ::= ORDER BY sortlist frame_opt */ + case 318: /* window ::= ORDER BY sortlist frame_opt */ { - yymsp[-3].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, 0); + yymsp[-3].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, 0); } break; - case 323: /* window ::= nm ORDER BY sortlist frame_opt */ + case 319: /* window ::= nm ORDER BY sortlist frame_opt */ { - yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0); + yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0); } - yymsp[-4].minor.yy211 = yylhsminor.yy211; + yymsp[-4].minor.yy483 = yylhsminor.yy483; break; - case 324: /* window ::= nm frame_opt */ + case 320: /* window ::= nm frame_opt */ { - yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, 0, &yymsp[-1].minor.yy0); + yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, 0, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy211 = yylhsminor.yy211; + yymsp[-1].minor.yy483 = yylhsminor.yy483; break; - case 325: /* frame_opt ::= */ + case 321: /* frame_opt ::= */ { - yymsp[1].minor.yy211 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); + yymsp[1].minor.yy483 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); } break; - case 326: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + case 322: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ { - yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy144, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy462); + yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy502, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy444); } - yymsp[-2].minor.yy211 = yylhsminor.yy211; + yymsp[-2].minor.yy483 = yylhsminor.yy483; break; - case 327: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + case 323: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ { - yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy144, yymsp[-3].minor.yy509.eType, yymsp[-3].minor.yy509.pExpr, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, yymsp[0].minor.yy462); + yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy502, yymsp[-3].minor.yy205.eType, yymsp[-3].minor.yy205.pExpr, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, yymsp[0].minor.yy444); } - yymsp[-5].minor.yy211 = yylhsminor.yy211; + yymsp[-5].minor.yy483 = yylhsminor.yy483; break; - case 329: /* frame_bound_s ::= frame_bound */ - case 331: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==331); -{yylhsminor.yy509 = yymsp[0].minor.yy509;} - yymsp[0].minor.yy509 = yylhsminor.yy509; + case 325: /* frame_bound_s ::= frame_bound */ + case 327: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==327); +{yylhsminor.yy205 = yymsp[0].minor.yy205;} + yymsp[0].minor.yy205 = yylhsminor.yy205; break; - case 330: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 332: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==332); - case 334: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==334); -{yylhsminor.yy509.eType = yymsp[-1].major; yylhsminor.yy509.pExpr = 0;} - yymsp[-1].minor.yy509 = yylhsminor.yy509; + case 326: /* frame_bound_s ::= UNBOUNDED PRECEDING */ + case 328: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==328); + case 330: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==330); +{yylhsminor.yy205.eType = yymsp[-1].major; yylhsminor.yy205.pExpr = 0;} + yymsp[-1].minor.yy205 = yylhsminor.yy205; break; - case 333: /* frame_bound ::= expr PRECEDING|FOLLOWING */ -{yylhsminor.yy509.eType = yymsp[0].major; yylhsminor.yy509.pExpr = yymsp[-1].minor.yy454;} - yymsp[-1].minor.yy509 = yylhsminor.yy509; + case 329: /* frame_bound ::= expr PRECEDING|FOLLOWING */ +{yylhsminor.yy205.eType = yymsp[0].major; yylhsminor.yy205.pExpr = yymsp[-1].minor.yy590;} + yymsp[-1].minor.yy205 = yylhsminor.yy205; break; - case 335: /* frame_exclude_opt ::= */ -{yymsp[1].minor.yy462 = 0;} + case 331: /* frame_exclude_opt ::= */ +{yymsp[1].minor.yy444 = 0;} break; - case 336: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ -{yymsp[-1].minor.yy462 = yymsp[0].minor.yy462;} + case 332: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ +{yymsp[-1].minor.yy444 = yymsp[0].minor.yy444;} break; - case 337: /* frame_exclude ::= NO OTHERS */ - case 338: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==338); -{yymsp[-1].minor.yy462 = yymsp[-1].major; /*A-overwrites-X*/} + case 333: /* frame_exclude ::= NO OTHERS */ + case 334: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==334); +{yymsp[-1].minor.yy444 = yymsp[-1].major; /*A-overwrites-X*/} break; - case 339: /* frame_exclude ::= GROUP|TIES */ -{yymsp[0].minor.yy462 = yymsp[0].major; /*A-overwrites-X*/} + case 335: /* frame_exclude ::= GROUP|TIES */ +{yymsp[0].minor.yy444 = yymsp[0].major; /*A-overwrites-X*/} break; - case 340: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy211 = yymsp[0].minor.yy211; } + case 336: /* window_clause ::= WINDOW windowdefn_list */ +{ yymsp[-1].minor.yy483 = yymsp[0].minor.yy483; } break; - case 341: /* filter_over ::= filter_clause over_clause */ + case 337: /* filter_over ::= filter_clause over_clause */ { - if( yymsp[0].minor.yy211 ){ - yymsp[0].minor.yy211->pFilter = yymsp[-1].minor.yy454; + if( yymsp[0].minor.yy483 ){ + yymsp[0].minor.yy483->pFilter = yymsp[-1].minor.yy590; }else{ - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); } - yylhsminor.yy211 = yymsp[0].minor.yy211; + yylhsminor.yy483 = yymsp[0].minor.yy483; } - yymsp[-1].minor.yy211 = yylhsminor.yy211; + yymsp[-1].minor.yy483 = yylhsminor.yy483; break; - case 342: /* filter_over ::= over_clause */ + case 338: /* filter_over ::= over_clause */ { - yylhsminor.yy211 = yymsp[0].minor.yy211; + yylhsminor.yy483 = yymsp[0].minor.yy483; } - yymsp[0].minor.yy211 = yylhsminor.yy211; + yymsp[0].minor.yy483 = yylhsminor.yy483; break; - case 343: /* filter_over ::= filter_clause */ + case 339: /* filter_over ::= filter_clause */ { - yylhsminor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy211 ){ - yylhsminor.yy211->eFrmType = TK_FILTER; - yylhsminor.yy211->pFilter = yymsp[0].minor.yy454; + yylhsminor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yylhsminor.yy483 ){ + yylhsminor.yy483->eFrmType = TK_FILTER; + yylhsminor.yy483->pFilter = yymsp[0].minor.yy590; }else{ - sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy454); + sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy590); } } - yymsp[0].minor.yy211 = yylhsminor.yy211; + yymsp[0].minor.yy483 = yylhsminor.yy483; break; - case 344: /* over_clause ::= OVER LP window RP */ + case 340: /* over_clause ::= OVER LP window RP */ { - yymsp[-3].minor.yy211 = yymsp[-1].minor.yy211; - assert( yymsp[-3].minor.yy211!=0 ); + yymsp[-3].minor.yy483 = yymsp[-1].minor.yy483; + assert( yymsp[-3].minor.yy483!=0 ); } break; - case 345: /* over_clause ::= OVER nm */ + case 341: /* over_clause ::= OVER nm */ { - yymsp[-1].minor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yymsp[-1].minor.yy211 ){ - yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); + yymsp[-1].minor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yymsp[-1].minor.yy483 ){ + yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); } } break; - case 346: /* filter_clause ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy454 = yymsp[-1].minor.yy454; } + case 342: /* filter_clause ::= FILTER LP WHERE expr RP */ +{ yymsp[-4].minor.yy590 = yymsp[-1].minor.yy590; } break; - case 347: /* term ::= QNUMBER */ + case 343: /* term ::= QNUMBER */ { - yylhsminor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); - sqlite3DequoteNumber(pParse, yylhsminor.yy454); + yylhsminor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); + sqlite3DequoteNumber(pParse, yylhsminor.yy590); } - yymsp[0].minor.yy454 = yylhsminor.yy454; + yymsp[0].minor.yy590 = yylhsminor.yy590; break; default: - /* (348) input ::= cmdlist */ yytestcase(yyruleno==348); - /* (349) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==349); - /* (350) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=350); - /* (351) ecmd ::= SEMI */ yytestcase(yyruleno==351); - /* (352) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==352); - /* (353) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=353); - /* (354) trans_opt ::= */ yytestcase(yyruleno==354); - /* (355) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==355); - /* (356) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==356); - /* (357) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==357); - /* (358) savepoint_opt ::= */ yytestcase(yyruleno==358); - /* (359) cmd ::= create_table create_table_args */ yytestcase(yyruleno==359); - /* (360) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=360); - /* (361) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==361); - /* (362) columnlist ::= columnname carglist */ yytestcase(yyruleno==362); - /* (363) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==363); - /* (364) nm ::= STRING */ yytestcase(yyruleno==364); - /* (365) typetoken ::= typename */ yytestcase(yyruleno==365); - /* (366) typename ::= ID|STRING */ yytestcase(yyruleno==366); - /* (367) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=367); - /* (368) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=368); - /* (369) carglist ::= carglist ccons */ yytestcase(yyruleno==369); - /* (370) carglist ::= */ yytestcase(yyruleno==370); - /* (371) ccons ::= NULL onconf */ yytestcase(yyruleno==371); - /* (372) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==372); - /* (373) ccons ::= AS generated */ yytestcase(yyruleno==373); - /* (374) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==374); - /* (375) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==375); - /* (376) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=376); - /* (377) tconscomma ::= */ yytestcase(yyruleno==377); - /* (378) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=378); - /* (379) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=379); - /* (380) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=380); - /* (381) oneselect ::= values */ yytestcase(yyruleno==381); - /* (382) sclp ::= selcollist COMMA */ yytestcase(yyruleno==382); - /* (383) as ::= ID|STRING */ yytestcase(yyruleno==383); - /* (384) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=384); - /* (385) returning ::= */ yytestcase(yyruleno==385); - /* (386) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=386); - /* (387) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==387); - /* (388) case_operand ::= expr */ yytestcase(yyruleno==388); - /* (389) exprlist ::= nexprlist */ yytestcase(yyruleno==389); - /* (390) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=390); - /* (391) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=391); - /* (392) nmnum ::= ON */ yytestcase(yyruleno==392); - /* (393) nmnum ::= DELETE */ yytestcase(yyruleno==393); - /* (394) nmnum ::= DEFAULT */ yytestcase(yyruleno==394); - /* (395) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==395); - /* (396) foreach_clause ::= */ yytestcase(yyruleno==396); - /* (397) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==397); - /* (398) tridxby ::= */ yytestcase(yyruleno==398); - /* (399) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==399); - /* (400) database_kw_opt ::= */ yytestcase(yyruleno==400); - /* (401) kwcolumn_opt ::= */ yytestcase(yyruleno==401); - /* (402) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==402); - /* (403) vtabarglist ::= vtabarg */ yytestcase(yyruleno==403); - /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==404); - /* (405) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==405); - /* (406) anylist ::= */ yytestcase(yyruleno==406); - /* (407) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==407); - /* (408) anylist ::= anylist ANY */ yytestcase(yyruleno==408); - /* (409) with ::= */ yytestcase(yyruleno==409); - /* (410) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=410); - /* (411) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=411); + /* (344) input ::= cmdlist */ yytestcase(yyruleno==344); + /* (345) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==345); + /* (346) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=346); + /* (347) ecmd ::= SEMI */ yytestcase(yyruleno==347); + /* (348) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==348); + /* (349) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=349); + /* (350) trans_opt ::= */ yytestcase(yyruleno==350); + /* (351) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==351); + /* (352) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==352); + /* (353) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==353); + /* (354) savepoint_opt ::= */ yytestcase(yyruleno==354); + /* (355) cmd ::= create_table create_table_args */ yytestcase(yyruleno==355); + /* (356) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=356); + /* (357) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==357); + /* (358) columnlist ::= columnname carglist */ yytestcase(yyruleno==358); + /* (359) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==359); + /* (360) nm ::= STRING */ yytestcase(yyruleno==360); + /* (361) typetoken ::= typename */ yytestcase(yyruleno==361); + /* (362) typename ::= ID|STRING */ yytestcase(yyruleno==362); + /* (363) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=363); + /* (364) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=364); + /* (365) carglist ::= carglist ccons */ yytestcase(yyruleno==365); + /* (366) carglist ::= */ yytestcase(yyruleno==366); + /* (367) ccons ::= NULL onconf */ yytestcase(yyruleno==367); + /* (368) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==368); + /* (369) ccons ::= AS generated */ yytestcase(yyruleno==369); + /* (370) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==370); + /* (371) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==371); + /* (372) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=372); + /* (373) tconscomma ::= */ yytestcase(yyruleno==373); + /* (374) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=374); + /* (375) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=375); + /* (376) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=376); + /* (377) oneselect ::= values */ yytestcase(yyruleno==377); + /* (378) sclp ::= selcollist COMMA */ yytestcase(yyruleno==378); + /* (379) as ::= ID|STRING */ yytestcase(yyruleno==379); + /* (380) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=380); + /* (381) returning ::= */ yytestcase(yyruleno==381); + /* (382) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=382); + /* (383) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==383); + /* (384) case_operand ::= expr */ yytestcase(yyruleno==384); + /* (385) exprlist ::= nexprlist */ yytestcase(yyruleno==385); + /* (386) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=386); + /* (387) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=387); + /* (388) nmnum ::= ON */ yytestcase(yyruleno==388); + /* (389) nmnum ::= DELETE */ yytestcase(yyruleno==389); + /* (390) nmnum ::= DEFAULT */ yytestcase(yyruleno==390); + /* (391) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==391); + /* (392) foreach_clause ::= */ yytestcase(yyruleno==392); + /* (393) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==393); + /* (394) trnm ::= nm */ yytestcase(yyruleno==394); + /* (395) tridxby ::= */ yytestcase(yyruleno==395); + /* (396) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==396); + /* (397) database_kw_opt ::= */ yytestcase(yyruleno==397); + /* (398) kwcolumn_opt ::= */ yytestcase(yyruleno==398); + /* (399) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==399); + /* (400) vtabarglist ::= vtabarg */ yytestcase(yyruleno==400); + /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==401); + /* (402) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==402); + /* (403) anylist ::= */ yytestcase(yyruleno==403); + /* (404) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==404); + /* (405) anylist ::= anylist ANY */ yytestcase(yyruleno==405); + /* (406) with ::= */ yytestcase(yyruleno==406); + /* (407) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=407); + /* (408) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=408); break; /********** End reduce actions ************************************************/ }; @@ -184887,8 +183554,8 @@ static const unsigned char aKWCode[148] = {0, /* Check to see if z[0..n-1] is a keyword. If it is, write the ** parser symbol code for that keyword into *pType. Always ** return the integer n (the length of the token). */ -static i64 keywordCode(const char *z, i64 n, int *pType){ - i64 i, j; +static int keywordCode(const char *z, int n, int *pType){ + int i, j; const char *zKW; assert( n>=2 ); i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127; @@ -185442,7 +184109,7 @@ SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *z, int *tokenType){ } case CC_DOLLAR: case CC_VARALPHA: { - i64 n = 0; + int n = 0; testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' ); testcase( z[0]=='#' ); *tokenType = TK_VARIABLE; @@ -185538,7 +184205,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ - i64 mxSqlLen; /* Max length of an SQL string */ + int mxSqlLen; /* Max length of an SQL string */ Parse *pParentParse = 0; /* Outer parse context, if any */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ @@ -187194,14 +185861,6 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ rc = setupLookaside(db, pBuf, sz, cnt); break; } - case SQLITE_DBCONFIG_FP_DIGITS: { - int nIn = va_arg(ap, int); - int *pOut = va_arg(ap, int*); - if( nIn>3 && nIn<24 ) db->nFpDigit = (u8)nIn; - if( pOut ) *pOut = db->nFpDigit; - rc = SQLITE_OK; - break; - } default: { static const struct { int op; /* The opcode */ @@ -188757,9 +187416,6 @@ SQLITE_API void *sqlite3_wal_hook( sqlite3_mutex_leave(db->mutex); return pRet; #else - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(xCallback); - UNUSED_PARAMETER(pArg); return 0; #endif } @@ -188775,11 +187431,6 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( int *pnCkpt /* OUT: Total number of frames checkpointed */ ){ #ifdef SQLITE_OMIT_WAL - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(zDb); - UNUSED_PARAMETER(eMode); - UNUSED_PARAMETER(pnLog); - UNUSED_PARAMETER(pnCkpt); return SQLITE_OK; #else int rc; /* Return code */ @@ -188793,12 +187444,11 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( if( pnLog ) *pnLog = -1; if( pnCkpt ) *pnCkpt = -1; - assert( SQLITE_CHECKPOINT_NOOP==-1 ); assert( SQLITE_CHECKPOINT_PASSIVE==0 ); assert( SQLITE_CHECKPOINT_FULL==1 ); assert( SQLITE_CHECKPOINT_RESTART==2 ); assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); - if( eMode<SQLITE_CHECKPOINT_NOOP || eMode>SQLITE_CHECKPOINT_TRUNCATE ){ + if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_TRUNCATE ){ /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint ** mode: */ return SQLITE_MISUSE_BKPT; @@ -189162,7 +187812,6 @@ static const int aHardLimit[] = { SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */ SQLITE_MAX_TRIGGER_DEPTH, SQLITE_MAX_WORKER_THREADS, - SQLITE_MAX_PARSER_DEPTH, }; /* @@ -189177,9 +187826,6 @@ static const int aHardLimit[] = { #if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH # error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH #endif -#if SQLITE_MAX_SQL_LENGTH>2147482624 /* 1024 less than 2^31 */ -# error SQLITE_MAX_SQL_LENGTH must not be greater than 2147482624 -#endif #if SQLITE_MAX_COMPOUND_SELECT<2 # error SQLITE_MAX_COMPOUND_SELECT must be at least 2 #endif @@ -189235,7 +187881,6 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH ); assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN ); assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH ); - assert( aHardLimit[SQLITE_LIMIT_PARSER_DEPTH]==SQLITE_MAX_PARSER_DEPTH ); assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT); assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP ); assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG ); @@ -189245,7 +187890,7 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS ); - assert( SQLITE_LIMIT_PARSER_DEPTH==(SQLITE_N_LIMIT-1) ); + assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) ); if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ @@ -189609,7 +188254,7 @@ static int openDatabase( db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; if( isThreadsafe -#if defined(SQLITE_THREAD_MISUSE_WARNINGS) +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS || sqlite3GlobalConfig.bCoreMutex #endif ){ @@ -189630,7 +188275,6 @@ static int openDatabase( db->aDb = db->aDbStatic; db->lookaside.bDisable = 1; db->lookaside.sz = 0; - db->nFpDigit = 17; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); @@ -190076,12 +188720,6 @@ SQLITE_API int sqlite3_collation_needed16( */ SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){ DbClientData *p; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zName || !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); for(p=db->pDbData; p; p=p->pNext){ if( strcmp(p->zName, zName)==0 ){ @@ -191155,7 +189793,6 @@ SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){ } SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){ #ifdef SQLITE_OMIT_WAL - UNUSED_PARAMETER(zFilename); return 0; #else zFilename = sqlite3_filename_journal(zFilename); @@ -192927,15 +191564,6 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \ ) -SQLITE_PRIVATE int sqlite3Fts3PrepareStmt( - Fts3Table *p, /* Prepare for this connection */ - const char *zSql, /* SQL to prepare */ - int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */ - int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */ - sqlite3_stmt **pp /* OUT: Prepared statement */ -); - - /* fts3.c */ SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...); SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); @@ -194543,7 +193171,9 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); if( !zSql ) return SQLITE_NOMEM; p->bLock++; - rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt); + rc = sqlite3_prepare_v3( + p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 + ); p->bLock--; sqlite3_free(zSql); } @@ -196118,7 +194748,9 @@ static int fts3FilterMethod( } if( zSql ){ p->bLock++; - rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt); + rc = sqlite3_prepare_v3( + p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 + ); p->bLock--; sqlite3_free(zSql); }else{ @@ -196741,7 +195373,6 @@ static int fts3IntegrityMethod( UNUSED_PARAMETER(isQuick); rc = sqlite3Fts3IntegrityCheck(p, &bOk); - assert( pVtab->zErrMsg==0 || rc!=SQLITE_OK ); assert( rc!=SQLITE_CORRUPT_VTAB ); if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){ *pzErr = sqlite3_mprintf("unable to validate the inverted index for" @@ -203179,9 +201810,9 @@ typedef struct SegmentWriter SegmentWriter; ** incrementally. See function fts3PendingListAppend() for details. */ struct PendingList { - sqlite3_int64 nData; + int nData; char *aData; - sqlite3_int64 nSpace; + int nSpace; sqlite3_int64 iLastDocid; sqlite3_int64 iLastCol; sqlite3_int64 iLastPos; @@ -203354,24 +201985,6 @@ struct SegmentNode { #define SQL_UPDATE_LEVEL_IDX 38 #define SQL_UPDATE_LEVEL 39 -/* -** Wrapper around sqlite3_prepare_v3() to ensure that SQLITE_PREPARE_FROM_DDL -** is always set. -*/ -SQLITE_PRIVATE int sqlite3Fts3PrepareStmt( - Fts3Table *p, /* Prepare for this connection */ - const char *zSql, /* SQL to prepare */ - int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */ - int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */ - sqlite3_stmt **pp /* OUT: Prepared statement */ -){ - int f = SQLITE_PREPARE_FROM_DDL - |((bAllowVtab==0) ? SQLITE_PREPARE_NO_VTAB : 0) - |(bPersist ? SQLITE_PREPARE_PERSISTENT : 0); - - return sqlite3_prepare_v3(p->db, zSql, -1, f, pp, NULL); -} - /* ** This function is used to obtain an SQLite prepared statement handle ** for the statement identified by the second argument. If successful, @@ -203497,12 +202110,12 @@ static int fts3SqlStmt( pStmt = p->aStmt[eStmt]; if( !pStmt ){ - int bAllowVtab = 0; + int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB; char *zSql; if( eStmt==SQL_CONTENT_INSERT ){ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist); }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){ - bAllowVtab = 1; + f &= ~SQLITE_PREPARE_NO_VTAB; zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist); }else{ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName); @@ -203510,7 +202123,7 @@ static int fts3SqlStmt( if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3Fts3PrepareStmt(p, zSql, 1, bAllowVtab, &pStmt); + rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL); sqlite3_free(zSql); assert( rc==SQLITE_OK || pStmt==0 ); p->aStmt[eStmt] = pStmt; @@ -203859,9 +202472,7 @@ static int fts3PendingTermsAddOne( pList = (PendingList *)fts3HashFind(pHash, zToken, nToken); if( pList ){ - assert( (i64)pList->nData+(i64)nToken+(i64)sizeof(Fts3HashElem) - <= (i64)p->nPendingData ); - p->nPendingData -= (int)(pList->nData + nToken + sizeof(Fts3HashElem)); + p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem)); } if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){ if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){ @@ -203874,9 +202485,7 @@ static int fts3PendingTermsAddOne( } } if( rc==SQLITE_OK ){ - assert( (i64)p->nPendingData + pList->nData + nToken - + sizeof(Fts3HashElem) <= 0x3fffffff ); - p->nPendingData += (int)(pList->nData + nToken + sizeof(Fts3HashElem)); + p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); } return rc; } @@ -206677,7 +205286,7 @@ static int fts3DoRebuild(Fts3Table *p){ if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); } @@ -208430,7 +207039,7 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){ if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); } @@ -208560,7 +207169,7 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ v = atoi(&zVal[9]); if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v; rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 11) ){ + }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ v = atoi(&zVal[11]); if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v; rc = SQLITE_OK; @@ -211835,10 +210444,7 @@ struct JsonString { #define JSON_SQL 0x02 /* Result is always SQL */ #define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */ #define JSON_ISSET 0x04 /* json_set(), not json_insert() */ -#define JSON_AINS 0x08 /* json_array_insert(), not json_insert() */ -#define JSON_BLOB 0x10 /* Use the BLOB output format */ - -#define JSON_INSERT_TYPE(X) (((X)&0xC)>>2) +#define JSON_BLOB 0x08 /* Use the BLOB output format */ /* A parsed JSON value. Lifecycle: @@ -211884,7 +210490,6 @@ struct JsonParse { #define JEDIT_REPL 2 /* Overwrite if exists */ #define JEDIT_INS 3 /* Insert if not exists */ #define JEDIT_SET 4 /* Insert or overwrite */ -#define JEDIT_AINS 5 /* array_insert() */ /* ** Maximum nesting depth of JSON for this implementation. @@ -214381,8 +212986,7 @@ static int jsonLabelCompare( */ #define JSON_LOOKUP_ERROR 0xffffffff #define JSON_LOOKUP_NOTFOUND 0xfffffffe -#define JSON_LOOKUP_NOTARRAY 0xfffffffd -#define JSON_LOOKUP_PATHERROR 0xfffffffc +#define JSON_LOOKUP_PATHERROR 0xfffffffd #define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR) /* Forward declaration */ @@ -214411,7 +213015,7 @@ static u32 jsonLookupStep(JsonParse*,u32,const char*,u32); static u32 jsonCreateEditSubstructure( JsonParse *pParse, /* The original JSONB that is being edited */ JsonParse *pIns, /* Populate this with the blob data to insert */ - const char *zTail /* Tail of the path that determines substructure */ + const char *zTail /* Tail of the path that determins substructure */ ){ static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT }; int rc; @@ -214446,9 +213050,9 @@ static u32 jsonCreateEditSubstructure( ** Return one of the JSON_LOOKUP error codes if problems are seen. ** ** This routine will also modify the blob. If pParse->eEdit is one of -** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, JEDIT_SET, or JEDIT_AINS, then changes -** might be made to the selected value. If an edit is performed, then the -** return value does not necessarily point to the select element. If an edit +** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be +** made to the selected value. If an edit is performed, then the return +** value does not necessarily point to the select element. If an edit ** is performed, the return value is only useful for detecting error ** conditions. */ @@ -214474,13 +213078,6 @@ static u32 jsonLookupStep( jsonBlobEdit(pParse, iRoot, sz, 0, 0); }else if( pParse->eEdit==JEDIT_INS ){ /* Already exists, so json_insert() is a no-op */ - }else if( pParse->eEdit==JEDIT_AINS ){ - /* json_array_insert() */ - if( zPath[-1]!=']' ){ - return JSON_LOOKUP_NOTARRAY; - }else{ - jsonBlobEdit(pParse, iRoot, 0, pParse->aIns, pParse->nIns); - } }else{ /* json_set() or json_replace() */ jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns); @@ -214552,10 +213149,6 @@ static u32 jsonLookupStep( JsonParse ix; /* Header of the label to be inserted */ testcase( pParse->eEdit==JEDIT_INS ); testcase( pParse->eEdit==JEDIT_SET ); - testcase( pParse->eEdit==JEDIT_AINS ); - if( pParse->eEdit==JEDIT_AINS && sqlite3_strglob("*]",&zPath[i])!=0 ){ - return JSON_LOOKUP_NOTARRAY; - } memset(&ix, 0, sizeof(ix)); ix.db = pParse->db; jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0); @@ -214583,32 +213176,28 @@ static u32 jsonLookupStep( return rc; } }else if( zPath[0]=='[' ){ - u64 kk = 0; x = pParse->aBlob[iRoot] & 0x0f; if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND; n = jsonbPayloadSize(pParse, iRoot, &sz); + k = 0; i = 1; while( sqlite3Isdigit(zPath[i]) ){ - if( kk<0xffffffff ) kk = kk*10 + zPath[i] - '0'; - /* ^^^^^^^^^^--- Allow kk to be bigger than any JSON array so that - ** we get NOTFOUND instead of PATHERROR, without overflowing kk. */ + k = k*10 + zPath[i] - '0'; i++; } if( i<2 || zPath[i]!=']' ){ if( zPath[1]=='#' ){ - kk = jsonbArrayCount(pParse, iRoot); + k = jsonbArrayCount(pParse, iRoot); i = 2; if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){ - u64 nn = 0; + unsigned int nn = 0; i = 3; do{ - if( nn<0xffffffff ) nn = nn*10 + zPath[i] - '0'; - /* ^^^^^^^^^^--- Allow nn to be bigger than any JSON array to - ** get NOTFOUND instead of PATHERROR, without overflowing nn. */ + nn = nn*10 + zPath[i] - '0'; i++; }while( sqlite3Isdigit(zPath[i]) ); - if( nn>kk ) return JSON_LOOKUP_NOTFOUND; - kk -= nn; + if( nn>k ) return JSON_LOOKUP_NOTFOUND; + k -= nn; } if( zPath[i]!=']' ){ return JSON_LOOKUP_PATHERROR; @@ -214620,22 +213209,21 @@ static u32 jsonLookupStep( j = iRoot+n; iEnd = j+sz; while( j<iEnd ){ - if( kk==0 ){ + if( k==0 ){ rc = jsonLookupStep(pParse, j, &zPath[i+1], 0); if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); return rc; } - kk--; + k--; n = jsonbPayloadSize(pParse, j, &sz); if( n==0 ) return JSON_LOOKUP_ERROR; j += n+sz; } if( j>iEnd ) return JSON_LOOKUP_ERROR; - if( kk>0 ) return JSON_LOOKUP_NOTFOUND; + if( k>0 ) return JSON_LOOKUP_NOTFOUND; if( pParse->eEdit>=JEDIT_INS ){ JsonParse v; testcase( pParse->eEdit==JEDIT_INS ); - testcase( pParse->eEdit==JEDIT_AINS ); testcase( pParse->eEdit==JEDIT_SET ); rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]); if( !JSON_LOOKUP_ISERROR(rc) @@ -214773,7 +213361,7 @@ static void jsonReturnFromBlob( to_double: z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); if( z==0 ) goto returnfromblob_oom; - rc = sqlite3AtoF(z, &r); + rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); sqlite3DbFree(db, z); if( rc<=0 ) goto returnfromblob_malformed; sqlite3_result_double(pCtx, r); @@ -214960,15 +213548,9 @@ static int jsonFunctionArgToBlob( */ static char *jsonBadPathError( sqlite3_context *ctx, /* The function call containing the error */ - const char *zPath, /* The path with the problem */ - int rc /* Maybe JSON_LOOKUP_NOTARRAY */ + const char *zPath /* The path with the problem */ ){ - char *zMsg; - if( rc==(int)JSON_LOOKUP_NOTARRAY ){ - zMsg = sqlite3_mprintf("not an array element: %Q", zPath); - }else{ - zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath); - } + char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath); if( ctx==0 ) return zMsg; if( zMsg ){ sqlite3_result_error(ctx, zMsg, -1); @@ -214985,13 +213567,13 @@ static char *jsonBadPathError( ** and return the result. ** ** The specific operation is determined by eEdit, which can be one -** of JEDIT_INS, JEDIT_REPL, JEDIT_SET, or JEDIT_AINS. +** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET. */ static void jsonInsertIntoBlob( sqlite3_context *ctx, int argc, sqlite3_value **argv, - int eEdit /* JEDIT_INS, JEDIT_REPL, JEDIT_SET, JEDIT_AINS */ + int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */ ){ int i; u32 rc = 0; @@ -215043,7 +213625,7 @@ static void jsonInsertIntoBlob( if( rc==JSON_LOOKUP_ERROR ){ sqlite3_result_error(ctx, "malformed JSON", -1); }else{ - jsonBadPathError(ctx, zPath, rc); + jsonBadPathError(ctx, zPath); } return; } @@ -215485,7 +214067,7 @@ static void jsonArrayLengthFunc( if( i==JSON_LOOKUP_NOTFOUND ){ /* no-op */ }else if( i==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); }else{ sqlite3_result_error(ctx, "malformed JSON", -1); } @@ -215590,7 +214172,7 @@ static void jsonExtractFunc( j = jsonLookupStep(p, 0, jx.zBuf, 0); jsonStringReset(&jx); }else{ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); goto json_extract_error; } if( j<p->nBlob ){ @@ -215625,7 +214207,7 @@ static void jsonExtractFunc( sqlite3_result_error(ctx, "malformed JSON", -1); goto json_extract_error; }else{ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); goto json_extract_error; } } @@ -215954,7 +214536,7 @@ static void jsonRemoveFunc( if( rc==JSON_LOOKUP_NOTFOUND ){ continue; /* No-op */ }else if( rc==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath, rc); + jsonBadPathError(ctx, zPath); }else{ sqlite3_result_error(ctx, "malformed JSON", -1); } @@ -215966,7 +214548,7 @@ static void jsonRemoveFunc( return; json_remove_patherror: - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); json_remove_done: jsonParseFree(p); @@ -216010,18 +214592,16 @@ static void jsonSetFunc( int argc, sqlite3_value **argv ){ + int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - int eInsType = JSON_INSERT_TYPE(flags); - static const char *azInsType[] = { "insert", "set", "array_insert" }; - static const u8 aEditType[] = { JEDIT_INS, JEDIT_SET, JEDIT_AINS }; + int bIsSet = (flags&JSON_ISSET)!=0; if( argc<1 ) return; - assert( eInsType>=0 && eInsType<=2 ); if( (argc&1)==0 ) { - jsonWrongNumArgs(ctx, azInsType[eInsType]); + jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); return; } - jsonInsertIntoBlob(ctx, argc, argv, aEditType[eInsType]); + jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS); } /* @@ -216046,7 +214626,7 @@ static void jsonTypeFunc( zPath = (const char*)sqlite3_value_text(argv[1]); if( zPath==0 ) goto json_type_done; if( zPath[0]!='$' ){ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); goto json_type_done; } i = jsonLookupStep(p, 0, zPath+1, 0); @@ -216054,7 +214634,7 @@ static void jsonTypeFunc( if( i==JSON_LOOKUP_NOTFOUND ){ /* no-op */ }else if( i==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); }else{ sqlite3_result_error(ctx, "malformed JSON", -1); } @@ -216310,11 +214890,12 @@ static void jsonArrayStep( } static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ JsonString *pStr; - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ + int flags; pStr->pCtx = ctx; jsonAppendChar(pStr, ']'); + flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); if( pStr->eErr ){ jsonReturnString(pStr, 0, 0); return; @@ -216335,9 +214916,6 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); jsonStringTrimOneChar(pStr); } - }else if( flags & JSON_BLOB ){ - static const u8 emptyArray = 0x0b; - sqlite3_result_blob(ctx, &emptyArray, 1, SQLITE_STATIC); }else{ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); } @@ -216434,11 +215012,12 @@ static void jsonObjectStep( } static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ JsonString *pStr; - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ + int flags; jsonAppendChar(pStr, '}'); pStr->pCtx = ctx; + flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); if( pStr->eErr ){ jsonReturnString(pStr, 0, 0); return; @@ -216459,9 +215038,6 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); jsonStringTrimOneChar(pStr); } - }else if( flags & JSON_BLOB ){ - static const unsigned char emptyObject = 0x0c; - sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC); }else{ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); } @@ -216962,7 +215538,7 @@ static int jsonEachFilter( if( zRoot==0 ) return SQLITE_OK; if( zRoot[0]!='$' ){ sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0); + cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); jsonEachCursorReset(p); return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; } @@ -216980,7 +215556,7 @@ static int jsonEachFilter( return SQLITE_OK; } sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0); + cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); jsonEachCursorReset(p); return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; } @@ -217070,8 +215646,6 @@ SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc), JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc), JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc), - JFUNCTION(json_array_insert, -1,1,1, 1,0,JSON_AINS, jsonSetFunc), - JFUNCTION(jsonb_array_insert,-1,1,0, 1,1,JSON_AINS, jsonSetFunc), JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc), JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc), JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc), @@ -221652,7 +220226,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ /* The sqlite3AtoF() routine is much much faster than atof(), if it ** is available */ double r; - (void)sqlite3AtoF((const char*)p->z, &r); + (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); *pVal = r; #else *pVal = (GeoCoord)atof((const char*)p->z); @@ -225591,7 +224165,7 @@ static int rbuDeltaApply( /* ERROR: copy exceeds output file size */ return -1; } - if( (u64)ofst+(u64)cnt > (u64)lenSrc ){ + if( (int)(ofst+cnt) > lenSrc ){ /* ERROR: copy extends past end of input */ return -1; } @@ -227237,8 +225811,8 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ /* If necessary, grow the pIter->aIdxCol[] array */ if( iIdxCol==nIdxAlloc ){ - RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc64( - pIter->aIdxCol, nIdxAlloc*sizeof(RbuSpan) + 16*sizeof(RbuSpan) + RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc( + pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan) ); if( aIdxCol==0 ){ rc = SQLITE_NOMEM; @@ -231911,7 +230485,6 @@ struct carray_bind { int nData; /* Number of elements */ int mFlags; /* Control flags */ void (*xDel)(void*); /* Destructor for aData */ - void *pDel; /* Alternative argument to xDel() */ }; @@ -232244,7 +230817,7 @@ static sqlite3_module carrayModule = { static void carrayBindDel(void *pPtr){ carray_bind *p = (carray_bind*)pPtr; if( p->xDel!=SQLITE_STATIC ){ - p->xDel(p->pDel); + p->xDel(p->aData); } sqlite3_free(p); } @@ -232252,26 +230825,14 @@ static void carrayBindDel(void *pPtr){ /* ** Invoke this interface in order to bind to the single-argument ** version of CARRAY(). -** -** pStmt The prepared statement to which to bind -** idx The index of the parameter of pStmt to which to bind -** aData The data to be bound -** nData The number of elements in aData -** mFlags One of SQLITE_CARRAY_xxxx indicating datatype of aData -** xDestroy Destructor for pDestroy or aData if pDestroy==NULL. -** pDestroy Invoke xDestroy on this pointer if not NULL -** -** The destructor is called pDestroy if pDestroy!=NULL, or against -** aData if pDestroy==NULL. */ -SQLITE_API int sqlite3_carray_bind_v2( +SQLITE_API int sqlite3_carray_bind( sqlite3_stmt *pStmt, int idx, void *aData, int nData, int mFlags, - void (*xDestroy)(void*), - void *pDestroy + void (*xDestroy)(void*) ){ carray_bind *pNew = 0; int i; @@ -232348,38 +230909,20 @@ SQLITE_API int sqlite3_carray_bind_v2( memcpy(pNew->aData, aData, sz); } pNew->xDel = sqlite3_free; - pNew->pDel = pNew->aData; }else{ pNew->aData = aData; pNew->xDel = xDestroy; - pNew->pDel = pDestroy; } return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel); carray_bind_error: if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){ - xDestroy(pDestroy); + xDestroy(aData); } sqlite3_free(pNew); return rc; } -/* -** Invoke this interface in order to bind to the single-argument -** version of CARRAY(). Same as sqlite3_carray_bind_v2() with the -** pDestroy parameter set to NULL. -*/ -SQLITE_API int sqlite3_carray_bind( - sqlite3_stmt *pStmt, - int idx, - void *aData, - int nData, - int mFlags, - void (*xDestroy)(void*) -){ - return sqlite3_carray_bind_v2(pStmt,idx,aData,nData,mFlags,xDestroy,aData); -} - /* ** Invoke this routine to register the carray() function. */ @@ -232742,20 +231285,6 @@ static int sessionVarintGet(const u8 *aBuf, int *piVal){ return getVarint32(aBuf, *piVal); } -/* -** Read a varint value from buffer aBuf[], size nBuf bytes, into *piVal. -** Return the number of bytes read. -*/ -static int sessionVarintGetSafe(const u8 *aBuf, int nBuf, int *piVal){ - u8 aCopy[5]; - const u8 *aRead = aBuf; - if( nBuf<5 ){ - memcpy(aCopy, aBuf, nBuf); - aRead = aCopy; - } - return getVarint32(aRead, *piVal); -} - /* Load an unaligned and unsigned 32-bit integer */ #define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) @@ -233050,10 +231579,14 @@ static unsigned int sessionChangeHash( int isPK = pTab->abPK[i]; if( bPkOnly && isPK==0 ) continue; + /* It is not possible for eType to be SQLITE_NULL here. The session + ** module does not record changes for rows with NULL values stored in + ** primary key columns. */ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT || eType==SQLITE_TEXT || eType==SQLITE_BLOB || eType==SQLITE_NULL || eType==0 ); + assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) ); if( isPK ){ a++; @@ -233061,16 +231594,12 @@ static unsigned int sessionChangeHash( if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ h = sessionHashAppendI64(h, sessionGetI64(a)); a += 8; - }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + }else{ int n; a += sessionVarintGet(a, &n); h = sessionHashAppendBlob(h, n, a); a += n; } - /* It should not be possible for eType to be SQLITE_NULL or 0x00 here, - ** as the session module does not record changes for rows with NULL - ** values stored in primary key columns. But a corrupt changesets - ** may contain such a value. */ }else{ a += sessionSerialLen(a); } @@ -235479,13 +234008,10 @@ static int sessionGenerateChangeset( } if( pSession->rc ) return pSession->rc; + rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); + if( rc!=SQLITE_OK ) return rc; sqlite3_mutex_enter(sqlite3_db_mutex(db)); - rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); - if( rc!=SQLITE_OK ){ - sqlite3_mutex_leave(sqlite3_db_mutex(db)); - return rc; - } for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ @@ -235968,8 +234494,7 @@ static int sessionReadRecord( u8 *aVal = &pIn->aData[pIn->iNext]; if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ int nByte; - int nRem = pIn->nData - pIn->iNext; - pIn->iNext += sessionVarintGetSafe(aVal, nRem, &nByte); + pIn->iNext += sessionVarintGet(aVal, &nByte); rc = sessionInputBuffer(pIn, nByte); if( rc==SQLITE_OK ){ if( nByte<0 || nByte>pIn->nData-pIn->iNext ){ @@ -236022,8 +234547,7 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ - int nBuf = pIn->nData - pIn->iNext; - nRead += sessionVarintGetSafe(&pIn->aData[pIn->iNext], nBuf, &nCol); + nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); /* The hard upper limit for the number of columns in an SQLite ** database table is, according to sqliteLimit.h, 32676. So ** consider any table-header that purports to have more than 65536 @@ -236043,15 +234567,8 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){ nRead++; } - - /* Break out of the loop if if the nul-terminator byte has been found. - ** Otherwise, read some more input data and keep seeking. If there is - ** no more input data, consider the changeset corrupt. */ if( (pIn->iNext + nRead)<pIn->nData ) break; rc = sessionInputBuffer(pIn, nRead + 100); - if( rc==SQLITE_OK && (pIn->iNext + nRead)>=pIn->nData ){ - rc = SQLITE_CORRUPT_BKPT; - } } *pnByte = nRead+1; return rc; @@ -236183,10 +234700,10 @@ static int sessionChangesetNextOne( memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); } - /* Make sure the buffer contains at least 2 bytes of input data, or all - ** remaining data if there are less than 2 bytes available. This is - ** sufficient either for the 'T' or 'P' byte that begins a new table, - ** or for the "op" and "bIndirect" single bytes otherwise. */ + /* Make sure the buffer contains at least 10 bytes of input data, or all + ** remaining data if there are less than 10 bytes available. This is + ** sufficient either for the 'T' or 'P' byte and the varint that follows + ** it, or for the two single byte values otherwise. */ p->rc = sessionInputBuffer(&p->in, 2); if( p->rc!=SQLITE_OK ) return p->rc; @@ -236216,13 +234733,11 @@ static int sessionChangesetNextOne( return (p->rc = SQLITE_CORRUPT_BKPT); } - if( (op!=SQLITE_UPDATE && op!=SQLITE_DELETE && op!=SQLITE_INSERT) - || (p->in.iNext>=p->in.nData) - ){ - return (p->rc = SQLITE_CORRUPT_BKPT); - } p->op = op; p->bIndirect = p->in.aData[p->in.iNext++]; + if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ + return (p->rc = SQLITE_CORRUPT_BKPT); + } if( paRec ){ int nVal; /* Number of values to buffer */ @@ -241110,22 +239625,14 @@ typedef union { #define sqlite3Fts5ParserARG_PARAM ,pParse #define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse; #define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse; -#undef fts5YYREALLOC #define fts5YYREALLOC realloc -#undef fts5YYFREE #define fts5YYFREE free -#undef fts5YYDYNSTACK #define fts5YYDYNSTACK 0 -#undef fts5YYSIZELIMIT -#define sqlite3Fts5ParserCTX(P) 0 #define sqlite3Fts5ParserCTX_SDECL #define sqlite3Fts5ParserCTX_PDECL #define sqlite3Fts5ParserCTX_PARAM #define sqlite3Fts5ParserCTX_FETCH #define sqlite3Fts5ParserCTX_STORE -#undef fts5YYERRORSYMBOL -#undef fts5YYERRSYMDT -#undef fts5YYFALLBACK #define fts5YYNSTATE 35 #define fts5YYNRULE 28 #define fts5YYNRULE_WITH_ACTION 28 @@ -241450,24 +239957,15 @@ static int fts5yyGrowStack(fts5yyParser *p){ int newSize; int idx; fts5yyStackEntry *pNew; -#ifdef fts5YYSIZELIMIT - int nLimit = fts5YYSIZELIMIT(sqlite3Fts5ParserCTX(p)); -#endif newSize = oldSize*2 + 100; -#ifdef fts5YYSIZELIMIT - if( newSize>nLimit ){ - newSize = nLimit; - if( newSize<=oldSize ) return 1; - } -#endif idx = (int)(p->fts5yytos - p->fts5yystack); if( p->fts5yystack==p->fts5yystk0 ){ - pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0]), sqlite3Fts5ParserCTX(p)); + pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; memcpy(pNew, p->fts5yystack, oldSize*sizeof(pNew[0])); }else{ - pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0]), sqlite3Fts5ParserCTX(p)); + pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; } p->fts5yystack = pNew; @@ -241647,9 +240145,7 @@ static void sqlite3Fts5ParserFinalize(void *p){ } #if fts5YYGROWABLESTACK - if( pParser->fts5yystack!=pParser->fts5yystk0 ){ - fts5YYFREE(pParser->fts5yystack, sqlite3Fts5ParserCTX(pParser)); - } + if( pParser->fts5yystack!=pParser->fts5yystk0 ) fts5YYFREE(pParser->fts5yystack); #endif } @@ -242931,7 +241427,7 @@ static void fts5SnippetFunction( iBestCol = (iCol>=0 ? iCol : 0); nPhrase = pApi->xPhraseCount(pFts); - aSeen = sqlite3_malloc64(nPhrase); + aSeen = sqlite3_malloc(nPhrase); if( aSeen==0 ){ rc = SQLITE_NOMEM; } @@ -243586,7 +242082,7 @@ static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){ if( nIn<0 ){ nIn = (int)strlen(pIn); } - zRet = (char*)sqlite3_malloc64((i64)nIn+1); + zRet = (char*)sqlite3_malloc(nIn+1); if( zRet ){ memcpy(zRet, pIn, nIn); zRet[nIn] = '\0'; @@ -244286,7 +242782,7 @@ static int sqlite3Fts5ConfigParse( sqlite3_int64 nByte; int bUnindexed = 0; /* True if there are one or more UNINDEXED */ - *ppOut = pRet = (Fts5Config*)sqlite3_malloc64(sizeof(Fts5Config)); + *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config)); if( pRet==0 ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(Fts5Config)); pRet->pGlobal = pGlobal; @@ -244834,6 +243330,8 @@ static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){ va_end(ap); } + + /* ** 2014 May 31 ** @@ -245150,7 +243648,7 @@ static int sqlite3Fts5ExprNew( assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 ); if( sParse.rc==SQLITE_OK ){ - *ppNew = pNew = sqlite3_malloc64(sizeof(Fts5Expr)); + *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); if( pNew==0 ){ sParse.rc = SQLITE_NOMEM; sqlite3Fts5ParseNodeFree(sParse.pExpr); @@ -245302,7 +243800,7 @@ static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ p2->pRoot = 0; if( sParse.rc==SQLITE_OK ){ - Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc64( + Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc( p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*) ); if( ap==0 ){ @@ -248214,7 +246712,7 @@ static int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte int rc = SQLITE_OK; Fts5Hash *pNew; - *ppNew = pNew = (Fts5Hash*)sqlite3_malloc64(sizeof(Fts5Hash)); + *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash)); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -250807,7 +249305,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){ /* If necessary, grow the pIter->aRowidOffset[] array. */ if( iRowidOffset>=pIter->nRowidOffset ){ - i64 nNew = pIter->nRowidOffset + 8; + int nNew = pIter->nRowidOffset + 8; int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int)); if( aNew==0 ){ p->rc = SQLITE_NOMEM; @@ -253954,7 +252452,7 @@ static void fts5DoSecureDelete( int iSegid = pSeg->pSeg->iSegid; u8 *aPg = pSeg->pLeaf->p; int nPg = pSeg->pLeaf->nn; - int iPgIdx = pSeg->pLeaf->szLeaf; /* Offset of page footer */ + int iPgIdx = pSeg->pLeaf->szLeaf; u64 iDelta = 0; int iNextOff = 0; @@ -254033,7 +252531,7 @@ static void fts5DoSecureDelete( iSOP += fts5GetVarint32(&aPg[iSOP], nPos); } assert_nc( iSOP==pSeg->iLeafOffset ); - iNextOff = iSOP + pSeg->nPos; + iNextOff = pSeg->iLeafOffset + pSeg->nPos; } } @@ -254113,31 +252611,31 @@ static void fts5DoSecureDelete( ** is another term following it on this page. So the subsequent term ** needs to be moved to replace the term associated with the entry ** being removed. */ - u64 nPrefix = 0; - u64 nSuffix = 0; - u64 nPrefix2 = 0; - u64 nSuffix2 = 0; + int nPrefix = 0; + int nSuffix = 0; + int nPrefix2 = 0; + int nSuffix2 = 0; iDelKeyOff = iNextOff; - iNextOff += fts5GetVarint(&aPg[iNextOff], &nPrefix2); - iNextOff += fts5GetVarint(&aPg[iNextOff], &nSuffix2); + iNextOff += fts5GetVarint32(&aPg[iNextOff], nPrefix2); + iNextOff += fts5GetVarint32(&aPg[iNextOff], nSuffix2); if( iKey!=1 ){ - iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nPrefix); + iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nPrefix); } - iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nSuffix); + iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix); nPrefix = MIN(nPrefix, nPrefix2); nSuffix = (nPrefix2 + nSuffix2) - nPrefix; - if( (iKeyOff+nSuffix)>(u64)iPgIdx || (iNextOff+nSuffix2)>(u64)iPgIdx ){ + if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ FTS5_CORRUPT_IDX(p); }else{ if( iKey!=1 ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); - if( nPrefix2>(u64)pSeg->term.n ){ + if( nPrefix2>pSeg->term.n ){ FTS5_CORRUPT_IDX(p); }else if( nPrefix2>nPrefix ){ memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); @@ -254168,7 +252666,7 @@ static void fts5DoSecureDelete( u8 *aTermIdx = &pTerm->p[pTerm->szLeaf]; int nTermIdx = pTerm->nn - pTerm->szLeaf; int iTermIdx = 0; - i64 iTermOff = 0; + int iTermOff = 0; while( 1 ){ u32 iVal = 0; @@ -254179,15 +252677,12 @@ static void fts5DoSecureDelete( } nTermIdx = iTermIdx; - if( iTermOff>pTerm->szLeaf ){ - FTS5_CORRUPT_IDX(p); - }else{ - memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx); - fts5PutU16(&pTerm->p[2], iTermOff); - fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx); - if( nTermIdx==0 ){ - fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno); - } + memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx); + fts5PutU16(&pTerm->p[2], iTermOff); + + fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx); + if( nTermIdx==0 ){ + fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno); } } fts5DataRelease(pTerm); @@ -254210,9 +252705,7 @@ static void fts5DoSecureDelete( int iPrevKeyOut = 0; int iKeyIn = 0; - if( nMove>0 ){ - memmove(&aPg[iOff], &aPg[iNextOff], nMove); - } + memmove(&aPg[iOff], &aPg[iNextOff], nMove); iPgIdx -= nShift; nPg = iPgIdx; fts5PutU16(&aPg[2], iPgIdx); @@ -255132,16 +253625,16 @@ struct Fts5TokenDataMap { ** aMap[] variables. */ struct Fts5TokenDataIter { - i64 nMapAlloc; /* Allocated size of aMap[] in entries */ - i64 nMap; /* Number of valid entries in aMap[] */ + int nMapAlloc; /* Allocated size of aMap[] in entries */ + int nMap; /* Number of valid entries in aMap[] */ Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */ /* The following are used for prefix-queries only. */ Fts5Buffer terms; /* The following are used for other full-token tokendata queries only. */ - i64 nIter; - i64 nIterAlloc; + int nIter; + int nIterAlloc; Fts5PoslistReader *aPoslistReader; int *aPoslistToIter; Fts5Iter *apIter[FLEXARRAY]; @@ -255197,11 +253690,11 @@ static void fts5TokendataIterAppendMap( ){ if( p->rc==SQLITE_OK ){ if( pT->nMap==pT->nMapAlloc ){ - i64 nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64; - i64 nAlloc = nNew * sizeof(Fts5TokenDataMap); + int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64; + int nAlloc = nNew * sizeof(Fts5TokenDataMap); Fts5TokenDataMap *aNew; - aNew = (Fts5TokenDataMap*)sqlite3_realloc64(pT->aMap, nAlloc); + aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc); if( aNew==0 ){ p->rc = SQLITE_NOMEM; return; @@ -255227,7 +253720,7 @@ static void fts5TokendataIterAppendMap( */ static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){ Fts5TokenDataMap *aTmp = 0; - i64 nByte = pT->nMap * sizeof(Fts5TokenDataMap); + int nByte = pT->nMap * sizeof(Fts5TokenDataMap); aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte); if( aTmp ){ @@ -255761,10 +254254,9 @@ static Fts5TokenDataIter *fts5AppendTokendataIter( if( p->rc==SQLITE_OK ){ if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){ - i64 nAlloc = pIn ? pIn->nIterAlloc*2 : 16; - i64 nByte = SZ_FTS5TOKENDATAITER(nAlloc+1); - Fts5TokenDataIter *pNew; - pNew = (Fts5TokenDataIter*)sqlite3_realloc64(pIn, nByte); + int nAlloc = pIn ? pIn->nIterAlloc*2 : 16; + int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1); + Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte); if( pNew==0 ){ p->rc = SQLITE_NOMEM; @@ -255861,8 +254353,8 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){ /* Ensure the token-mapping is large enough */ if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){ - i64 nNew = (pT->nMapAlloc + nByte) * 2; - Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc64( + int nNew = (pT->nMapAlloc + nByte) * 2; + Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc( pT->aMap, nNew*sizeof(Fts5TokenDataMap) ); if( aNew==0 ){ @@ -258891,7 +257383,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ return SQLITE_ERROR; } - idxStr = (char*)sqlite3_malloc64((i64)pInfo->nConstraint * 8 + 1); + idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1); if( idxStr==0 ) return SQLITE_NOMEM; pInfo->idxStr = idxStr; pInfo->needToFreeIdxStr = 1; @@ -260341,7 +258833,6 @@ static int fts5UpdateMethod( } update_out: - sqlite3Fts5IndexCloseReader(pTab->p.pIndex); pTab->p.pConfig->pzErrmsg = 0; return rc; } @@ -261859,7 +260350,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075", -1, SQLITE_TRANSIENT); } /* @@ -262023,7 +260514,7 @@ static int fts5Init(sqlite3 *db){ int rc; Fts5Global *pGlobal = 0; - pGlobal = (Fts5Global*)sqlite3_malloc64(sizeof(Fts5Global)); + pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global)); if( pGlobal==0 ){ rc = SQLITE_NOMEM; }else{ @@ -263739,7 +262230,7 @@ static int fts5AsciiCreate( if( nArg%2 ){ rc = SQLITE_ERROR; }else{ - p = sqlite3_malloc64(sizeof(AsciiTokenizer)); + p = sqlite3_malloc(sizeof(AsciiTokenizer)); if( p==0 ){ rc = SQLITE_NOMEM; }else{ @@ -264034,7 +262525,7 @@ static int fts5UnicodeCreate( if( nArg%2 ){ rc = SQLITE_ERROR; }else{ - p = (Unicode61Tokenizer*)sqlite3_malloc64(sizeof(Unicode61Tokenizer)); + p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); if( p ){ const char *zCat = "L* N* Co"; int i; @@ -264257,7 +262748,7 @@ static int fts5PorterCreate( zBase = azArg[0]; } - pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer)); + pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer)); if( pRet ){ memset(pRet, 0, sizeof(PorterTokenizer)); rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2); @@ -264964,7 +263455,7 @@ static int fts5TriCreate( rc = SQLITE_ERROR; }else{ int i; - pNew = (TrigramTokenizer*)sqlite3_malloc64(sizeof(*pNew)); + pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew)); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -266950,7 +265441,7 @@ static int fts5VocabFilterMethod( const char *zCopy = (const char *)sqlite3_value_text(pLe); if( zCopy==0 ) zCopy = ""; pCsr->nLeTerm = sqlite3_value_bytes(pLe); - pCsr->zLeTerm = sqlite3_malloc64((i64)pCsr->nLeTerm+1); + pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1); if( pCsr->zLeTerm==0 ){ rc = SQLITE_NOMEM; }else{ diff --git a/cgosqlite/sqlite3.h b/cgosqlite/sqlite3.h index 3385675..6e975a6 100644 --- a/cgosqlite/sqlite3.h +++ b/cgosqlite/sqlite3.h @@ -146,12 +146,12 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.52.0" -#define SQLITE_VERSION_NUMBER 3052000 -#define SQLITE_SOURCE_ID "2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.52.0" -#define SQLITE_SCM_DATETIME "2026-03-06T16:01:44.367Z" +#define SQLITE_VERSION "3.51.2" +#define SQLITE_VERSION_NUMBER 3051002 +#define SQLITE_SOURCE_ID "2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075" +#define SQLITE_SCM_BRANCH "branch-3.51" +#define SQLITE_SCM_TAGS "release version-3.51.2" +#define SQLITE_SCM_DATETIME "2026-01-09T17:27:48.405Z" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1490,7 +1490,7 @@ typedef const char *sqlite3_filename; ** greater and the function pointer is not NULL) and will fall back ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. ** -** ^The xSetSystemCall(), xGetSystemCall(), and xNextSystemCall() interfaces +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces ** are not used by the SQLite core. These optional interfaces are provided ** by some VFSes to facilitate testing of the VFS code. By overriding ** system calls with functions under its control, a test program can @@ -2567,15 +2567,12 @@ struct sqlite3_mem_methods { ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] ** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt> ** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in -** [SQLITE_ENABLE_STMT_SCANSTATUS] builds. In this case, it sets or clears -** a flag that enables collection of run-time performance statistics -** used by [sqlite3_stmt_scanstatus_v2()] and the [nexec and ncycle] -** columns of the [bytecode virtual table]. -** For statistics to be collected, the flag must be set on -** the database handle both when the SQL statement is -** [sqlite3_prepare|prepared] and when it is [sqlite3_step|stepped]. -** The flag is set (collection of statistics is enabled) by default. -** <p>This option takes two arguments: an integer and a pointer to +** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears +** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() +** statistics. For statistics to be collected, the flag must be set on +** the database handle both when the SQL statement is prepared and when it +** is stepped. The flag is set (collection of statistics is enabled) +** by default. <p>This option takes two arguments: an integer and a pointer to ** an integer. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the statement scanstatus option. If the second argument ** is not NULL, then the value of the statement scanstatus setting after @@ -2648,22 +2645,6 @@ struct sqlite3_mem_methods { ** comments are allowed in SQL text after processing the first argument. ** </dd> ** -** [[SQLITE_DBCONFIG_FP_DIGITS]] -** <dt>SQLITE_DBCONFIG_FP_DIGITS</dt> -** <dd>The SQLITE_DBCONFIG_FP_DIGITS setting is a small integer that determines -** the number of significant digits that SQLite will attempt to preserve when -** converting floating point numbers (IEEE 754 "doubles") into text. The -** default value 17, as of SQLite version 3.52.0. The value was 15 in all -** prior versions.<p> -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is a small integer, between 3 and 23, or -** zero. The FP_DIGITS setting is changed to that small integer, or left -** altered if the first argument is zero or out of range. The second argument -** is a pointer to an integer. If the pointer is not NULL, then the value of -** the FP_DIGITS setting, after possibly being modified by the first -** arguments, is written into the integer to which the second argument points. -** </dd> -** ** </dl> ** ** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3> @@ -2681,10 +2662,9 @@ struct sqlite3_mem_methods { ** the first argument. ** ** <p>While most SQLITE_DBCONFIG options use the argument format -** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME], -** [SQLITE_DBCONFIG_LOOKASIDE], and [SQLITE_DBCONFIG_FP_DIGITS] options -** are different. See the documentation of those exceptional options for -** details. +** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME] +** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the +** documentation of those exceptional options for details. */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ @@ -2709,8 +2689,7 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */ -#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -4192,7 +4171,6 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** <li> sqlite3_errmsg() ** <li> sqlite3_errmsg16() ** <li> sqlite3_error_offset() -** <li> sqlite3_db_handle() ** </ul> ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language @@ -4239,7 +4217,7 @@ SQLITE_API const char *sqlite3_errstr(int); SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* -** CAPI3REF: Set Error Code And Message +** CAPI3REF: Set Error Codes And Message ** METHOD: sqlite3 ** ** Set the error code of the database handle passed as the first argument @@ -4358,10 +4336,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt> ** <dd>The maximum depth of the parse tree on any expression.</dd>)^ ** -** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt> -** <dd>The maximum depth of the LALR(1) parser stack used to analyze -** input SQL statements.</dd>)^ -** ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt> ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^ ** @@ -4406,7 +4380,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 -#define SQLITE_LIMIT_PARSER_DEPTH 12 /* ** CAPI3REF: Prepare Flags @@ -4451,29 +4424,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** fails, the sqlite3_prepare_v3() call returns the same error indications ** with or without this flag; it just omits the call to [sqlite3_log()] that ** logs the error. -** -** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt> -** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to enforce -** security constraints that would otherwise only be enforced when parsing -** the database schema. In other words, the SQLITE_PREPARE_FROM_DDL flag -** causes the SQL compiler to treat the SQL statement being prepared as if -** it had come from an attacker. When SQLITE_PREPARE_FROM_DDL is used and -** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] is off, SQL functions may only be called -** if they are tagged with [SQLITE_INNOCUOUS] and virtual tables may only -** be used if they are tagged with [SQLITE_VTAB_INNOCUOUS]. Best practice -** is to use the SQLITE_PREPARE_FROM_DDL option when preparing any SQL that -** is derived from parts of the database schema. In particular, virtual -** table implementations that run SQL statements that are derived from -** arguments to their CREATE VIRTUAL TABLE statement should always use -** [sqlite3_prepare_v3()] and set the SQLITE_PREPARE_FROM_DDL flag to -** prevent bypass of the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks. ** </dl> */ #define SQLITE_PREPARE_PERSISTENT 0x01 #define SQLITE_PREPARE_NORMALIZE 0x02 #define SQLITE_PREPARE_NO_VTAB 0x04 #define SQLITE_PREPARE_DONT_LOG 0x10 -#define SQLITE_PREPARE_FROM_DDL 0x20 /* ** CAPI3REF: Compiling An SQL Statement @@ -4487,9 +4443,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** The preferred routine to use is [sqlite3_prepare_v2()]. The ** [sqlite3_prepare()] interface is legacy and should be avoided. -** [sqlite3_prepare_v3()] has an extra -** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times -** needed for special purpose or to pass along security restrictions. +** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used +** for special purposes. ** ** The use of the UTF-8 interfaces is preferred, as SQLite currently ** does all parsing using UTF-8. The UTF-16 interfaces are provided @@ -4894,8 +4849,8 @@ typedef struct sqlite3_context sqlite3_context; ** it should be a pointer to well-formed UTF16 text. ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then ** it should be a pointer to a well-formed unicode string that is -** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT, -** or UTF16 otherwise. +** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 +** otherwise. ** ** [[byte-order determination rules]] ^The byte-order of ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) @@ -4941,15 +4896,10 @@ typedef struct sqlite3_context sqlite3_context; ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** -** ^The sixth argument (the E argument) -** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of -** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE] to specify the encoding of the text in the -** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the -** string argument is both UTF-8 encoded and is zero-terminated. In other -** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at -** least N+1 bytes and that the Z&#91;N&#93; byte is zero. If -** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the +** ^The sixth argument to sqlite3_bind_text64() must be one of +** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] +** to specify the encoding of the text in the third parameter. If +** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior ** is undefined. @@ -5816,51 +5766,6 @@ SQLITE_API int sqlite3_create_window_function( ** ** These constants define integer codes that represent the various ** text encodings supported by SQLite. -** -** <dl> -** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd> -** -** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16 -** with each code point being expressed "little endian" - the least significant -** byte first. This is the usual encoding, for example on Windows.</dd> -** -** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16 -** with each code point being expressed "big endian" - the most significant -** byte first. This encoding is less common, but is still sometimes seen, -** specially on older systems. -** -** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16 -** with each code point being expressed either little endian or as big -** endian, according to the native endianness of the host computer. -** -** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used -** to declare the preferred text for [application-defined SQL functions] -** created using [sqlite3_create_function()] and similar. If the preferred -** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep -** parameter) is SQLITE_ANY, that indicates that the function does not have -** a preference regarding the text encoding of its parameters and can take -** any text encoding that the SQLite core find convenient to supply. This -** option is deprecated. Please do not use it in new applications. -** -** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding -** value may be used as the 3rd parameter (the eTextRep parameter) to -** [sqlite3_create_collation()] and similar. This encoding value means -** that the application-defined collating sequence created expects its -** input strings to be in UTF16 in native byte order, and that the start -** of the strings must be aligned to a 2-byte boundary. -** -** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be -** used to specify the text encoding to strings input to [sqlite3_result_text64()] -** and [sqlite3_bind_text64()]. It means that the input string (call it "z") -** is UTF-8 encoded and that it is zero-terminated. If the length parameter -** (call it "n") is non-negative, this encoding option means that the caller -** guarantees that z array contains at least n+1 bytes and that the z&#91;n&#93; -** byte has a value of zero. -** This option gives the same output as SQLITE_UTF8, but can be more efficient -** by avoiding the need to make a copy of the input string, in some cases. -** However, if z is allocated to hold fewer than n+1 bytes or if the -** z&#91;n&#93; byte is not zero, undefined behavior may result. -** </dl> */ #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ @@ -5868,7 +5773,6 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ -#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */ /* ** CAPI3REF: Function Flags @@ -6374,14 +6278,10 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi ** ** There is no limit (other than available memory) on the number of different ** client data pointers (with different names) that can be attached to a -** single database connection. However, the current implementation stores -** the content on a linked list. Insert and retrieval performance will -** be proportional to the number of entries. The design use case, and -** the use case for which the implementation is optimized, is -** that an application will store only small number of client data names, -** typically just one or two. This interface is not intended to be a -** generalized key/value store for thousands or millions of keys. It -** will work for that, but performance might be disappointing. +** single database connection. However, the implementation is optimized +** for the case of having only one or two different client data names. +** Applications and wrapper libraries are discouraged from using more than +** one client data name each. ** ** There is no way to enumerate the client data pointers ** associated with a database connection. The N parameter can be thought @@ -6489,14 +6389,10 @@ typedef void (*sqlite3_destructor_type)(void*); ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. -** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an +** ^The sqlite3_result_text64() interface sets the return value of an ** application-defined function to be a text string in an encoding -** specified the E parameter, which must be one -** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that -** the result text is both UTF-8 and zero-terminated. In other words, -** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that -** the Z&#91;N&#93; is zero. +** specified by the fifth (and last) parameter, which must be one +** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces @@ -6583,7 +6479,7 @@ SQLITE_API void sqlite3_result_int(sqlite3_context*, int); SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); SQLITE_API void sqlite3_result_null(sqlite3_context*); SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n, +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); @@ -7522,7 +7418,7 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The sqlite3_load_extension() interface attempts to load an ** [SQLite extension] library contained in the file zFile. If ** the file cannot be loaded directly, attempts are made to load -** with various operating-system specific filename extensions added. +** with various operating-system specific extensions added. ** So for example, if "samplelib" cannot be loaded, then names like ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might ** be tried also. @@ -7530,10 +7426,10 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The entry point is zProc. ** ^(zProc may be 0, in which case SQLite will try to come up with an ** entry point name on its own. It first tries "sqlite3_extension_init". -** If that does not work, it tries names of the form "sqlite3_X_init" -** where X consists of the lower-case equivalent of all ASCII alphabetic -** characters or all ASCII alphanumeric characters in the filename from -** the last "/" to the first following "." and omitting any initial "lib".)^ +** If that does not work, it constructs a name "sqlite3_X_init" where +** X consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the @@ -8826,22 +8722,17 @@ SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ** pass the returned value to [sqlite3_free()] to avoid a memory leak. ** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ** errors were encountered during construction of the string. ^The -** [sqlite3_str_finish(X)] interface might also return a NULL pointer if the +** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ** string in [sqlite3_str] object X is zero bytes long. -** -** ^The [sqlite3_str_free(X)] interface destroys both the sqlite3_str object -** X and the string content it contains. Calling sqlite3_str_free(X) is -** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)). */ SQLITE_API char *sqlite3_str_finish(sqlite3_str*); -SQLITE_API void sqlite3_str_free(sqlite3_str*); /* ** CAPI3REF: Add Content To A Dynamic String ** METHOD: sqlite3_str ** -** These interfaces add or remove content to an sqlite3_str object -** previously obtained from [sqlite3_str_new()]. +** These interfaces add content to an sqlite3_str object previously obtained +** from [sqlite3_str_new()]. ** ** ^The [sqlite3_str_appendf(X,F,...)] and ** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] @@ -8864,10 +8755,6 @@ SQLITE_API void sqlite3_str_free(sqlite3_str*); ** ^The [sqlite3_str_reset(X)] method resets the string under construction ** inside [sqlite3_str] object X back to zero bytes in length. ** -** ^The [sqlite3_str_truncate(X,N)] method changes the length of the string -** under construction to be N bytes are less. This routine is a no-op if -** N is negative or if the string is already N bytes or smaller in size. -** ** These methods do not return a result code. ^If an error occurs, that fact ** is recorded in the [sqlite3_str] object and can be recovered by a ** subsequent call to [sqlite3_str_errcode(X)]. @@ -8878,7 +8765,6 @@ SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); SQLITE_API void sqlite3_str_reset(sqlite3_str*); -SQLITE_API void sqlite3_str_truncate(sqlite3_str*,int N); /* ** CAPI3REF: Status Of A Dynamic String @@ -10712,9 +10598,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** a variable pointed to by the "pOut" parameter. ** ** The "flags" parameter must be passed a mask of flags. At present only -** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX +** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX ** is specified, then status information is available for all elements -** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If +** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If ** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements ** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of ** the EXPLAIN QUERY PLAN output) are available. Invoking API @@ -10728,8 +10614,7 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** elements used to implement the statement - a non-zero value is returned and ** the variable that pOut points to is unchanged. ** -** See also: [sqlite3_stmt_scanstatus_reset()] and the -** [nexec and ncycle] columnes of the [bytecode virtual table]. +** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ @@ -11271,41 +11156,19 @@ SQLITE_API int sqlite3_deserialize( /* ** CAPI3REF: Bind array values to the CARRAY table-valued function ** -** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to -** parameter that is the first argument of the [carray() table-valued function]. -** The S parameter is a pointer to the [prepared statement] that uses the carray() -** functions. I is the parameter index to be bound. I must be the index of the -** parameter that is the first argument to the carray() table-valued function. -** P is a pointer to the array to be bound, and N is the number of elements in -** the array. The F argument is one of constants [SQLITE_CARRAY_INT32], -** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], -** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P. -** -** If the X argument is not a NULL pointer or one of the special -** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke -** the function X with argument D when it is finished using the data in P. -** The call to X(D) is a destructor for the array P. The destructor X(D) -** is invoked even if the call to sqlite3_carray_bind() fails. If the X -** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes -** that the data static and the destructor is never invoked. If the X -** parameter is the special-case value [SQLITE_TRANSIENT], then -** sqlite3_carray_bind_v2() makes its own private copy of the data prior -** to returning and never invokes the destructor X. -** -** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2() -** with a D parameter set to P. In other words, -** sqlite3_carray_bind(S,I,P,N,F,X) is same as -** sqlite3_carray_bind(S,I,P,N,F,X,P). -*/ -SQLITE_API int sqlite3_carray_bind_v2( - sqlite3_stmt *pStmt, /* Statement to be bound */ - int i, /* Parameter index */ - void *aData, /* Pointer to array data */ - int nData, /* Number of data elements */ - int mFlags, /* CARRAY flags */ - void (*xDel)(void*), /* Destructor for aData */ - void *pDel /* Optional argument to xDel() */ -); +** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to +** one of the first argument of the [carray() table-valued function]. The +** S parameter is a pointer to the [prepared statement] that uses the carray() +** functions. I is the parameter index to be bound. P is a pointer to the +** array to be bound, and N is the number of eements in the array. The +** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], +** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to +** indicate the datatype of the array being bound. The X argument is not a +** NULL pointer, then SQLite will invoke the function X on the P parameter +** after it has finished using P, even if the call to +** sqlite3_carray_bind() fails. The special-case finalizer +** SQLITE_TRANSIENT has no effect here. +*/ SQLITE_API int sqlite3_carray_bind( sqlite3_stmt *pStmt, /* Statement to be bound */ int i, /* Parameter index */ diff --git a/cgosqlite/sqlite3_trunk.c b/cgosqlite/sqlite3_trunk.c index a5c5a71..7b3949f 100644 --- a/cgosqlite/sqlite3_trunk.c +++ b/cgosqlite/sqlite3_trunk.c @@ -20,7 +20,7 @@ ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** 557aeb43869d3585137b17690cb3b64f7de6 with changes in files: +** 61f8a28591a833b1f5834a347feefeba8414 with changes in files: ** ** */ @@ -471,10 +471,10 @@ extern "C" { */ #define SQLITE_VERSION "3.52.0" #define SQLITE_VERSION_NUMBER 3052000 -#define SQLITE_SOURCE_ID "2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6" +#define SQLITE_SOURCE_ID "2026-03-04 13:08:14 61f8a28591a833b1f5834a347feefeba8414fecc7ff154f1b6ef19963f181812" #define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.52.0" -#define SQLITE_SCM_DATETIME "2026-03-06T16:01:44.367Z" +#define SQLITE_SCM_TAGS "" +#define SQLITE_SCM_DATETIME "2026-03-04T13:08:14.899Z" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -15450,7 +15450,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); # define float sqlite_int64 # define fabs(X) ((X)<0?-(X):(X)) # define sqlite3IsOverflow(X) 0 -# define INFINITY (9223372036854775807LL) # ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # endif @@ -29806,12 +29805,11 @@ static int checkMutexNotheld(sqlite3_mutex *p){ */ static int checkMutexInit(void){ pGlobalMutexMethods = sqlite3DefaultMutex(); - return pGlobalMutexMethods->xMutexInit(); + return SQLITE_OK; } static int checkMutexEnd(void){ - int rc = pGlobalMutexMethods->xMutexEnd(); pGlobalMutexMethods = 0; - return rc; + return SQLITE_OK; } /* @@ -261860,7 +261858,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2026-03-04 13:08:14 61f8a28591a833b1f5834a347feefeba8414fecc7ff154f1b6ef19963f181812", -1, SQLITE_TRANSIENT); } /* @@ -267463,5 +267461,4 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } #endif /* SQLITE_AMALGAMATION */ /************************** End of sqlite3.c ******************************/ - -#endif +#endif \ No newline at end of file diff --git a/cgosqlite/sqlite3_trunk.h b/cgosqlite/sqlite3_trunk.h index 3385675..2212fa6 100644 --- a/cgosqlite/sqlite3_trunk.h +++ b/cgosqlite/sqlite3_trunk.h @@ -148,10 +148,10 @@ extern "C" { */ #define SQLITE_VERSION "3.52.0" #define SQLITE_VERSION_NUMBER 3052000 -#define SQLITE_SOURCE_ID "2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6" +#define SQLITE_SOURCE_ID "2026-03-04 13:08:14 61f8a28591a833b1f5834a347feefeba8414fecc7ff154f1b6ef19963f181812" #define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.52.0" -#define SQLITE_SCM_DATETIME "2026-03-06T16:01:44.367Z" +#define SQLITE_SCM_TAGS "" +#define SQLITE_SCM_DATETIME "2026-03-04T13:08:14.899Z" /* ** CAPI3REF: Run-Time Library Version Numbers diff --git a/cgosqlite/sqlite3ext.h b/cgosqlite/sqlite3ext.h index cad1a2a..5258faa 100644 --- a/cgosqlite/sqlite3ext.h +++ b/cgosqlite/sqlite3ext.h @@ -371,11 +371,7 @@ struct sqlite3_api_routines { /* Version 3.51.0 and later */ int (*set_errmsg)(sqlite3*,int,const char*); int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); - /* Version 3.52.0 and later */ - void (*str_truncate)(sqlite3_str*,int); - void (*str_free)(sqlite3_str*); - int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*)); - int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*); + }; /* @@ -714,11 +710,6 @@ typedef int (*sqlite3_loadext_entry)( /* Version 3.51.0 and later */ #define sqlite3_set_errmsg sqlite3_api->set_errmsg #define sqlite3_db_status64 sqlite3_api->db_status64 -/* Version 3.52.0 and later */ -#define sqlite3_str_truncate sqlite3_api->str_truncate -#define sqlite3_str_free sqlite3_api->str_free -#define sqlite3_carray_bind sqlite3_api->carray_bind -#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)