summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chromium/third_party/sqlite/BUILD.gn28
-rw-r--r--chromium/third_party/sqlite/OWNERS1
-rw-r--r--chromium/third_party/sqlite/README.chromium4
-rw-r--r--chromium/third_party/sqlite/amalgamation/sqlite3.c11094
-rw-r--r--chromium/third_party/sqlite/amalgamation/sqlite3.h61
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3.c858
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_write.c819
-rw-r--r--chromium/third_party/sqlite/src/manifest1269
-rw-r--r--chromium/third_party/sqlite/src/src/btree.c2138
-rw-r--r--chromium/third_party/sqlite/src/src/build.c1574
-rw-r--r--chromium/third_party/sqlite/src/src/select.c1844
-rw-r--r--chromium/third_party/sqlite/src/src/update.c835
12 files changed, 12740 insertions, 7785 deletions
diff --git a/chromium/third_party/sqlite/BUILD.gn b/chromium/third_party/sqlite/BUILD.gn
index b71d4bca8bc..e5f7b99c54f 100644
--- a/chromium/third_party/sqlite/BUILD.gn
+++ b/chromium/third_party/sqlite/BUILD.gn
@@ -18,6 +18,17 @@ import("//third_party/protobuf/proto_library.gni")
#
# The vast majority of the macros here are documented at
# https://www.sqlite.org/compile.html
+#
+# By default, we disable all SQLite features that can be disabled by adding a
+# SQLITE_OMIT_ define, or by leaving out a SQLITE_ENABLE_ define. We only enable
+# features that have compelling use cases in the codebase.
+#
+# Each SQLite feature carries a cost to our users (binary size, pressure on
+# caches and branch predictors, extra surface area for security
+# vulnerabilities), as well as a maintenance cost (more surface area to be
+# covered by our fuzzers, more logic to reason through when debugging a crash
+# or a security vulnerability report). Enabled features must provide benefits
+# that outweigh these costs.
config("chromium_sqlite3_compile_options") {
defines = [
# Skip writing transaction rollback journals on f2fs.
@@ -109,6 +120,20 @@ config("chromium_sqlite3_compile_options") {
# Chrome initializes SQLite manually in //sql/connection.cc.
"SQLITE_OMIT_AUTOINIT",
+ # Chrome should not use queries with the pathologic performance cases
+ # mitigated by automatic indexes.
+ #
+ # Disabling automatic indexing exposes the pathological performance problems,
+ # instead of having SQLite paper over them. This helps us catch the prbolems
+ # in early testing, such as pinpoint and Finch.
+ #
+ # As a bonus, disabling automatic indexing simplifies the mental model for
+ # SQLite's optimizer, which makes a bit it easier to reason about SQL
+ # statement performance.
+ #
+ # See https://www.sqlite.org/optoverview.html#autoindex
+ "SQLITE_OMIT_AUTOMATIC_INDEX",
+
# Chrome calls sqlite3_reset() correctly to reset prepared statements.
"SQLITE_OMIT_AUTORESET",
@@ -138,6 +163,9 @@ config("chromium_sqlite3_compile_options") {
# Chrome does not use sqlite3_{get,free}_table().
"SQLITE_OMIT_GET_TABLE",
+ # Chrome does not use PRAGMA {function,module,pragma}_list.
+ "SQLITE_OMIT_INTROSPECTION_PRAGMAS",
+
# Chrome does not use sqlite3_{enable_}load_extension().
# Asides from giving us fairly minor code savings, this option disables code
# that breaks our method for renaming SQLite's exported symbols. Last,
diff --git a/chromium/third_party/sqlite/OWNERS b/chromium/third_party/sqlite/OWNERS
index 578d82212d8..c1c64be0132 100644
--- a/chromium/third_party/sqlite/OWNERS
+++ b/chromium/third_party/sqlite/OWNERS
@@ -3,4 +3,5 @@ huangdarwin@chromium.org
# Secondary:
cmumford@google.com
+mek@chromium.org
pwnall@chromium.org
diff --git a/chromium/third_party/sqlite/README.chromium b/chromium/third_party/sqlite/README.chromium
index 4ae58cf99eb..7cb5f8cc5ef 100644
--- a/chromium/third_party/sqlite/README.chromium
+++ b/chromium/third_party/sqlite/README.chromium
@@ -1,7 +1,7 @@
Name: sqlite
URL: https://sqlite.org/
-Version: 3.34.0
-CPEPrefix: cpe:/a:sqlite:sqlite:3.34.0
+Version: 3.35.5
+CPEPrefix: cpe:/a:sqlite:sqlite:3.35.5
Included In Release: Yes
Security Critical: Yes
License: Public domain
diff --git a/chromium/third_party/sqlite/amalgamation/sqlite3.c b/chromium/third_party/sqlite/amalgamation/sqlite3.c
index f22c51cd758..7f20d385d7f 100644
--- a/chromium/third_party/sqlite/amalgamation/sqlite3.c
+++ b/chromium/third_party/sqlite/amalgamation/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.34.0. By combining all the individual C code files into this
+** version 3.35.5. 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
@@ -284,6 +284,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_LOCKING_STYLE
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
+#if SQLITE_ENABLE_MATH_FUNCTIONS
+ "ENABLE_MATH_FUNCTIONS",
+#endif
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
"ENABLE_MEMORY_MANAGEMENT",
#endif
@@ -990,6 +993,18 @@ SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
# define MSVC_VERSION 0
#endif
+/*
+** Some C99 functions in "math.h" are only present for MSVC when its version
+** is associated with Visual Studio 2013 or higher.
+*/
+#ifndef SQLITE_HAVE_C99_MATH_FUNCS
+# if MSVC_VERSION==0 || MSVC_VERSION>=1800
+# define SQLITE_HAVE_C99_MATH_FUNCS (1)
+# else
+# define SQLITE_HAVE_C99_MATH_FUNCS (0)
+# endif
+#endif
+
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
@@ -1171,9 +1186,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.34.0"
-#define SQLITE_VERSION_NUMBER 3034000
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
+#define SQLITE_VERSION "3.35.5"
+#define SQLITE_VERSION_NUMBER 3035005
+#define SQLITE_SOURCE_ID "2021-04-19 18:32:05 7dd0b0cff3f06b1f1a3bc94233e1d1574288f3ed9bbc277639d2cc5713d0alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -3163,7 +3178,13 @@ struct sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the trigger setting is not reported back. </dd>
+** which case the trigger setting is not reported back.
+**
+** <p>Originally this option disabled all triggers. ^(However, since
+** SQLite version 3.35.0, TEMP triggers are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** triggers in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
@@ -3174,7 +3195,13 @@ struct sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the view setting is not reported back. </dd>
+** which case the view setting is not reported back.
+**
+** <p>Originally this option disabled all views. ^(However, since
+** SQLite version 3.35.0, TEMP views are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** views in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
@@ -4547,6 +4574,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** that uses dot-files in place of posix advisory locking.
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
+** Use "ro" instead: "file:data.db?mode=ro".
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
@@ -4745,7 +4773,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
** If the Y parameter to sqlite3_free_filename(Y) is anything other
** than a NULL pointer or a pointer previously acquired from
** sqlite3_create_filename(), then bad things such as heap
-** corruption or segfaults may occur. The value Y should be
+** corruption or segfaults may occur. The value Y should not be
** used again after sqlite3_free_filename(Y) has been called. This means
** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
** then the corresponding [sqlite3_module.xClose() method should also be
@@ -8813,7 +8841,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_SEEK_COUNT 30
-#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_TRACEFLAGS 31
+#define SQLITE_TESTCTRL_LAST 31 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -11487,6 +11516,14 @@ SQLITE_API int sqlite3session_patchset(
SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
/*
+** CAPI3REF: Query for the amount of heap memory used by a session object.
+**
+** This API returns the total amount of heap memory in bytes currently
+** used by the session object passed as the only argument.
+*/
+SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
+
+/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
** CONSTRUCTOR: sqlite3_changeset_iter
**
@@ -11588,18 +11625,23 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
-** If argument pzTab is not NULL, then *pzTab is set to point to a
-** nul-terminated utf-8 encoded string containing the name of the table
-** affected by the current change. The buffer remains valid until either
-** sqlite3changeset_next() is called on the iterator or until the
-** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
-** set to the number of columns in the table affected by the change. If
-** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
+** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
+** outputs are set through these pointers:
+**
+** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the type of change that the iterator currently points to;
+**
+** *pnCol is set to the number of columns in the table affected by the change; and
+**
+** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
+** the name of the table affected by the current change. The buffer remains
+** valid until either sqlite3changeset_next() is called on the iterator
+** or until the conflict-handler function returns.
+**
+** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
-** changes. Finally, if pOp is not NULL, then *pOp is set to one of
-** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
-** type of change that the iterator currently points to.
+** changes.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
@@ -13528,7 +13570,8 @@ struct fts5_api {
#ifndef __has_extension
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
#endif
-#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
+#if GCC_VERSION>=4007000 || \
+ (__has_extension(c_atomic) && __has_extension(c_atomic_store_n))
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
@@ -14085,87 +14128,89 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_LAST 84
#define TK_GENERATED 85
#define TK_ALWAYS 86
-#define TK_REINDEX 87
-#define TK_RENAME 88
-#define TK_CTIME_KW 89
-#define TK_ANY 90
-#define TK_BITAND 91
-#define TK_BITOR 92
-#define TK_LSHIFT 93
-#define TK_RSHIFT 94
-#define TK_PLUS 95
-#define TK_MINUS 96
-#define TK_STAR 97
-#define TK_SLASH 98
-#define TK_REM 99
-#define TK_CONCAT 100
-#define TK_COLLATE 101
-#define TK_BITNOT 102
-#define TK_ON 103
-#define TK_INDEXED 104
-#define TK_STRING 105
-#define TK_JOIN_KW 106
-#define TK_CONSTRAINT 107
-#define TK_DEFAULT 108
-#define TK_NULL 109
-#define TK_PRIMARY 110
-#define TK_UNIQUE 111
-#define TK_CHECK 112
-#define TK_REFERENCES 113
-#define TK_AUTOINCR 114
-#define TK_INSERT 115
-#define TK_DELETE 116
-#define TK_UPDATE 117
-#define TK_SET 118
-#define TK_DEFERRABLE 119
-#define TK_FOREIGN 120
-#define TK_DROP 121
-#define TK_UNION 122
-#define TK_ALL 123
-#define TK_EXCEPT 124
-#define TK_INTERSECT 125
-#define TK_SELECT 126
-#define TK_VALUES 127
-#define TK_DISTINCT 128
-#define TK_DOT 129
-#define TK_FROM 130
-#define TK_JOIN 131
-#define TK_USING 132
-#define TK_ORDER 133
-#define TK_GROUP 134
-#define TK_HAVING 135
-#define TK_LIMIT 136
-#define TK_WHERE 137
-#define TK_INTO 138
-#define TK_NOTHING 139
-#define TK_FLOAT 140
-#define TK_BLOB 141
-#define TK_INTEGER 142
-#define TK_VARIABLE 143
-#define TK_CASE 144
-#define TK_WHEN 145
-#define TK_THEN 146
-#define TK_ELSE 147
-#define TK_INDEX 148
-#define TK_ALTER 149
-#define TK_ADD 150
-#define TK_COLUMN 151
-#define TK_AGG_FUNCTION 152
-#define TK_AGG_COLUMN 153
-#define TK_TRUEFALSE 154
-#define TK_ISNOT 155
-#define TK_FUNCTION 156
-#define TK_UMINUS 157
-#define TK_UPLUS 158
-#define TK_TRUTH 159
-#define TK_REGISTER 160
-#define TK_VECTOR 161
-#define TK_SELECT_COLUMN 162
-#define TK_IF_NULL_ROW 163
-#define TK_ASTERISK 164
-#define TK_SPAN 165
-#define TK_SPACE 166
-#define TK_ILLEGAL 167
+#define TK_MATERIALIZED 87
+#define TK_REINDEX 88
+#define TK_RENAME 89
+#define TK_CTIME_KW 90
+#define TK_ANY 91
+#define TK_BITAND 92
+#define TK_BITOR 93
+#define TK_LSHIFT 94
+#define TK_RSHIFT 95
+#define TK_PLUS 96
+#define TK_MINUS 97
+#define TK_STAR 98
+#define TK_SLASH 99
+#define TK_REM 100
+#define TK_CONCAT 101
+#define TK_COLLATE 102
+#define TK_BITNOT 103
+#define TK_ON 104
+#define TK_INDEXED 105
+#define TK_STRING 106
+#define TK_JOIN_KW 107
+#define TK_CONSTRAINT 108
+#define TK_DEFAULT 109
+#define TK_NULL 110
+#define TK_PRIMARY 111
+#define TK_UNIQUE 112
+#define TK_CHECK 113
+#define TK_REFERENCES 114
+#define TK_AUTOINCR 115
+#define TK_INSERT 116
+#define TK_DELETE 117
+#define TK_UPDATE 118
+#define TK_SET 119
+#define TK_DEFERRABLE 120
+#define TK_FOREIGN 121
+#define TK_DROP 122
+#define TK_UNION 123
+#define TK_ALL 124
+#define TK_EXCEPT 125
+#define TK_INTERSECT 126
+#define TK_SELECT 127
+#define TK_VALUES 128
+#define TK_DISTINCT 129
+#define TK_DOT 130
+#define TK_FROM 131
+#define TK_JOIN 132
+#define TK_USING 133
+#define TK_ORDER 134
+#define TK_GROUP 135
+#define TK_HAVING 136
+#define TK_LIMIT 137
+#define TK_WHERE 138
+#define TK_RETURNING 139
+#define TK_INTO 140
+#define TK_NOTHING 141
+#define TK_FLOAT 142
+#define TK_BLOB 143
+#define TK_INTEGER 144
+#define TK_VARIABLE 145
+#define TK_CASE 146
+#define TK_WHEN 147
+#define TK_THEN 148
+#define TK_ELSE 149
+#define TK_INDEX 150
+#define TK_ALTER 151
+#define TK_ADD 152
+#define TK_COLUMN 153
+#define TK_AGG_FUNCTION 154
+#define TK_AGG_COLUMN 155
+#define TK_TRUEFALSE 156
+#define TK_ISNOT 157
+#define TK_FUNCTION 158
+#define TK_UMINUS 159
+#define TK_UPLUS 160
+#define TK_TRUTH 161
+#define TK_REGISTER 162
+#define TK_VECTOR 163
+#define TK_SELECT_COLUMN 164
+#define TK_IF_NULL_ROW 165
+#define TK_ASTERISK 166
+#define TK_SPAN 167
+#define TK_SPACE 168
+#define TK_ILLEGAL 169
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -14581,15 +14626,14 @@ typedef INT16_TYPE LogEst;
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
*/
-#if defined(SQLITE_ENABLE_SELECTTRACE)
-# define SELECTTRACE_ENABLED 1
-#else
-# define SELECTTRACE_ENABLED 0
+#if !defined(SQLITE_AMALGAMATION)
+SQLITE_PRIVATE u32 sqlite3SelectTrace;
#endif
-#if defined(SQLITE_ENABLE_SELECTTRACE)
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE))
# define SELECTTRACE_ENABLED 1
# define SELECTTRACE(K,P,S,X) \
- if(sqlite3_unsupported_selecttrace&(K)) \
+ if(sqlite3SelectTrace&(K)) \
sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlite3DebugPrintf X
#else
@@ -14598,6 +14642,19 @@ typedef INT16_TYPE LogEst;
#endif
/*
+** Macros for "wheretrace"
+*/
+SQLITE_PRIVATE u32 sqlite3WhereTrace;
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
+# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
+# define WHERETRACE_ENABLED 1
+#else
+# define WHERETRACE(K,X)
+#endif
+
+
+/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
**
@@ -14708,7 +14765,10 @@ typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
+typedef struct Cte Cte;
+typedef struct CteUse CteUse;
typedef struct Db Db;
+typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
@@ -14726,14 +14786,17 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
+typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
typedef struct RenameToken RenameToken;
+typedef struct Returning Returning;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
typedef struct Table Table;
@@ -15305,6 +15368,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
#define BTREE_APPEND 0x08 /* Insert is likely an append */
+#define BTREE_PREFORMAT 0x80 /* Inserted data is a preformated cell */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -15404,6 +15468,8 @@ SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif
+SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
+
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
@@ -15703,103 +15769,105 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Copy 77 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
#define OP_SCopy 78 /* synopsis: r[P2]=r[P1] */
#define OP_IntCopy 79 /* synopsis: r[P2]=r[P1] */
-#define OP_ResultRow 80 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 81
-#define OP_AddImm 82 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 83
-#define OP_Cast 84 /* synopsis: affinity(r[P1]) */
-#define OP_Permutation 85
-#define OP_Compare 86 /* synopsis: r[P1@P3] <-> r[P2@P3] */
-#define OP_IsTrue 87 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
-#define OP_Offset 88 /* synopsis: r[P3] = sqlite_offset(P1) */
-#define OP_Column 89 /* synopsis: r[P3]=PX */
-#define OP_Affinity 90 /* synopsis: affinity(r[P1@P2]) */
-#define OP_BitAnd 91 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 92 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 93 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-#define OP_ShiftRight 94 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-#define OP_Add 95 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 96 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 97 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 98 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 99 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 100 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_BitNot 102 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_Count 103 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 104
-#define OP_String8 105 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_SetCookie 106
-#define OP_ReopenIdx 107 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenRead 108 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 109 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenDup 110
-#define OP_OpenAutoindex 111 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 112 /* synopsis: nColumn=P2 */
-#define OP_SorterOpen 113
-#define OP_SequenceTest 114 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 115 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 116
-#define OP_ColumnsUsed 117
-#define OP_SeekScan 118 /* synopsis: Scan-ahead up to P1 rows */
-#define OP_SeekHit 119 /* synopsis: set P2<=seekHit<=P3 */
-#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
-#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_Delete 123
-#define OP_ResetCount 124
-#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 126 /* synopsis: r[P2]=data */
-#define OP_RowData 127 /* synopsis: r[P2]=data */
-#define OP_Rowid 128 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 129
-#define OP_SeekEnd 130
-#define OP_IdxInsert 131 /* synopsis: key=r[P2] */
-#define OP_SorterInsert 132 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */
-#define OP_FinishSeek 136
-#define OP_Destroy 137
-#define OP_Clear 138
-#define OP_ResetSorter 139
-#define OP_Real 140 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_CreateBtree 141 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_SqlExec 142
-#define OP_ParseSchema 143
-#define OP_LoadAnalysis 144
-#define OP_DropTable 145
-#define OP_DropIndex 146
-#define OP_DropTrigger 147
-#define OP_IntegrityCk 148
-#define OP_RowSetAdd 149 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 150
-#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
-#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */
-#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 159
-#define OP_CursorLock 160
-#define OP_CursorUnlock 161
-#define OP_TableLock 162 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 163
-#define OP_VCreate 164
-#define OP_VDestroy 165
-#define OP_VOpen 166
-#define OP_VColumn 167 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 168
-#define OP_Pagecount 169
-#define OP_MaxPgcnt 170
-#define OP_Trace 171
-#define OP_CursorHint 172
-#define OP_ReleaseReg 173 /* synopsis: release r[P1@P2] mask P3 */
-#define OP_Noop 174
-#define OP_Explain 175
-#define OP_Abortable 176
+#define OP_ChngCntRow 80 /* synopsis: output=r[P1] */
+#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 82
+#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_RealAffinity 84
+#define OP_Cast 85 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 86
+#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
+#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 90 /* synopsis: r[P3]=PX */
+#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */
+#define OP_BitAnd 92 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 93 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 94 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight 95 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add 96 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 97 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 98 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 99 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 100 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 101 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_MakeRecord 102 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_BitNot 103 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
+#define OP_Count 104 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 105
+#define OP_String8 106 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_SetCookie 107
+#define OP_ReopenIdx 108 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 109 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 110 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenDup 111
+#define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 114
+#define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 116 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 117
+#define OP_ColumnsUsed 118
+#define OP_SeekScan 119 /* synopsis: Scan-ahead up to P1 rows */
+#define OP_SeekHit 120 /* synopsis: set P2<=seekHit<=P3 */
+#define OP_Sequence 121 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 122 /* synopsis: r[P2]=rowid */
+#define OP_Insert 123 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_RowCell 124
+#define OP_Delete 125
+#define OP_ResetCount 126
+#define OP_SorterCompare 127 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 128 /* synopsis: r[P2]=data */
+#define OP_RowData 129 /* synopsis: r[P2]=data */
+#define OP_Rowid 130 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 131
+#define OP_SeekEnd 132
+#define OP_IdxInsert 133 /* synopsis: key=r[P2] */
+#define OP_SorterInsert 134 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 135 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 136 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 137 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 138
+#define OP_Destroy 139
+#define OP_Clear 140
+#define OP_ResetSorter 141
+#define OP_Real 142 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_CreateBtree 143 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 144
+#define OP_ParseSchema 145
+#define OP_LoadAnalysis 146
+#define OP_DropTable 147
+#define OP_DropIndex 148
+#define OP_DropTrigger 149
+#define OP_IntegrityCk 150
+#define OP_RowSetAdd 151 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 152
+#define OP_FkCounter 153 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 154 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 155 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 156 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 157 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 158 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 159 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 160 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 161
+#define OP_CursorLock 162
+#define OP_CursorUnlock 163
+#define OP_TableLock 164 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 165
+#define OP_VCreate 166
+#define OP_VDestroy 167
+#define OP_VOpen 168
+#define OP_VColumn 169 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 170
+#define OP_Pagecount 171
+#define OP_MaxPgcnt 172
+#define OP_Trace 173
+#define OP_CursorHint 174
+#define OP_ReleaseReg 175 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 176
+#define OP_Explain 177
+#define OP_Abortable 178
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -15822,19 +15890,19 @@ typedef struct VdbeOpList VdbeOpList;
/* 56 */ 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x00,\
/* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\
/* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\
-/* 80 */ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x12,\
-/* 88 */ 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12, 0x10,\
-/* 104 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 80 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
+/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\
+/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
+/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
-/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
-/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\
-/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 120 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 128 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x04, 0x00,\
+/* 136 */ 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10,\
+/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\
+/* 152 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 176 */ 0x00,}
+/* 168 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\
+/* 176 */ 0x00, 0x00, 0x00,}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -15902,7 +15970,7 @@ SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char*,const char*);
#else
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
-SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
@@ -16874,6 +16942,11 @@ SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
#endif /* SQLITE_OMIT_DEPRECATED */
#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
+/*
+** Maximum number of sqlite3.aDb[] entries. This is the number of attached
+** databases plus 2 for "main" and "temp".
+*/
+#define SQLITE_MAX_DB (SQLITE_MAX_ATTACHED+2)
/*
** Each database connection is an instance of the following structure.
@@ -16894,7 +16967,7 @@ struct sqlite3 {
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
int iSysErrno; /* Errno value from last system error */
- u16 dbOptFlags; /* Flags to enable/disable optimizations */
+ u32 dbOptFlags; /* Flags to enable/disable optimizations */
u8 enc; /* Text encoding */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
@@ -16921,7 +16994,10 @@ struct sqlite3 {
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
+ unsigned bDropColumn : 1; /* Doing schema check after DROP COLUMN */
char **azInit; /* "type", "name", and "tbl_name" columns */
+ /* or if bDropColumn, then azInit[0] is the */
+ /* name of the column being dropped */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
@@ -17101,24 +17177,26 @@ struct sqlite3 {
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
*/
-#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
-#define SQLITE_WindowFunc 0x0002 /* Use xInverse for window functions */
-#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
-#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
-#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
-#define SQLITE_Transitive 0x0080 /* Transitive constraints */
-#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
-#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
-#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
-#define SQLITE_Stat4 0x0800 /* Use STAT4 data */
- /* TH3 expects the Stat4 ^^^^^^ value to be 0x0800. Don't change it */
-#define SQLITE_PushDown 0x1000 /* The push-down optimization */
-#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
-#define SQLITE_SkipScan 0x4000 /* Skip-scans */
-#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */
-#define SQLITE_AllOpts 0xffff /* All optimizations */
+#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
+#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
+#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
+#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
+#define SQLITE_Transitive 0x00000080 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
+#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
+#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
+#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
+ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
+#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
+#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
+#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
+#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
+#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
+#define SQLITE_ExistsToIN 0x00020000 /* The EXISTS-to-IN optimization */
+#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
@@ -17274,6 +17352,9 @@ struct FuncDestructor {
** a single query. The iArg is ignored. The user-data is always set
** to a NULL pointer. The bNC parameter is not used.
**
+** MFUNCTION(zName, nArg, xPtr, xFunc)
+** For math-library functions. xPtr is an arbitrary pointer.
+**
** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
** Used for "pure" date/time functions, this macro is like DFUNCTION
** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
@@ -17309,6 +17390,9 @@ struct FuncDestructor {
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define MFUNCTION(zName, nArg, xPtr, xFunc) \
+ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
+ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
@@ -17403,7 +17487,12 @@ struct Column {
u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
-/* Allowed values for Column.colFlags:
+/* Allowed values for Column.colFlags.
+**
+** Constraints:
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
*/
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
@@ -17579,7 +17668,6 @@ struct Table {
#endif
Trigger *pTrigger; /* List of triggers stored in pSchema */
Schema *pSchema; /* Schema that contains this table */
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
};
/*
@@ -17593,11 +17681,12 @@ struct Table {
**
** Constraints:
**
-** TF_HasVirtual == COLFLAG_Virtual
-** TF_HasStored == COLFLAG_Stored
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
*/
#define TF_Readonly 0x0001 /* Read-only system table */
-#define TF_Ephemeral 0x0002 /* An ephemeral table */
+#define TF_HasHidden 0x0002 /* Has one or more hidden columns */
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
@@ -17612,6 +17701,7 @@ struct Table {
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
+#define TF_Ephemeral 0x4000 /* An ephemeral table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -17708,16 +17798,22 @@ struct FKey {
** is returned. REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed. Processing continues and no error is reported.
+** UPDATE applies to insert operations only and means that the insert
+** is omitted and the DO UPDATE clause of an upsert is run instead.
**
-** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
+** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
-** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
+** key is set to NULL. SETDFLT means that the foreign key is set
+** to its default value. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
**
+** The OE_Default value is a place holder that means to use whatever
+** conflict resolution algorthm is required from context.
+**
** The following symbolic values are used to record which type
-** of action to take.
+** of conflict resolution action to take.
*/
#define OE_None 0 /* There is no constraint to check */
#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
@@ -17974,7 +18070,6 @@ struct AggInfo {
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
- AggInfo *pNext; /* Next in list of them all */
};
/*
@@ -18103,7 +18198,7 @@ struct Expr {
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
- i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
+ int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
@@ -18145,7 +18240,7 @@ struct Expr {
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
-#define EP_Alias 0x400000 /* Is an alias for a result set column */
+ /* 0x400000 // Available */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
@@ -18294,6 +18389,45 @@ struct IdList {
};
/*
+** The SrcItem object represents a single term in the FROM clause of a query.
+** The SrcList object is mostly an array of SrcItems.
+*/
+struct SrcItem {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ char *zName; /* Name of the table */
+ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
+ Table *pTab; /* An SQL table corresponding to zName */
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to manifest a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
+ struct {
+ u8 jointype; /* Type of join between this table and the previous */
+ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
+ unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
+ unsigned isTabFunc :1; /* True if table-valued-function syntax */
+ unsigned isCorrelated :1; /* True if sub-query is correlated */
+ unsigned viaCoroutine :1; /* Implemented as a co-routine */
+ unsigned isRecursive :1; /* True for recursive reference in WITH */
+ unsigned fromDDL :1; /* Comes from sqlite_schema */
+ unsigned isCte :1; /* This is a CTE */
+ } fg;
+ int iCursor; /* The VDBE cursor number used to access this table */
+ Expr *pOn; /* The ON clause of a join */
+ IdList *pUsing; /* The USING clause of a join */
+ Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
+ union {
+ char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
+ ExprList *pFuncArg; /* Arguments to table-valued-function */
+ } u1;
+ union {
+ Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
+ CteUse *pCteUse; /* CTE Usage info info fg.isCte is true */
+ } u2;
+};
+
+/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
@@ -18315,36 +18449,7 @@ struct IdList {
struct SrcList {
int nSrc; /* Number of tables or subqueries in the FROM clause */
u32 nAlloc; /* Number of entries allocated in a[] below */
- struct SrcList_item {
- Schema *pSchema; /* Schema to which this item is fixed */
- char *zDatabase; /* Name of database holding this table */
- char *zName; /* Name of the table */
- char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int addrFillSub; /* Address of subroutine to manifest a subquery */
- int regReturn; /* Register holding return address of addrFillSub */
- int regResult; /* Registers holding results of a co-routine */
- struct {
- u8 jointype; /* Type of join between this table and the previous */
- unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
- unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
- unsigned isTabFunc :1; /* True if table-valued-function syntax */
- unsigned isCorrelated :1; /* True if sub-query is correlated */
- unsigned viaCoroutine :1; /* Implemented as a co-routine */
- unsigned isRecursive :1; /* True for recursive reference in WITH */
- unsigned fromDDL :1; /* Comes from sqlite_schema */
- } fg;
- int iCursor; /* The VDBE cursor number used to access this table */
- Expr *pOn; /* The ON clause of a join */
- IdList *pUsing; /* The USING clause of a join */
- Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
- union {
- char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
- ExprList *pFuncArg; /* Arguments to table-valued-function */
- } u1;
- Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
- } a[1]; /* One entry for each identifier on the list */
+ SrcItem a[1]; /* One entry for each identifier on the list */
};
/*
@@ -18420,6 +18525,7 @@ struct NameContext {
ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
+ int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
@@ -18448,6 +18554,7 @@ struct NameContext {
#define NC_UEList 0x00080 /* True if uNC.pEList is used */
#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
+#define NC_UBaseReg 0x00400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
#define NC_Complex 0x02000 /* True if a function or subquery seen */
#define NC_AllowWin 0x04000 /* Window functions are allowed here */
@@ -18471,15 +18578,21 @@ struct NameContext {
** WHERE clause is omitted.
*/
struct Upsert {
- ExprList *pUpsertTarget; /* Optional description of conflicting index */
+ ExprList *pUpsertTarget; /* Optional description of conflict target */
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
- /* The fields above comprise the parse tree for the upsert clause.
- ** The fields below are used to transfer information from the INSERT
- ** processing down into the UPDATE processing while generating code.
- ** Upsert owns the memory allocated above, but not the memory below. */
- Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
+ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
+ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
+ /* Above this point is the parse tree for the ON CONFLICT clauses.
+ ** The next group of fields stores intermediate data. */
+ void *pToFree; /* Free memory when deleting the Upsert object */
+ /* All fields above are owned by the Upsert object and must be freed
+ ** when the Upsert is destroyed. The fields below are used to transfer
+ ** information from the INSERT processing down into the UPDATE processing
+ ** while generating code. The fields below are owned by the INSERT
+ ** statement and will be freed by INSERT processing. */
+ Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
SrcList *pUpsertSrc; /* Table to be updated */
int regData; /* First register holding array of VALUES */
int iDataCur; /* Index of the data cursor */
@@ -18559,6 +18672,8 @@ struct Select {
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
#define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */
+#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
+#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -18730,6 +18845,17 @@ struct TriggerPrg {
#endif
/*
+** An instance of the ParseCleanup object specifies an operation that
+** should be performed after parsing to deallocation resources obtained
+** during the parse and which are no longer needed.
+*/
+struct ParseCleanup {
+ ParseCleanup *pNext; /* Next cleanup task */
+ void *pPtr; /* Pointer to object to deallocate */
+ void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
+};
+
+/*
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
@@ -18760,6 +18886,9 @@ struct Parse {
u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 disableVtab; /* Disable all virtual tables for this parse */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
+#endif
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -18787,12 +18916,15 @@ struct Parse {
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
Parse *pParentParse; /* Parent parser if this parser is nested */
- AggInfo *pAggList; /* List of all AggInfo objects */
- int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
+ union {
+ int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
+ Returning *pReturning; /* The RETURNING clause */
+ } u1;
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
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 */
@@ -18838,10 +18970,9 @@ struct Parse {
Token sArg; /* Complete text of a module argument */
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
- Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
- With *pWithToFree; /* Free this WITH object at the end of the parse */
+ ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
#ifndef SQLITE_OMIT_ALTERTABLE
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
#endif
@@ -18921,6 +19052,7 @@ struct AuthContext {
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
+#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
/*
* Each trigger present in the database schema is stored as an instance of
@@ -18942,6 +19074,7 @@ struct Trigger {
char *table; /* The table or view to which the trigger applies */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
+ u8 bReturning; /* This trigger implements a RETURNING clause */
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
the <column-list> is stored here */
@@ -19000,14 +19133,15 @@ struct Trigger {
*
*/
struct TriggerStep {
- u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
+ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
+ ** or TK_RETURNING */
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 ... */
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 */
+ ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
IdList *pIdList; /* Column names for INSERT */
Upsert *pUpsert; /* Upsert clauses on an INSERT */
char *zSpan; /* Original SQL text of this command */
@@ -19016,18 +19150,16 @@ struct TriggerStep {
};
/*
-** The following structure contains information used by the sqliteFix...
-** routines as they walk the parse tree to make database references
-** explicit.
+** Information about a RETURNING clause
*/
-typedef struct DbFixer DbFixer;
-struct DbFixer {
- Parse *pParse; /* The parsing context. Error messages written here */
- Schema *pSchema; /* Fix items to this schema */
- u8 bTemp; /* True for TEMP schema entries */
- const char *zDb; /* Make sure all objects are contained in this database */
- const char *zType; /* Type of the container - used for error messages */
- const Token *pName; /* Name of the container - used for error messages */
+struct Returning {
+ Parse *pParse; /* The parse that includes the RETURNING clause */
+ ExprList *pReturnEL; /* List of expressions to return */
+ Trigger retTrig; /* The transient trigger that implements RETURNING */
+ TriggerStep retTStep; /* The trigger step */
+ int iRetCur; /* Transient table holding RETURNING results */
+ int nRetCol; /* Number of in pReturnEL after expansion */
+ int iRetReg; /* Register array for holding a row of RETURNING */
};
/*
@@ -19067,7 +19199,8 @@ typedef struct {
/*
** Allowed values for mInitFlags
*/
-#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */
+#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
+#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
/*
** Structure containing global configuration data for the SQLite library.
@@ -19179,10 +19312,26 @@ struct Walker {
struct WhereConst *pConst; /* WHERE clause constants */
struct RenameCtx *pRename; /* RENAME COLUMN context */
struct Table *pTab; /* Table of generated column */
- struct SrcList_item *pSrcItem; /* A single FROM clause item */
+ SrcItem *pSrcItem; /* A single FROM clause item */
+ DbFixer *pFix;
} u;
};
+/*
+** The following structure contains information used by the sqliteFix...
+** routines as they walk the parse tree to make database references
+** explicit.
+*/
+struct DbFixer {
+ Parse *pParse; /* The parsing context. Error messages written here */
+ Walker w; /* Walker object */
+ Schema *pSchema; /* Fix items to this schema */
+ u8 bTemp; /* True for TEMP schema entries */
+ const char *zDb; /* Make sure all objects are contained in this database */
+ const char *zType; /* Type of the container - used for error messages */
+ const Token *pName; /* Name of the container - used for error messages */
+};
+
/* Forward declarations */
SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
@@ -19208,20 +19357,55 @@ SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
#define WRC_Abort 2 /* Abandon the tree walk */
/*
-** An instance of this structure represents a set of one or more CTEs
-** (common table expressions) created by a single WITH clause.
+** A single common table expression
+*/
+struct Cte {
+ char *zName; /* Name of this CTE */
+ ExprList *pCols; /* List of explicit column names, or NULL */
+ Select *pSelect; /* The definition of this CTE */
+ const char *zCteErr; /* Error message for circular references */
+ CteUse *pUse; /* Usage information for this CTE */
+ u8 eM10d; /* The MATERIALIZED flag */
+};
+
+/*
+** Allowed values for the materialized flag (eM10d):
+*/
+#define M10d_Yes 0 /* AS MATERIALIZED */
+#define M10d_Any 1 /* Not specified. Query planner's choice */
+#define M10d_No 2 /* AS NOT MATERIALIZED */
+
+/*
+** An instance of the With object represents a WITH clause containing
+** one or more CTEs (common table expressions).
*/
struct With {
- int nCte; /* Number of CTEs in the WITH clause */
- With *pOuter; /* Containing WITH clause, or NULL */
- struct Cte { /* For each CTE in the WITH clause.... */
- char *zName; /* Name of this CTE */
- ExprList *pCols; /* List of explicit column names, or NULL */
- Select *pSelect; /* The definition of this CTE */
- const char *zCteErr; /* Error message for circular references */
- } a[1];
+ int nCte; /* Number of CTEs in the WITH clause */
+ With *pOuter; /* Containing WITH clause, or NULL */
+ Cte a[1]; /* For each CTE in the WITH clause.... */
};
+/*
+** The Cte object is not guaranteed to persist for the entire duration
+** of code generation. (The query flattener or other parser tree
+** edits might delete it.) The following object records information
+** about each Common Table Expression that must be preserved for the
+** duration of the parse.
+**
+** The CteUse objects are freed using sqlite3ParserAddCleanup() rather
+** than sqlite3SelectDelete(), which is what enables them to persist
+** until the end of code generation.
+*/
+struct CteUse {
+ int nUse; /* Number of users of this CTE */
+ int addrM9e; /* Start of subroutine to compute materialization */
+ int regRtn; /* Return address register for addrM9e subroutine */
+ int iCur; /* Ephemeral table holding the materialization */
+ LogEst nRowEst; /* Estimated number of rows in the table */
+ u8 eM10d; /* The MATERIALIZED flag */
+};
+
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
@@ -19567,6 +19751,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
+SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
@@ -19615,6 +19800,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*)
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
+SQLITE_PRIVATE void sqlite3AddReturning(Parse*,ExprList*);
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
#define sqlite3CodecQueryParameters(A,B,C) 0
@@ -19680,7 +19866,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, T
Token*, Select*, Expr*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
-SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
+SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *);
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*);
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
@@ -19708,6 +19894,7 @@ SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
+SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
@@ -19741,7 +19928,7 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
#define LOCATE_VIEW 0x01
#define LOCATE_NOERR 0x02
SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
-SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *);
SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
@@ -19869,6 +20056,7 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
#endif
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
+SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol);
SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int);
SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int);
@@ -19891,7 +20079,6 @@ SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Tok
SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
-SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64);
SQLITE_PRIVATE void sqlite3Int64ToText(i64,char*);
@@ -19954,6 +20141,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
SQLITE_PRIVATE void sqlite3Error(sqlite3*,int);
+SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*);
SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int);
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
@@ -20017,7 +20205,6 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
-SQLITE_API extern u32 sqlite3_unsupported_selecttrace;
#ifndef SQLITE_OMIT_WSD
SQLITE_PRIVATE int sqlite3PendingByte;
#endif
@@ -20036,7 +20223,7 @@ SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, 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*, struct SrcList_item*);
+SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
SQLITE_PRIVATE int sqlite3MatchEName(
const struct ExprList_item*,
@@ -20054,6 +20241,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
+SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*);
SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
@@ -20077,6 +20265,7 @@ SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
+SQLITE_PRIVATE const char *sqlite3SelectOpName(int);
SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse*, ExprList*);
#ifdef SQLITE_DEBUG
@@ -20207,6 +20396,7 @@ SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE void sqlite3ParserReset(Parse*);
+SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
#ifdef SQLITE_ENABLE_NORMALIZE
SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*);
#endif
@@ -20221,23 +20411,32 @@ SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
#endif
#ifndef SQLITE_OMIT_CTE
-SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
+SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8);
+SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*);
+SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*);
SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*);
SQLITE_PRIVATE void sqlite3WithPush(Parse*, With*, u8);
#else
-#define sqlite3WithPush(x,y,z)
-#define sqlite3WithDelete(x,y)
+# define sqlite3CteNew(P,T,E,S) ((void*)0)
+# define sqlite3CteDelete(D,C)
+# define sqlite3CteWithAdd(P,W,C) ((void*)0)
+# define sqlite3WithDelete(x,y)
+# define sqlite3WithPush(x,y,z)
#endif
#ifndef SQLITE_OMIT_UPSERT
-SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
+SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*);
SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
+SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
+SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*);
#else
-#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
+#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
#define sqlite3UpsertDelete(x,y)
-#define sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0)
+#define sqlite3UpsertNextIsIPK(x) 0
#endif
@@ -20733,9 +20932,10 @@ SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
#endif
/*
-** Flags for select tracing and the ".selecttrace" macro of the CLI
+** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
*/
-SQLITE_API u32 sqlite3_unsupported_selecttrace = 0;
+SQLITE_PRIVATE u32 sqlite3SelectTrace = 0;
+SQLITE_PRIVATE u32 sqlite3WhereTrace = 0;
/* #include "opcodes.h" */
/*
@@ -20859,6 +21059,7 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
+ Bool hasBeenDuped:1; /* This cursor was source or target of OP_OpenDup */
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
@@ -21154,7 +21355,7 @@ struct Vdbe {
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
- u32 magic; /* Magic number for sanity checking */
+ u32 iVdbeMagic; /* Magic number defining state of the SQL statement */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
u32 cacheCtr; /* VdbeCursor row cache generation counter */
@@ -22659,6 +22860,7 @@ static int isDate(
int eType;
memset(p, 0, sizeof(*p));
if( argc==0 ){
+ if( !sqlite3NotPureFunc(context) ) return 1;
return setDateTimeToCurrent(context, p);
}
if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
@@ -23159,6 +23361,8 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_TEST
if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
&& op!=SQLITE_FCNTL_LOCK_TIMEOUT
+ && op!=SQLITE_FCNTL_CKPT_DONE
+ && op!=SQLITE_FCNTL_CKPT_START
){
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
** is using a regular VFS, it is called after the corresponding
@@ -23169,7 +23373,12 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
** The core must call OsFileControl() though, not OsFileControlHint(),
** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
** means the commit really has failed and an error should be returned
- ** to the user. */
+ ** to the user.
+ **
+ ** The CKPT_DONE and CKPT_START file-controls are write-only signals
+ ** to the cksumvfs. Their return code is meaningless and is ignored
+ ** by the SQLite core, so there is no point in simulating OOMs for them.
+ */
DO_OS_MALLOC_TEST(id);
}
#endif
@@ -29068,7 +29277,7 @@ SQLITE_API void sqlite3_str_vappendf(
case etSRCLIST: {
SrcList *pSrc;
int k;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
pSrc = va_arg(ap, SrcList*);
k = va_arg(ap, int);
@@ -29133,7 +29342,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}else{
char *zOld = isMalloced(p) ? p->zText : 0;
i64 szNew = p->nChar;
- szNew += N + 1;
+ szNew += (sqlite3_int64)N + 1;
if( szNew+p->nChar<=p->mxAlloc ){
/* Force exponential buffer size growth as long as it does not overflow,
** to avoid having to call this routine too often */
@@ -29636,7 +29845,10 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
}
sqlite3_str_appendf(&x, ")");
}
- sqlite3_str_appendf(&x, " AS");
+ if( pCte->pUse ){
+ sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
+ pCte->pUse->nUse);
+ }
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
@@ -29652,7 +29864,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
int i;
for(i=0; i<pSrc->nSrc; i++){
- const struct SrcList_item *pItem = &pSrc->a[i];
+ const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
@@ -29675,6 +29887,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
if( pItem->fg.fromDDL ){
sqlite3_str_appendf(&x, " DDL");
}
+ if( pItem->fg.isCte ){
+ sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
+ }
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
if( pItem->pSelect ){
@@ -31372,6 +31587,16 @@ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){
}
/*
+** The equivalent of sqlite3Error(db, SQLITE_OK). Clear the error state
+** and error message.
+*/
+SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){
+ assert( db!=0 );
+ db->errCode = SQLITE_OK;
+ if( db->pErr ) sqlite3ValueSetNull(db->pErr);
+}
+
+/*
** Load the sqlite3.iSysErrno field if that is an appropriate thing
** to do based on the SQLite error code in rc.
*/
@@ -33317,103 +33542,105 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 77 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
/* 78 */ "SCopy" OpHelp("r[P2]=r[P1]"),
/* 79 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
- /* 80 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 81 */ "CollSeq" OpHelp(""),
- /* 82 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 83 */ "RealAffinity" OpHelp(""),
- /* 84 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 85 */ "Permutation" OpHelp(""),
- /* 86 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
- /* 87 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
- /* 88 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
- /* 89 */ "Column" OpHelp("r[P3]=PX"),
- /* 90 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 91 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 92 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 93 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
- /* 94 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
- /* 95 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 96 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 97 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 98 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 99 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 100 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 102 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 103 */ "Count" OpHelp("r[P2]=count()"),
- /* 104 */ "ReadCookie" OpHelp(""),
- /* 105 */ "String8" OpHelp("r[P2]='P4'"),
- /* 106 */ "SetCookie" OpHelp(""),
- /* 107 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 108 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 109 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 110 */ "OpenDup" OpHelp(""),
- /* 111 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 112 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 113 */ "SorterOpen" OpHelp(""),
- /* 114 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 115 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 116 */ "Close" OpHelp(""),
- /* 117 */ "ColumnsUsed" OpHelp(""),
- /* 118 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
- /* 119 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
- /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 123 */ "Delete" OpHelp(""),
- /* 124 */ "ResetCount" OpHelp(""),
- /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 126 */ "SorterData" OpHelp("r[P2]=data"),
- /* 127 */ "RowData" OpHelp("r[P2]=data"),
- /* 128 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 129 */ "NullRow" OpHelp(""),
- /* 130 */ "SeekEnd" OpHelp(""),
- /* 131 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 132 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 136 */ "FinishSeek" OpHelp(""),
- /* 137 */ "Destroy" OpHelp(""),
- /* 138 */ "Clear" OpHelp(""),
- /* 139 */ "ResetSorter" OpHelp(""),
- /* 140 */ "Real" OpHelp("r[P2]=P4"),
- /* 141 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 142 */ "SqlExec" OpHelp(""),
- /* 143 */ "ParseSchema" OpHelp(""),
- /* 144 */ "LoadAnalysis" OpHelp(""),
- /* 145 */ "DropTable" OpHelp(""),
- /* 146 */ "DropIndex" OpHelp(""),
- /* 147 */ "DropTrigger" OpHelp(""),
- /* 148 */ "IntegrityCk" OpHelp(""),
- /* 149 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 150 */ "Param" OpHelp(""),
- /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
- /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"),
- /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 159 */ "Expire" OpHelp(""),
- /* 160 */ "CursorLock" OpHelp(""),
- /* 161 */ "CursorUnlock" OpHelp(""),
- /* 162 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 163 */ "VBegin" OpHelp(""),
- /* 164 */ "VCreate" OpHelp(""),
- /* 165 */ "VDestroy" OpHelp(""),
- /* 166 */ "VOpen" OpHelp(""),
- /* 167 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 168 */ "VRename" OpHelp(""),
- /* 169 */ "Pagecount" OpHelp(""),
- /* 170 */ "MaxPgcnt" OpHelp(""),
- /* 171 */ "Trace" OpHelp(""),
- /* 172 */ "CursorHint" OpHelp(""),
- /* 173 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
- /* 174 */ "Noop" OpHelp(""),
- /* 175 */ "Explain" OpHelp(""),
- /* 176 */ "Abortable" OpHelp(""),
+ /* 80 */ "ChngCntRow" OpHelp("output=r[P1]"),
+ /* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 82 */ "CollSeq" OpHelp(""),
+ /* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 84 */ "RealAffinity" OpHelp(""),
+ /* 85 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 86 */ "Permutation" OpHelp(""),
+ /* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
+ /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 90 */ "Column" OpHelp("r[P3]=PX"),
+ /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 92 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 93 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 94 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
+ /* 95 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
+ /* 96 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 97 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 98 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 99 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 100 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 101 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 102 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 103 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
+ /* 104 */ "Count" OpHelp("r[P2]=count()"),
+ /* 105 */ "ReadCookie" OpHelp(""),
+ /* 106 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 107 */ "SetCookie" OpHelp(""),
+ /* 108 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 109 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 110 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 111 */ "OpenDup" OpHelp(""),
+ /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 114 */ "SorterOpen" OpHelp(""),
+ /* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 116 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 117 */ "Close" OpHelp(""),
+ /* 118 */ "ColumnsUsed" OpHelp(""),
+ /* 119 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
+ /* 120 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
+ /* 121 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 122 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 123 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 124 */ "RowCell" OpHelp(""),
+ /* 125 */ "Delete" OpHelp(""),
+ /* 126 */ "ResetCount" OpHelp(""),
+ /* 127 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 128 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 129 */ "RowData" OpHelp("r[P2]=data"),
+ /* 130 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 131 */ "NullRow" OpHelp(""),
+ /* 132 */ "SeekEnd" OpHelp(""),
+ /* 133 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 134 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 135 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 136 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 137 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 138 */ "FinishSeek" OpHelp(""),
+ /* 139 */ "Destroy" OpHelp(""),
+ /* 140 */ "Clear" OpHelp(""),
+ /* 141 */ "ResetSorter" OpHelp(""),
+ /* 142 */ "Real" OpHelp("r[P2]=P4"),
+ /* 143 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 144 */ "SqlExec" OpHelp(""),
+ /* 145 */ "ParseSchema" OpHelp(""),
+ /* 146 */ "LoadAnalysis" OpHelp(""),
+ /* 147 */ "DropTable" OpHelp(""),
+ /* 148 */ "DropIndex" OpHelp(""),
+ /* 149 */ "DropTrigger" OpHelp(""),
+ /* 150 */ "IntegrityCk" OpHelp(""),
+ /* 151 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 152 */ "Param" OpHelp(""),
+ /* 153 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 154 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 155 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 156 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 157 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 158 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 159 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 160 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 161 */ "Expire" OpHelp(""),
+ /* 162 */ "CursorLock" OpHelp(""),
+ /* 163 */ "CursorUnlock" OpHelp(""),
+ /* 164 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 165 */ "VBegin" OpHelp(""),
+ /* 166 */ "VCreate" OpHelp(""),
+ /* 167 */ "VDestroy" OpHelp(""),
+ /* 168 */ "VOpen" OpHelp(""),
+ /* 169 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 170 */ "VRename" OpHelp(""),
+ /* 171 */ "Pagecount" OpHelp(""),
+ /* 172 */ "MaxPgcnt" OpHelp(""),
+ /* 173 */ "Trace" OpHelp(""),
+ /* 174 */ "CursorHint" OpHelp(""),
+ /* 175 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 176 */ "Noop" OpHelp(""),
+ /* 177 */ "Explain" OpHelp(""),
+ /* 178 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -39982,7 +40209,8 @@ static int unixBackupDir(const char *z, int *pJ){
int j = *pJ;
int i;
if( j<=0 ) return 0;
- for(i=j-1; ALWAYS(i>0) && z[i-1]!='/'; i--){}
+ for(i=j-1; i>0 && z[i-1]!='/'; i--){}
+ if( i==0 ) return 0;
if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
*pJ = i-1;
return 1;
@@ -52341,6 +52569,7 @@ struct PagerSavepoint {
Bitvec *pInSavepoint; /* Set of pages in this savepoint */
Pgno nOrig; /* Original number of pages in file */
Pgno iSubRec; /* Index of first record in sub-journal */
+ int bTruncateOnRelease; /* If stmt journal may be truncated on RELEASE */
#ifndef SQLITE_OMIT_WAL
u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
#endif
@@ -52976,6 +53205,9 @@ static int subjRequiresPage(PgHdr *pPg){
for(i=0; i<pPager->nSavepoint; i++){
p = &pPager->aSavepoint[i];
if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
+ for(i=i+1; i<pPager->nSavepoint; i++){
+ pPager->aSavepoint[i].bTruncateOnRelease = 0;
+ }
return 1;
}
}
@@ -58754,6 +58986,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){
}
aNew[ii].iSubRec = pPager->nSubRec;
aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
+ aNew[ii].bTruncateOnRelease = 1;
if( !aNew[ii].pInSavepoint ){
return SQLITE_NOMEM_BKPT;
}
@@ -58835,13 +59068,15 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
/* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( op==SAVEPOINT_RELEASE ){
- if( nNew==0 && isOpen(pPager->sjfd) ){
+ PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
+ if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
/* Only truncate if it is an in-memory sub-journal. */
if( sqlite3JournalIsInMemory(pPager->sjfd) ){
- rc = sqlite3OsTruncate(pPager->sjfd, 0);
+ i64 sz = (pPager->pageSize+4)*pRel->iSubRec;
+ rc = sqlite3OsTruncate(pPager->sjfd, sz);
assert( rc==SQLITE_OK );
}
- pPager->nSubRec = 0;
+ pPager->nSubRec = pRel->iSubRec;
}
}
/* Else this is a rollback operation, playback the specified savepoint.
@@ -64032,7 +64267,7 @@ struct Btree {
u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
int nBackup; /* Number of backup operations reading this btree */
- u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
+ u32 iBDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
#ifdef SQLITE_DEBUG
@@ -64137,6 +64372,7 @@ struct BtShared {
Btree *pWriter; /* Btree with currently open write transaction */
#endif
u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
+ int nPreformatSize; /* Size of last cell written by TransferRow() */
};
/*
@@ -65851,6 +66087,24 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
}
/*
+** Given a record with nPayload bytes of payload stored within btree
+** page pPage, return the number of bytes of payload stored locally.
+*/
+static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
+ int maxLocal; /* Maximum amount of payload held locally */
+ maxLocal = pPage->maxLocal;
+ if( nPayload<=maxLocal ){
+ return nPayload;
+ }else{
+ int minLocal; /* Minimum amount of payload held locally */
+ int surplus; /* Overflow payload available for local storage */
+ minLocal = pPage->minLocal;
+ surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
+ return ( surplus <= maxLocal ) ? surplus : minLocal;
+ }
+}
+
+/*
** The following routines are implementations of the MemPage.xParseCell()
** method.
**
@@ -67426,19 +67680,23 @@ static void freeTempSpace(BtShared *pBt){
*/
SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
- BtCursor *pCur;
/* Close all cursors opened via this handle. */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
- pCur = pBt->pCursor;
- while( pCur ){
- BtCursor *pTmp = pCur;
- pCur = pCur->pNext;
- if( pTmp->pBtree==p ){
- sqlite3BtreeCloseCursor(pTmp);
+
+ /* Verify that no other cursors have this Btree open */
+#ifdef SQLITE_DEBUG
+ {
+ BtCursor *pCur = pBt->pCursor;
+ while( pCur ){
+ BtCursor *pTmp = pCur;
+ pCur = pCur->pNext;
+ assert( pTmp->pBtree!=p );
+
}
}
+#endif
/* Rollback any active transaction and free the handle structure.
** The call to sqlite3BtreeRollback() drops any table-locks held by
@@ -67590,6 +67848,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve,
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pCursor );
+ if( nReserve>32 && pageSize==512 ) pageSize = 1024;
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@@ -68819,7 +69078,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
sqlite3BtreeLeave(p);
return rc;
}
- p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
+ p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
@@ -69229,7 +69488,14 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
sqlite3_free(pCur->pKey);
- sqlite3BtreeLeave(pBtree);
+ if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){
+ /* Since the BtShared is not sharable, there is no need to
+ ** worry about the missing sqlite3BtreeLeave() call here. */
+ assert( pBtree->sharable==0 );
+ sqlite3BtreeClose(pBtree);
+ }else{
+ sqlite3BtreeLeave(pBtree);
+ }
pCur->pBtree = 0;
}
return SQLITE_OK;
@@ -71844,7 +72110,9 @@ static int pageFreeArray(
}
pFree = pCell;
szFree = sz;
- if( pFree+sz>pEnd ) return 0;
+ if( NEVER(pFree+sz>pEnd) ){
+ return 0; /* Corruption - should be previously detected */
+ }
}else{
pFree = pCell;
szFree += sz;
@@ -72663,6 +72931,9 @@ static int balance_nonroot(
apOld[i] = 0;
rc = sqlite3PagerWrite(pNew->pDbPage);
nNew++;
+ if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
if( rc ) goto balance_cleanup;
}else{
assert( i>0 );
@@ -72699,7 +72970,7 @@ static int balance_nonroot(
aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
aPgFlags[i] = apNew[i]->pDbPage->flags;
for(j=0; j<i; j++){
- if( aPgno[j]==aPgno[i] ){
+ if( NEVER(aPgno[j]==aPgno[i]) ){
/* This branch is taken if the set of sibling pages somehow contains
** duplicate entries. This can happen if the database is corrupt.
** It would be simpler to detect this as part of the loop below, but
@@ -72817,6 +73088,7 @@ static int balance_nonroot(
u8 *pCell;
u8 *pTemp;
int sz;
+ u8 *pSrcEnd;
MemPage *pNew = apNew[i];
j = cntNew[i];
@@ -72860,6 +73132,12 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
+ for(k=0; b.ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pSrcEnd = b.apEnd[k];
+ if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto balance_cleanup;
+ }
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -73367,7 +73645,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
- assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
+ assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
+ assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
@@ -73385,7 +73664,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
- assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
+ assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
/* Save the positions of any other cursors open on this table.
**
@@ -73495,7 +73774,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
|| CORRUPT_DB );
pPage = pCur->pPage;
- assert( pPage->intKey || pX->nKey>=0 );
+ assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
if( pCur->eState>CURSOR_INVALID ){
@@ -73512,7 +73791,21 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
assert( pPage->isInit );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
- rc = fillInCell(pPage, newCell, pX, &szNew);
+ if( flags & BTREE_PREFORMAT ){
+ rc = SQLITE_OK;
+ szNew = pBt->nPreformatSize;
+ if( szNew<4 ) szNew = 4;
+ if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
+ CellInfo info;
+ pPage->xParseCell(pPage, newCell, &info);
+ if( info.nPayload!=info.nLocal ){
+ Pgno ovfl = get4byte(&newCell[szNew-4]);
+ ptrmapPut(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
+ }
+ }
+ }else{
+ rc = fillInCell(pPage, newCell, pX, &szNew);
+ }
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
@@ -73620,6 +73913,114 @@ end_insert:
}
/*
+** This function is used as part of copying the current row from cursor
+** pSrc into cursor pDest. If the cursors are open on intkey tables, then
+** parameter iKey is used as the rowid value when the record is copied
+** into pDest. Otherwise, the record is copied verbatim.
+**
+** This function does not actually write the new value to cursor pDest.
+** Instead, it creates and populates any required overflow pages and
+** writes the data for the new cell into the BtShared.pTmpSpace buffer
+** for the destination database. The size of the cell, in bytes, is left
+** in BtShared.nPreformatSize. The caller completes the insertion by
+** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
+ int rc = SQLITE_OK;
+ BtShared *pBt = pDest->pBt;
+ u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
+ const u8 *aIn; /* Pointer to next input buffer */
+ u32 nIn; /* Size of input buffer aIn[] */
+ u32 nRem; /* Bytes of data still to copy */
+
+ getCellInfo(pSrc);
+ aOut += putVarint32(aOut, pSrc->info.nPayload);
+ if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
+ nIn = pSrc->info.nLocal;
+ aIn = pSrc->info.pPayload;
+ if( aIn+nIn>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nRem = pSrc->info.nPayload;
+ if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
+ memcpy(aOut, aIn, nIn);
+ pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ }else{
+ Pager *pSrcPager = pSrc->pBt->pPager;
+ u8 *pPgnoOut = 0;
+ Pgno ovflIn = 0;
+ DbPage *pPageIn = 0;
+ MemPage *pPageOut = 0;
+ u32 nOut; /* Size of output buffer aOut[] */
+
+ nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
+ pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ if( nOut<pSrc->info.nPayload ){
+ pPgnoOut = &aOut[nOut];
+ pBt->nPreformatSize += 4;
+ }
+
+ if( nRem>nIn ){
+ if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
+ }
+
+ do {
+ nRem -= nOut;
+ do{
+ assert( nOut>0 );
+ if( nIn>0 ){
+ int nCopy = MIN(nOut, nIn);
+ memcpy(aOut, aIn, nCopy);
+ nOut -= nCopy;
+ nIn -= nCopy;
+ aOut += nCopy;
+ aIn += nCopy;
+ }
+ if( nOut>0 ){
+ sqlite3PagerUnref(pPageIn);
+ pPageIn = 0;
+ rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
+ if( rc==SQLITE_OK ){
+ aIn = (const u8*)sqlite3PagerGetData(pPageIn);
+ ovflIn = get4byte(aIn);
+ aIn += 4;
+ nIn = pSrc->pBt->usableSize - 4;
+ }
+ }
+ }while( rc==SQLITE_OK && nOut>0 );
+
+ if( rc==SQLITE_OK && nRem>0 ){
+ Pgno pgnoNew;
+ MemPage *pNew = 0;
+ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+ put4byte(pPgnoOut, pgnoNew);
+ if( ISAUTOVACUUM && pPageOut ){
+ ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
+ }
+ releasePage(pPageOut);
+ pPageOut = pNew;
+ if( pPageOut ){
+ pPgnoOut = pPageOut->aData;
+ put4byte(pPgnoOut, 0);
+ aOut = &pPgnoOut[4];
+ nOut = MIN(pBt->usableSize - 4, nRem);
+ }
+ }
+ }while( nRem>0 && rc==SQLITE_OK );
+
+ releasePage(pPageOut);
+ sqlite3PagerUnref(pPageIn);
+ }
+
+ return rc;
+}
+
+/*
** Delete the entry that the cursor is pointing to.
**
** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
@@ -74216,7 +74617,7 @@ SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
assert( idx>=0 && idx<=15 );
if( idx==BTREE_DATA_VERSION ){
- *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
+ *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion;
}else{
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
}
@@ -78007,7 +78408,7 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
- p->magic = VDBE_MAGIC_INIT;
+ p->iVdbeMagic = VDBE_MAGIC_INIT;
p->pParse = pParse;
pParse->pVdbe = p;
assert( pParse->aLabel==0 );
@@ -78208,7 +78609,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
VdbeOp *pOp;
i = p->nOp;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( op>=0 && op<0xff );
if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
@@ -78443,9 +78844,10 @@ SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){
** The zWhere string must have been obtained from sqlite3_malloc().
** This routine will take ownership of the allocated memory.
*/
-SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
int j;
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
+ sqlite3VdbeChangeP5(p, p5);
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
sqlite3MayAbort(p->pParse);
}
@@ -78537,7 +78939,7 @@ static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
- assert( v->magic==VDBE_MAGIC_INIT );
+ assert( v->iVdbeMagic==VDBE_MAGIC_INIT );
assert( j<-p->nLabel );
assert( j>=0 );
#ifdef SQLITE_DEBUG
@@ -78862,7 +79264,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
** Return the address of the next instruction to be inserted.
*/
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
return p->nOp;
}
@@ -78947,7 +79349,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(
int i;
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
return 0;
}
@@ -79271,7 +79673,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
sqlite3 *db;
assert( p!=0 );
db = p->db;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( p->aOp!=0 || db->mallocFailed );
if( db->mallocFailed ){
if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
@@ -79400,7 +79802,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
if( addr<0 ){
addr = p->nOp - 1;
}
@@ -80085,7 +80487,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
Op *pOp; /* Current opcode */
assert( p->explain );
- assert( p->magic==VDBE_MAGIC_RUN );
+ assert( p->iVdbeMagic==VDBE_MAGIC_RUN );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
/* Even though this opcode does not use dynamic strings for
@@ -80265,14 +80667,14 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
int i;
#endif
assert( p!=0 );
- assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT || p->iVdbeMagic==VDBE_MAGIC_RESET );
/* There should be at least one opcode.
*/
assert( p->nOp>0 );
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
- p->magic = VDBE_MAGIC_RUN;
+ p->iVdbeMagic = VDBE_MAGIC_RUN;
#ifdef SQLITE_DEBUG
for(i=0; i<p->nMem; i++){
@@ -80328,8 +80730,10 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
assert( p!=0 );
assert( p->nOp>0 );
assert( pParse!=0 );
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( pParse==p->pParse );
+ p->pVList = pParse->pVList;
+ pParse->pVList = 0;
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
@@ -80414,8 +80818,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
}
}
- p->pVList = pParse->pVList;
- pParse->pVList = 0;
if( db->mallocFailed ){
p->nVar = 0;
p->nCursor = 0;
@@ -80443,20 +80845,15 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
return;
}
assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
+ assert( pCx->pBtx==0 || pCx->isEphemeral );
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
- if( pCx->isEphemeral ){
- if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx);
- /* The pCx->pCursor will be close automatically, if it exists, by
- ** the call above. */
- }else{
- assert( pCx->uc.pCursor!=0 );
- sqlite3BtreeCloseCursor(pCx->uc.pCursor);
- }
+ assert( pCx->uc.pCursor!=0 );
+ sqlite3BtreeCloseCursor(pCx->uc.pCursor);
break;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -81013,7 +81410,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
- if( p->magic!=VDBE_MAGIC_RUN ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
}
if( db->mallocFailed ){
@@ -81171,7 +81568,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
assert( db->nVdbeRead>=db->nVdbeWrite );
assert( db->nVdbeWrite>=0 );
}
- p->magic = VDBE_MAGIC_HALT;
+ p->iVdbeMagic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
@@ -81344,7 +81741,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
- p->magic = VDBE_MAGIC_RESET;
+ p->iVdbeMagic = VDBE_MAGIC_RESET;
return p->rc & db->errMask;
}
@@ -81354,7 +81751,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
*/
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
- if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
+ if( p->iVdbeMagic==VDBE_MAGIC_RUN || p->iVdbeMagic==VDBE_MAGIC_HALT ){
rc = sqlite3VdbeReset(p);
assert( (rc & p->db->errMask)==rc );
}
@@ -81415,7 +81812,7 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlite3DbFree(db, pSub);
}
- if( p->magic!=VDBE_MAGIC_INIT ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_INIT ){
releaseMemArray(p->aVar, p->nVar);
sqlite3DbFree(db, p->pVList);
sqlite3DbFree(db, p->pFree);
@@ -81463,7 +81860,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
- p->magic = VDBE_MAGIC_DEAD;
+ p->iVdbeMagic = VDBE_MAGIC_DEAD;
p->db = 0;
sqlite3DbFreeNN(db, p);
}
@@ -81540,6 +81937,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){
assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
if( p->deferredMoveto ){
u32 iMap;
+ assert( !p->isEphemeral );
if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){
*pp = p->pAltCursor;
*piCol = iMap - 1;
@@ -83842,7 +84240,7 @@ static int sqlite3Step(Vdbe *p){
int rc;
assert(p);
- if( p->magic!=VDBE_MAGIC_RUN ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){
/* We used to require that sqlite3_reset() be called before retrying
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
@@ -84558,7 +84956,7 @@ static int vdbeUnbind(Vdbe *p, int i){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
- if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE);
sqlite3_mutex_leave(p->db->mutex);
sqlite3_log(SQLITE_MISUSE,
@@ -84912,7 +85310,7 @@ SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){
*/
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
- return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
+ return v!=0 && v->iVdbeMagic==VDBE_MAGIC_RUN && v->pc>=0;
}
/*
@@ -85404,7 +85802,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
assert( idx>0 );
}
zRawSql += nToken;
- nextIndex = idx + 1;
+ nextIndex = MAX(idx + 1, nextIndex);
assert( idx>0 && idx<=p->nVar );
pVar = &p->aVar[idx-1];
if( pVar->flags & MEM_Null ){
@@ -85748,11 +86146,6 @@ static VdbeCursor *allocateCursor(
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
- /* Before calling sqlite3VdbeFreeCursor(), ensure the isEphemeral flag
- ** is clear. Otherwise, if this is an ephemeral cursor created by
- ** OP_OpenDup, the cursor will not be closed and will still be part
- ** of a BtShared.pCursor list. */
- if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0;
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
@@ -86250,7 +86643,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#endif
/*** INSERT STACK UNION HERE ***/
- assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
+ assert( p->iVdbeMagic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
sqlite3VdbeEnter(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
@@ -87010,6 +87403,26 @@ case OP_IntCopy: { /* out2 */
break;
}
+/* Opcode: ChngCntRow P1 P2 * * *
+** Synopsis: output=r[P1]
+**
+** Output value in register P1 as the chance count for a DML statement,
+** due to the "PRAGMA count_changes=ON" setting. Or, if there was a
+** foreign key error in the statement, trigger the error now.
+**
+** This opcode is a variant of OP_ResultRow that checks the foreign key
+** immediate constraint count and throws an error if the count is
+** non-zero. The P2 opcode must be 1.
+*/
+case OP_ChngCntRow: {
+ assert( pOp->p2==1 );
+ if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ /* Fall through to the next case, OP_ResultRow */
+ /* no break */ deliberate_fall_through
+}
+
/* Opcode: ResultRow P1 P2 * * *
** Synopsis: output=r[P1@P2]
**
@@ -87026,34 +87439,6 @@ case OP_ResultRow: {
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
- /* If this statement has violated immediate foreign key constraints, do
- ** not return the number of rows modified. And do not RELEASE the statement
- ** transaction. It needs to be rolled back. */
- if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
- assert( db->flags&SQLITE_CountRows );
- assert( p->usesStmtJournal );
- goto abort_due_to_error;
- }
-
- /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
- ** DML statements invoke this opcode to return the number of rows
- ** modified to the user. This is the only way that a VM that
- ** opens a statement transaction may invoke this opcode.
- **
- ** In case this is such a statement, close any statement transaction
- ** opened by this VM before returning control to the user. This is to
- ** ensure that statement-transactions are always nested, not overlapping.
- ** If the open statement-transaction is not closed here, then the user
- ** may step another VM that opens its own statement transaction. This
- ** may lead to overlapping statement transactions.
- **
- ** The statement transaction is never a top-level transaction. Hence
- ** the RELEASE call below can never fail.
- */
- assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
- rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
- assert( rc==SQLITE_OK );
-
/* Invalidate all ephemeral cursor row caches */
p->cacheCtr = (p->cacheCtr + 2)|1;
@@ -89446,7 +89831,7 @@ case OP_OpenDup: {
pOrig = p->apCsr[pOp->p2];
assert( pOrig );
- assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
+ assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */
pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
if( pCx==0 ) goto no_mem;
@@ -89456,7 +89841,10 @@ case OP_OpenDup: {
pCx->isTable = pOrig->isTable;
pCx->pgnoRoot = pOrig->pgnoRoot;
pCx->isOrdered = pOrig->isOrdered;
- rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pCx->pBtx = pOrig->pBtx;
+ pCx->hasBeenDuped = 1;
+ pOrig->hasBeenDuped = 1;
+ rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
** opened for a database. Since there is already an open cursor when this
@@ -89522,9 +89910,10 @@ case OP_OpenEphemeral: {
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
- if( pCx && pCx->pBtx ){
- /* If the ephermeral table is already open, erase all existing content
- ** so that the table is empty again, rather than creating a new table. */
+ if( pCx && !pCx->hasBeenDuped ){
+ /* If the ephermeral table is already open and has no duplicates from
+ ** OP_OpenDup, then erase all existing content so that the table is
+ ** empty again, rather than creating a new table. */
assert( pCx->isEphemeral );
pCx->seqCount = 0;
pCx->cacheStatus = CACHE_STALE;
@@ -89538,33 +89927,36 @@ case OP_OpenEphemeral: {
vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
- }
- if( rc==SQLITE_OK ){
- /* If a transient index is required, create it by calling
- ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
- ** opening it. If a transient table is required, just use the
- ** automatically created table with root-page 1 (an BLOB_INTKEY table).
- */
- if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
- assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot,
- BTREE_BLOBKEY | pOp->p5);
- if( rc==SQLITE_OK ){
- assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
- assert( pKeyInfo->db==db );
- assert( pKeyInfo->enc==ENC(db) );
- rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
- pKeyInfo, pCx->uc.pCursor);
+ if( rc==SQLITE_OK ){
+ /* If a transient index is required, create it by calling
+ ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
+ ** opening it. If a transient table is required, just use the
+ ** automatically created table with root-page 1 (an BLOB_INTKEY table).
+ */
+ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ assert( pOp->p4type==P4_KEYINFO );
+ rc = sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot,
+ BTREE_BLOBKEY | pOp->p5);
+ if( rc==SQLITE_OK ){
+ assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
+ assert( pKeyInfo->db==db );
+ assert( pKeyInfo->enc==ENC(db) );
+ rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pKeyInfo, pCx->uc.pCursor);
+ }
+ pCx->isTable = 0;
+ }else{
+ pCx->pgnoRoot = SCHEMA_ROOT;
+ rc = sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR,
+ 0, pCx->uc.pCursor);
+ pCx->isTable = 1;
}
- pCx->isTable = 0;
- }else{
- pCx->pgnoRoot = SCHEMA_ROOT;
- rc = sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR,
- 0, pCx->uc.pCursor);
- pCx->isTable = 1;
+ }
+ pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ if( rc ){
+ sqlite3BtreeClose(pCx->pBtx);
}
}
- pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
}
if( rc ) goto abort_due_to_error;
pCx->nullRow = 1;
@@ -89998,13 +90390,13 @@ seek_not_found:
**
** There are three possible outcomes from this opcode:<ol>
**
-** <li> If after This.P1 steps, the cursor is still point to a place that
-** is earlier in the btree than the target row,
-** then fall through into the subsquence OP_SeekGE opcode.
+** <li> If after This.P1 steps, the cursor is still pointing to a place that
+** is earlier in the btree than the target row, then fall through
+** into the subsquence OP_SeekGE opcode.
**
** <li> If the cursor is successfully moved to the target row by 0 or more
** sqlite3BtreeNext() calls, then jump to This.P2, which will land just
-** past the OP_IdxGT opcode that follows the OP_SeekGE.
+** past the OP_IdxGT or OP_IdxGE opcode that follows the OP_SeekGE.
**
** <li> If the cursor ends up past the target row (indicating the the target
** row does not exist in the btree) then jump to SeekOP.P2.
@@ -90021,7 +90413,8 @@ case OP_SeekScan: {
/* pOp->p2 points to the first instruction past the OP_IdxGT that
** follows the OP_SeekGE. */
assert( pOp->p2>=(int)(pOp-aOp)+2 );
- assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
+ assert( aOp[pOp->p2-1].opcode==OP_IdxGT || aOp[pOp->p2-1].opcode==OP_IdxGE );
+ testcase( aOp[pOp->p2-1].opcode==OP_IdxGE );
assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
@@ -90474,8 +90867,10 @@ case OP_NewRowid: { /* out2 */
VdbeCursor *pC; /* Cursor of table to get the new rowid */
int res; /* Result of an sqlite3BtreeLast() */
int cnt; /* Counter to limit the number of searches */
+#ifndef SQLITE_OMIT_AUTOINCREMENT
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
VdbeFrame *pFrame; /* Root frame of VDBE */
+#endif
v = 0;
res = 0;
@@ -90691,7 +91086,8 @@ case OP_Insert: {
}
x.pKey = 0;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
+ seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -90708,6 +91104,33 @@ case OP_Insert: {
break;
}
+/* Opcode: RowCell P1 P2 P3 * *
+**
+** P1 and P2 are both open cursors. Both must be opened on the same type
+** of table - intkey or index. This opcode is used as part of copying
+** the current row from P2 into P1. If the cursors are opened on intkey
+** tables, register P3 contains the rowid to use with the new record in
+** P1. If they are opened on index tables, P3 is not used.
+**
+** This opcode must be followed by either an Insert or InsertIdx opcode
+** with the OPFLAG_PREFORMAT flag set to complete the insert operation.
+*/
+case OP_RowCell: {
+ VdbeCursor *pDest; /* Cursor to write to */
+ VdbeCursor *pSrc; /* Cursor to read from */
+ i64 iKey; /* Rowid value to insert with */
+ assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert );
+ assert( pOp[1].opcode==OP_Insert || pOp->p3==0 );
+ assert( pOp[1].opcode==OP_IdxInsert || pOp->p3>0 );
+ assert( pOp[1].p5 & OPFLAG_PREFORMAT );
+ pDest = p->apCsr[pOp->p1];
+ pSrc = p->apCsr[pOp->p2];
+ iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0;
+ rc = sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ break;
+};
+
/* Opcode: Delete P1 P2 P3 P4 P5
**
** Delete the record at which the P1 cursor is currently pointing.
@@ -91363,7 +91786,7 @@ case OP_IdxInsert: { /* in2 */
assert( pC!=0 );
assert( !isSorter(pC) );
pIn2 = &aMem[pOp->p2];
- assert( pIn2->flags & MEM_Blob );
+ assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->isTable==0 );
@@ -91374,7 +91797,7 @@ case OP_IdxInsert: { /* in2 */
x.aMem = aMem + pOp->p3;
x.nMem = (u16)pOp->p4.i;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
@@ -91447,7 +91870,7 @@ case OP_IdxDelete: {
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
if( rc ) goto abort_due_to_error;
}else if( pOp->p5 ){
- rc = SQLITE_CORRUPT_INDEX;
+ rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
goto abort_due_to_error;
}
assert( pC->deferredMoveto==0 );
@@ -91526,6 +91949,8 @@ case OP_IdxRowid: { /* out2 */
pTabCur->deferredMoveto = 1;
assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
pTabCur->aAltMap = pOp->p4.ai;
+ assert( !pC->isEphemeral );
+ assert( !pTabCur->isEphemeral );
pTabCur->pAltCursor = pC;
}else{
pOut = out2Prerelease(p, pOp);
@@ -91873,7 +92298,7 @@ case OP_ParseSchema: {
if( pOp->p4.z==0 ){
sqlite3SchemaClear(db->aDb[iDb].pSchema);
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
- rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable);
+ rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
db->mDbFlags |= DBFLAG_SchemaChange;
p->expired = 0;
}else
@@ -97581,7 +98006,6 @@ struct MemJournal {
int nChunkSize; /* In-memory chunk-size */
int nSpill; /* Bytes of data before flushing */
- int nSize; /* Bytes of data currently in memory */
FileChunk *pFirst; /* Head of in-memory chunk-list */
FilePoint endpoint; /* Pointer to the end of the file */
FilePoint readpoint; /* Pointer to the end of the last xRead() */
@@ -97642,14 +98066,13 @@ static int memjrnlRead(
/*
** Free the list of FileChunk structures headed at MemJournal.pFirst.
*/
-static void memjrnlFreeChunks(MemJournal *p){
+static void memjrnlFreeChunks(FileChunk *pFirst){
FileChunk *pIter;
FileChunk *pNext;
- for(pIter=p->pFirst; pIter; pIter=pNext){
+ for(pIter=pFirst; pIter; pIter=pNext){
pNext = pIter->pNext;
sqlite3_free(pIter);
}
- p->pFirst = 0;
}
/*
@@ -97676,7 +98099,7 @@ static int memjrnlCreateFile(MemJournal *p){
}
if( rc==SQLITE_OK ){
/* No error has occurred. Free the in-memory buffers. */
- memjrnlFreeChunks(&copy);
+ memjrnlFreeChunks(copy.pFirst);
}
}
if( rc!=SQLITE_OK ){
@@ -97759,7 +98182,6 @@ static int memjrnlWrite(
nWrite -= iSpace;
p->endpoint.iOffset += iSpace;
}
- p->nSize = iAmt + iOfst;
}
}
@@ -97767,22 +98189,30 @@ static int memjrnlWrite(
}
/*
-** Truncate the file.
-**
-** If the journal file is already on disk, truncate it there. Or, if it
-** is still in main memory but is being truncated to zero bytes in size,
-** ignore
+** Truncate the in-memory file.
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
- if( ALWAYS(size==0) ){
- memjrnlFreeChunks(p);
- p->nSize = 0;
- p->endpoint.pChunk = 0;
- p->endpoint.iOffset = 0;
- p->readpoint.pChunk = 0;
- p->readpoint.iOffset = 0;
+ FileChunk *pIter = 0;
+
+ if( size==0 ){
+ memjrnlFreeChunks(p->pFirst);
+ p->pFirst = 0;
+ }else{
+ i64 iOff = p->nChunkSize;
+ for(pIter=p->pFirst; ALWAYS(pIter) && iOff<=size; pIter=pIter->pNext){
+ iOff += p->nChunkSize;
+ }
+ if( ALWAYS(pIter) ){
+ memjrnlFreeChunks(pIter->pNext);
+ pIter->pNext = 0;
+ }
}
+
+ p->endpoint.pChunk = pIter;
+ p->endpoint.iOffset = size;
+ p->readpoint.pChunk = 0;
+ p->readpoint.iOffset = 0;
return SQLITE_OK;
}
@@ -97791,7 +98221,7 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
*/
static int memjrnlClose(sqlite3_file *pJfd){
MemJournal *p = (MemJournal *)pJfd;
- memjrnlFreeChunks(p);
+ memjrnlFreeChunks(p->pFirst);
return SQLITE_OK;
}
@@ -97965,7 +98395,7 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
** Walk all expressions linked into the list of Window objects passed
** as the second argument.
*/
-static int walkWindowList(Walker *pWalker, Window *pList){
+static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){
Window *pWin;
for(pWin=pList; pWin; pWin=pWin->pNextWin){
int rc;
@@ -97984,6 +98414,7 @@ static int walkWindowList(Walker *pWalker, Window *pList){
if( NEVER(rc) ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
if( NEVER(rc) ) return WRC_Abort;
+ if( bOneOnly ) break;
}
return WRC_Continue;
}
@@ -98031,7 +98462,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
+ if( walkWindowList(pWalker, pExpr->y.pWin, 1) ) return WRC_Abort;
}
#endif
}
@@ -98078,7 +98509,7 @@ SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( pParse && IN_RENAME_OBJECT ){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
- int rc = walkWindowList(pWalker, p->pWinDefn);
+ int rc = walkWindowList(pWalker, p->pWinDefn, 0);
return rc;
}
}
@@ -98096,7 +98527,7 @@ SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
SrcList *pSrc;
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pSrc = p->pSrc;
if( pSrc ){
@@ -98262,7 +98693,6 @@ static void resolveAlias(
ExprList *pEList, /* A result set */
int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
Expr *pExpr, /* Transform this into an alias to the result set */
- const char *zType, /* "GROUP" or "ORDER" or "" */
int nSubquery /* Number of subqueries that the label is moving */
){
Expr *pOrig; /* The iCol-th column of the result set */
@@ -98275,7 +98705,7 @@ static void resolveAlias(
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup!=0 ){
- if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
+ incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
@@ -98304,7 +98734,6 @@ static void resolveAlias(
}
sqlite3DbFree(db, pDup);
}
- ExprSetProperty(pExpr, EP_Alias);
}
@@ -98439,8 +98868,8 @@ static int lookupName(
int cntTab = 0; /* Number of matching table names */
int nSubquery = 0; /* How many levels of subquery */
sqlite3 *db = pParse->db; /* The database connection */
- struct SrcList_item *pItem; /* Use for looping over pSrcList items */
- struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ SrcItem *pItem; /* Use for looping over pSrcList items */
+ SrcItem *pMatch = 0; /* The matching pSrcList item */
NameContext *pTopNC = pNC; /* First namecontext in the list */
Schema *pSchema = 0; /* Schema of the expression */
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
@@ -98561,25 +98990,33 @@ static int lookupName(
#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT)
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference. Or
- ** maybe it is an excluded.* from an upsert.
+ ** maybe it is an excluded.* from an upsert. Or maybe it is
+ ** a reference in the RETURNING clause to a table being modified.
*/
- if( zDb==0 && zTab!=0 && cntTab==0 ){
+ if( cnt==0 && zDb==0 ){
pTab = 0;
#ifndef SQLITE_OMIT_TRIGGER
if( pParse->pTriggerTab!=0 ){
int op = pParse->eTriggerOp;
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
- if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
+ if( pParse->bReturning ){
+ if( (pNC->ncFlags & NC_UBaseReg)!=0
+ && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
+ ){
+ pExpr->iTable = op!=TK_DELETE;
+ pTab = pParse->pTriggerTab;
+ }
+ }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
pExpr->iTable = 1;
pTab = pParse->pTriggerTab;
- }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
+ }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
pExpr->iTable = 0;
pTab = pParse->pTriggerTab;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
- if( (pNC->ncFlags & NC_UUpsert)!=0 ){
+ if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
pTab = pUpsert->pUpsertSrc->a[0].pTab;
@@ -98607,6 +99044,7 @@ static int lookupName(
}
if( iCol<pTab->nCol ){
cnt++;
+ pMatch = 0;
#ifndef SQLITE_OMIT_UPSERT
if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){
testcase( iCol==(-1) );
@@ -98618,27 +99056,32 @@ static int lookupName(
pExpr->iTable = pNC->uNC.pUpsert->regData +
sqlite3TableColumnToStorage(pTab, iCol);
eNewExprOp = TK_REGISTER;
- ExprSetProperty(pExpr, EP_Alias);
}
}else
#endif /* SQLITE_OMIT_UPSERT */
{
-#ifndef SQLITE_OMIT_TRIGGER
- if( iCol<0 ){
- pExpr->affExpr = SQLITE_AFF_INTEGER;
- }else if( pExpr->iTable==0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
- }else{
- testcase( iCol==31 );
- testcase( iCol==32 );
- pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
- }
pExpr->y.pTab = pTab;
- pExpr->iColumn = (i16)iCol;
- eNewExprOp = TK_TRIGGER;
+ if( pParse->bReturning ){
+ eNewExprOp = TK_REGISTER;
+ pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable +
+ sqlite3TableColumnToStorage(pTab, iCol) + 1;
+ }else{
+ pExpr->iColumn = (i16)iCol;
+ eNewExprOp = TK_TRIGGER;
+#ifndef SQLITE_OMIT_TRIGGER
+ if( iCol<0 ){
+ pExpr->affExpr = SQLITE_AFF_INTEGER;
+ }else if( pExpr->iTable==0 ){
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
+ }else{
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
+ }
#endif /* SQLITE_OMIT_TRIGGER */
+ }
}
}
}
@@ -98708,7 +99151,7 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "row value misused");
return WRC_Abort;
}
- resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
+ resolveAlias(pParse, pEList, j, pExpr, nSubquery);
cnt = 1;
pMatch = 0;
assert( zTab==0 && zDb==0 );
@@ -98743,6 +99186,7 @@ static int lookupName(
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted)
&& areDoubleQuotedStringsEnabled(db, pTopNC)
+ && (db->init.bDropColumn==0 || sqlite3StrICmp(zCol, db->init.azInit[0])!=0)
){
/* If a double-quoted identifier does not match any known column name,
** then treat it as a string.
@@ -98757,6 +99201,11 @@ static int lookupName(
** Someday, I hope to get rid of this hack. Unfortunately there is
** a huge amount of legacy SQL that uses it. So for now, we just
** issue a warning.
+ **
+ ** 2021-03-15: ticket 1c24a659e6d7f3a1
+ ** Do not do the ID-to-STRING conversion when doing the schema
+ ** sanity check following a DROP COLUMN if the identifer name matches
+ ** the name of the column being dropped.
*/
sqlite3_log(SQLITE_WARNING,
"double-quoted string literal: \"%w\"", zCol);
@@ -98810,18 +99259,24 @@ static int lookupName(
/* Clean up and return
*/
- sqlite3ExprDelete(db, pExpr->pLeft);
- pExpr->pLeft = 0;
- sqlite3ExprDelete(db, pExpr->pRight);
- pExpr->pRight = 0;
+ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
+ sqlite3ExprDelete(db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqlite3ExprDelete(db, pExpr->pRight);
+ pExpr->pRight = 0;
+ }
pExpr->op = eNewExprOp;
ExprSetProperty(pExpr, EP_Leaf);
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
- if( !ExprHasProperty(pExpr, EP_Alias) ){
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pParse->db->xAuth
+ && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
+ ){
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
+#endif
/* Increment the nRef value on all name contexts from TopNC up to
** the point where the name matched. */
for(;;){
@@ -98843,7 +99298,7 @@ lookupname_end:
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
- struct SrcList_item *pItem = &pSrc->a[iSrc];
+ SrcItem *pItem = &pSrc->a[iSrc];
Table *pTab = p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
@@ -98955,7 +99410,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
*/
case TK_ROW: {
SrcList *pSrcList = pNC->pSrcList;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert( pSrcList && pSrcList->nSrc>=1 );
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
@@ -98966,6 +99421,47 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
break;
}
+ /* An optimization: Attempt to convert
+ **
+ ** "expr IS NOT NULL" --> "TRUE"
+ ** "expr IS NULL" --> "FALSE"
+ **
+ ** if we can prove that "expr" is never NULL. Call this the
+ ** "NOT NULL strength reduction optimization".
+ **
+ ** If this optimization occurs, also restore the NameContext ref-counts
+ ** to the state they where in before the "column" LHS expression was
+ ** resolved. This prevents "column" from being counted as having been
+ ** referenced, which might prevent a SELECT from being erroneously
+ ** marked as correlated.
+ */
+ case TK_NOTNULL:
+ case TK_ISNULL: {
+ int anRef[8];
+ NameContext *p;
+ int i;
+ for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
+ anRef[i] = p->nRef;
+ }
+ sqlite3WalkExpr(pWalker, pExpr->pLeft);
+ if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
+ if( pExpr->op==TK_NOTNULL ){
+ pExpr->u.zToken = "true";
+ ExprSetProperty(pExpr, EP_IsTrue);
+ }else{
+ pExpr->u.zToken = "false";
+ ExprSetProperty(pExpr, EP_IsFalse);
+ }
+ pExpr->op = TK_TRUEFALSE;
+ for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
+ p->nRef = anRef[i];
+ }
+ sqlite3ExprDelete(pParse->db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ }
+ return WRC_Prune;
+ }
+
/* A column name: ID
** Or table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
@@ -99193,6 +99689,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
+ if( pParse->db->mallocFailed ) break;
}
sqlite3WalkExprList(pWalker, pWin->pPartition);
sqlite3WalkExprList(pWalker, pWin->pOrderBy);
@@ -99267,7 +99764,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
- if( pRight && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
+ if( ALWAYS(pRight) && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
int rc = resolveExprStep(pWalker, pRight);
if( rc==WRC_Abort ) return WRC_Abort;
if( pRight->op==TK_TRUEFALSE ){
@@ -99583,8 +100080,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
return 1;
}
- resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
- zType,0);
+ resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0);
}
}
return 0;
@@ -99769,27 +100265,26 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Recursively resolve names in all subqueries
*/
for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
+ SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
- NameContext *pNC; /* Used to iterate name contexts */
- int nRef = 0; /* Refcount for pOuterNC and outer contexts */
+ int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
- /* Count the total number of references to pOuterNC and all of its
- ** parent contexts. After resolving references to expressions in
- ** pItem->pSelect, check if this value has changed. If so, then
- ** SELECT statement pItem->pSelect must be correlated. Set the
- ** pItem->fg.isCorrelated flag if this is the case. */
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
-
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
- assert( pItem->fg.isCorrelated==0 && nRef<=0 );
- pItem->fg.isCorrelated = (nRef!=0);
+ /* If the number of references to the outer context changed when
+ ** expressions in the sub-select were resolved, the sub-select
+ ** is correlated. It is not required to check the refcount on any
+ ** but the innermost outer context object, as lookupName() increments
+ ** the refcount on all contexts between the current one and the
+ ** context containing the column when it resolves a name. */
+ if( pOuterNC ){
+ assert( pItem->fg.isCorrelated==0 && pOuterNC->nRef>=nRef );
+ pItem->fg.isCorrelated = (pOuterNC->nRef>nRef);
+ }
}
}
@@ -99831,7 +100326,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** Minor point: If this is the case, then the expression will be
** re-evaluated for each reference to it.
*/
- assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert))==0 );
+ assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
sNC.uNC.pEList = p->pEList;
sNC.ncFlags |= NC_UEList;
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
@@ -99839,7 +100334,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Resolve names in table-valued-function arguments */
for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
+ SrcItem *pItem = &p->pSrc->a[i];
if( pItem->fg.isTabFunc
&& sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg)
){
@@ -100248,7 +100743,18 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */
){
- if( pCollName->n>0 ){
+ assert( pExpr!=0 || pParse->db->mallocFailed );
+ if( pExpr==0 ) return 0;
+ if( pExpr->op==TK_VECTOR ){
+ ExprList *pList = pExpr->x.pList;
+ if( ALWAYS(pList!=0) ){
+ int i;
+ for(i=0; i<pList->nExpr; i++){
+ pList->a[i].pExpr = sqlite3ExprAddCollateToken(pParse,pList->a[i].pExpr,
+ pCollName, dequote);
+ }
+ }
+ }else if( pCollName->n>0 ){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
if( pNew ){
pNew->pLeft = pExpr;
@@ -101100,8 +101606,8 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
}else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
&& !IN_RENAME_OBJECT
){
- sqlite3ExprDelete(db, pLeft);
- sqlite3ExprDelete(db, pRight);
+ sqlite3ExprDeferredDelete(pParse, pLeft);
+ sqlite3ExprDeferredDelete(pParse, pRight);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
@@ -101298,6 +101804,22 @@ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
+
+/*
+** Arrange to cause pExpr to be deleted when the pParse is deleted.
+** This is similar to sqlite3ExprDelete() except that the delete is
+** deferred untilthe pParse is deleted.
+**
+** The pExpr might be deleted immediately on an OOM error.
+**
+** The deferred delete is (currently) implemented by adding the
+** pExpr to the pParse->pConstExpr list with a register number of 0.
+*/
+SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
+ pParse->pConstExpr =
+ sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+}
+
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
@@ -101672,8 +102194,8 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
- struct SrcList_item *pNewItem = &pNew->a[i];
- struct SrcList_item *pOldItem = &p->a[i];
+ SrcItem *pNewItem = &pNew->a[i];
+ SrcItem *pOldItem = &p->a[i];
Table *pTab;
pNewItem->pSchema = pOldItem->pSchema;
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
@@ -101686,7 +102208,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
}
- pNewItem->pIBIndex = pOldItem->pIBIndex;
+ pNewItem->u2 = pOldItem->u2;
+ if( pNewItem->fg.isCte ){
+ pNewItem->u2.pCteUse->nUse++;
+ }
if( pNewItem->fg.isTabFunc ){
pNewItem->u1.pFuncArg =
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
@@ -102724,7 +103249,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
/* Code an OP_Transaction and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
+ assert( iDb>=0 && iDb<SQLITE_MAX_DB );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -105920,8 +106445,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
- pParse->pConstExpr =
- sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}else{
@@ -105930,8 +106454,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
- pParse->pConstExpr =
- sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}
@@ -106003,7 +106526,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
if( ALWAYS(pSrcList!=0) ){
- struct SrcList_item *pItem = pSrcList->a;
+ SrcItem *pItem = pSrcList->a;
for(i=0; i<pSrcList->nSrc; i++, pItem++){
struct AggInfo_col *pCol;
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
@@ -106292,15 +106815,22 @@ static int isAlterableTable(Parse *pParse, Table *pTab){
** statement to ensure that the operation has not rendered any schema
** objects unusable.
*/
-static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
+static void renameTestSchema(
+ Parse *pParse, /* Parse context */
+ const char *zDb, /* Name of db to verify schema of */
+ int bTemp, /* True if this is the temp db */
+ const char *zWhen, /* "when" part of error message */
+ const char *zDropColumn /* Name of column being dropped */
+){
+ pParse->colNamesSet = 1;
sqlite3NestedParse(pParse,
"SELECT 1 "
"FROM \"%w\"." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
+ " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %Q)=NULL ",
zDb,
- zDb, bTemp
+ zDb, bTemp, zWhen, zDropColumn
);
if( bTemp==0 ){
@@ -106309,8 +106839,8 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
"FROM temp." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
- zDb
+ " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %Q)=NULL ",
+ zDb, zWhen, zDropColumn
);
}
}
@@ -106319,12 +106849,12 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.
*/
-static void renameReloadSchema(Parse *pParse, int iDb){
+static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){
Vdbe *v = pParse->pVdbe;
if( v ){
sqlite3ChangeCookie(pParse, iDb);
- sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0);
- if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0);
+ sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5);
+ if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5);
}
}
@@ -106473,7 +107003,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
"tbl_name = "
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
- " sqlite_rename_test(%Q, sql, type, name, 1) "
+ " sqlite_rename_test(%Q, sql, type, name, 1, 'after rename',0) "
"THEN %Q ELSE tbl_name END "
"WHERE type IN ('view', 'trigger')"
, zDb, zTabName, zName, zTabName, zDb, zName);
@@ -106492,8 +107022,8 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
}
#endif
- renameReloadSchema(pParse, iDb);
- renameTestSchema(pParse, zDb, iDb==1);
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
+ renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);
exit_rename_table:
sqlite3SrcListDelete(db, pSrc);
@@ -106624,11 +107154,14 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
*zEnd-- = '\0';
}
db->mDbFlags |= DBFLAG_PreferBuiltin;
+ /* substr() operations on characters, but addColOffset is in bytes. So we
+ ** have to use printf() to translate between these units: */
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
- "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
+ "sql = printf('%%.%ds, ',sql) || %Q"
+ " || substr(sql,1+length(printf('%%.%ds',sql))) "
"WHERE type = 'table' AND name = %Q",
- zDb, pNew->addColOffset, zCol, pNew->addColOffset+1,
+ zDb, pNew->addColOffset, zCol, pNew->addColOffset,
zTab
);
sqlite3DbFree(db, zCol);
@@ -106652,7 +107185,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
}
/* Reload the table definition */
- renameReloadSchema(pParse, iDb);
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
}
/*
@@ -106752,7 +107285,7 @@ exit_begin_add_column:
** 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){
+static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
const char *zType = 0;
#ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){
@@ -106765,15 +107298,16 @@ static int isRealTable(Parse *pParse, Table *pTab){
}
#endif
if( zType ){
- sqlite3ErrorMsg(
- pParse, "cannot rename columns of %s \"%s\"", zType, pTab->zName
+ sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"",
+ (bDrop ? "drop column from" : "rename columns of"),
+ zType, pTab->zName
);
return 1;
}
return 0;
}
#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
-# define isRealTable(x,y) (0)
+# define isRealTable(x,y,z) (0)
#endif
/*
@@ -106802,7 +107336,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn(
/* Cannot alter a system table */
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
- if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
+ if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column;
/* Which schema holds the table to be altered */
iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -106856,8 +107390,8 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn(
);
/* Drop and reload the database schema. */
- renameReloadSchema(pParse, iSchema);
- renameTestSchema(pParse, zDb, iSchema==1);
+ renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
+ renameTestSchema(pParse, zDb, iSchema==1, "after rename", 0);
exit_rename_column:
sqlite3SrcListDelete(db, pSrc);
@@ -107109,23 +107643,33 @@ static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
/*
** Search the Parse object passed as the first argument for a RenameToken
-** object associated with parse tree element pPtr. If found, remove it
-** from the Parse object and add it to the list maintained by the
-** RenameCtx object passed as the second argument.
+** object associated with parse tree element pPtr. If found, return a pointer
+** to it. Otherwise, return NULL.
+**
+** If the second argument passed to this function is not NULL and a matching
+** RenameToken object is found, remove it from the Parse object and add it to
+** the list maintained by the RenameCtx object.
*/
-static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
+static RenameToken *renameTokenFind(
+ Parse *pParse,
+ struct RenameCtx *pCtx,
+ void *pPtr
+){
RenameToken **pp;
assert( pPtr!=0 );
for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
if( (*pp)->p==pPtr ){
RenameToken *pToken = *pp;
- *pp = pToken->pNext;
- pToken->pNext = pCtx->pList;
- pCtx->pList = pToken;
- pCtx->nList++;
- break;
+ if( pCtx ){
+ *pp = pToken->pNext;
+ pToken->pNext = pCtx->pList;
+ pCtx->pList = pToken;
+ pCtx->nList++;
+ }
+ return pToken;
}
}
+ return 0;
}
/*
@@ -107196,7 +107740,7 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
*/
static void renameColumnParseError(
sqlite3_context *pCtx,
- int bPost,
+ const char *zWhen,
sqlite3_value *pType,
sqlite3_value *pObject,
Parse *pParse
@@ -107205,8 +107749,8 @@ static void renameColumnParseError(
const char *zN = (const char*)sqlite3_value_text(pObject);
char *zErr;
- zErr = sqlite3_mprintf("error in %s %s%s: %s",
- zT, zN, (bPost ? " after rename" : ""),
+ zErr = sqlite3_mprintf("error in %s %s%s%s: %s",
+ zT, zN, (zWhen[0] ? " " : ""), zWhen,
pParse->zErrMsg
);
sqlite3_result_error(pCtx, zErr, -1);
@@ -107271,12 +107815,17 @@ static int renameParseSql(
const char *zDb, /* Name of schema SQL belongs to */
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL to parse */
- int bTemp /* True if SQL is from temp schema */
+ int bTemp, /* True if SQL is from temp schema */
+ const char *zDropColumn /* Name of column being dropped */
){
int rc;
char *zErr = 0;
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
+ if( zDropColumn ){
+ db->init.bDropColumn = 1;
+ db->init.azInit = (char**)&zDropColumn;
+ }
/* Parse the SQL statement passed as the first argument. If no error
** occurs and the parse does not result in a new table, index or
@@ -107285,7 +107834,7 @@ static int renameParseSql(
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
- rc = sqlite3RunParser(p, zSql, &zErr);
+ rc = zSql ? sqlite3RunParser(p, zSql, &zErr) : SQLITE_NOMEM;
assert( p->zErrMsg==0 );
assert( rc!=SQLITE_OK || zErr==0 );
p->zErrMsg = zErr;
@@ -107309,6 +107858,7 @@ static int renameParseSql(
#endif
db->init.iDb = 0;
+ db->init.bDropColumn = 0;
return rc;
}
@@ -107438,7 +107988,7 @@ static int renameResolveTrigger(Parse *pParse){
if( pSrc ){
int i;
for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
- struct SrcList_item *p = &pSrc->a[i];
+ SrcItem *p = &pSrc->a[i];
p->iCursor = pParse->nTab++;
if( p->pSelect ){
sqlite3SelectPrep(pParse, p->pSelect, 0);
@@ -107464,9 +108014,8 @@ static int renameResolveTrigger(Parse *pParse){
rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
}
assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) );
- if( pStep->pUpsert ){
+ if( pStep->pUpsert && rc==SQLITE_OK ){
Upsert *pUpsert = pStep->pUpsert;
- assert( rc==SQLITE_OK );
pUpsert->pUpsertSrc = pSrc;
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
@@ -107611,7 +108160,7 @@ static void renameColumnFunc(
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = 0;
#endif
- rc = renameParseSql(&sParse, zDb, db, zSql, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zSql, bTemp, 0);
/* Find tokens that need to be replaced. */
memset(&sWalker, 0, sizeof(Walker));
@@ -107653,12 +108202,12 @@ static void renameColumnFunc(
for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
- }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- for(i=0; i<sParse.pNewTable->nCol; i++){
- sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
- }
+ for(i=0; i<sParse.pNewTable->nCol; i++){
+ sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
+ }
#endif
+ }
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
for(i=0; i<pFKey->nCol; i++){
@@ -107712,7 +108261,7 @@ static void renameColumnFunc(
renameColumnFunc_done:
if( rc!=SQLITE_OK ){
if( sParse.zErrMsg ){
- renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlite3_result_error_code(context, rc);
}
@@ -107750,7 +108299,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
return WRC_Abort;
}
for(i=0; i<pSrc->nSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
+ SrcItem *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
@@ -107815,7 +108364,7 @@ static void renameTableFunc(
sWalker.xSelectCallback = renameTableSelectCb;
sWalker.u.pRename = &sCtx;
- rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, 0);
if( rc==SQLITE_OK ){
int isLegacy = (db->flags & SQLITE_LegacyAlter);
@@ -107901,7 +108450,7 @@ static void renameTableFunc(
}
if( rc!=SQLITE_OK ){
if( sParse.zErrMsg ){
- renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlite3_result_error_code(context, rc);
}
@@ -107930,6 +108479,8 @@ static void renameTableFunc(
** 2: Object type ("view", "table", "trigger" or "index").
** 3: Object name.
** 4: True if object is from temp schema.
+** 5: "when" part of error message.
+** 6: Name of column being dropped, or NULL.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
@@ -107947,6 +108498,8 @@ static void renameTableTest(
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
int bTemp = sqlite3_value_int(argv[4]);
int isLegacy = (db->flags & SQLITE_LegacyAlter);
+ char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
+ char const *zDropColumn = (const char*)sqlite3_value_text(argv[6]);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
@@ -107957,7 +108510,7 @@ static void renameTableTest(
if( zDb && zInput ){
int rc;
Parse sParse;
- rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, zDropColumn);
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
@@ -107979,8 +108532,8 @@ static void renameTableTest(
}
}
- if( rc!=SQLITE_OK ){
- renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
+ if( rc!=SQLITE_OK && zWhen ){
+ renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse);
}
renameParseCleanup(&sParse);
}
@@ -107991,13 +108544,216 @@ static void renameTableTest(
}
/*
+** The implementation of internal UDF sqlite_drop_column().
+**
+** Arguments:
+**
+** argv[0]: An integer - the index of the schema containing the table
+** argv[1]: CREATE TABLE statement to modify.
+** argv[2]: An integer - the index of the column to remove.
+**
+** The value returned is a string containing the CREATE TABLE statement
+** with column argv[2] removed.
+*/
+static void dropColumnFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ int iSchema = sqlite3_value_int(argv[0]);
+ const char *zSql = (const char*)sqlite3_value_text(argv[1]);
+ int iCol = sqlite3_value_int(argv[2]);
+ const char *zDb = db->aDb[iSchema].zDbSName;
+ int rc;
+ Parse sParse;
+ RenameToken *pCol;
+ Table *pTab;
+ const char *zEnd;
+ char *zNew = 0;
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ UNUSED_PARAMETER(NotUsed);
+ rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1, 0);
+ if( rc!=SQLITE_OK ) goto drop_column_done;
+ pTab = sParse.pNewTable;
+ if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){
+ /* This can happen if the sqlite_schema table is corrupt */
+ rc = SQLITE_CORRUPT_BKPT;
+ goto drop_column_done;
+ }
+
+ pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zName);
+ if( iCol<pTab->nCol-1 ){
+ RenameToken *pEnd;
+ pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName);
+ zEnd = (const char*)pEnd->t.z;
+ }else{
+ zEnd = (const char*)&zSql[pTab->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);
+ sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
+ sqlite3_free(zNew);
+
+drop_column_done:
+ renameParseCleanup(&sParse);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(context, rc);
+ }
+}
+
+/*
+** This function is called by the parser upon parsing an
+**
+** ALTER TABLE pSrc DROP COLUMN pName
+**
+** statement. Argument pSrc contains the possibly qualified name of the
+** table being edited, and token pName the name of the column to drop.
+*/
+SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
+ sqlite3 *db = pParse->db; /* Database handle */
+ Table *pTab; /* Table to modify */
+ int iDb; /* Index of db containing pTab in aDb[] */
+ const char *zDb; /* Database containing pTab ("main" etc.) */
+ char *zCol = 0; /* Name of column to drop */
+ int iCol; /* Index of column zCol in pTab->aCol[] */
+
+ /* Look up the table being altered. */
+ assert( pParse->pNewTable==0 );
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ if( NEVER(db->mallocFailed) ) goto exit_drop_column;
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
+ if( !pTab ) goto exit_drop_column;
+
+ /* Make sure this is not an attempt to ALTER a view, virtual table or
+ ** system table. */
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_column;
+ if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_column;
+
+ /* Find the index of the column being dropped. */
+ zCol = sqlite3NameFromToken(db, pName);
+ if( zCol==0 ){
+ assert( db->mallocFailed );
+ goto exit_drop_column;
+ }
+ iCol = sqlite3ColumnIndex(pTab, zCol);
+ if( iCol<0 ){
+ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol);
+ goto exit_drop_column;
+ }
+
+ /* Do not allow the user to drop a PRIMARY KEY column or a column
+ ** constrained by a UNIQUE constraint. */
+ if( pTab->aCol[iCol].colFlags & (COLFLAG_PRIMKEY|COLFLAG_UNIQUE) ){
+ sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"",
+ (pTab->aCol[iCol].colFlags&COLFLAG_PRIMKEY) ? "PRIMARY KEY" : "UNIQUE",
+ zCol
+ );
+ goto exit_drop_column;
+ }
+
+ /* Do not allow the number of columns to go to zero */
+ if( pTab->nCol<=1 ){
+ sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist",zCol);
+ goto exit_drop_column;
+ }
+
+ /* Edit the sqlite_schema table */
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb>=0 );
+ zDb = db->aDb[iDb].zDbSName;
+ renameTestSchema(pParse, zDb, iDb==1, "", 0);
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
+ "sql = sqlite_drop_column(%d, sql, %d) "
+ "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
+ , zDb, iDb, iCol, pTab->zName
+ );
+
+ /* Drop and reload the database schema. */
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
+ renameTestSchema(pParse, zDb, iDb==1, "after drop column", zCol);
+
+ /* Edit rows of table on disk */
+ if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
+ int i;
+ int addr;
+ int reg;
+ int regRec;
+ Index *pPk = 0;
+ int nField = 0; /* Number of non-virtual columns after drop */
+ int iCur;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ iCur = pParse->nTab++;
+ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
+ reg = ++pParse->nMem;
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
+ pParse->nMem += pTab->nCol;
+ }else{
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ pParse->nMem += pPk->nColumn;
+ for(i=0; i<pPk->nKeyCol; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1);
+ }
+ nField = pPk->nKeyCol;
+ }
+ regRec = ++pParse->nMem;
+ for(i=0; i<pTab->nCol; i++){
+ if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
+ int regOut;
+ if( pPk ){
+ int iPos = sqlite3TableColumnToIndex(pPk, i);
+ int iColPos = sqlite3TableColumnToIndex(pPk, iCol);
+ if( iPos<pPk->nKeyCol ) continue;
+ regOut = reg+1+iPos-(iPos>iColPos);
+ }else{
+ regOut = reg+1+nField;
+ }
+ if( i==pTab->iPKey ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
+ }else{
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
+ }
+ nField++;
+ }
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
+ if( pPk ){
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
+ }
+ sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
+
+ sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v);
+ sqlite3VdbeJumpHere(v, addr);
+ }
+
+exit_drop_column:
+ sqlite3DbFree(db, zCol);
+ sqlite3SrcListDelete(db, pSrc);
+}
+
+/*
** Register built-in functions used to help implement ALTER TABLE
*/
SQLITE_PRIVATE void sqlite3AlterFunctions(void){
static FuncDef aAlterTableFuncs[] = {
- INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
- INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
- INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
+ INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
@@ -110387,6 +111143,62 @@ SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *p
#endif /* SQLITE_OMIT_ATTACH */
/*
+** Expression callback used by sqlite3FixAAAA() routines.
+*/
+static int fixExprCb(Walker *p, Expr *pExpr){
+ DbFixer *pFix = p->u.pFix;
+ if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
+ if( pExpr->op==TK_VARIABLE ){
+ if( pFix->pParse->db->init.busy ){
+ pExpr->op = TK_NULL;
+ }else{
+ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
+ return WRC_Abort;
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Select callback used by sqlite3FixAAAA() routines.
+*/
+static int fixSelectCb(Walker *p, Select *pSelect){
+ DbFixer *pFix = p->u.pFix;
+ int i;
+ SrcItem *pItem;
+ sqlite3 *db = pFix->pParse->db;
+ int iDb = sqlite3FindDbName(db, pFix->zDb);
+ SrcList *pList = pSelect->pSrc;
+
+ if( NEVER(pList==0) ) return WRC_Continue;
+ for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+ if( pFix->bTemp==0 ){
+ if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
+ sqlite3ErrorMsg(pFix->pParse,
+ "%s %T cannot reference objects in database %s",
+ pFix->zType, pFix->pName, pItem->zDatabase);
+ return WRC_Abort;
+ }
+ sqlite3DbFree(db, pItem->zDatabase);
+ pItem->zDatabase = 0;
+ pItem->pSchema = pFix->pSchema;
+ pItem->fg.fromDDL = 1;
+ }
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
+ if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
+#endif
+ }
+ if( pSelect->pWith ){
+ for(i=0; i<pSelect->pWith->nCte; i++){
+ if( sqlite3WalkSelect(p, pSelect->pWith->a[i].pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
*/
@@ -110397,9 +111209,7 @@ SQLITE_PRIVATE void sqlite3FixInit(
const char *zType, /* "view", "trigger", or "index" */
const Token *pName /* Name of the view, trigger, or index */
){
- sqlite3 *db;
-
- db = pParse->db;
+ sqlite3 *db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zDbSName;
@@ -110407,6 +111217,13 @@ SQLITE_PRIVATE void sqlite3FixInit(
pFix->zType = zType;
pFix->pName = pName;
pFix->bTemp = (iDb==1);
+ pFix->w.pParse = pParse;
+ pFix->w.xExprCallback = fixExprCb;
+ pFix->w.xSelectCallback = fixSelectCb;
+ pFix->w.xSelectCallback2 = 0;
+ pFix->w.walkerDepth = 0;
+ pFix->w.eCode = 0;
+ pFix->w.u.pFix = pFix;
}
/*
@@ -110427,115 +111244,27 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
DbFixer *pFix, /* Context of the fixation */
SrcList *pList /* The Source list to check and modify */
){
- int i;
- struct SrcList_item *pItem;
- sqlite3 *db = pFix->pParse->db;
- int iDb = sqlite3FindDbName(db, pFix->zDb);
-
- if( NEVER(pList==0) ) return 0;
-
- for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pFix->bTemp==0 ){
- if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
- sqlite3ErrorMsg(pFix->pParse,
- "%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
- return 1;
- }
- sqlite3DbFree(db, pItem->zDatabase);
- pItem->zDatabase = 0;
- pItem->pSchema = pFix->pSchema;
- pItem->fg.fromDDL = 1;
- }
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
- if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
- if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
-#endif
- if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){
- return 1;
- }
+ int res = 0;
+ if( pList ){
+ Select s;
+ memset(&s, 0, sizeof(s));
+ s.pSrc = pList;
+ res = sqlite3WalkSelect(&pFix->w, &s);
}
- return 0;
+ return res;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE int sqlite3FixSelect(
DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */
){
- while( pSelect ){
- if( sqlite3FixExprList(pFix, pSelect->pEList) ){
- return 1;
- }
- if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
- return 1;
- }
- if( pSelect->pWith ){
- int i;
- for(i=0; i<pSelect->pWith->nCte; i++){
- if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
- return 1;
- }
- }
- }
- pSelect = pSelect->pPrior;
- }
- return 0;
+ return sqlite3WalkSelect(&pFix->w, pSelect);
}
SQLITE_PRIVATE int sqlite3FixExpr(
DbFixer *pFix, /* Context of the fixation */
Expr *pExpr /* The expression to be fixed to one database */
){
- while( pExpr ){
- if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
- if( pExpr->op==TK_VARIABLE ){
- if( pFix->pParse->db->init.busy ){
- pExpr->op = TK_NULL;
- }else{
- sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
- return 1;
- }
- }
- if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
- }else{
- if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
- }
- if( sqlite3FixExpr(pFix, pExpr->pRight) ){
- return 1;
- }
- pExpr = pExpr->pLeft;
- }
- return 0;
-}
-SQLITE_PRIVATE int sqlite3FixExprList(
- DbFixer *pFix, /* Context of the fixation */
- ExprList *pList /* The expression to be fixed to one database */
-){
- int i;
- struct ExprList_item *pItem;
- if( pList==0 ) return 0;
- for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
- if( sqlite3FixExpr(pFix, pItem->pExpr) ){
- return 1;
- }
- }
- return 0;
+ return sqlite3WalkExpr(&pFix->w, pExpr);
}
#endif
@@ -110545,25 +111274,20 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(
TriggerStep *pStep /* The trigger step be fixed to one database */
){
while( pStep ){
- if( sqlite3FixSelect(pFix, pStep->pSelect) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pStep->pWhere) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pStep->pExprList) ){
- return 1;
- }
- if( pStep->pFrom && sqlite3FixSrcList(pFix, pStep->pFrom) ){
+ if( sqlite3WalkSelect(&pFix->w, pStep->pSelect)
+ || sqlite3WalkExpr(&pFix->w, pStep->pWhere)
+ || sqlite3WalkExprList(&pFix->w, pStep->pExprList)
+ || sqlite3FixSrcList(pFix, pStep->pFrom)
+ ){
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
if( pStep->pUpsert ){
Upsert *pUp = pStep->pUpsert;
- if( sqlite3FixExprList(pFix, pUp->pUpsertTarget)
- || sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere)
- || sqlite3FixExprList(pFix, pUp->pUpsertSet)
- || sqlite3FixExpr(pFix, pUp->pUpsertWhere)
+ if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
+ || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
+ || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
+ || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
){
return 1;
}
@@ -110571,6 +111295,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(
#endif
pStep = pStep->pNext;
}
+
return 0;
}
#endif
@@ -110722,7 +111447,6 @@ SQLITE_PRIVATE void sqlite3AuthRead(
Schema *pSchema, /* The schema of the expression */
SrcList *pTabList /* All table that pExpr might refer to */
){
- sqlite3 *db = pParse->db;
Table *pTab = 0; /* The table being read */
const char *zCol; /* Name of the column of the table */
int iSrc; /* Index in pTabList->a[] of table being read */
@@ -110730,8 +111454,8 @@ SQLITE_PRIVATE void sqlite3AuthRead(
int iCol; /* Index of column in table */
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
- assert( !IN_RENAME_OBJECT || db->xAuth==0 );
- if( db->xAuth==0 ) return;
+ assert( !IN_RENAME_OBJECT );
+ assert( pParse->db->xAuth!=0 );
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
/* An attempt to read a column out of a subquery or other
@@ -110743,7 +111467,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
pTab = pParse->pTriggerTab;
}else{
assert( pTabList );
- for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
+ for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
pTab = pTabList->a[iSrc].pTab;
break;
@@ -110751,7 +111475,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
}
}
iCol = pExpr->iColumn;
- if( NEVER(pTab==0) ) return;
+ if( pTab==0 ) return;
if( iCol>=0 ){
assert( iCol<pTab->nCol );
@@ -110762,7 +111486,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
}else{
zCol = "ROWID";
}
- assert( iDb>=0 && iDb<db->nDb );
+ assert( iDb>=0 && iDb<pParse->db->nDb );
if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
pExpr->op = TK_NULL;
}
@@ -110788,11 +111512,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
- if( db->init.busy || IN_SPECIAL_PARSE ){
- return SQLITE_OK;
- }
-
- if( db->xAuth==0 ){
+ if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
@@ -110998,10 +111718,36 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
/* Begin by generating some termination code at the end of the
** vdbe program
*/
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
+ if( v==0 ){
+ if( db->init.busy ){
+ pParse->rc = SQLITE_DONE;
+ return;
+ }
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) pParse->rc = SQLITE_ERROR;
+ }
assert( !pParse->isMultiWrite
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
+ if( pParse->bReturning ){
+ Returning *pReturning = pParse->u1.pReturning;
+ int addrRewind;
+ int i;
+ int reg;
+
+ addrRewind =
+ sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
+ VdbeCoverage(v);
+ reg = pReturning->iRetReg;
+ for(i=0; i<pReturning->nRetCol; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i);
+ }
+ sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i);
+ sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1);
+ VdbeCoverage(v);
+ sqlite3VdbeJumpHere(v, addrRewind);
+ }
sqlite3VdbeAddOp0(v, OP_Halt);
#if SQLITE_USER_AUTHENTICATION
@@ -111079,12 +111825,16 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
}
+ if( pParse->bReturning ){
+ Returning *pRet = pParse->u1.pReturning;
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
+ }
+
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeGoto(v, 1);
}
}
-
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 && !db->mallocFailed ){
@@ -111303,10 +112053,10 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
SQLITE_PRIVATE Table *sqlite3LocateTableItem(
Parse *pParse,
u32 flags,
- struct SrcList_item *p
+ SrcItem *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
@@ -112061,7 +112811,8 @@ SQLITE_PRIVATE void sqlite3StartTable(
}else
#endif
{
- pParse->addrCrTab =
+ assert( !pParse->bReturning );
+ pParse->u1.addrCrTab =
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlite3OpenSchemaTable(pParse, iDb);
@@ -112088,12 +112839,85 @@ begin_table_error:
SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
pCol->colFlags |= COLFLAG_HIDDEN;
+ if( pTab ) pTab->tabFlags |= TF_HasHidden;
}else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
pTab->tabFlags |= TF_OOOHidden;
}
}
#endif
+/*
+** Name of the special TEMP trigger used to implement RETURNING. The
+** name begins with "sqlite_" so that it is guaranteed not to collide
+** with any application-generated triggers.
+*/
+#define RETURNING_TRIGGER_NAME "sqlite_returning"
+
+/*
+** Clean up the data structures associated with the RETURNING clause.
+*/
+static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
+ Hash *pHash;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
+ sqlite3ExprListDelete(db, pRet->pReturnEL);
+ sqlite3DbFree(db, pRet);
+}
+
+/*
+** Add the RETURNING clause to the parse currently underway.
+**
+** This routine creates a special TEMP trigger that will fire for each row
+** of the DML statement. That TEMP trigger contains a single SELECT
+** statement with a result set that is the argument of the RETURNING clause.
+** The trigger has the Trigger.bReturning flag and an opcode of
+** TK_RETURNING instead of TK_SELECT, so that the trigger code generator
+** knows to handle it specially. The TEMP trigger is automatically
+** removed at the end of the parse.
+**
+** When this routine is called, we do not yet know if the RETURNING clause
+** is attached to a DELETE, INSERT, or UPDATE, so construct it as a
+** RETURNING trigger instead. It will then be converted into the appropriate
+** type on the first call to sqlite3TriggersExist().
+*/
+SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){
+ Returning *pRet;
+ Hash *pHash;
+ sqlite3 *db = pParse->db;
+ if( pParse->pNewTrigger ){
+ sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger");
+ }else{
+ assert( pParse->bReturning==0 );
+ }
+ pParse->bReturning = 1;
+ pRet = sqlite3DbMallocZero(db, sizeof(*pRet));
+ if( pRet==0 ){
+ sqlite3ExprListDelete(db, pList);
+ return;
+ }
+ pParse->u1.pReturning = pRet;
+ pRet->pParse = pParse;
+ pRet->pReturnEL = pList;
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
+ testcase( pParse->earlyCleanup );
+ if( db->mallocFailed ) return;
+ pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
+ pRet->retTrig.op = TK_RETURNING;
+ pRet->retTrig.tr_tm = TRIGGER_AFTER;
+ pRet->retTrig.bReturning = 1;
+ pRet->retTrig.pSchema = db->aDb[1].pSchema;
+ pRet->retTrig.step_list = &pRet->retTStep;
+ pRet->retTStep.op = TK_RETURNING;
+ pRet->retTStep.pTrig = &pRet->retTrig;
+ pRet->retTStep.pExprList = pList;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr );
+ if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
+ ==&pRet->retTrig ){
+ sqlite3OomFault(db);
+ }
+}
/*
** Add a new column to the table currently being constructed.
@@ -112110,6 +112934,8 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
char *zType;
Column *pCol;
sqlite3 *db = pParse->db;
+ u8 hName;
+
if( (p = pParse->pNewTable)==0 ) return;
if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
@@ -112121,8 +112947,9 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
memcpy(z, pName->z, pName->n);
z[pName->n] = 0;
sqlite3Dequote(z);
+ hName = sqlite3StrIHash(z);
for(i=0; i<p->nCol; i++){
- if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
+ if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqlite3DbFree(db, z);
return;
@@ -112140,7 +112967,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
- pCol->hName = sqlite3StrIHash(z);
+ pCol->hName = hName;
sqlite3ColumnPropertiesFromName(p, pCol);
if( pType->n==0 ){
@@ -112923,9 +113750,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
- if( pParse->addrCrTab ){
+ assert( !pParse->bReturning );
+ if( pParse->u1.addrCrTab ){
assert( v );
- sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
+ sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
@@ -113389,7 +114217,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
/* Reparse everything to update our internal data structures */
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
+ sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0);
}
/* Add the table to the in-memory representation of the database.
@@ -113406,20 +114234,17 @@ SQLITE_PRIVATE void sqlite3EndTable(
}
pParse->pNewTable = 0;
db->mDbFlags |= DBFLAG_SchemaChange;
+ }
#ifndef SQLITE_OMIT_ALTERTABLE
- if( !p->pSelect ){
- const char *zName = (const char *)pParse->sNameToken.z;
- int nName;
- assert( !pSelect && pCons && pEnd );
- if( pCons->z==0 ){
- pCons = pEnd;
- }
- nName = (int)((const char *)pCons->z - zName);
- p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
+ if( !pSelect && !p->pSelect ){
+ assert( pCons && pEnd );
+ if( pCons->z==0 ){
+ pCons = pEnd;
}
-#endif
+ p->addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
}
+#endif
}
#ifndef SQLITE_OMIT_VIEW
@@ -113610,6 +114435,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
+ pTable->tabFlags |= (pSelTab->tabFlags & COLFLAG_NOINSERT);
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
@@ -114877,7 +115703,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
sqlite3RefillIndex(pParse, pIndex, iMem);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
+ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0);
sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
}
@@ -114898,7 +115724,11 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
if( pIndex ) sqlite3FreeIndex(db, pIndex);
- if( pTab ){ /* Ensure all REPLACE indexes are at the end of the list */
+ if( pTab ){
+ /* Ensure all REPLACE indexes on pTab are at the end of the pIndex list.
+ ** The list was already ordered when this routine was entered, so at this
+ ** point at most a single index (the newly added index) will be out of
+ ** order. So we have to reorder at most one index. */
Index **ppFrom = &pTab->pIndex;
Index *pThis;
for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
@@ -114912,6 +115742,16 @@ exit_create_index:
}
break;
}
+#ifdef SQLITE_DEBUG
+ /* Verify that all REPLACE indexes really are now at the end
+ ** of the index list. In other words, no other index type ever
+ ** comes after a REPLACE index on the list. */
+ for(pThis = pTab->pIndex; pThis; pThis=pThis->pNext){
+ assert( pThis->onError!=OE_Replace
+ || pThis->pNext==0
+ || pThis->pNext->onError==OE_Replace );
+ }
+#endif
}
sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
@@ -115270,7 +116110,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
sqlite3 *db;
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
assert( pParse!=0 );
@@ -115311,7 +116151,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
*/
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert(pList || pParse->db->mallocFailed );
if( pList ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
@@ -115329,7 +116169,7 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
*/
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
@@ -115371,7 +116211,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
Expr *pOn, /* The ON clause of a join */
IdList *pUsing /* The USING clause of a join */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
sqlite3 *db = pParse->db;
if( !p && (pOn || pUsing) ){
sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
@@ -115415,7 +116255,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
if( p && pIndexedBy->n>0 ){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert( p->nSrc>0 );
pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
@@ -115445,7 +116285,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, Src
sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
- memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(struct SrcList_item));
+ memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
sqlite3DbFree(pParse->db, p2);
}
}
@@ -115458,7 +116298,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, Src
*/
SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
if( p ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
+ SrcItem *pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
assert( pItem->fg.isIndexedBy==0 );
assert( pItem->fg.isTabFunc==0 );
@@ -115613,7 +116453,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
assert( iDb>=0 && iDb<pToplevel->db->nDb );
assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
- assert( iDb<SQLITE_MAX_ATTACHED+2 );
+ assert( iDb<SQLITE_MAX_DB );
assert( sqlite3SchemaMutexHeld(pToplevel->db, iDb, 0) );
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
DbMaskSet(pToplevel->cookieMask, iDb);
@@ -115956,23 +116796,75 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
#ifndef SQLITE_OMIT_CTE
/*
+** Create a new CTE object
+*/
+SQLITE_PRIVATE Cte *sqlite3CteNew(
+ Parse *pParse, /* Parsing context */
+ Token *pName, /* Name of the common-table */
+ ExprList *pArglist, /* Optional column name list for the table */
+ Select *pQuery, /* Query used to initialize the table */
+ u8 eM10d /* The MATERIALIZED flag */
+){
+ Cte *pNew;
+ sqlite3 *db = pParse->db;
+
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew));
+ assert( pNew!=0 || db->mallocFailed );
+
+ if( db->mallocFailed ){
+ sqlite3ExprListDelete(db, pArglist);
+ sqlite3SelectDelete(db, pQuery);
+ }else{
+ pNew->pSelect = pQuery;
+ pNew->pCols = pArglist;
+ pNew->zName = sqlite3NameFromToken(pParse->db, pName);
+ pNew->eM10d = eM10d;
+ }
+ return pNew;
+}
+
+/*
+** Clear information from a Cte object, but do not deallocate storage
+** for the object itself.
+*/
+static void cteClear(sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ sqlite3ExprListDelete(db, pCte->pCols);
+ sqlite3SelectDelete(db, pCte->pSelect);
+ sqlite3DbFree(db, pCte->zName);
+}
+
+/*
+** Free the contents of the CTE object passed as the second argument.
+*/
+SQLITE_PRIVATE void sqlite3CteDelete(sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ cteClear(db, pCte);
+ sqlite3DbFree(db, pCte);
+}
+
+/*
** This routine is invoked once per CTE by the parser while parsing a
-** WITH clause.
+** WITH clause. The CTE described by teh third argument is added to
+** the WITH clause of the second argument. If the second argument is
+** NULL, then a new WITH argument is created.
*/
SQLITE_PRIVATE With *sqlite3WithAdd(
Parse *pParse, /* Parsing context */
With *pWith, /* Existing WITH clause, or NULL */
- Token *pName, /* Name of the common-table */
- ExprList *pArglist, /* Optional column name list for the table */
- Select *pQuery /* Query used to initialize the table */
+ Cte *pCte /* CTE to add to the WITH clause */
){
sqlite3 *db = pParse->db;
With *pNew;
char *zName;
+ if( pCte==0 ){
+ return pWith;
+ }
+
/* Check that the CTE name is unique within this WITH clause. If
** not, store an error in the Parse structure. */
- zName = sqlite3NameFromToken(pParse->db, pName);
+ zName = pCte->zName;
if( zName && pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
@@ -115991,16 +116883,11 @@ SQLITE_PRIVATE With *sqlite3WithAdd(
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
if( db->mallocFailed ){
- sqlite3ExprListDelete(db, pArglist);
- sqlite3SelectDelete(db, pQuery);
- sqlite3DbFree(db, zName);
+ sqlite3CteDelete(db, pCte);
pNew = pWith;
}else{
- pNew->a[pNew->nCte].pSelect = pQuery;
- pNew->a[pNew->nCte].pCols = pArglist;
- pNew->a[pNew->nCte].zName = zName;
- pNew->a[pNew->nCte].zCteErr = 0;
- pNew->nCte++;
+ pNew->a[pNew->nCte++] = *pCte;
+ sqlite3DbFree(db, pCte);
}
return pNew;
@@ -116013,10 +116900,7 @@ SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){
if( pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
- struct Cte *pCte = &pWith->a[i];
- sqlite3ExprListDelete(db, pCte->pCols);
- sqlite3SelectDelete(db, pCte->pSelect);
- sqlite3DbFree(db, pCte->zName);
+ cteClear(db, &pWith->a[i]);
}
sqlite3DbFree(db, pWith);
}
@@ -116595,7 +117479,7 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
**
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
- struct SrcList_item *pItem = pSrc->a;
+ SrcItem *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc>=1 );
pTab = sqlite3LocateTableItem(pParse, 0, pItem);
@@ -116603,9 +117487,9 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
pItem->pTab = pTab;
if( pTab ){
pTab->nTabRef++;
- }
- if( sqlite3IndexedByLookup(pParse, pItem) ){
- pTab = 0;
+ if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){
+ pTab = 0;
+ }
}
return pTab;
}
@@ -116773,9 +117657,15 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSrc->a[0].pTab = 0;
- pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
+ pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
pSrc->a[0].pTab = pTab;
- pSrc->a[0].pIBIndex = 0;
+ if( pSrc->a[0].fg.isIndexedBy ){
+ pSrc->a[0].u2.pIBIndex = 0;
+ pSrc->a[0].fg.isIndexedBy = 0;
+ sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
+ }else if( pSrc->a[0].fg.isCte ){
+ pSrc->a[0].u2.pCteUse->nUse++;
+ }
/* generate the SELECT expression tree. */
pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
@@ -116953,6 +117843,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
if( (db->flags & SQLITE_CountRows)!=0
&& !pParse->nested
&& !pParse->pTriggerTab
+ && !pParse->bReturning
){
memCnt = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
@@ -117174,7 +118065,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
** invoke the callback function.
*/
if( memCnt ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
+ sqlite3VdbeAddOp2(v, OP_ChngCntRow, memCnt, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
}
@@ -118222,7 +119113,8 @@ static int patternCompare(
/* Skip over multiple "*" characters in the pattern. If there
** are also "?" characters, skip those as well, but consume a
** single character of the input string for each "?" skipped */
- while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
+ while( (c=Utf8Read(zPattern)) == matchAll
+ || (c == matchOne && matchOne!=0) ){
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
return SQLITE_NOWILDCARDMATCH;
}
@@ -119393,7 +120285,9 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
int nExpr;
- if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
+ assert( pExpr!=0 );
+ assert( pExpr->op==TK_FUNCTION );
+ if( !pExpr->x.pList ){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -119432,6 +120326,203 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
return 1;
}
+/* Mathematical Constants */
+#ifndef M_PI
+# define M_PI 3.141592653589793238462643383279502884
+#endif
+#ifndef M_LN10
+# define M_LN10 2.302585092994045684017991454684364208
+#endif
+#ifndef M_LN2
+# define M_LN2 0.693147180559945309417232121458176568
+#endif
+
+
+/* Extra math functions that require linking with -lm
+*/
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+/*
+** Implementation SQL functions:
+**
+** ceil(X)
+** ceiling(X)
+** floor(X)
+**
+** The sqlite3_user_data() pointer is a pointer to the libm implementation
+** of the underlying C function.
+*/
+static void ceilingFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==1 );
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER: {
+ sqlite3_result_int64(context, sqlite3_value_int64(argv[0]));
+ break;
+ }
+ case SQLITE_FLOAT: {
+ double (*x)(double) = (double(*)(double))sqlite3_user_data(context);
+ sqlite3_result_double(context, x(sqlite3_value_double(argv[0])));
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+}
+
+/*
+** On some systems, ceil() and floor() are intrinsic function. You are
+** unable to take a pointer to these functions. Hence, we here wrap them
+** in our own actual functions.
+*/
+static double xCeil(double x){ return ceil(x); }
+static double xFloor(double x){ return floor(x); }
+
+/*
+** Implementation of SQL functions:
+**
+** ln(X) - natural logarithm
+** log(X) - log X base 10
+** log10(X) - log X base 10
+** log(B,X) - log X base B
+*/
+static void logFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ double x, b, ans;
+ assert( argc==1 || argc==2 );
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ x = sqlite3_value_double(argv[0]);
+ if( x<=0.0 ) return;
+ break;
+ default:
+ return;
+ }
+ if( argc==2 ){
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ b = log(x);
+ if( b<=0.0 ) return;
+ x = sqlite3_value_double(argv[1]);
+ if( x<=0.0 ) return;
+ break;
+ default:
+ return;
+ }
+ ans = log(x)/b;
+ }else{
+ ans = log(x);
+ switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
+ case 1:
+ /* Convert from natural logarithm to log base 10 */
+ ans *= 1.0/M_LN10;
+ break;
+ case 2:
+ /* Convert from natural logarithm to log base 2 */
+ ans *= 1.0/M_LN2;
+ break;
+ default:
+ break;
+ }
+ }
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Functions to converts degrees to radians and radians to degrees.
+*/
+static double degToRad(double x){ return x*(M_PI/180.0); }
+static double radToDeg(double x){ return x*(180.0/M_PI); }
+
+/*
+** Implementation of 1-argument SQL math functions:
+**
+** exp(X) - Compute e to the X-th power
+*/
+static void math1Func(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int type0;
+ double v0, ans;
+ double (*x)(double);
+ assert( argc==1 );
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ v0 = sqlite3_value_double(argv[0]);
+ x = (double(*)(double))sqlite3_user_data(context);
+ ans = x(v0);
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 2-argument SQL math functions:
+**
+** power(X,Y) - Compute X to the Y-th power
+*/
+static void math2Func(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int type0, type1;
+ double v0, v1, ans;
+ double (*x)(double,double);
+ assert( argc==2 );
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ type1 = sqlite3_value_numeric_type(argv[1]);
+ if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return;
+ v0 = sqlite3_value_double(argv[0]);
+ v1 = sqlite3_value_double(argv[1]);
+ x = (double(*)(double,double))sqlite3_user_data(context);
+ ans = x(v0, v1);
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 2-argument SQL math functions:
+**
+** power(X,Y) - Compute X to the Y-th power
+*/
+static void piFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==0 );
+ sqlite3_result_double(context, M_PI);
+}
+
+#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
+
+/*
+** Implementation of sign(X) function.
+*/
+static void signFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int type0;
+ double x;
+ UNUSED_PARAMETER(argc);
+ assert( argc==1 );
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ x = sqlite3_value_double(argv[0]);
+ sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
+}
+
/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
@@ -119550,6 +120641,43 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
#endif
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+ MFUNCTION(ceil, 1, xCeil, ceilingFunc ),
+ MFUNCTION(ceiling, 1, xCeil, ceilingFunc ),
+ MFUNCTION(floor, 1, xFloor, ceilingFunc ),
+#if SQLITE_HAVE_C99_MATH_FUNCS
+ MFUNCTION(trunc, 1, trunc, ceilingFunc ),
+#endif
+ FUNCTION(ln, 1, 0, 0, logFunc ),
+ FUNCTION(log, 1, 1, 0, logFunc ),
+ FUNCTION(log10, 1, 1, 0, logFunc ),
+ FUNCTION(log2, 1, 2, 0, logFunc ),
+ FUNCTION(log, 2, 0, 0, logFunc ),
+ MFUNCTION(exp, 1, exp, math1Func ),
+ MFUNCTION(pow, 2, pow, math2Func ),
+ MFUNCTION(power, 2, pow, math2Func ),
+ MFUNCTION(mod, 2, fmod, math2Func ),
+ MFUNCTION(acos, 1, acos, math1Func ),
+ MFUNCTION(asin, 1, asin, math1Func ),
+ MFUNCTION(atan, 1, atan, math1Func ),
+ MFUNCTION(atan2, 2, atan2, math2Func ),
+ MFUNCTION(cos, 1, cos, math1Func ),
+ MFUNCTION(sin, 1, sin, math1Func ),
+ MFUNCTION(tan, 1, tan, math1Func ),
+ MFUNCTION(cosh, 1, cosh, math1Func ),
+ MFUNCTION(sinh, 1, sinh, math1Func ),
+ MFUNCTION(tanh, 1, tanh, math1Func ),
+#if SQLITE_HAVE_C99_MATH_FUNCS
+ MFUNCTION(acosh, 1, acosh, math1Func ),
+ MFUNCTION(asinh, 1, asinh, math1Func ),
+ MFUNCTION(atanh, 1, atanh, math1Func ),
+#endif
+ MFUNCTION(sqrt, 1, sqrt, math1Func ),
+ MFUNCTION(radians, 1, degToRad, math1Func ),
+ MFUNCTION(degrees, 1, radToDeg, math1Func ),
+ FUNCTION(pi, 0, 0, 0, piFunc ),
+#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
+ FUNCTION(sign, 1, 0, 0, signFunc ),
INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
};
@@ -120605,7 +121733,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
** child table as a SrcList for sqlite3WhereBegin() */
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
- struct SrcList_item *pItem = pSrc->a;
+ SrcItem *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
pItem->pTab->nTabRef++;
@@ -120693,7 +121821,9 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
**
** For an UPDATE, this function returns 2 if:
**
-** * There are any FKs for which pTab is the child and the parent table, or
+** * There are any FKs for which pTab is the child and the parent table
+** and any FK processing at all is required (even of a different FK), or
+**
** * the UPDATE modifies one or more parent keys for which the action is
** not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL).
**
@@ -120705,13 +121835,14 @@ SQLITE_PRIVATE int sqlite3FkRequired(
int *aChange, /* Non-NULL for UPDATE operations */
int chngRowid /* True for UPDATE that affects rowid */
){
- int eRet = 0;
+ int eRet = 1; /* Value to return if bHaveFK is true */
+ int bHaveFK = 0; /* If FK processing is required */
if( pParse->db->flags&SQLITE_ForeignKeys ){
if( !aChange ){
/* A DELETE operation. Foreign key processing is required if the
** table in question is either the child or parent table for any
** foreign key constraint. */
- eRet = (sqlite3FkReferences(pTab) || pTab->pFKey);
+ bHaveFK = (sqlite3FkReferences(pTab) || pTab->pFKey);
}else{
/* This is an UPDATE. Foreign key processing is only required if the
** operation modifies one or more child or parent key columns. */
@@ -120719,9 +121850,9 @@ SQLITE_PRIVATE int sqlite3FkRequired(
/* Check if any child key columns are being modified. */
for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2;
if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
- eRet = 1;
+ if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
+ bHaveFK = 1;
}
}
@@ -120729,12 +121860,12 @@ SQLITE_PRIVATE int sqlite3FkRequired(
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
if( fkParentIsModified(pTab, p, aChange, chngRowid) ){
if( p->aAction[1]!=OE_None ) return 2;
- eRet = 1;
+ bHaveFK = 1;
}
}
}
}
- return eRet;
+ return bHaveFK ? eRet : 0;
}
/*
@@ -121403,7 +122534,9 @@ static int autoIncBegin(
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
if( pInfo==0 ){
pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
- if( pInfo==0 ) return 0;
+ sqlite3ParserAddCleanup(pToplevel, sqlite3DbFree, pInfo);
+ testcase( pParse->earlyCleanup );
+ if( pParse->db->mallocFailed ) return 0;
pInfo->pNext = pToplevel->pAinc;
pToplevel->pAinc = pInfo;
pInfo->pTab = pTab;
@@ -121961,19 +123094,24 @@ SQLITE_PRIVATE void sqlite3Insert(
}
}
#endif
- }
- /* Make sure the number of columns in the source data matches the number
- ** of columns to be inserted into the table.
- */
- for(i=0; i<pTab->nCol; i++){
- if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
- }
- if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
- sqlite3ErrorMsg(pParse,
- "table %S has %d columns but %d values were supplied",
- pTabList, 0, pTab->nCol-nHidden, nColumn);
- goto insert_cleanup;
+ /* Make sure the number of columns in the source data matches the number
+ ** of columns to be inserted into the table.
+ */
+ assert( TF_HasHidden==COLFLAG_HIDDEN );
+ assert( TF_HasGenerated==COLFLAG_GENERATED );
+ assert( COLFLAG_NOINSERT==(COLFLAG_GENERATED|COLFLAG_HIDDEN) );
+ if( (pTab->tabFlags & (TF_HasGenerated|TF_HasHidden))!=0 ){
+ for(i=0; i<pTab->nCol; i++){
+ if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
+ }
+ }
+ if( nColumn!=(pTab->nCol-nHidden) ){
+ sqlite3ErrorMsg(pParse,
+ "table %S has %d columns but %d values were supplied",
+ pTabList, 0, pTab->nCol-nHidden, nColumn);
+ goto insert_cleanup;
+ }
}
if( pColumn!=0 && nColumn!=pColumn->nId ){
sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
@@ -121985,6 +123123,7 @@ SQLITE_PRIVATE void sqlite3Insert(
if( (db->flags & SQLITE_CountRows)!=0
&& !pParse->nested
&& !pParse->pTriggerTab
+ && !pParse->bReturning
){
regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
@@ -122008,6 +123147,7 @@ SQLITE_PRIVATE void sqlite3Insert(
}
#ifndef SQLITE_OMIT_UPSERT
if( pUpsert ){
+ Upsert *pNx;
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
pTab->zName);
@@ -122021,13 +123161,19 @@ SQLITE_PRIVATE void sqlite3Insert(
goto insert_cleanup;
}
pTabList->a[0].iCursor = iDataCur;
- pUpsert->pUpsertSrc = pTabList;
- pUpsert->regData = regData;
- pUpsert->iDataCur = iDataCur;
- pUpsert->iIdxCur = iIdxCur;
- if( pUpsert->pUpsertTarget ){
- sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert);
- }
+ pNx = pUpsert;
+ do{
+ pNx->pUpsertSrc = pTabList;
+ pNx->regData = regData;
+ pNx->iDataCur = iDataCur;
+ pNx->iIdxCur = iIdxCur;
+ if( pNx->pUpsertTarget ){
+ if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
+ goto insert_cleanup;
+ }
+ }
+ pNx = pNx->pNextUpsert;
+ }while( pNx!=0 );
}
#endif
@@ -122168,11 +123314,6 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
}
- /* Cannot have triggers on a virtual table. If it were possible,
- ** this block would have to account for hidden column.
- */
- assert( !IsVirtual(pTab) );
-
/* Copy the new data already generated. */
assert( pTab->nNVCol>0 );
sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);
@@ -122327,7 +123468,9 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3VdbeJumpHere(v, addrInsTop);
}
+#ifndef SQLITE_OMIT_XFER_OPT
insert_end:
+#endif /* SQLITE_OMIT_XFER_OPT */
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
** autoincrement tables.
@@ -122342,7 +123485,7 @@ insert_end:
** invoke the callback function.
*/
if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
+ sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
}
@@ -122433,6 +123576,70 @@ SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(
}
/*
+** The sqlite3GenerateConstraintChecks() routine usually wants to visit
+** the indexes of a table in the order provided in the Table->pIndex list.
+** However, sometimes (rarely - when there is an upsert) it wants to visit
+** the indexes in a different order. The following data structures accomplish
+** this.
+**
+** The IndexIterator object is used to walk through all of the indexes
+** of a table in either Index.pNext order, or in some other order established
+** by an array of IndexListTerm objects.
+*/
+typedef struct IndexListTerm IndexListTerm;
+typedef struct IndexIterator IndexIterator;
+struct IndexIterator {
+ int eType; /* 0 for Index.pNext list. 1 for an array of IndexListTerm */
+ int i; /* Index of the current item from the list */
+ union {
+ struct { /* Use this object for eType==0: A Index.pNext list */
+ Index *pIdx; /* The current Index */
+ } lx;
+ struct { /* Use this object for eType==1; Array of IndexListTerm */
+ int nIdx; /* Size of the array */
+ IndexListTerm *aIdx; /* Array of IndexListTerms */
+ } ax;
+ } u;
+};
+
+/* When IndexIterator.eType==1, then each index is an array of instances
+** of the following object
+*/
+struct IndexListTerm {
+ Index *p; /* The index */
+ int ix; /* Which entry in the original Table.pIndex list is this index*/
+};
+
+/* Return the first index on the list */
+static Index *indexIteratorFirst(IndexIterator *pIter, int *pIx){
+ assert( pIter->i==0 );
+ if( pIter->eType ){
+ *pIx = pIter->u.ax.aIdx[0].ix;
+ return pIter->u.ax.aIdx[0].p;
+ }else{
+ *pIx = 0;
+ return pIter->u.lx.pIdx;
+ }
+}
+
+/* Return the next index from the list. Return NULL when out of indexes */
+static Index *indexIteratorNext(IndexIterator *pIter, int *pIx){
+ if( pIter->eType ){
+ int i = ++pIter->i;
+ if( i>=pIter->u.ax.nIdx ){
+ *pIx = i;
+ return 0;
+ }
+ *pIx = pIter->u.ax.aIdx[i].ix;
+ return pIter->u.ax.aIdx[i].p;
+ }else{
+ ++(*pIx);
+ pIter->u.lx.pIdx = pIter->u.lx.pIdx->pNext;
+ return pIter->u.lx.pIdx;
+ }
+}
+
+/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
@@ -122540,7 +123747,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
){
Vdbe *v; /* VDBE under constrution */
Index *pIdx; /* Pointer to one of the indices */
- Index *pPk = 0; /* The PRIMARY KEY index */
+ Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */
sqlite3 *db; /* Database connection */
int i; /* loop counter */
int ix; /* Index loop counter */
@@ -122548,11 +123755,11 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int onError; /* Conflict resolution strategy */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
- Index *pUpIdx = 0; /* Index to which to apply the upsert */
- u8 isUpdate; /* True if this is an UPDATE operation */
+ Upsert *pUpsertClause = 0; /* The specific ON CONFLICT clause for pIdx */
+ u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
- int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */
- int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */
+ int upsertIpkReturn = 0; /* Address of Goto at end of IPK uniqueness check */
+ int upsertIpkDelay = 0; /* Address of Goto to bypass initial IPK check */
int ipkTop = 0; /* Top of the IPK uniqueness check */
int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
/* Variables associated with retesting uniqueness constraints after
@@ -122562,6 +123769,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
Trigger *pTrigger; /* List of DELETE triggers on the table pTab */
int nReplaceTrig = 0; /* Number of replace triggers coded */
+ IndexIterator sIdxIter; /* Index iterator */
isUpdate = regOldData!=0;
db = pParse->db;
@@ -122759,19 +123967,63 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** list of indexes attached to a table puts all OE_Replace indexes last
** in the list. See sqlite3CreateIndex() for where that happens.
*/
-
+ sIdxIter.eType = 0;
+ sIdxIter.i = 0;
+ sIdxIter.u.ax.aIdx = 0; /* Silence harmless compiler warning */
+ sIdxIter.u.lx.pIdx = pTab->pIndex;
if( pUpsert ){
if( pUpsert->pUpsertTarget==0 ){
- /* An ON CONFLICT DO NOTHING clause, without a constraint-target.
- ** Make all unique constraint resolution be OE_Ignore */
- assert( pUpsert->pUpsertSet==0 );
- overrideError = OE_Ignore;
- pUpsert = 0;
- }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
- /* If the constraint-target uniqueness check must be run first.
- ** Jump to that uniqueness check now */
- upsertJump = sqlite3VdbeAddOp0(v, OP_Goto);
- VdbeComment((v, "UPSERT constraint goes first"));
+ /* There is just on ON CONFLICT clause and it has no constraint-target */
+ assert( pUpsert->pNextUpsert==0 );
+ if( pUpsert->isDoUpdate==0 ){
+ /* A single ON CONFLICT DO NOTHING clause, without a constraint-target.
+ ** Make all unique constraint resolution be OE_Ignore */
+ overrideError = OE_Ignore;
+ pUpsert = 0;
+ }else{
+ /* A single ON CONFLICT DO UPDATE. Make all resolutions OE_Update */
+ overrideError = OE_Update;
+ }
+ }else if( pTab->pIndex!=0 ){
+ /* Otherwise, we'll need to run the IndexListTerm array version of the
+ ** iterator to ensure that all of the ON CONFLICT conditions are
+ ** checked first and in order. */
+ int nIdx, jj;
+ u64 nByte;
+ Upsert *pTerm;
+ u8 *bUsed;
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
+ assert( aRegIdx[nIdx]>0 );
+ }
+ sIdxIter.eType = 1;
+ sIdxIter.u.ax.nIdx = nIdx;
+ nByte = (sizeof(IndexListTerm)+1)*nIdx + nIdx;
+ sIdxIter.u.ax.aIdx = sqlite3DbMallocZero(db, nByte);
+ if( sIdxIter.u.ax.aIdx==0 ) return; /* OOM */
+ bUsed = (u8*)&sIdxIter.u.ax.aIdx[nIdx];
+ pUpsert->pToFree = sIdxIter.u.ax.aIdx;
+ for(i=0, pTerm=pUpsert; pTerm; pTerm=pTerm->pNextUpsert){
+ if( pTerm->pUpsertTarget==0 ) break;
+ if( pTerm->pUpsertIdx==0 ) continue; /* Skip ON CONFLICT for the IPK */
+ jj = 0;
+ pIdx = pTab->pIndex;
+ while( ALWAYS(pIdx!=0) && pIdx!=pTerm->pUpsertIdx ){
+ pIdx = pIdx->pNext;
+ jj++;
+ }
+ if( bUsed[jj] ) continue; /* Duplicate ON CONFLICT clause ignored */
+ bUsed[jj] = 1;
+ sIdxIter.u.ax.aIdx[i].p = pIdx;
+ sIdxIter.u.ax.aIdx[i].ix = jj;
+ i++;
+ }
+ for(jj=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, jj++){
+ if( bUsed[jj] ) continue;
+ sIdxIter.u.ax.aIdx[i].p = pIdx;
+ sIdxIter.u.ax.aIdx[i].ix = jj;
+ i++;
+ }
+ assert( i==nIdx );
}
}
@@ -122834,11 +124086,20 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
/* figure out whether or not upsert applies in this case */
- if( pUpsert && pUpsert->pUpsertIdx==0 ){
- if( pUpsert->pUpsertSet==0 ){
- onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
- }else{
- onError = OE_Update; /* DO UPDATE */
+ if( pUpsert ){
+ pUpsertClause = sqlite3UpsertOfIndex(pUpsert,0);
+ if( pUpsertClause!=0 ){
+ if( pUpsertClause->isDoUpdate==0 ){
+ onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
+ }else{
+ onError = OE_Update; /* DO UPDATE */
+ }
+ }
+ if( pUpsertClause!=pUpsert ){
+ /* The first ON CONFLICT clause has a conflict target other than
+ ** the IPK. We have to jump ahead to that first ON CONFLICT clause
+ ** and then come back here and deal with the IPK afterwards */
+ upsertIpkDelay = sqlite3VdbeAddOp0(v, OP_Goto);
}
}
@@ -122848,7 +124109,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** the UNIQUE constraints have run.
*/
if( onError==OE_Replace /* IPK rule is REPLACE */
- && onError!=overrideError /* Rules for other contraints are different */
+ && onError!=overrideError /* Rules for other constraints are different */
&& pTab->pIndex /* There exist other constraints */
){
ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
@@ -122945,7 +124206,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeResolveLabel(v, addrRowidOk);
- if( ipkTop ){
+ if( pUpsert && pUpsertClause!=pUpsert ){
+ upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto);
+ }else if( ipkTop ){
ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, ipkTop-1);
}
@@ -122958,7 +124221,10 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** This loop also handles the case of the PRIMARY KEY index for a
** WITHOUT ROWID table.
*/
- for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
+ for(pIdx = indexIteratorFirst(&sIdxIter, &ix);
+ pIdx;
+ pIdx = indexIteratorNext(&sIdxIter, &ix)
+ ){
int regIdx; /* Range of registers hold conent for pIdx */
int regR; /* Range of registers holding conflicting PK */
int iThisCur; /* Cursor for this UNIQUE index */
@@ -122966,15 +124232,14 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int addrConflictCk; /* First opcode in the conflict check logic */
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
- if( pUpIdx==pIdx ){
- addrUniqueOk = upsertJump+1;
- upsertBypass = sqlite3VdbeGoto(v, 0);
- VdbeComment((v, "Skip upsert subroutine"));
- sqlite3VdbeJumpHere(v, upsertJump);
- }else{
- addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
+ if( pUpsert ){
+ pUpsertClause = sqlite3UpsertOfIndex(pUpsert, pIdx);
+ if( upsertIpkDelay && pUpsertClause==pUpsert ){
+ sqlite3VdbeJumpHere(v, upsertIpkDelay);
+ }
}
- if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
+ addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
+ if( bAffinityDone==0 ){
sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
@@ -123045,8 +124310,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
/* Figure out if the upsert clause applies to this index */
- if( pUpIdx==pIdx ){
- if( pUpsert->pUpsertSet==0 ){
+ if( pUpsertClause ){
+ if( pUpsertClause->isDoUpdate==0 ){
onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
}else{
onError = OE_Update; /* DO UPDATE */
@@ -123084,7 +124349,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
/* Generate code to handle collisions */
- regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
+ regR = pIdx==pPk ? regIdx : sqlite3GetTempRange(pParse, nPkField);
if( isUpdate || onError==OE_Replace ){
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
@@ -123236,13 +124501,16 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
break;
}
}
- if( pUpIdx==pIdx ){
- sqlite3VdbeGoto(v, upsertJump+1);
- sqlite3VdbeJumpHere(v, upsertBypass);
- }else{
- sqlite3VdbeResolveLabel(v, addrUniqueOk);
- }
+ sqlite3VdbeResolveLabel(v, addrUniqueOk);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
+ if( pUpsertClause
+ && upsertIpkReturn
+ && sqlite3UpsertNextIsIPK(pUpsertClause)
+ ){
+ sqlite3VdbeGoto(v, upsertIpkDelay+1);
+ sqlite3VdbeJumpHere(v, upsertIpkReturn);
+ upsertIpkReturn = 0;
+ }
}
/* If the IPK constraint is a REPLACE, run it last */
@@ -123309,6 +124577,32 @@ SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
#endif
/*
+** Table pTab is a WITHOUT ROWID table that is being written to. The cursor
+** number is iCur, and register regData contains the new record for the
+** PK index. This function adds code to invoke the pre-update hook,
+** if one is registered.
+*/
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+static void codeWithoutRowidPreupdate(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Table being updated */
+ int iCur, /* Cursor number for table */
+ int regData /* Data containing new record */
+){
+ Vdbe *v = pParse->pVdbe;
+ int r = sqlite3GetTempReg(pParse);
+ assert( !HasRowid(pTab) );
+ assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) || CORRUPT_DB );
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
+ sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE);
+ sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
+ sqlite3ReleaseTempReg(pParse, r);
+}
+#else
+# define codeWithoutRowidPreupdate(a,b,c,d)
+#endif
+
+/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
** A consecutive range of registers starting at regNewData contains the
@@ -123356,17 +124650,9 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( update_flags==0 ){
- int r = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
- sqlite3VdbeAddOp4(v, OP_Insert,
- iIdxCur+i, aRegIdx[i], r, (char*)pTab, P4_TABLE
- );
- sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
- sqlite3ReleaseTempReg(pParse, r);
+ codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]);
}
-#endif
}
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
aRegIdx[i]+1,
@@ -123564,7 +124850,7 @@ static int xferOptimization(
ExprList *pEList; /* The result set of the SELECT */
Table *pSrc; /* The table in the FROM clause of SELECT */
Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
- struct SrcList_item *pItem; /* An element of pSelect->pSrc */
+ SrcItem *pItem; /* An element of pSelect->pSrc */
int i; /* Loop counter */
int iDbSrc; /* The database of pSrc */
int iSrc, iDest; /* Cursors from source and destination */
@@ -123781,6 +125067,7 @@ static int xferOptimization(
iDest = pParse->nTab++;
regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
regData = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regData);
regRowid = sqlite3GetTempReg(pParse);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
assert( HasRowid(pDest) || destHasUniqueIdx );
@@ -123816,11 +125103,13 @@ static int xferOptimization(
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- sqlite3VdbeVerifyAbortable(v, onError);
- addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
- VdbeCoverage(v);
- sqlite3RowidConstraint(pParse, onError, pDest);
- sqlite3VdbeJumpHere(v, addr2);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlite3VdbeVerifyAbortable(v, onError);
+ addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
+ VdbeCoverage(v);
+ sqlite3RowidConstraint(pParse, onError, pDest);
+ sqlite3VdbeJumpHere(v, addr2);
+ }
autoIncStep(pParse, regAutoinc, regRowid);
}else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){
addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
@@ -123828,16 +125117,28 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
+
if( db->mDbFlags & DBFLAG_Vacuum ){
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
- insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
+ insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
}else{
- insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT;
+ }
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ insFlags &= ~OPFLAG_PREFORMAT;
+ }else
+#endif
+ {
+ sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid);
+ }
+ sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlite3VdbeChangeP4(v, -1, (char*)pDest, P4_TABLE);
}
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
- sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
- (char*)pDest, P4_TABLE);
sqlite3VdbeChangeP5(v, insFlags);
+
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
@@ -123879,13 +125180,22 @@ static int xferOptimization(
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
}
if( i==pSrcIdx->nColumn ){
- idxInsFlags = OPFLAG_USESEEKRESULT;
+ idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
+ sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc);
}
}else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
idxInsFlags |= OPFLAG_NCHANGE;
}
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0
+ && !HasRowid(pDest)
+ && IsPrimaryKeyIndex(pDestIdx)
+ ){
+ codeWithoutRowidPreupdate(pParse, pDest, iDest, regData);
+ }
+ }
sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
@@ -128201,7 +129511,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** Checkpoint the database.
*/
case PragTyp_WAL_CHECKPOINT: {
- int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
+ int iBt = (pId2->z?iDb:SQLITE_MAX_DB);
int eMode = SQLITE_CHECKPOINT_PASSIVE;
if( zRight ){
if( sqlite3StrICmp(zRight, "full")==0 ){
@@ -128849,7 +130159,7 @@ SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName)
*/
static void corruptSchema(
InitData *pData, /* Initialization context */
- const char *zObj, /* Object being parsed at the point of error */
+ char **azObj, /* Type and name of object being parsed */
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
@@ -128857,14 +130167,18 @@ static void corruptSchema(
pData->rc = SQLITE_NOMEM_BKPT;
}else if( pData->pzErrMsg[0]!=0 ){
/* A error message has already been generated. Do not overwrite it */
- }else if( pData->mInitFlags & INITFLAG_AlterTable ){
- *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra);
+ }else if( pData->mInitFlags & (INITFLAG_AlterRename|INITFLAG_AlterDrop) ){
+ *pData->pzErrMsg = sqlite3MPrintf(db,
+ "error in %s %s after %s: %s", azObj[0], azObj[1],
+ (pData->mInitFlags & INITFLAG_AlterRename) ? "rename" : "drop column",
+ zExtra
+ );
pData->rc = SQLITE_ERROR;
}else if( db->flags & SQLITE_WriteSchema ){
pData->rc = SQLITE_CORRUPT_BKPT;
}else{
char *z;
- if( zObj==0 ) zObj = "?";
+ const char *zObj = azObj[1] ? azObj[1] : "?";
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
*pData->pzErrMsg = z;
@@ -128922,19 +130236,26 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
db->mDbFlags |= DBFLAG_EncodingFixed;
pData->nInitRow++;
if( db->mallocFailed ){
- corruptSchema(pData, argv[1], 0);
+ corruptSchema(pData, argv, 0);
return 1;
}
assert( iDb>=0 && iDb<db->nDb );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[3]==0 ){
- corruptSchema(pData, argv[1], 0);
- }else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
+ corruptSchema(pData, argv, 0);
+ }else if( argv[4]
+ && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]]
+ && 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
+ **
+ ** No other valid SQL statement, other than the variable CREATE statements,
+ ** can begin with the letters "C" and "R". Thus, it is not possible run
+ ** any other kind of statement while parsing the schema, even a corrupt
+ ** schema.
*/
int rc;
u8 saved_iDb = db->init.iDb;
@@ -128947,7 +130268,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
|| (db->init.newTnum>pData->mxPage && pData->mxPage>0)
){
if( sqlite3Config.bExtraSchemaChecks ){
- corruptSchema(pData, argv[1], "invalid rootpage");
+ corruptSchema(pData, argv, "invalid rootpage");
}
}
db->init.orphanTrigger = 0;
@@ -128966,13 +130287,13 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(db);
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
- corruptSchema(pData, argv[1], sqlite3_errmsg(db));
+ corruptSchema(pData, argv, sqlite3_errmsg(db));
}
}
}
sqlite3_finalize(pStmt);
}else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
- corruptSchema(pData, argv[1], 0);
+ corruptSchema(pData, argv, 0);
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@@ -128983,7 +130304,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
if( pIndex==0 ){
- corruptSchema(pData, argv[1], "orphan index");
+ corruptSchema(pData, argv, "orphan index");
}else
if( sqlite3GetUInt32(argv[3],&pIndex->tnum)==0
|| pIndex->tnum<2
@@ -128991,7 +130312,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
|| sqlite3IndexHasDuplicateRootPage(pIndex)
){
if( sqlite3Config.bExtraSchemaChecks ){
- corruptSchema(pData, argv[1], "invalid rootpage");
+ corruptSchema(pData, argv, "invalid rootpage");
}
}
}
@@ -129372,27 +130693,20 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
}
/*
-** Deallocate a single AggInfo object
-*/
-static void agginfoFree(sqlite3 *db, AggInfo *p){
- sqlite3DbFree(db, p->aCol);
- sqlite3DbFree(db, p->aFunc);
- sqlite3DbFree(db, p);
-}
-
-/*
** Free all memory allocations in the pParse object
*/
SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){
sqlite3 *db = pParse->db;
- AggInfo *pThis = pParse->pAggList;
- while( pThis ){
- AggInfo *pNext = pThis->pNext;
- agginfoFree(db, pThis);
- pThis = pNext;
+ while( pParse->pCleanup ){
+ ParseCleanup *pCleanup = pParse->pCleanup;
+ pParse->pCleanup = pCleanup->pNext;
+ pCleanup->xCleanup(db, pCleanup->pPtr);
+ sqlite3DbFreeNN(db, pCleanup);
}
sqlite3DbFree(db, pParse->aLabel);
- sqlite3ExprListDelete(db, pParse->pConstExpr);
+ if( pParse->pConstExpr ){
+ sqlite3ExprListDelete(db, pParse->pConstExpr);
+ }
if( db ){
assert( db->lookaside.bDisable >= pParse->disableLookaside );
db->lookaside.bDisable -= pParse->disableLookaside;
@@ -129402,6 +130716,55 @@ SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){
}
/*
+** Add a new cleanup operation to a Parser. The cleanup should happen when
+** the parser object is destroyed. But, beware: the cleanup might happen
+** immediately.
+**
+** Use this mechanism for uncommon cleanups. There is a higher setup
+** cost for this mechansim (an extra malloc), so it should not be used
+** for common cleanups that happen on most calls. But for less
+** common cleanups, we save a single NULL-pointer comparison in
+** sqlite3ParserReset(), which reduces the total CPU cycle count.
+**
+** If a memory allocation error occurs, then the cleanup happens immediately.
+** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
+** pParse->earlyCleanup flag is set in that case. Calling code show verify
+** that test cases exist for which this happens, to guard against possible
+** use-after-free errors following an OOM. The preferred way to do this is
+** to immediately follow the call to this routine with:
+**
+** testcase( pParse->earlyCleanup );
+**
+** This routine returns a copy of its pPtr input (the third parameter)
+** except if an early cleanup occurs, in which case it returns NULL. So
+** another way to check for early cleanup is to check the return value.
+** Or, stop using the pPtr parameter with this call and use only its
+** return value thereafter. Something like this:
+**
+** pObj = sqlite3ParserAddCleanup(pParse, destructor, pObj);
+*/
+SQLITE_PRIVATE void *sqlite3ParserAddCleanup(
+ Parse *pParse, /* Destroy when this Parser finishes */
+ void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
+ void *pPtr /* Pointer to object to be cleaned up */
+){
+ ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
+ if( pCleanup ){
+ pCleanup->pNext = pParse->pCleanup;
+ pParse->pCleanup = pCleanup;
+ pCleanup->pPtr = pPtr;
+ pCleanup->xCleanup = xCleanup;
+ }else{
+ xCleanup(pParse->db, pPtr);
+ pPtr = 0;
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ pParse->earlyCleanup = 1;
+#endif
+ }
+ return pPtr;
+}
+
+/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
static int sqlite3Prepare(
@@ -129499,12 +130862,6 @@ static int sqlite3Prepare(
}
assert( 0==sParse.nQueryLoop );
- if( sParse.rc==SQLITE_DONE ){
- sParse.rc = SQLITE_OK;
- }
- if( sParse.checkSchema ){
- schemaIsValid(&sParse);
- }
if( pzTail ){
*pzTail = sParse.zTail;
}
@@ -129515,20 +130872,28 @@ static int sqlite3Prepare(
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
}
- rc = sParse.rc;
- if( rc!=SQLITE_OK ){
- if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe);
- assert(!(*ppStmt));
+ if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
+ if( sParse.checkSchema ){
+ schemaIsValid(&sParse);
+ }
+ if( sParse.pVdbe ){
+ sqlite3VdbeFinalize(sParse.pVdbe);
+ }
+ assert( 0==(*ppStmt) );
+ rc = sParse.rc;
+ if( zErrMsg ){
+ sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
+ }else{
+ sqlite3Error(db, rc);
+ }
}else{
+ assert( zErrMsg==0 );
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
+ rc = SQLITE_OK;
+ sqlite3ErrorClear(db);
}
- if( zErrMsg ){
- sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
- sqlite3DbFree(db, zErrMsg);
- }else{
- sqlite3Error(db, rc);
- }
/* Delete any TriggerPrg structures allocated while parsing this statement. */
while( sParse.pTriggerPrg ){
@@ -129874,12 +131239,16 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
+ if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
sqlite3WindowListDelete(db, p->pWinDefn);
}
+ while( p->pWin ){
+ assert( p->pWin->ppThis==&p->pWin );
+ sqlite3WindowUnlinkFromSelect(p->pWin);
+ }
#endif
- if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
@@ -130051,7 +131420,7 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p
** Return the index of a column in a table. Return -1 if the column
** is not contained in the table.
*/
-static int columnIndex(Table *pTab, const char *zCol){
+SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
int i;
u8 h = sqlite3StrIHash(zCol);
Column *pCol;
@@ -130083,7 +131452,7 @@ static int tableAndColumnIndex(
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=0; i<N; i++){
- iCol = columnIndex(pSrc->a[i].pTab, zCol);
+ iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
if( iCol>=0
&& (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
){
@@ -130136,7 +131505,7 @@ static void addWhereTerm(
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pEq, EP_NoReduce);
- pEq->iRightJoinTable = (i16)pE2->iTable;
+ pEq->iRightJoinTable = pE2->iTable;
}
*ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq);
}
@@ -130172,7 +131541,7 @@ SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
- p->iRightJoinTable = (i16)iTable;
+ p->iRightJoinTable = iTable;
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
@@ -130196,6 +131565,9 @@ static void unsetJoinExpr(Expr *p, int iTable){
&& (iTable<0 || p->iRightJoinTable==iTable) ){
ExprClearProperty(p, EP_FromJoin);
}
+ if( p->op==TK_COLUMN && p->iTable==iTable ){
+ ExprClearProperty(p, EP_CanBeNull);
+ }
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
@@ -130224,8 +131596,8 @@ static void unsetJoinExpr(Expr *p, int iTable){
static int sqliteProcessJoin(Parse *pParse, Select *p){
SrcList *pSrc; /* All tables in the FROM clause */
int i, j; /* Loop counters */
- struct SrcList_item *pLeft; /* Left table being joined */
- struct SrcList_item *pRight; /* Right table being joined */
+ SrcItem *pLeft; /* Left table being joined */
+ SrcItem *pRight; /* Right table being joined */
pSrc = p->pSrc;
pLeft = &pSrc->a[0];
@@ -130293,7 +131665,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
int iRightCol; /* Column number of matching column on the right */
zName = pList->a[j].zName;
- iRightCol = columnIndex(pRightTab, zName);
+ iRightCol = sqlite3ColumnIndex(pRightTab, zName);
if( iRightCol<0
|| !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
){
@@ -131172,7 +132544,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(
/*
** Name of the connection operator, used for error messages.
*/
-static const char *selectOpName(int id){
+SQLITE_PRIVATE const char *sqlite3SelectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
@@ -131768,7 +133140,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
nCol = pEList->nExpr;
aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
testcase( aCol==0 );
- if( nCol>32767 ) nCol = 32767;
+ if( NEVER(nCol>32767) ) nCol = 32767;
}else{
nCol = 0;
aCol = 0;
@@ -131875,6 +133247,7 @@ SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const char *zType;
int n, m;
+ pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
p = a[i].pExpr;
zType = columnType(&sNC, p, 0, 0, 0);
/* pCol->szEst = ... // Column size est for SELECT tables never used */
@@ -132390,12 +133763,8 @@ static int multiSelect(
db = pParse->db;
pPrior = p->pPrior;
dest = *pDest;
- if( pPrior->pOrderBy || pPrior->pLimit ){
- sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
- pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op));
- rc = 1;
- goto multi_select_end;
- }
+ assert( pPrior->pOrderBy==0 );
+ assert( pPrior->pLimit==0 );
v = sqlite3GetVdbe(pParse);
assert( v!=0 ); /* The VDBE already created by calling function */
@@ -132452,7 +133821,7 @@ static int multiSelect(
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
rc = sqlite3Select(pParse, pPrior, &dest);
- p->pLimit = 0;
+ pPrior->pLimit = 0;
if( rc ){
goto multi_select_end;
}
@@ -132473,8 +133842,8 @@ static int multiSelect(
pDelete = p->pPrior;
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- if( pPrior->pLimit
- && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
+ if( p->pLimit
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlite3LogEst((u64)nLimit);
@@ -132538,7 +133907,7 @@ static int multiSelect(
p->pLimit = 0;
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlite3SelectOpName(p->op)));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
assert( p->pOrderBy==0 );
@@ -132614,7 +133983,7 @@ static int multiSelect(
p->pLimit = 0;
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlite3SelectOpName(p->op)));
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -132723,7 +134092,8 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
}else{
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
- " do not have the same number of result columns", selectOpName(p->op));
+ " do not have the same number of result columns",
+ sqlite3SelectOpName(p->op));
}
}
@@ -132820,10 +134190,8 @@ static int generateOutputSubroutine(
** if it is the RHS of a row-value IN operator.
*/
case SRT_Mem: {
- if( pParse->nErr==0 ){
- testcase( pIn->nSdst>1 );
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
- }
+ testcase( pIn->nSdst>1 );
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
/* The LIMIT clause will jump out of the loop for us */
break;
}
@@ -133115,7 +134483,7 @@ static int multiSelectOrderBy(
sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
- ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op)));
+ ExplainQueryPlan((pParse, 1, "MERGE (%s)", sqlite3SelectOpName(p->op)));
/* Generate a coroutine to evaluate the SELECT statement to the
** left of the compound operator - the "A" select.
@@ -133385,7 +134753,7 @@ static void substSelect(
int doPrior /* Do substitutes on p->pPrior too */
){
SrcList *pSrc;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
int i;
if( !p ) return;
do{
@@ -133415,7 +134783,7 @@ static void substSelect(
** pSrcItem->colUsed mask.
*/
static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
pItem = pWalker->u.pSrcItem;
if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
@@ -133425,7 +134793,7 @@ static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
}
static void recomputeColumnsUsed(
Select *pSelect, /* The complete SELECT statement */
- struct SrcList_item *pSrcItem /* Which FROM clause item to recompute */
+ SrcItem *pSrcItem /* Which FROM clause item to recompute */
){
Walker w;
if( NEVER(pSrcItem->pTab==0) ) return;
@@ -133440,6 +134808,92 @@ static void recomputeColumnsUsed(
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
+** Assign new cursor numbers to each of the items in pSrc. For each
+** new cursor number assigned, set an entry in the aCsrMap[] array
+** to map the old cursor number to the new:
+**
+** aCsrMap[iOld] = iNew;
+**
+** The array is guaranteed by the caller to be large enough for all
+** existing cursor numbers in pSrc.
+**
+** If pSrc contains any sub-selects, call this routine recursively
+** on the FROM clause of each such sub-select, with iExcept set to -1.
+*/
+static void srclistRenumberCursors(
+ Parse *pParse, /* Parse context */
+ int *aCsrMap, /* Array to store cursor mappings in */
+ SrcList *pSrc, /* FROM clause to renumber */
+ int iExcept /* FROM clause item to skip */
+){
+ int i;
+ SrcItem *pItem;
+ for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
+ if( i!=iExcept ){
+ Select *p;
+ if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
+ aCsrMap[pItem->iCursor] = pParse->nTab++;
+ }
+ pItem->iCursor = aCsrMap[pItem->iCursor];
+ for(p=pItem->pSelect; p; p=p->pPrior){
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ }
+ }
+ }
+}
+
+/*
+** Expression walker callback used by renumberCursors() to update
+** Expr objects to match newly assigned cursor numbers.
+*/
+static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
+ int *aCsrMap = pWalker->u.aiCol;
+ int op = pExpr->op;
+ if( (op==TK_COLUMN || op==TK_IF_NULL_ROW) && aCsrMap[pExpr->iTable] ){
+ pExpr->iTable = aCsrMap[pExpr->iTable];
+ }
+ if( ExprHasProperty(pExpr, EP_FromJoin) && aCsrMap[pExpr->iRightJoinTable] ){
+ pExpr->iRightJoinTable = aCsrMap[pExpr->iRightJoinTable];
+ }
+ return WRC_Continue;
+}
+
+/*
+** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
+** of the SELECT statement passed as the second argument, and to each
+** cursor in the FROM clause of any FROM clause sub-selects, recursively.
+** Except, do not assign a new cursor number to the iExcept'th element in
+** the FROM clause of (*p). Update all expressions and other references
+** to refer to the new cursor numbers.
+**
+** Argument aCsrMap is an array that may be used for temporary working
+** space. Two guarantees are made by the caller:
+**
+** * the array is larger than the largest cursor number used within the
+** select statement passed as an argument, and
+**
+** * the array entries for all cursor numbers that do *not* appear in
+** FROM clauses of the select statement as described above are
+** initialized to zero.
+*/
+static void renumberCursors(
+ Parse *pParse, /* Parse context */
+ Select *p, /* Select to renumber cursors within */
+ int iExcept, /* FROM clause item to skip */
+ int *aCsrMap /* Working space */
+){
+ Walker w;
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
+ memset(&w, 0, sizeof(w));
+ w.u.aiCol = aCsrMap;
+ w.xExprCallback = renumberCursorsCb;
+ w.xSelectCallback = sqlite3SelectWalkNoop;
+ sqlite3WalkSelect(&w, p);
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/*
** This routine attempts to flatten subqueries as a performance optimization.
** This routine returns 1 if it makes changes and 0 if no flattening occurs.
**
@@ -133532,9 +134986,9 @@ static void recomputeColumnsUsed(
** (17c) every term within the subquery compound must have a FROM clause
** (17d) the outer query may not be
** (17d1) aggregate, or
-** (17d2) DISTINCT, or
-** (17d3) a join.
-** (17e) the subquery may not contain window functions
+** (17d2) DISTINCT
+** (17e) the subquery may not contain window functions, and
+** (17f) the subquery must not be the RHS of a LEFT JOIN.
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -133550,8 +135004,8 @@ static void recomputeColumnsUsed(
** syntax error and return a detailed message.
**
** (18) If the sub-query is a compound select, then all terms of the
-** ORDER BY clause of the parent must be simple references to
-** columns of the sub-query.
+** ORDER BY clause of the parent must be copies of a term returned
+** by the parent query.
**
** (19) If the subquery uses LIMIT then the outer query may not
** have a WHERE clause.
@@ -133567,9 +135021,8 @@ static void recomputeColumnsUsed(
**
** (22) The subquery may not be a recursive CTE.
**
-** (**) Subsumed into restriction (17d3). Was: If the outer query is
-** a recursive CTE, then the sub-query may not be a compound query.
-** This restriction is because transforming the
+** (23) If the outer query is a recursive CTE, then the sub-query may not be
+** a compound query. This restriction is because transforming the
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
@@ -133611,9 +135064,10 @@ static int flattenSubquery(
int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
int i; /* Loop counter */
Expr *pWhere; /* The WHERE clause */
- struct SrcList_item *pSubitem; /* The subquery */
+ SrcItem *pSubitem; /* The subquery */
sqlite3 *db = pParse->db;
Walker w; /* Walker to persist agginfo data */
+ int *aCsrMap = 0;
/* Check to see if flattening is permitted. Return 0 if not.
*/
@@ -133709,13 +135163,14 @@ static int flattenSubquery(
if( pSub->pOrderBy ){
return 0; /* Restriction (20) */
}
- if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
- return 0; /* (17d1), (17d2), or (17d3) */
+ if( isAgg || (p->selFlags & SF_Distinct)!=0 || isLeftJoin>0 ){
+ return 0; /* (17d1), (17d2), or (17f) */
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
+ assert( (pSub->selFlags & SF_Recursive)==0 );
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
@@ -133736,15 +135191,15 @@ static int flattenSubquery(
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
- }
- /* Ex-restriction (23):
- ** The only way that the recursive part of a CTE can contain a compound
- ** subquery is for the subquery to be one term of a join. But if the
- ** subquery is a join, then the flattening has already been stopped by
- ** restriction (17d3)
- */
- assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
+ /* Restriction (23) */
+ if( (p->selFlags & SF_Recursive) ) return 0;
+
+ if( pSrc->nSrc>1 ){
+ if( pParse->nSelect>500 ) return 0;
+ aCsrMap = sqlite3DbMallocZero(db, pParse->nTab*sizeof(int));
+ }
+ }
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
@@ -133756,6 +135211,17 @@ static int flattenSubquery(
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
+ /* Delete the transient structures associated with thesubquery */
+ pSub1 = pSubitem->pSelect;
+ sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlite3DbFree(db, pSubitem->zName);
+ sqlite3DbFree(db, pSubitem->zAlias);
+ pSubitem->zDatabase = 0;
+ pSubitem->zName = 0;
+ pSubitem->zAlias = 0;
+ pSubitem->pSelect = 0;
+ assert( pSubitem->pOn==0 );
+
/* If the sub-query is a compound SELECT statement, then (by restrictions
** 17 and 18 above) it must be a UNION ALL and the parent query must
** be of the form:
@@ -133794,18 +135260,23 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
+ Table *pItemTab = pSubitem->pTab;
+ pSubitem->pTab = 0;
p->pOrderBy = 0;
- p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p, 0);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
- p->pSrc = pSrc;
p->op = TK_ALL;
+ pSubitem->pTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
+ pNew->selId = ++pParse->nSelect;
+ if( aCsrMap && db->mallocFailed==0 ){
+ renumberCursors(pParse, pNew, iFrom, aCsrMap);
+ }
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
@@ -133813,24 +135284,13 @@ static int flattenSubquery(
SELECTTRACE(2,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
- if( db->mallocFailed ) return 1;
+ assert( pSubitem->pSelect==0 );
+ }
+ sqlite3DbFree(db, aCsrMap);
+ if( db->mallocFailed ){
+ pSubitem->pSelect = pSub1;
+ return 1;
}
-
- /* Begin flattening the iFrom-th entry of the FROM clause
- ** in the outer query.
- */
- pSub = pSub1 = pSubitem->pSelect;
-
- /* Delete the transient table structure associated with the
- ** subquery
- */
- sqlite3DbFree(db, pSubitem->zDatabase);
- sqlite3DbFree(db, pSubitem->zName);
- sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
- pSubitem->zName = 0;
- pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
/* Defer deleting the Table object associated with the
** subquery until code generation is
@@ -133843,8 +135303,10 @@ static int flattenSubquery(
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- pTabToDel->pNextZombie = pToplevel->pZombieTab;
- pToplevel->pZombieTab = pTabToDel;
+ sqlite3ParserAddCleanup(pToplevel,
+ (void(*)(sqlite3*,void*))sqlite3DeleteTable,
+ pTabToDel);
+ testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
}
@@ -133864,6 +135326,7 @@ static int flattenSubquery(
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
+ pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
@@ -133872,14 +135335,8 @@ static int flattenSubquery(
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
- if( pSrc ){
- assert( pParent==p ); /* First time through the loop */
- jointype = pSubitem->fg.jointype;
- }else{
- assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
- if( pSrc==0 ) break;
- pParent->pSrc = pSrc;
+ if( pParent==p ){
+ jointype = pSubitem->fg.jointype; /* First time through the loop */
}
/* The subquery uses a single slot of the FROM clause of the outer
@@ -133999,7 +135456,7 @@ static int flattenSubquery(
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -134194,6 +135651,35 @@ static int propagateConstants(
}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+# if !defined(SQLITE_OMIT_WINDOWFUNC)
+/*
+** This function is called to determine whether or not it is safe to
+** push WHERE clause expression pExpr down to FROM clause sub-query
+** pSubq, which contains at least one window function. Return 1
+** if it is safe and the expression should be pushed down, or 0
+** otherwise.
+**
+** It is only safe to push the expression down if it consists only
+** of constants and copies of expressions that appear in the PARTITION
+** BY clause of all window function used by the sub-query. It is safe
+** to filter out entire partitions, but not rows within partitions, as
+** this may change the results of the window functions.
+**
+** At the time this function is called it is guaranteed that
+**
+** * the sub-query uses only one distinct window frame, and
+** * that the window frame has a PARTITION BY clase.
+*/
+static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
+ assert( pSubq->pWin->pPartition );
+ assert( (pSubq->selFlags & SF_MultiPart)==0 );
+ assert( pSubq->pPrior==0 );
+ return sqlite3ExprIsConstantOrGroupBy(pParse, pExpr, pSubq->pWin->pPartition);
+}
+# endif /* SQLITE_OMIT_WINDOWFUNC */
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
** the WHERE clause of subquery. Example:
@@ -134240,9 +135726,24 @@ static int propagateConstants(
** But if the (b2=2) term were to be pushed down into the bb subquery,
** then the (1,1,NULL) row would be suppressed.
**
-** (6) The inner query features one or more window-functions (since
-** changes to the WHERE clause of the inner query could change the
-** window over which window functions are calculated).
+** (6) Window functions make things tricky as changes to the WHERE clause
+** of the inner query could change the window over which window
+** functions are calculated. Therefore, do not attempt the optimization
+** if:
+**
+** (6a) The inner query uses multiple incompatible window partitions.
+**
+** (6b) The inner query is a compound and uses window-functions.
+**
+** (6c) The WHERE clause does not consist entirely of constants and
+** copies of expressions found in the PARTITION BY clause of
+** all window-functions used by the sub-query. It is safe to
+** filter out entire partitions, as this does not change the
+** window over which any window-function is calculated.
+**
+** (7) The inner query is a Common Table Expression (CTE) that should
+** be materialized. (This restriction is implemented in the calling
+** routine.)
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
@@ -134256,13 +135757,17 @@ static int pushDownWhereTerms(
){
Expr *pNew;
int nChng = 0;
- Select *pSel;
if( pWhere==0 ) return 0;
- if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
+ if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
- for(pSel=pSubq; pSel; pSel=pSel->pPrior){
- if( pSel->pWin ) return 0; /* restriction (6) */
+ if( pSubq->pPrior ){
+ Select *pSel;
+ for(pSel=pSubq; pSel; pSel=pSel->pPrior){
+ if( pSel->pWin ) return 0; /* restriction (6b) */
+ }
+ }else{
+ if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0;
}
#endif
@@ -134298,6 +135803,7 @@ static int pushDownWhereTerms(
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
+ pSubq->selFlags |= SF_PushDown;
while( pSubq ){
SubstContext x;
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -134308,6 +135814,14 @@ static int pushDownWhereTerms(
x.isLeftJoin = 0;
x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
+ /* Restriction 6c has prevented push-down in this case */
+ sqlite3ExprDelete(pParse->db, pNew);
+ nChng--;
+ break;
+ }
+#endif
if( pSubq->selFlags & SF_Aggregate ){
pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew);
}else{
@@ -134346,7 +135860,11 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
assert( *ppMinMax==0 );
assert( pFunc->op==TK_AGG_FUNCTION );
assert( !IsWindowFunc(pFunc) );
- if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){
+ if( pEList==0
+ || pEList->nExpr!=1
+ || ExprHasProperty(pFunc, EP_WinFunc)
+ || OptimizationDisabled(db, SQLITE_MinMaxOpt)
+ ){
return eRet;
}
zFunc = pFunc->u.zToken;
@@ -134409,24 +135927,26 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
** pFrom->pIndex and return SQLITE_OK.
*/
-SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
- if( pFrom->pTab && pFrom->fg.isIndexedBy ){
- Table *pTab = pFrom->pTab;
- char *zIndexedBy = pFrom->u1.zIndexedBy;
- Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
- pIdx=pIdx->pNext
- );
- if( !pIdx ){
- sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
- pParse->checkSchema = 1;
- return SQLITE_ERROR;
- }
- pFrom->pIBIndex = pIdx;
+SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
+ Table *pTab = pFrom->pTab;
+ char *zIndexedBy = pFrom->u1.zIndexedBy;
+ Index *pIdx;
+ assert( pTab!=0 );
+ assert( pFrom->fg.isIndexedBy!=0 );
+
+ for(pIdx=pTab->pIndex;
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
+ pIdx=pIdx->pNext
+ );
+ if( !pIdx ){
+ sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
+ pParse->checkSchema = 1;
+ return SQLITE_ERROR;
}
+ pFrom->u2.pIBIndex = pIdx;
return SQLITE_OK;
}
+
/*
** Detect compound SELECT statements that use an ORDER BY clause with
** an alternative collating sequence.
@@ -134513,7 +136033,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
** arguments. If it does, leave an error message in pParse and return
** non-zero, since pFrom is not allowed to be a table-valued function.
*/
-static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
+static int cannotBeFunction(Parse *pParse, SrcItem *pFrom){
if( pFrom->fg.isTabFunc ){
sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName);
return 1;
@@ -134534,19 +136054,19 @@ static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
*/
static struct Cte *searchWith(
With *pWith, /* Current innermost WITH clause */
- struct SrcList_item *pItem, /* FROM clause element to resolve */
+ SrcItem *pItem, /* FROM clause element to resolve */
With **ppContext /* OUT: WITH clause return value belongs to */
){
- const char *zName;
- if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
- With *p;
- for(p=pWith; p; p=p->pOuter){
- int i;
- for(i=0; i<p->nCte; i++){
- if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
- *ppContext = p;
- return &p->a[i];
- }
+ const char *zName = pItem->zName;
+ With *p;
+ assert( pItem->zDatabase==0 );
+ assert( zName!=0 );
+ for(p=pWith; p; p=p->pOuter){
+ int i;
+ for(i=0; i<p->nCte; i++){
+ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
+ *ppContext = p;
+ return &p->a[i];
}
}
}
@@ -134564,46 +136084,54 @@ static struct Cte *searchWith(
** statement with which it is associated.
*/
SQLITE_PRIVATE void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
- assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
if( pWith ){
assert( pParse->pWith!=pWith );
pWith->pOuter = pParse->pWith;
pParse->pWith = pWith;
- if( bFree ) pParse->pWithToFree = pWith;
+ if( bFree ){
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3WithDelete,
+ pWith);
+ testcase( pParse->earlyCleanup );
+ }
}
}
/*
** This function checks if argument pFrom refers to a CTE declared by
-** a WITH clause on the stack currently maintained by the parser. And,
-** if currently processing a CTE expression, if it is a recursive
-** reference to the current CTE.
+** a WITH clause on the stack currently maintained by the parser (on the
+** pParse->pWith linked list). And if currently processing a CTE
+** CTE expression, through routine checks to see if the reference is
+** a recursive reference to the CTE.
**
-** If pFrom falls into either of the two categories above, pFrom->pTab
-** and other fields are populated accordingly. The caller should check
-** (pFrom->pTab!=0) to determine whether or not a successful match
-** was found.
+** If pFrom matches a CTE according to either of these two above, pFrom->pTab
+** and other fields are populated accordingly.
**
-** Whether or not a match is found, SQLITE_OK is returned if no error
-** occurs. If an error does occur, an error message is stored in the
-** parser and some error code other than SQLITE_OK returned.
+** Return 0 if no match is found.
+** Return 1 if a match is found.
+** Return 2 if an error condition is detected.
*/
-static int withExpand(
- Walker *pWalker,
- struct SrcList_item *pFrom
+static int resolveFromTermToCte(
+ Parse *pParse, /* The parsing context */
+ Walker *pWalker, /* Current tree walker */
+ SrcItem *pFrom /* The FROM clause term to check */
){
- Parse *pParse = pWalker->pParse;
- sqlite3 *db = pParse->db;
- struct Cte *pCte; /* Matched CTE (or NULL if no match) */
- With *pWith; /* WITH clause that pCte belongs to */
+ Cte *pCte; /* Matched CTE (or NULL if no match) */
+ With *pWith; /* The matching WITH */
assert( pFrom->pTab==0 );
- if( pParse->nErr ){
- return SQLITE_ERROR;
+ if( pParse->pWith==0 ){
+ /* There are no WITH clauses in the stack. No match is possible */
+ return 0;
+ }
+ if( pFrom->zDatabase!=0 ){
+ /* The FROM term contains a schema qualifier (ex: main.t1) and so
+ ** it cannot possibly be a CTE reference. */
+ return 0;
}
-
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
+ sqlite3 *db = pParse->db;
Table *pTab;
ExprList *pEList;
Select *pSel;
@@ -134612,6 +136140,7 @@ static int withExpand(
int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
int iRecTab = -1; /* Cursor for recursive table */
+ CteUse *pCteUse;
/* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -134619,21 +136148,39 @@ static int withExpand(
** In this case, proceed. */
if( pCte->zCteErr ){
sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName);
- return SQLITE_ERROR;
+ return 2;
}
- if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;
+ if( cannotBeFunction(pParse, pFrom) ) return 2;
assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
+ pTab = sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTab==0 ) return 2;
+ pCteUse = pCte->pUse;
+ if( pCteUse==0 ){
+ pCte->pUse = pCteUse = sqlite3DbMallocZero(db, sizeof(pCteUse[0]));
+ if( pCteUse==0
+ || sqlite3ParserAddCleanup(pParse,sqlite3DbFree,pCteUse)==0
+ ){
+ sqlite3DbFree(db, pTab);
+ return 2;
+ }
+ pCteUse->eM10d = pCte->eM10d;
+ }
+ pFrom->pTab = pTab;
pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
- if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
+ if( db->mallocFailed ) return 2;
assert( pFrom->pSelect );
+ pFrom->fg.isCte = 1;
+ pFrom->u2.pCteUse = pCteUse;
+ pCteUse->nUse++;
+ if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){
+ pCteUse->eM10d = M10d_Yes;
+ }
/* Check if this is a recursive CTE. */
pRecTerm = pSel = pFrom->pSelect;
@@ -134643,7 +136190,7 @@ static int withExpand(
SrcList *pSrc = pRecTerm->pSrc;
assert( pRecTerm->pPrior!=0 );
for(i=0; i<pSrc->nSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
+ SrcItem *pItem = &pSrc->a[i];
if( pItem->zDatabase==0
&& pItem->zName!=0
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
@@ -134655,7 +136202,7 @@ static int withExpand(
sqlite3ErrorMsg(pParse,
"multiple references to recursive table: %s", pCte->zName
);
- return SQLITE_ERROR;
+ return 2;
}
pRecTerm->selFlags |= SF_Recursive;
if( iRecTab<0 ) iRecTab = pParse->nTab++;
@@ -134670,16 +136217,24 @@ static int withExpand(
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
if( pSel->selFlags & SF_Recursive ){
+ int rc;
assert( pRecTerm!=0 );
assert( (pRecTerm->selFlags & SF_Recursive)==0 );
assert( pRecTerm->pNext!=0 );
assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
assert( pRecTerm->pWith==0 );
pRecTerm->pWith = pSel->pWith;
- sqlite3WalkSelect(pWalker, pRecTerm);
+ rc = sqlite3WalkSelect(pWalker, pRecTerm);
pRecTerm->pWith = 0;
+ if( rc ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}else{
- sqlite3WalkSelect(pWalker, pSel);
+ if( sqlite3WalkSelect(pWalker, pSel) ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}
pParse->pWith = pWith;
@@ -134691,7 +136246,7 @@ static int withExpand(
pCte->zName, pEList->nExpr, pCte->pCols->nExpr
);
pParse->pWith = pSavedWith;
- return SQLITE_ERROR;
+ return 2;
}
pEList = pCte->pCols;
}
@@ -134707,9 +136262,9 @@ static int withExpand(
}
pCte->zCteErr = 0;
pParse->pWith = pSavedWith;
+ return 1; /* Success */
}
-
- return SQLITE_OK;
+ return 0; /* No match */
}
#endif
@@ -134743,7 +136298,7 @@ static void selectPopWith(Walker *pWalker, Select *p){
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
** SQLITE_NOMEM.
*/
-SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
+SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
Select *pSel = pFrom->pSelect;
Table *pTab;
@@ -134791,10 +136346,10 @@ SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFr
*/
static int selectExpander(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
- int i, j, k;
+ int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
sqlite3 *db = pParse->db;
Expr *pE, *pRight, *pExpr;
u16 selFlags = p->selFlags;
@@ -134830,10 +136385,6 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
if( pFrom->pTab ) continue;
assert( pFrom->fg.isRecursive==0 );
-#ifndef SQLITE_OMIT_CTE
- if( withExpand(pWalker, pFrom) ) return WRC_Abort;
- if( pFrom->pTab ) {} else
-#endif
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
Select *pSel = pFrom->pSelect;
@@ -134843,6 +136394,12 @@ static int selectExpander(Walker *pWalker, Select *p){
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
+#ifndef SQLITE_OMIT_CTE
+ }else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
+ if( rc>1 ) return WRC_Abort;
+ pTab = pFrom->pTab;
+ assert( pTab!=0 );
+#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
@@ -134864,7 +136421,10 @@ static int selectExpander(Walker *pWalker, Select *p){
u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
- if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){
+ if( pTab->pSelect
+ && (db->flags & SQLITE_EnableView)==0
+ && pTab->pSchema!=db->aDb[1].pSchema
+ ){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName);
}
@@ -134890,7 +136450,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
/* Locate the index named by the INDEXED BY clause, if any. */
- if( sqlite3IndexedByLookup(pParse, pFrom) ){
+ if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){
return WRC_Abort;
}
}
@@ -135133,7 +136693,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Parse *pParse;
int i;
SrcList *pTabList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
assert( p->selFlags & SF_Resolved );
if( p->selFlags & SF_HasTypeInfo ) return;
@@ -135445,7 +137005,7 @@ static void havingToWhere(Parse *pParse, Select *p){
sWalker.u.pSelect = p;
sqlite3WalkExpr(&sWalker, p->pHaving);
#if SELECTTRACE_ENABLED
- if( sWalker.eCode && (sqlite3_unsupported_selecttrace & 0x100)!=0 ){
+ if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){
SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -135457,11 +137017,13 @@ static void havingToWhere(Parse *pParse, Select *p){
** If it is, then return the SrcList_item for the prior view. If it is not,
** then return 0.
*/
-static struct SrcList_item *isSelfJoinView(
+static SrcItem *isSelfJoinView(
SrcList *pTabList, /* Search for self-joins in this FROM clause */
- struct SrcList_item *pThis /* Search for prior reference to this subquery */
+ SrcItem *pThis /* Search for prior reference to this subquery */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
+ assert( pThis->pSelect!=0 );
+ if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
for(pItem = pTabList->a; pItem<pThis; pItem++){
Select *pS1;
if( pItem->pSelect==0 ) continue;
@@ -135477,9 +137039,7 @@ static struct SrcList_item *isSelfJoinView(
** names in the same FROM clause. */
continue;
}
- if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1)
- || sqlite3ExprCompare(0, pThis->pSelect->pHaving, pS1->pHaving, -1)
- ){
+ if( pItem->pSelect->selFlags & SF_PushDown ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -135489,6 +137049,15 @@ static struct SrcList_item *isSelfJoinView(
return 0;
}
+/*
+** Deallocate a single AggInfo object
+*/
+static void agginfoFree(sqlite3 *db, AggInfo *p){
+ sqlite3DbFree(db, p->aCol);
+ sqlite3DbFree(db, p->aFunc);
+ sqlite3DbFreeNN(db, p);
+}
+
#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
/*
** Attempt to transform a query of the form
@@ -135567,7 +137136,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
p->selFlags &= ~SF_Aggregate;
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -135620,7 +137189,7 @@ SQLITE_PRIVATE int sqlite3Select(
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -135634,8 +137203,19 @@ SQLITE_PRIVATE int sqlite3Select(
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 */
- sqlite3ExprListDelete(db, p->pOrderBy);
- p->pOrderBy = 0;
+ if( p->pOrderBy ){
+#if SELECTTRACE_ENABLED
+ SELECTTRACE(1,pParse,p, ("dropping superfluous ORDER BY:\n"));
+ if( sqlite3SelectTrace & 0x100 ){
+ sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
+ }
+#endif
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
+ p->pOrderBy);
+ testcase( pParse->earlyCleanup );
+ p->pOrderBy = 0;
+ }
p->selFlags &= ~SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
@@ -135645,7 +137225,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
assert( p->pEList!=0 );
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x104 ){
+ if( sqlite3SelectTrace & 0x104 ){
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -135656,9 +137236,9 @@ SQLITE_PRIVATE int sqlite3Select(
** In this case, it is an error if the target object (pSrc->a[0]) name
** or alias is duplicated within FROM clause (pSrc->a[1..n]). */
if( p->selFlags & SF_UpdateFrom ){
- struct SrcList_item *p0 = &p->pSrc->a[0];
+ SrcItem *p0 = &p->pSrc->a[0];
for(i=1; i<p->pSrc->nSrc; i++){
- struct SrcList_item *p1 = &p->pSrc->a[i];
+ SrcItem *p1 = &p->pSrc->a[i];
if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
@@ -135680,7 +137260,7 @@ SQLITE_PRIVATE int sqlite3Select(
goto select_end;
}
#if SELECTTRACE_ENABLED
- if( p->pWin && (sqlite3_unsupported_selecttrace & 0x108)!=0 ){
+ if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -135696,7 +137276,7 @@ SQLITE_PRIVATE int sqlite3Select(
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
Table *pTab = pItem->pTab;
@@ -135787,7 +137367,7 @@ SQLITE_PRIVATE int sqlite3Select(
rc = multiSelect(pParse, p, pDest);
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
- if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
+ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -135806,7 +137386,7 @@ SQLITE_PRIVATE int sqlite3Select(
&& propagateConstants(pParse, p)
){
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -135830,7 +137410,8 @@ SQLITE_PRIVATE int sqlite3Select(
** (2) Generate code for all sub-queries
*/
for(i=0; i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
+ SrcItem *pPrior;
SelectDest dest;
Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@@ -135890,16 +137471,18 @@ SQLITE_PRIVATE int sqlite3Select(
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
+ && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes)
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
(pItem->fg.jointype & JT_OUTER)!=0)
){
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,
("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
+ assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
}else{
SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
}
@@ -135909,16 +137492,18 @@ SQLITE_PRIVATE int sqlite3Select(
/* Generate code to implement the subquery
**
- ** The subquery is implemented as a co-routine if the subquery is
- ** guaranteed to be the outer loop (so that it does not need to be
- ** computed more than once)
+ ** The subquery is implemented as a co-routine if:
+ ** (1) the subquery is guaranteed to be the outer loop (so that
+ ** it does not need to be computed more than once), and
+ ** (2) the subquery is not a CTE that should be materialized
**
- ** TODO: Are there other reasons beside (1) to use a co-routine
+ ** TODO: Are there other reasons beside (1) and (2) to use a co-routine
** implementation?
*/
if( i==0
&& (pTabList->nSrc==1
|| (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
+ && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
@@ -135938,16 +137523,32 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeEndCoroutine(v, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
- }else{
- /* Generate a subroutine that will fill an ephemeral table with
- ** the content of this subquery. pItem->addrFillSub will point
- ** to the address of the generated subroutine. pItem->regReturn
- ** is a register allocated to hold the subroutine return address
- */
+ }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
+ /* This is a CTE for which materialization code has already been
+ ** generated. Invoke the subroutine to compute the materialization,
+ ** the make the pItem->iCursor be a copy of the ephemerial table that
+ ** holds the result of the materialization. */
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
+ if( pItem->iCursor!=pCteUse->iCur ){
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pCteUse->iCur);
+ }
+ pSub->nSelectRow = pCteUse->nRowEst;
+ }else if( (pPrior = isSelfJoinView(pTabList, pItem))!=0 ){
+ /* This view has already been materialized by a prior entry in
+ ** this same FROM clause. Reuse it. */
+ if( pPrior->addrFillSub ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
+ }
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
+ pSub->nSelectRow = pPrior->pSelect->nSelectRow;
+ }else{
+ /* Materalize the view. If the view is not correlated, generate a
+ ** subroutine to do the materialization so that subsequent uses of
+ ** the same view can reuse the materialization. */
int topAddr;
int onceAddr = 0;
int retAddr;
- struct SrcList_item *pPrior;
testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */
pItem->regReturn = ++pParse->nMem;
@@ -135962,22 +137563,22 @@ SQLITE_PRIVATE int sqlite3Select(
}else{
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
}
- pPrior = isSelfJoinView(pTabList, pItem);
- if( pPrior ){
- sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
- assert( pPrior->pSelect!=0 );
- pSub->nSelectRow = pPrior->pSelect->nSelectRow;
- }else{
- sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
- sqlite3Select(pParse, pSub, &dest);
- }
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
+ ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
+ sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
+ if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ pCteUse->addrM9e = pItem->addrFillSub;
+ pCteUse->regRtn = pItem->regReturn;
+ pCteUse->iCur = pItem->iCursor;
+ pCteUse->nRowEst = pSub->nSelectRow;
+ }
}
if( db->mallocFailed ) goto select_end;
pParse->nHeight -= sqlite3SelectExprHeight(p);
@@ -135994,7 +137595,7 @@ SQLITE_PRIVATE int sqlite3Select(
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -136030,7 +137631,7 @@ SQLITE_PRIVATE int sqlite3Select(
assert( sDistinct.isTnct );
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -136122,6 +137723,7 @@ SQLITE_PRIVATE int sqlite3Select(
sSort.pOrderBy = 0;
}
}
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -136160,6 +137762,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* End the database scan loop.
*/
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
}
}else{
@@ -136230,11 +137833,14 @@ SQLITE_PRIVATE int sqlite3Select(
** SELECT statement.
*/
pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
- if( pAggInfo==0 ){
+ if( pAggInfo ){
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))agginfoFree, pAggInfo);
+ testcase( pParse->earlyCleanup );
+ }
+ if( db->mallocFailed ){
goto select_end;
}
- pAggInfo->pNext = pParse->pAggList;
- pParse->pAggList = pAggInfo;
pAggInfo->selId = p->selId;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
@@ -136278,10 +137884,14 @@ SQLITE_PRIVATE int sqlite3Select(
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0);
+ if( minMaxFlag ){
+ sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag);
+ sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
+ }
for(ii=0; ii<pAggInfo->nColumn; ii++){
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
ii, pAggInfo->aCol[ii].iMem);
@@ -136349,6 +137959,7 @@ SQLITE_PRIVATE int sqlite3Select(
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
);
if( pWInfo==0 ) goto select_end;
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
@@ -136397,6 +138008,7 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nCol);
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++;
sortOut = sqlite3GetTempReg(pParse);
@@ -136471,9 +138083,10 @@ SQLITE_PRIVATE int sqlite3Select(
/* End of the loop
*/
if( groupBySort ){
- sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop);
+ sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
VdbeCoverage(v);
}else{
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
@@ -136583,7 +138196,6 @@ SQLITE_PRIVATE int sqlite3Select(
explainSimpleCount(pParse, pTab, pBest);
}else{
int regAcc = 0; /* "populate accumulators" flag */
- int addrSkip;
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
@@ -136630,12 +138242,13 @@ SQLITE_PRIVATE int sqlite3Select(
if( pWInfo==0 ){
goto select_end;
}
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
updateAccumulator(pParse, regAcc, pAggInfo);
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
- addrSkip = sqlite3WhereOrderByLimitOptLabel(pWInfo);
- if( addrSkip!=sqlite3WhereContinueLabel(pWInfo) ){
- sqlite3VdbeGoto(v, addrSkip);
+ if( minMaxFlag ){
+ sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
}
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, pAggInfo);
}
@@ -136680,15 +138293,13 @@ select_end:
if( pAggInfo && !db->mallocFailed ){
for(i=0; i<pAggInfo->nColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pCExpr;
- assert( pExpr!=0 || db->mallocFailed );
- if( pExpr==0 ) continue;
+ assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
- assert( pExpr!=0 || db->mallocFailed );
- if( pExpr==0 ) continue;
+ assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
@@ -136697,7 +138308,7 @@ select_end:
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
- if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
+ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -136958,28 +138569,39 @@ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerS
** pTab as well as the triggers lised in pTab->pTrigger.
*/
SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
- Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
- Trigger *pList = 0; /* List of triggers to return */
+ Schema *pTmpSchema; /* Schema of the pTab table */
+ Trigger *pList; /* List of triggers to return */
+ HashElem *p; /* Loop variable for TEMP triggers */
if( pParse->disableTriggers ){
return 0;
}
-
+ pTmpSchema = pParse->db->aDb[1].pSchema;
+ p = sqliteHashFirst(&pTmpSchema->trigHash);
+ if( p==0 ){
+ return pTab->pTrigger;
+ }
+ pList = pTab->pTrigger;
if( pTmpSchema!=pTab->pSchema ){
- HashElem *p;
- assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
- for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
+ while( p ){
Trigger *pTrig = (Trigger *)sqliteHashData(p);
if( pTrig->pTabSchema==pTab->pSchema
&& 0==sqlite3StrICmp(pTrig->table, pTab->zName)
){
- pTrig->pNext = (pList ? pList : pTab->pTrigger);
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }else if( pTrig->op==TK_RETURNING ){
+ assert( pParse->bReturning );
+ assert( &(pParse->u1.pReturning->retTrig) == pTrig );
+ pTrig->table = pTab->zName;
+ pTrig->pTabSchema = pTab->pSchema;
+ pTrig->pNext = pList;
pList = pTrig;
}
+ p = sqliteHashNext(p);
}
}
-
- return (pList ? pList : pTab->pTrigger);
+ return pList;
}
/*
@@ -137255,7 +138877,7 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
+ sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0);
}
if( db->init.busy ){
@@ -137468,7 +139090,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(
** Recursively delete a Trigger structure
*/
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
- if( pTrigger==0 ) return;
+ if( pTrigger==0 || pTrigger->bReturning ) return;
sqlite3DeleteTriggerStep(db, pTrigger->step_list);
sqlite3DbFree(db, pTrigger->zName);
sqlite3DbFree(db, pTrigger->table);
@@ -137633,15 +139255,53 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist(
Trigger *pList = 0;
Trigger *p;
- if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){
- pList = sqlite3TriggerList(pParse, pTab);
- }
- assert( pList==0 || IsVirtual(pTab)==0 );
- for(p=pList; p; p=p->pNext){
- if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
- mask |= p->tr_tm;
+ pList = sqlite3TriggerList(pParse, pTab);
+ assert( pList==0 || IsVirtual(pTab)==0
+ || (pList->bReturning && pList->pNext==0) );
+ if( pList!=0 ){
+ p = pList;
+ if( (pParse->db->flags & SQLITE_EnableTrigger)==0
+ && pTab->pTrigger!=0
+ ){
+ /* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that
+ ** only TEMP triggers are allowed. Truncate the pList so that it
+ ** includes only TEMP triggers */
+ if( pList==pTab->pTrigger ){
+ pList = 0;
+ goto exit_triggers_exist;
+ }
+ while( ALWAYS(p->pNext) && p->pNext!=pTab->pTrigger ) p = p->pNext;
+ p->pNext = 0;
+ p = pList;
}
+ do{
+ if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
+ mask |= p->tr_tm;
+ }else if( p->op==TK_RETURNING ){
+ /* The first time a RETURNING trigger is seen, the "op" value tells
+ ** us what time of trigger it should be. */
+ assert( sqlite3IsToplevel(pParse) );
+ p->op = op;
+ if( IsVirtual(pTab) ){
+ if( op!=TK_INSERT ){
+ sqlite3ErrorMsg(pParse,
+ "%s RETURNING is not available on virtual tables",
+ op==TK_DELETE ? "DELETE" : "UPDATE");
+ }
+ p->tr_tm = TRIGGER_BEFORE;
+ }else{
+ p->tr_tm = TRIGGER_AFTER;
+ }
+ mask |= p->tr_tm;
+ }else if( p->bReturning && p->op==TK_INSERT && op==TK_UPDATE
+ && sqlite3IsToplevel(pParse) ){
+ /* Also fire a RETURNING trigger for an UPSERT */
+ mask |= p->tr_tm;
+ }
+ p = p->pNext;
+ }while( p );
}
+exit_triggers_exist:
if( pMask ){
*pMask = mask;
}
@@ -137685,6 +139345,131 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(
}
/*
+** 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
+** form "table.*".
+*/
+static int isAsteriskTerm(
+ Parse *pParse, /* Parsing context */
+ Expr *pTerm /* A term in the RETURNING clause */
+){
+ assert( pTerm!=0 );
+ if( pTerm->op==TK_ASTERISK ) return 1;
+ if( pTerm->op!=TK_DOT ) return 0;
+ assert( pTerm->pRight!=0 );
+ assert( pTerm->pLeft!=0 );
+ if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
+ sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
+ return 1;
+}
+
+/* The input list pList is the list of result set terms from a RETURNING
+** clause. The table that we are returning from is pTab.
+**
+** This routine makes a copy of the pList, and at the same time expands
+** any "*" wildcards to be the complete set of columns from pTab.
+*/
+static ExprList *sqlite3ExpandReturning(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* The arguments to RETURNING */
+ Table *pTab /* The table being updated */
+){
+ ExprList *pNew = 0;
+ sqlite3 *db = pParse->db;
+ int i;
+
+ for(i=0; i<pList->nExpr; i++){
+ Expr *pOldExpr = pList->a[i].pExpr;
+ if( NEVER(pOldExpr==0) ) continue;
+ if( isAsteriskTerm(pParse, pOldExpr) ){
+ int jj;
+ for(jj=0; jj<pTab->nCol; jj++){
+ Expr *pNewExpr;
+ if( IsHiddenColumn(pTab->aCol+jj) ) continue;
+ pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
+ pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
+ if( !db->mallocFailed ){
+ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
+ pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zName);
+ pItem->eEName = ENAME_NAME;
+ }
+ }
+ }else{
+ Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0);
+ pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
+ if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
+ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
+ pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
+ pItem->eEName = pList->a[i].eEName;
+ }
+ }
+ }
+ if( !db->mallocFailed ){
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ sqlite3VdbeSetNumCols(v, pNew->nExpr);
+ for(i=0; i<pNew->nExpr; i++){
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, pNew->a[i].zEName,
+ SQLITE_TRANSIENT);
+ }
+ }
+ return pNew;
+}
+
+/*
+** Generate code for the RETURNING trigger. Unlike other triggers
+** that invoke a subprogram in the bytecode, the code for RETURNING
+** is generated in-line.
+*/
+static void codeReturningTrigger(
+ Parse *pParse, /* Parse context */
+ Trigger *pTrigger, /* The trigger step that defines the RETURNING */
+ Table *pTab, /* The table to code triggers from */
+ int regIn /* The first in an array of registers */
+){
+ Vdbe *v = pParse->pVdbe;
+ ExprList *pNew;
+ Returning *pReturning;
+
+ assert( v!=0 );
+ assert( pParse->bReturning );
+ pReturning = pParse->u1.pReturning;
+ assert( pTrigger == &(pReturning->retTrig) );
+ pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
+ if( pNew ){
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ if( pReturning->nRetCol==0 ){
+ pReturning->nRetCol = pNew->nExpr;
+ pReturning->iRetCur = pParse->nTab++;
+ }
+ sNC.pParse = pParse;
+ sNC.uNC.iBaseReg = regIn;
+ sNC.ncFlags = NC_UBaseReg;
+ pParse->eTriggerOp = pTrigger->op;
+ pParse->pTriggerTab = pTab;
+ if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){
+ int i;
+ int nCol = pNew->nExpr;
+ int reg = pParse->nMem+1;
+ pParse->nMem += nCol+2;
+ pReturning->iRetReg = reg;
+ for(i=0; i<nCol; i++){
+ sqlite3ExprCodeFactorable(pParse, pNew->a[i].pExpr, reg+i);
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
+ sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
+ }
+ sqlite3ExprListDelete(pParse->db, pNew);
+ pParse->eTriggerOp = 0;
+ pParse->pTriggerTab = 0;
+ }
+}
+
+
+
+/*
** Generate VDBE code for the statements inside the body of a single
** trigger.
*/
@@ -137733,6 +139518,7 @@ static int codeTriggerProgram(
sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf, 0, 0, 0
);
+ sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
case TK_INSERT: {
@@ -137743,6 +139529,7 @@ static int codeTriggerProgram(
pParse->eOrconf,
sqlite3UpsertDup(db, pStep->pUpsert)
);
+ sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
case TK_DELETE: {
@@ -137750,6 +139537,7 @@ static int codeTriggerProgram(
sqlite3TriggerStepSrc(pParse, pStep),
sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
);
+ sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
default: assert( pStep->op==TK_SELECT ); {
@@ -137761,9 +139549,6 @@ static int codeTriggerProgram(
break;
}
}
- if( pStep->op!=TK_SELECT ){
- sqlite3VdbeAddOp0(v, OP_ResetCount);
- }
}
return 0;
@@ -137910,7 +139695,6 @@ static TriggerPrg *codeRowTrigger(
sqlite3VdbeDelete(v);
}
- assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
sqlite3ParserReset(pSubParse);
sqlite3StackFree(db, pSubParse);
@@ -138012,7 +139796,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
** ... ...
** reg+N OLD.* value of right-most column of pTab
** reg+N+1 NEW.rowid
-** reg+N+2 OLD.* value of left-most column of pTab
+** reg+N+2 NEW.* value of left-most column of pTab
** ... ...
** reg+N+N+1 NEW.* value of right-most column of pTab
**
@@ -138057,12 +139841,20 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger(
assert( p->pSchema==p->pTabSchema
|| p->pSchema==pParse->db->aDb[1].pSchema );
- /* Determine whether we should code this trigger */
- if( p->op==op
+ /* Determine whether we should code this trigger. One of two choices:
+ ** 1. The trigger is an exact match to the current DML statement
+ ** 2. This is a RETURNING trigger for INSERT but we are currently
+ ** doing the UPDATE part of an UPSERT.
+ */
+ if( (p->op==op || (p->bReturning && p->op==TK_INSERT && op==TK_UPDATE))
&& p->tr_tm==tr_tm
&& checkColumnOverlap(p->pColumns, pChanges)
){
- sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+ if( !p->bReturning ){
+ sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+ }else if( sqlite3IsToplevel(pParse) ){
+ codeReturningTrigger(pParse, p, pTab, reg);
+ }
}
}
}
@@ -138107,13 +139899,18 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(
assert( isNew==1 || isNew==0 );
for(p=pTrigger; p; p=p->pNext){
- if( p->op==op && (tr_tm&p->tr_tm)
+ if( p->op==op
+ && (tr_tm&p->tr_tm)
&& checkColumnOverlap(p->pColumns,pChanges)
){
- TriggerPrg *pPrg;
- pPrg = getRowTrigger(pParse, p, pTab, orconf);
- if( pPrg ){
- mask |= pPrg->aColmask[isNew];
+ if( p->bReturning ){
+ mask = 0xffffffff;
+ }else{
+ TriggerPrg *pPrg;
+ pPrg = getRowTrigger(pParse, p, pTab, orconf);
+ if( pPrg ){
+ mask |= pPrg->aColmask[isNew];
+ }
}
}
}
@@ -138347,6 +140144,10 @@ static void updateFromSelect(
assert( pTabList->nSrc>1 );
if( pSrc ){
+ if( pSrc->a[0].zDatabase==0 ){
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
+ }
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
@@ -138770,6 +140571,7 @@ SQLITE_PRIVATE void sqlite3Update(
if( (db->flags&SQLITE_CountRows)!=0
&& !pParse->pTriggerTab
&& !pParse->nested
+ && !pParse->bReturning
&& pUpsert==0
){
regRowCount = ++pParse->nMem;
@@ -139233,7 +141035,7 @@ SQLITE_PRIVATE void sqlite3Update(
** that information.
*/
if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
+ sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
}
@@ -139468,15 +141270,22 @@ static void updateVirtualTable(
/*
** Free a list of Upsert objects
*/
-SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
- if( p ){
+static void SQLITE_NOINLINE upsertDelete(sqlite3 *db, Upsert *p){
+ do{
+ Upsert *pNext = p->pNextUpsert;
sqlite3ExprListDelete(db, p->pUpsertTarget);
sqlite3ExprDelete(db, p->pUpsertTargetWhere);
sqlite3ExprListDelete(db, p->pUpsertSet);
sqlite3ExprDelete(db, p->pUpsertWhere);
+ sqlite3DbFree(db, p->pToFree);
sqlite3DbFree(db, p);
- }
+ p = pNext;
+ }while( p );
}
+SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
+ if( p ) upsertDelete(db, p);
+}
+
/*
** Duplicate an Upsert object.
@@ -139487,7 +141296,8 @@ SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){
sqlite3ExprListDup(db, p->pUpsertTarget, 0),
sqlite3ExprDup(db, p->pUpsertTargetWhere, 0),
sqlite3ExprListDup(db, p->pUpsertSet, 0),
- sqlite3ExprDup(db, p->pUpsertWhere, 0)
+ sqlite3ExprDup(db, p->pUpsertWhere, 0),
+ sqlite3UpsertDup(db, p->pNextUpsert)
);
}
@@ -139499,22 +141309,25 @@ SQLITE_PRIVATE Upsert *sqlite3UpsertNew(
ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */
Expr *pTargetWhere, /* Optional WHERE clause on the target */
ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */
- Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */
+ Expr *pWhere, /* WHERE clause for the ON CONFLICT UPDATE */
+ Upsert *pNext /* Next ON CONFLICT clause in the list */
){
Upsert *pNew;
- pNew = sqlite3DbMallocRaw(db, sizeof(Upsert));
+ pNew = sqlite3DbMallocZero(db, sizeof(Upsert));
if( pNew==0 ){
sqlite3ExprListDelete(db, pTarget);
sqlite3ExprDelete(db, pTargetWhere);
sqlite3ExprListDelete(db, pSet);
sqlite3ExprDelete(db, pWhere);
+ sqlite3UpsertDelete(db, pNext);
return 0;
}else{
pNew->pUpsertTarget = pTarget;
pNew->pUpsertTargetWhere = pTargetWhere;
pNew->pUpsertSet = pSet;
pNew->pUpsertWhere = pWhere;
- pNew->pUpsertIdx = 0;
+ pNew->isDoUpdate = pSet!=0;
+ pNew->pNextUpsert = pNext;
}
return pNew;
}
@@ -139539,6 +141352,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
Expr *pTerm; /* One term of the conflict-target clause */
NameContext sNC; /* Context for resolving symbolic names */
Expr sCol[2]; /* Index column converted into an Expr */
+ int nClause = 0; /* Counter of ON CONFLICT clauses */
assert( pTabList->nSrc==1 );
assert( pTabList->a[0].pTab!=0 );
@@ -139552,87 +141366,131 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
- rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
- if( rc ) return rc;
- rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
- if( rc ) return rc;
+ for(; pUpsert && pUpsert->pUpsertTarget;
+ pUpsert=pUpsert->pNextUpsert, nClause++){
+ rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
+ if( rc ) return rc;
+ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
+ if( rc ) return rc;
- /* Check to see if the conflict target matches the rowid. */
- pTab = pTabList->a[0].pTab;
- pTarget = pUpsert->pUpsertTarget;
- iCursor = pTabList->a[0].iCursor;
- if( HasRowid(pTab)
- && pTarget->nExpr==1
- && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
- && pTerm->iColumn==XN_ROWID
- ){
- /* The conflict-target is the rowid of the primary table */
- assert( pUpsert->pUpsertIdx==0 );
- return SQLITE_OK;
- }
+ /* Check to see if the conflict target matches the rowid. */
+ pTab = pTabList->a[0].pTab;
+ pTarget = pUpsert->pUpsertTarget;
+ iCursor = pTabList->a[0].iCursor;
+ if( HasRowid(pTab)
+ && pTarget->nExpr==1
+ && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
+ && pTerm->iColumn==XN_ROWID
+ ){
+ /* The conflict-target is the rowid of the primary table */
+ assert( pUpsert->pUpsertIdx==0 );
+ continue;
+ }
- /* Initialize sCol[0..1] to be an expression parse tree for a
- ** single column of an index. The sCol[0] node will be the TK_COLLATE
- ** operator and sCol[1] will be the TK_COLUMN operator. Code below
- ** will populate the specific collation and column number values
- ** prior to comparing against the conflict-target expression.
- */
- memset(sCol, 0, sizeof(sCol));
- sCol[0].op = TK_COLLATE;
- sCol[0].pLeft = &sCol[1];
- sCol[1].op = TK_COLUMN;
- sCol[1].iTable = pTabList->a[0].iCursor;
+ /* Initialize sCol[0..1] to be an expression parse tree for a
+ ** single column of an index. The sCol[0] node will be the TK_COLLATE
+ ** operator and sCol[1] will be the TK_COLUMN operator. Code below
+ ** will populate the specific collation and column number values
+ ** prior to comparing against the conflict-target expression.
+ */
+ memset(sCol, 0, sizeof(sCol));
+ sCol[0].op = TK_COLLATE;
+ sCol[0].pLeft = &sCol[1];
+ sCol[1].op = TK_COLUMN;
+ sCol[1].iTable = pTabList->a[0].iCursor;
- /* Check for matches against other indexes */
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int ii, jj, nn;
- if( !IsUniqueIndex(pIdx) ) continue;
- if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
- if( pIdx->pPartIdxWhere ){
- if( pUpsert->pUpsertTargetWhere==0 ) continue;
- if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
- pIdx->pPartIdxWhere, iCursor)!=0 ){
- continue;
+ /* Check for matches against other indexes */
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int ii, jj, nn;
+ if( !IsUniqueIndex(pIdx) ) continue;
+ if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
+ if( pIdx->pPartIdxWhere ){
+ if( pUpsert->pUpsertTargetWhere==0 ) continue;
+ if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
+ pIdx->pPartIdxWhere, iCursor)!=0 ){
+ continue;
+ }
}
- }
- nn = pIdx->nKeyCol;
- for(ii=0; ii<nn; ii++){
- Expr *pExpr;
- sCol[0].u.zToken = (char*)pIdx->azColl[ii];
- if( pIdx->aiColumn[ii]==XN_EXPR ){
- assert( pIdx->aColExpr!=0 );
- assert( pIdx->aColExpr->nExpr>ii );
- pExpr = pIdx->aColExpr->a[ii].pExpr;
- if( pExpr->op!=TK_COLLATE ){
- sCol[0].pLeft = pExpr;
+ nn = pIdx->nKeyCol;
+ for(ii=0; ii<nn; ii++){
+ Expr *pExpr;
+ sCol[0].u.zToken = (char*)pIdx->azColl[ii];
+ if( pIdx->aiColumn[ii]==XN_EXPR ){
+ assert( pIdx->aColExpr!=0 );
+ assert( pIdx->aColExpr->nExpr>ii );
+ pExpr = pIdx->aColExpr->a[ii].pExpr;
+ if( pExpr->op!=TK_COLLATE ){
+ sCol[0].pLeft = pExpr;
+ pExpr = &sCol[0];
+ }
+ }else{
+ sCol[0].pLeft = &sCol[1];
+ sCol[1].iColumn = pIdx->aiColumn[ii];
pExpr = &sCol[0];
}
- }else{
- sCol[0].pLeft = &sCol[1];
- sCol[1].iColumn = pIdx->aiColumn[ii];
- pExpr = &sCol[0];
- }
- for(jj=0; jj<nn; jj++){
- if( sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,iCursor)<2 ){
- break; /* Column ii of the index matches column jj of target */
+ for(jj=0; jj<nn; jj++){
+ if( sqlite3ExprCompare(pParse,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){
+ break; /* Column ii of the index matches column jj of target */
+ }
+ }
+ if( jj>=nn ){
+ /* The target contains no match for column jj of the index */
+ break;
}
}
- if( jj>=nn ){
- /* The target contains no match for column jj of the index */
- break;
+ if( ii<nn ){
+ /* Column ii of the index did not match any term of the conflict target.
+ ** Continue the search with the next index. */
+ continue;
}
+ pUpsert->pUpsertIdx = pIdx;
+ break;
}
- if( ii<nn ){
- /* Column ii of the index did not match any term of the conflict target.
- ** Continue the search with the next index. */
- continue;
+ if( pUpsert->pUpsertIdx==0 ){
+ char zWhich[16];
+ if( nClause==0 && pUpsert->pNextUpsert==0 ){
+ zWhich[0] = 0;
+ }else{
+ sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1);
+ }
+ sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any "
+ "PRIMARY KEY or UNIQUE constraint", zWhich);
+ return SQLITE_ERROR;
}
- pUpsert->pUpsertIdx = pIdx;
- return SQLITE_OK;
}
- sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any "
- "PRIMARY KEY or UNIQUE constraint");
- return SQLITE_ERROR;
+ return SQLITE_OK;
+}
+
+/*
+** Return true if pUpsert is the last ON CONFLICT clause with a
+** conflict target, or if pUpsert is followed by another ON CONFLICT
+** clause that targets the INTEGER PRIMARY KEY.
+*/
+SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
+ Upsert *pNext;
+ if( NEVER(pUpsert==0) ) return 0;
+ pNext = pUpsert->pNextUpsert;
+ if( pNext==0 ) return 1;
+ if( pNext->pUpsertTarget==0 ) return 1;
+ if( pNext->pUpsertIdx==0 ) return 1;
+ return 0;
+}
+
+/*
+** Given the list of ON CONFLICT clauses described by pUpsert, and
+** a particular index pIdx, return a pointer to the particular ON CONFLICT
+** clause that applies to the index. Or, if the index is not subject to
+** any ON CONFLICT clause, return NULL.
+*/
+SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){
+ while(
+ pUpsert
+ && pUpsert->pUpsertTarget!=0
+ && pUpsert->pUpsertIdx!=pIdx
+ ){
+ pUpsert = pUpsert->pNextUpsert;
+ }
+ return pUpsert;
}
/*
@@ -139656,11 +141514,13 @@ SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
SrcList *pSrc; /* FROM clause for the UPDATE */
int iDataCur;
int i;
+ Upsert *pTop = pUpsert;
assert( v!=0 );
assert( pUpsert!=0 );
- VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
iDataCur = pUpsert->iDataCur;
+ pUpsert = sqlite3UpsertOfIndex(pTop, pIdx);
+ VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
if( pIdx && iCur!=iDataCur ){
if( HasRowid(pTab) ){
int regRowid = sqlite3GetTempReg(pParse);
@@ -139690,19 +141550,17 @@ SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
sqlite3VdbeJumpHere(v, i);
}
}
- /* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So
- ** we have to make a copy before passing it down into sqlite3Update() */
- pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
+ /* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does.
+ ** So we have to make a copy before passing it down into sqlite3Update() */
+ pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0);
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
- sqlite3VdbeAddOp1(v, OP_RealAffinity, pUpsert->regData+i);
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
}
}
- sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
- pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
- pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */
- pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlite3Update() */
+ sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
+ sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert);
VdbeNoopComment((v, "End DO UPDATE of UPSERT"));
}
@@ -140608,7 +142466,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
sqlite3VdbeAddOp0(v, OP_Expire);
zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
- sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+ sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0);
sqlite3DbFree(db, zStmt);
iReg = ++pParse->nMem;
@@ -140779,6 +142637,7 @@ static int vtabCallConstructor(
zType[i-1] = '\0';
}
pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
+ pTab->tabFlags |= TF_HasHidden;
oooHidden = TF_OOOHidden;
}else{
pTab->tabFlags |= oooHidden;
@@ -140947,7 +142806,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Table *pNew = sParse.pNewTable;
Index *pIdx;
pTab->aCol = pNew->aCol;
- pTab->nCol = pNew->nCol;
+ pTab->nNVCol = pTab->nCol = pNew->nCol;
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
pNew->nCol = 0;
pNew->aCol = 0;
@@ -141479,19 +143338,6 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
#ifndef SQLITE_WHEREINT_H
#define SQLITE_WHEREINT_H
-/*
-** Trace output macros
-*/
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ extern int sqlite3WhereTrace;
-#endif
-#if defined(SQLITE_DEBUG) \
- && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
-# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
-# define WHERETRACE_ENABLED 1
-#else
-# define WHERETRACE(K,X)
-#endif
/* Forward references
*/
@@ -141745,11 +143591,7 @@ struct WhereTerm {
#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */
-#ifdef SQLITE_ENABLE_STAT4
-# define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
-#else
-# define TERM_VNULL 0x0000 /* Disabled if not using stat4 */
-#endif
+#define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x0400 /* The original LIKE operator */
@@ -142019,7 +143861,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
-SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
+SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
@@ -142197,7 +144039,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
if( sqlite3ParseToplevel(pParse)->explain==2 )
#endif
{
- struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
+ SrcItem *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
@@ -142990,7 +144832,7 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/
static void codeCursorHint(
- struct SrcList_item *pTabItem, /* FROM clause item */
+ SrcItem *pTabItem, /* FROM clause item */
WhereInfo *pWInfo, /* The where clause */
WhereLevel *pLevel, /* Which loop to provide hints for */
WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */
@@ -143365,7 +145207,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
sqlite3 *db; /* Database connection */
- struct SrcList_item *pTabItem; /* FROM clause term being coded */
+ SrcItem *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
@@ -143811,6 +145653,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
SWAP(u8, nBtm, nTop);
}
+ if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
+ /* In case OP_SeekScan is used, ensure that the index cursor does not
+ ** point to a valid row for the first iteration of this loop. */
+ sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
+ }
+
/* Generate code to evaluate all constraint terms using == or IN
** and store the values of those terms in an array of registers
** starting at regBase.
@@ -144147,7 +145995,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
*/
if( pWInfo->nLevel>1 ){
int nNotReady; /* The number of notReady tables */
- struct SrcList_item *origSrc; /* Original list of tables */
+ SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
pOrTab = sqlite3StackAllocRaw(db,
sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
@@ -145070,6 +146918,7 @@ static void whereCombineDisjuncts(
int op; /* Operator for the combined expression */
int idxNew; /* Index in pWC of the next virtual term */
+ 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
@@ -145567,6 +147416,277 @@ static int exprMightBeIndexed(
}
/*
+** Expression callback for exprUsesSrclist().
+*/
+static int exprUsesSrclistCb(Walker *p, Expr *pExpr){
+ if( pExpr->op==TK_COLUMN ){
+ SrcList *pSrc = p->u.pSrcList;
+ int iCsr = pExpr->iTable;
+ int ii;
+ for(ii=0; ii<pSrc->nSrc; ii++){
+ if( pSrc->a[ii].iCursor==iCsr ){
+ return p->eCode ? WRC_Abort : WRC_Continue;
+ }
+ }
+ return p->eCode ? WRC_Continue : WRC_Abort;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Select callback for exprUsesSrclist().
+*/
+static int exprUsesSrclistSelectCb(Walker *NotUsed1, Select *NotUsed2){
+ UNUSED_PARAMETER(NotUsed1);
+ UNUSED_PARAMETER(NotUsed2);
+ return WRC_Abort;
+}
+
+/*
+** This function always returns true if expression pExpr contains
+** a sub-select.
+**
+** If there is no sub-select in pExpr, then return true if pExpr
+** contains a TK_COLUMN node for a table that is (bUses==1)
+** or is not (bUses==0) in pSrc.
+**
+** Said another way:
+**
+** bUses Return Meaning
+** -------- ------ ------------------------------------------------
+**
+** bUses==1 true pExpr contains either a sub-select or a
+** TK_COLUMN referencing pSrc.
+**
+** bUses==1 false pExpr contains no sub-selects and all TK_COLUMN
+** nodes reference tables not found in pSrc
+**
+** bUses==0 true pExpr contains either a sub-select or a TK_COLUMN
+** that references a table not in pSrc.
+**
+** bUses==0 false pExpr contains no sub-selects and all TK_COLUMN
+** nodes reference pSrc
+*/
+static int exprUsesSrclist(SrcList *pSrc, Expr *pExpr, int bUses){
+ Walker sWalker;
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.eCode = bUses;
+ sWalker.u.pSrcList = pSrc;
+ sWalker.xExprCallback = exprUsesSrclistCb;
+ sWalker.xSelectCallback = exprUsesSrclistSelectCb;
+ return (sqlite3WalkExpr(&sWalker, pExpr)==WRC_Abort);
+}
+
+/*
+** Context object used by exprExistsToInIter() as it iterates through an
+** expression tree.
+*/
+struct ExistsToInCtx {
+ SrcList *pSrc; /* The tables in an EXISTS(SELECT ... FROM <here> ...) */
+ Expr *pInLhs; /* OUT: Use this as the LHS of the IN operator */
+ Expr *pEq; /* OUT: The == term that include pInLhs */
+ Expr **ppAnd; /* OUT: The AND operator that includes pEq as a child */
+ Expr **ppParent; /* The AND operator currently being examined */
+};
+
+/*
+** Iterate through all AND connected nodes in the expression tree
+** headed by (*ppExpr), populating the structure passed as the first
+** argument with the values required by exprAnalyzeExistsFindEq().
+**
+** This function returns non-zero if the expression tree does not meet
+** the two conditions described by the header comment for
+** exprAnalyzeExistsFindEq(), or zero if it does.
+*/
+static int exprExistsToInIter(struct ExistsToInCtx *p, Expr **ppExpr){
+ Expr *pExpr = *ppExpr;
+ switch( pExpr->op ){
+ case TK_AND:
+ p->ppParent = ppExpr;
+ if( exprExistsToInIter(p, &pExpr->pLeft) ) return 1;
+ p->ppParent = ppExpr;
+ if( exprExistsToInIter(p, &pExpr->pRight) ) return 1;
+ break;
+ case TK_EQ: {
+ int bLeft = exprUsesSrclist(p->pSrc, pExpr->pLeft, 0);
+ int bRight = exprUsesSrclist(p->pSrc, pExpr->pRight, 0);
+ if( bLeft || bRight ){
+ if( (bLeft && bRight) || p->pInLhs ) return 1;
+ p->pInLhs = bLeft ? pExpr->pLeft : pExpr->pRight;
+ if( exprUsesSrclist(p->pSrc, p->pInLhs, 1) ) return 1;
+ p->pEq = pExpr;
+ p->ppAnd = p->ppParent;
+ }
+ break;
+ }
+ default:
+ if( exprUsesSrclist(p->pSrc, pExpr, 0) ){
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*
+** This function is used by exprAnalyzeExists() when creating virtual IN(...)
+** terms equivalent to user-supplied EXIST(...) clauses. It splits the WHERE
+** clause of the Select object passed as the first argument into one or more
+** expressions joined by AND operators, and then tests if the following are
+** true:
+**
+** 1. Exactly one of the AND separated terms refers to the outer
+** query, and it is an == (TK_EQ) expression.
+**
+** 2. Only one side of the == expression refers to the outer query, and
+** it does not refer to any columns from the inner query.
+**
+** If both these conditions are true, then a pointer to the side of the ==
+** expression that refers to the outer query is returned. The caller will
+** use this expression as the LHS of the IN(...) virtual term. Or, if one
+** or both of the above conditions are not true, NULL is returned.
+**
+** If non-NULL is returned and ppEq is non-NULL, *ppEq is set to point
+** to the == expression node before returning. If pppAnd is non-NULL and
+** the == node is not the root of the WHERE clause, then *pppAnd is set
+** to point to the pointer to the AND node that is the parent of the ==
+** node within the WHERE expression tree.
+*/
+static Expr *exprAnalyzeExistsFindEq(
+ Select *pSel, /* The SELECT of the EXISTS */
+ Expr **ppEq, /* OUT: == node from WHERE clause */
+ Expr ***pppAnd /* OUT: Pointer to parent of ==, if any */
+){
+ struct ExistsToInCtx ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.pSrc = pSel->pSrc;
+ if( exprExistsToInIter(&ctx, &pSel->pWhere) ){
+ return 0;
+ }
+ if( ppEq ) *ppEq = ctx.pEq;
+ if( pppAnd ) *pppAnd = ctx.ppAnd;
+ return ctx.pInLhs;
+}
+
+/*
+** Term idxTerm of the WHERE clause passed as the second argument is an
+** EXISTS expression with a correlated SELECT statement on the RHS.
+** This function analyzes the SELECT statement, and if possible adds an
+** equivalent "? IN(SELECT...)" virtual term to the WHERE clause.
+**
+** For an EXISTS term such as the following:
+**
+** EXISTS (SELECT ... FROM <srclist> WHERE <e1> = <e2> AND <e3>)
+**
+** The virtual IN() term added is:
+**
+** <e1> IN (SELECT <e2> FROM <srclist> WHERE <e3>)
+**
+** The virtual term is only added if the following conditions are met:
+**
+** 1. The sub-select must not be an aggregate or use window functions,
+**
+** 2. The sub-select must not be a compound SELECT,
+**
+** 3. Expression <e1> must refer to at least one column from the outer
+** query, and must not refer to any column from the inner query
+** (i.e. from <srclist>).
+**
+** 4. <e2> and <e3> must not refer to any values from the outer query.
+** In other words, once <e1> has been removed, the inner query
+** must not be correlated.
+**
+*/
+static void exprAnalyzeExists(
+ SrcList *pSrc, /* the FROM clause */
+ WhereClause *pWC, /* the WHERE clause */
+ int idxTerm /* Index of the term to be analyzed */
+){
+ Parse *pParse = pWC->pWInfo->pParse;
+ WhereTerm *pTerm = &pWC->a[idxTerm];
+ Expr *pExpr = pTerm->pExpr;
+ Select *pSel = pExpr->x.pSelect;
+ Expr *pDup = 0;
+ Expr *pEq = 0;
+ Expr *pRet = 0;
+ Expr *pInLhs = 0;
+ Expr **ppAnd = 0;
+ int idxNew;
+ sqlite3 *db = pParse->db;
+
+ assert( pExpr->op==TK_EXISTS );
+ assert( (pExpr->flags & EP_VarSelect) && (pExpr->flags & EP_xIsSelect) );
+
+ if( pSel->selFlags & SF_Aggregate ) return;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pSel->pWin ) return;
+#endif
+ if( pSel->pPrior ) return;
+ if( pSel->pWhere==0 ) return;
+ if( pSel->pLimit ) return;
+ if( 0==exprAnalyzeExistsFindEq(pSel, 0, 0) ) return;
+
+ pDup = sqlite3ExprDup(db, pExpr, 0);
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDup);
+ return;
+ }
+ pSel = pDup->x.pSelect;
+ sqlite3ExprListDelete(db, pSel->pEList);
+ pSel->pEList = 0;
+
+ pInLhs = exprAnalyzeExistsFindEq(pSel, &pEq, &ppAnd);
+ assert( pInLhs && pEq );
+ assert( pEq==pSel->pWhere || ppAnd );
+ if( pInLhs==pEq->pLeft ){
+ pRet = pEq->pRight;
+ }else{
+ CollSeq *p = sqlite3ExprCompareCollSeq(pParse, pEq);
+ pInLhs = sqlite3ExprAddCollateString(pParse, pInLhs, p?p->zName:"BINARY");
+ pRet = pEq->pLeft;
+ }
+
+ assert( pDup->pLeft==0 );
+ pDup->op = TK_IN;
+ pDup->pLeft = pInLhs;
+ pDup->flags &= ~EP_VarSelect;
+ if( pRet->op==TK_VECTOR ){
+ pSel->pEList = pRet->x.pList;
+ pRet->x.pList = 0;
+ sqlite3ExprDelete(db, pRet);
+ }else{
+ pSel->pEList = sqlite3ExprListAppend(pParse, 0, pRet);
+ }
+ pEq->pLeft = 0;
+ pEq->pRight = 0;
+ if( ppAnd ){
+ Expr *pAnd = *ppAnd;
+ Expr *pOther = (pAnd->pLeft==pEq) ? pAnd->pRight : pAnd->pLeft;
+ pAnd->pLeft = pAnd->pRight = 0;
+ sqlite3ExprDelete(db, pAnd);
+ *ppAnd = pOther;
+ }else{
+ assert( pSel->pWhere==pEq );
+ pSel->pWhere = 0;
+ }
+ sqlite3ExprDelete(db, pEq);
+
+#ifdef WHERETRACE_ENABLED /* 0x20 */
+ if( sqlite3WhereTrace & 0x20 ){
+ sqlite3DebugPrintf("Convert EXISTS:\n");
+ sqlite3TreeViewExpr(0, pExpr, 0);
+ sqlite3DebugPrintf("into IN:\n");
+ sqlite3TreeViewExpr(0, pDup, 0);
+ }
+#endif
+ idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
+ exprAnalyze(pSrc, pWC, idxNew);
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pWC->a[idxTerm].wtFlags |= TERM_COPIED;
+}
+
+/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in. The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
@@ -145699,6 +147819,12 @@ static void exprAnalyze(
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
+ }else if( op==TK_ISNULL && 0==sqlite3ExprCanBeNull(pLeft) ){
+ pExpr->op = TK_TRUEFALSE;
+ pExpr->u.zToken = "false";
+ ExprSetProperty(pExpr, EP_IsFalse);
+ pTerm->prereqAll = 0;
+ pTerm->eOperator = 0;
}
}
@@ -145751,6 +147877,52 @@ static void exprAnalyze(
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+ else if( pExpr->op==TK_EXISTS ){
+ /* Perhaps treat an EXISTS operator as an IN operator */
+ if( (pExpr->flags & EP_VarSelect)!=0
+ && OptimizationEnabled(db, SQLITE_ExistsToIN)
+ ){
+ exprAnalyzeExists(pSrc, pWC, idxTerm);
+ }
+ }
+
+ /* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
+ ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
+ ** virtual term of that form.
+ **
+ ** The virtual term must be tagged with TERM_VNULL.
+ */
+ else if( pExpr->op==TK_NOTNULL ){
+ if( pExpr->pLeft->op==TK_COLUMN
+ && pExpr->pLeft->iColumn>=0
+ && !ExprHasProperty(pExpr, EP_FromJoin)
+ ){
+ Expr *pNewExpr;
+ Expr *pLeft = pExpr->pLeft;
+ int idxNew;
+ WhereTerm *pNewTerm;
+
+ pNewExpr = sqlite3PExpr(pParse, TK_GT,
+ sqlite3ExprDup(db, pLeft, 0),
+ sqlite3ExprAlloc(db, TK_NULL, 0, 0));
+
+ idxNew = whereClauseInsert(pWC, pNewExpr,
+ TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
+ if( idxNew ){
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = 0;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_GT;
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ }
+ }
+
+
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
/* Add constraints to reduce the search space on a LIKE or GLOB
** operator.
@@ -145765,7 +147937,8 @@ static void exprAnalyze(
** bound is made all lowercase so that the bounds also work when comparing
** BLOBs.
*/
- if( pWC->op==TK_AND
+ else if( pExpr->op==TK_FUNCTION
+ && pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
){
Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -145835,52 +148008,6 @@ static void exprAnalyze(
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* Add a WO_AUX auxiliary term to the constraint set if the
- ** current expression is of the form "column OP expr" where OP
- ** is an operator that gets passed into virtual tables but which is
- ** not normally optimized for ordinary tables. In other words, OP
- ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
- ** This information is used by the xBestIndex methods of
- ** virtual tables. The native query optimizer does not attempt
- ** to do anything with MATCH functions.
- */
- if( pWC->op==TK_AND ){
- Expr *pRight = 0, *pLeft = 0;
- int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
- while( res-- > 0 ){
- int idxNew;
- WhereTerm *pNewTerm;
- Bitmask prereqColumn, prereqExpr;
-
- prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
- prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
- if( (prereqExpr & prereqColumn)==0 ){
- Expr *pNewExpr;
- pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
- 0, sqlite3ExprDup(db, pRight, 0));
- if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
- ExprSetProperty(pNewExpr, EP_FromJoin);
- pNewExpr->iRightJoinTable = pExpr->iRightJoinTable;
- }
- idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
- testcase( idxNew==0 );
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = prereqExpr;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.x.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_AUX;
- pNewTerm->eMatchOp = eOp2;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
- }
- SWAP(Expr*, pLeft, pRight);
- }
- }
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
/* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
** new terms for each component comparison - "a = ?" and "b = ?". The
** new terms completely replace the original vector comparison, which is
@@ -145888,12 +148015,12 @@ static void exprAnalyze(
**
** This is only required if at least one side of the comparison operation
** is not a sub-select. */
- if( pWC->op==TK_AND
- && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
- && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
- && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
- && ( (pExpr->pLeft->flags & EP_xIsSelect)==0
- || (pExpr->pRight->flags & EP_xIsSelect)==0)
+ if( (pExpr->op==TK_EQ || pExpr->op==TK_IS)
+ && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
+ && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
+ && ( (pExpr->pLeft->flags & EP_xIsSelect)==0
+ || (pExpr->pRight->flags & EP_xIsSelect)==0)
+ && pWC->op==TK_AND
){
int i;
for(i=0; i<nLeft; i++){
@@ -145921,12 +148048,14 @@ static void exprAnalyze(
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
- if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0
+ else if( pExpr->op==TK_IN
+ && pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
+ && pWC->op==TK_AND
){
int i;
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
@@ -145938,44 +148067,51 @@ static void exprAnalyze(
}
}
-#ifdef SQLITE_ENABLE_STAT4
- /* When sqlite_stat4 histogram data is available an operator of the
- ** form "x IS NOT NULL" can sometimes be evaluated more efficiently
- ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
- ** virtual term of that form.
- **
- ** Note that the virtual term must be tagged with TERM_VNULL.
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Add a WO_AUX auxiliary term to the constraint set if the
+ ** current expression is of the form "column OP expr" where OP
+ ** is an operator that gets passed into virtual tables but which is
+ ** not normally optimized for ordinary tables. In other words, OP
+ ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
+ ** This information is used by the xBestIndex methods of
+ ** virtual tables. The native query optimizer does not attempt
+ ** to do anything with MATCH functions.
*/
- if( pExpr->op==TK_NOTNULL
- && pExpr->pLeft->op==TK_COLUMN
- && pExpr->pLeft->iColumn>=0
- && !ExprHasProperty(pExpr, EP_FromJoin)
- && OptimizationEnabled(db, SQLITE_Stat4)
- ){
- Expr *pNewExpr;
- Expr *pLeft = pExpr->pLeft;
- int idxNew;
- WhereTerm *pNewTerm;
-
- pNewExpr = sqlite3PExpr(pParse, TK_GT,
- sqlite3ExprDup(db, pLeft, 0),
- sqlite3ExprAlloc(db, TK_NULL, 0, 0));
-
- idxNew = whereClauseInsert(pWC, pNewExpr,
- TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
- if( idxNew ){
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = 0;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.x.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_GT;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
+ else if( pWC->op==TK_AND ){
+ Expr *pRight = 0, *pLeft = 0;
+ int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
+ while( res-- > 0 ){
+ int idxNew;
+ WhereTerm *pNewTerm;
+ Bitmask prereqColumn, prereqExpr;
+
+ prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
+ prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
+ if( (prereqExpr & prereqColumn)==0 ){
+ Expr *pNewExpr;
+ pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
+ 0, sqlite3ExprDup(db, pRight, 0));
+ if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
+ ExprSetProperty(pNewExpr, EP_FromJoin);
+ pNewExpr->iRightJoinTable = pExpr->iRightJoinTable;
+ }
+ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_AUX;
+ pNewTerm->eMatchOp = eOp2;
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ SWAP(Expr*, pLeft, pRight);
}
}
-#endif /* SQLITE_ENABLE_STAT4 */
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
** an index for tables to the left of the join.
@@ -146135,7 +148271,7 @@ SQLITE_PRIVATE void sqlite3WhereExprAnalyze(
*/
SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
Parse *pParse, /* Parsing context */
- struct SrcList_item *pItem, /* The FROM clause term to process */
+ SrcItem *pItem, /* The FROM clause term to process */
WhereClause *pWC /* Xfer function arguments to here */
){
Table *pTab;
@@ -146212,12 +148348,6 @@ struct HiddenIndexInfo {
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
-/* Test variable that can be set to enable WHERE tracing */
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ int sqlite3WhereTrace = 0;
-#endif
-
-
/*
** Return the estimated number of output rows from a WHERE clause
*/
@@ -146281,6 +148411,32 @@ SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){
}
/*
+** While generating code for the min/max optimization, after handling
+** the aggregate-step call to min() or max(), check to see if any
+** additional looping is required. If the output order is such that
+** we are certain that the correct answer has already been found, then
+** code an OP_Goto to by pass subsequent processing.
+**
+** Any extra OP_Goto that is coded here is an optimization. The
+** correct answer should be obtained regardless. This OP_Goto just
+** makes the answer appear faster.
+*/
+SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){
+ WhereLevel *pInner;
+ int i;
+ if( !pWInfo->bOrderedInnerLoop ) return;
+ if( pWInfo->nOBSat==0 ) return;
+ for(i=pWInfo->nLevel-1; i>=0; i--){
+ pInner = &pWInfo->a[i];
+ if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){
+ sqlite3VdbeGoto(v, pInner->addrNxt);
+ return;
+ }
+ }
+ sqlite3VdbeGoto(v, pWInfo->iBreak);
+}
+
+/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
*/
@@ -146849,7 +149005,7 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
*/
static int termCanDriveIndex(
WhereTerm *pTerm, /* WHERE clause term to check */
- struct SrcList_item *pSrc, /* Table we are trying to access */
+ SrcItem *pSrc, /* Table we are trying to access */
Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
@@ -146883,7 +149039,7 @@ static int termCanDriveIndex(
static void constructAutomaticIndex(
Parse *pParse, /* The parsing context */
WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to get the next index */
+ SrcItem *pSrc, /* The FROM clause term to get the next index */
Bitmask notReady, /* Mask of cursors that are not available */
WhereLevel *pLevel /* Write new index here */
){
@@ -146907,7 +149063,7 @@ static void constructAutomaticIndex(
u8 sentWarning = 0; /* True if a warnning has been issued */
Expr *pPartial = 0; /* Partial Index Expression */
int iContinue = 0; /* Jump here to skip excluded rows */
- struct SrcList_item *pTabItem; /* FROM clause term being indexed */
+ SrcItem *pTabItem; /* FROM clause term being indexed */
int addrCounter = 0; /* Address where integer counter is initialized */
int regBase; /* Array of registers where record is assembled */
@@ -147091,7 +149247,7 @@ static sqlite3_index_info *allocateIndexInfo(
Parse *pParse, /* The parsing context */
WhereClause *pWC, /* The WHERE clause being analyzed */
Bitmask mUnusable, /* Ignore terms with these prereqs */
- struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */
+ SrcItem *pSrc, /* The FROM clause term that is the vtab */
ExprList *pOrderBy, /* The ORDER BY clause */
u16 *pmNoOmit /* Mask of terms not to omit */
){
@@ -147989,7 +150145,7 @@ SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){
SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){
WhereInfo *pWInfo = pWC->pWInfo;
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
- struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
+ SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
Table *pTab = pItem->pTab;
Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
@@ -148600,7 +150756,7 @@ static int whereRangeVectorLen(
*/
static int whereLoopAddBtreeIndex(
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
- struct SrcList_item *pSrc, /* FROM clause term being analyzed */
+ SrcItem *pSrc, /* FROM clause term being analyzed */
Index *pProbe, /* An index on pSrc */
LogEst nInMul /* log(Number of iterations due to IN) */
){
@@ -148786,7 +150942,7 @@ static int whereLoopAddBtreeIndex(
pBtm = pTerm;
pTop = 0;
if( pTerm->wtFlags & TERM_LIKEOPT ){
- /* Range contraints that come from the LIKE optimization are
+ /* Range constraints that come from the LIKE optimization are
** always used in pairs. */
pTop = &pTerm[1];
assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
@@ -149091,7 +151247,7 @@ static int whereLoopAddBtree(
LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */
i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */
SrcList *pTabList; /* The FROM clause */
- struct SrcList_item *pSrc; /* The FROM clause btree term to add */
+ SrcItem *pSrc; /* The FROM clause btree term to add */
WhereLoop *pNew; /* Template WhereLoop object */
int rc = SQLITE_OK; /* Return code */
int iSortIdx = 1; /* Index number */
@@ -149109,9 +151265,9 @@ static int whereLoopAddBtree(
pWC = pBuilder->pWC;
assert( !IsVirtual(pSrc->pTab) );
- if( pSrc->pIBIndex ){
+ if( pSrc->fg.isIndexedBy ){
/* An INDEXED BY clause specifies a particular index to use */
- pProbe = pSrc->pIBIndex;
+ pProbe = pSrc->u2.pIBIndex;
}else if( !HasRowid(pTab) ){
pProbe = pTab->pIndex;
}else{
@@ -149147,7 +151303,7 @@ static int whereLoopAddBtree(
if( !pBuilder->pOrSet /* Not part of an OR optimization */
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
- && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */
+ && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
&& HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
@@ -149197,7 +151353,7 @@ static int whereLoopAddBtree(
/* Loop over all indices. If there was an INDEXED BY clause, then only
** consider index pProbe. */
for(; rc==SQLITE_OK && pProbe;
- pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
+ pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++
){
int isLeft = (pSrc->fg.jointype & JT_OUTER)!=0;
if( pProbe->pPartIdxWhere!=0
@@ -149372,7 +151528,7 @@ static int whereLoopAddVirtualOne(
int rc = SQLITE_OK;
WhereLoop *pNew = pBuilder->pNew;
Parse *pParse = pBuilder->pWInfo->pParse;
- struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
+ SrcItem *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
int nConstraint = pIdxInfo->nConstraint;
assert( (mUsable & mPrereq)==mPrereq );
@@ -149564,7 +151720,7 @@ static int whereLoopAddVirtual(
WhereInfo *pWInfo; /* WHERE analysis context */
Parse *pParse; /* The parsing context */
WhereClause *pWC; /* The WHERE clause */
- struct SrcList_item *pSrc; /* The FROM clause term to search */
+ SrcItem *pSrc; /* The FROM clause term to search */
sqlite3_index_info *p; /* Object to pass to xBestIndex() */
int nConstraint; /* Number of constraints in p */
int bIn; /* True if plan uses IN(...) operator */
@@ -149692,7 +151848,7 @@ static int whereLoopAddOr(
WhereClause tempWC;
WhereLoopBuilder sSubBuild;
WhereOrSet sSum, sCur;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pWC = pBuilder->pWC;
pWCEnd = pWC->a + pWC->nTerm;
@@ -149808,8 +151964,8 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
Bitmask mPrior = 0;
int iTab;
SrcList *pTabList = pWInfo->pTabList;
- struct SrcList_item *pItem;
- struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel];
+ SrcItem *pItem;
+ SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
sqlite3 *db = pWInfo->pParse->db;
int rc = SQLITE_OK;
WhereLoop *pNew;
@@ -149832,7 +151988,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
- struct SrcList_item *p;
+ SrcItem *p;
for(p=&pItem[1]; p<pEnd; p++){
if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){
mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
@@ -150687,7 +152843,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
*/
static int whereShortCut(WhereLoopBuilder *pBuilder){
WhereInfo *pWInfo;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
WhereClause *pWC;
WhereTerm *pTerm;
WhereLoop *pLoop;
@@ -151146,7 +153302,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
pWInfo->revMask = ALLBITS;
}
- if( pParse->nErr || NEVER(db->mallocFailed) ){
+ if( pParse->nErr || db->mallocFailed ){
goto whereBeginError;
}
#ifdef WHERETRACE_ENABLED
@@ -151217,7 +153373,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
for(i=pWInfo->nLevel-1; i>=1; i--){
WhereTerm *pTerm, *pEnd;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pLoop = pWInfo->a[i].pWLoop;
pItem = &pWInfo->pTabList->a[pLoop->iTab];
if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
@@ -151307,7 +153463,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
- struct SrcList_item *pTabItem;
+ SrcItem *pTabItem;
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
@@ -151644,7 +153800,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
int k, last;
VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
- struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
+ SrcItem *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
pLoop = pLevel->pWLoop;
@@ -151720,7 +153876,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
#endif
pOp = sqlite3VdbeGetOp(v, k);
pLastOp = pOp + (last - k);
- assert( pOp<pLastOp );
+ assert( pOp<pLastOp || (pParse->nErr>0 && pOp==pLastOp) );
do{
if( pOp->p1!=pLevel->iTabCur ){
/* no-op */
@@ -153088,15 +155244,19 @@ SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
** SELECT, or (b) the windows already linked use a compatible window frame.
*/
SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin){
- if( pSel!=0
- && (0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0))
- ){
- pWin->pNextWin = pSel->pWin;
- if( pSel->pWin ){
- pSel->pWin->ppThis = &pWin->pNextWin;
+ if( pSel ){
+ if( 0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0) ){
+ pWin->pNextWin = pSel->pWin;
+ if( pSel->pWin ){
+ pSel->pWin->ppThis = &pWin->pNextWin;
+ }
+ pSel->pWin = pWin;
+ pWin->ppThis = &pSel->pWin;
+ }else{
+ if( sqlite3ExprListCompare(pWin->pPartition, pSel->pWin->pPartition,-1) ){
+ pSel->selFlags |= SF_MultiPart;
+ }
}
- pSel->pWin = pWin;
- pWin->ppThis = &pSel->pWin;
}
}
@@ -153249,6 +155409,7 @@ static void windowCheckValue(Parse *pParse, int reg, int eCond){
VdbeCoverageIf(v, eCond==2);
}
sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
+ sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC);
VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */
VdbeCoverageNeverNullIf(v, eCond==2);
@@ -153845,6 +156006,7 @@ static void windowCodeRangeTest(
int regString = ++pParse->nMem; /* Reg. for constant value '' */
int arith = OP_Add; /* OP_Add or OP_Subtract */
int addrGe; /* Jump destination */
+ CollSeq *pColl;
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( pOrderBy && pOrderBy->nExpr==1 );
@@ -153935,6 +156097,8 @@ static void windowCodeRangeTest(
** control skips over this test if the BIGNULL flag is set and either
** reg1 or reg2 contain a NULL value. */
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
+ pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
+ sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
@@ -154941,11 +157105,21 @@ static void updateDeleteLimitError(
static void parserDoubleLinkSelect(Parse *pParse, Select *p){
assert( p!=0 );
if( p->pPrior ){
- Select *pNext = 0, *pLoop;
- int mxSelect, cnt = 0;
- for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
+ Select *pNext = 0, *pLoop = p;
+ int mxSelect, cnt = 1;
+ while(1){
pLoop->pNext = pNext;
pLoop->selFlags |= SF_Compound;
+ pNext = pLoop;
+ pLoop = pLoop->pPrior;
+ if( pLoop==0 ) break;
+ cnt++;
+ if( pLoop->pOrderBy || pLoop->pLimit ){
+ sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
+ pLoop->pOrderBy!=0 ? "ORDER BY" : "LIMIT",
+ sqlite3SelectOpName(pNext->op));
+ break;
+ }
}
if( (p->selFlags & SF_MultiValue)==0 &&
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
@@ -154956,6 +157130,19 @@ static void updateDeleteLimitError(
}
}
+ /* Attach a With object describing the WITH clause to a Select
+ ** object describing the query for which the WITH clause is a prefix.
+ */
+ static Select *attachWithToSelect(Parse *pParse, Select *pSelect, With *pWith){
+ if( pSelect ){
+ pSelect->pWith = pWith;
+ parserDoubleLinkSelect(pParse, pSelect);
+ }else{
+ sqlite3WithDelete(pParse->db, pWith);
+ }
+ return pSelect;
+ }
+
/* Construct a new Expr object from a single identifier. Use the
** new Expr to populate pOut. Set the span of pOut to be the identifier
@@ -155121,87 +157308,89 @@ static void updateDeleteLimitError(
#define TK_LAST 84
#define TK_GENERATED 85
#define TK_ALWAYS 86
-#define TK_REINDEX 87
-#define TK_RENAME 88
-#define TK_CTIME_KW 89
-#define TK_ANY 90
-#define TK_BITAND 91
-#define TK_BITOR 92
-#define TK_LSHIFT 93
-#define TK_RSHIFT 94
-#define TK_PLUS 95
-#define TK_MINUS 96
-#define TK_STAR 97
-#define TK_SLASH 98
-#define TK_REM 99
-#define TK_CONCAT 100
-#define TK_COLLATE 101
-#define TK_BITNOT 102
-#define TK_ON 103
-#define TK_INDEXED 104
-#define TK_STRING 105
-#define TK_JOIN_KW 106
-#define TK_CONSTRAINT 107
-#define TK_DEFAULT 108
-#define TK_NULL 109
-#define TK_PRIMARY 110
-#define TK_UNIQUE 111
-#define TK_CHECK 112
-#define TK_REFERENCES 113
-#define TK_AUTOINCR 114
-#define TK_INSERT 115
-#define TK_DELETE 116
-#define TK_UPDATE 117
-#define TK_SET 118
-#define TK_DEFERRABLE 119
-#define TK_FOREIGN 120
-#define TK_DROP 121
-#define TK_UNION 122
-#define TK_ALL 123
-#define TK_EXCEPT 124
-#define TK_INTERSECT 125
-#define TK_SELECT 126
-#define TK_VALUES 127
-#define TK_DISTINCT 128
-#define TK_DOT 129
-#define TK_FROM 130
-#define TK_JOIN 131
-#define TK_USING 132
-#define TK_ORDER 133
-#define TK_GROUP 134
-#define TK_HAVING 135
-#define TK_LIMIT 136
-#define TK_WHERE 137
-#define TK_INTO 138
-#define TK_NOTHING 139
-#define TK_FLOAT 140
-#define TK_BLOB 141
-#define TK_INTEGER 142
-#define TK_VARIABLE 143
-#define TK_CASE 144
-#define TK_WHEN 145
-#define TK_THEN 146
-#define TK_ELSE 147
-#define TK_INDEX 148
-#define TK_ALTER 149
-#define TK_ADD 150
-#define TK_COLUMN 151
-#define TK_AGG_FUNCTION 152
-#define TK_AGG_COLUMN 153
-#define TK_TRUEFALSE 154
-#define TK_ISNOT 155
-#define TK_FUNCTION 156
-#define TK_UMINUS 157
-#define TK_UPLUS 158
-#define TK_TRUTH 159
-#define TK_REGISTER 160
-#define TK_VECTOR 161
-#define TK_SELECT_COLUMN 162
-#define TK_IF_NULL_ROW 163
-#define TK_ASTERISK 164
-#define TK_SPAN 165
-#define TK_SPACE 166
-#define TK_ILLEGAL 167
+#define TK_MATERIALIZED 87
+#define TK_REINDEX 88
+#define TK_RENAME 89
+#define TK_CTIME_KW 90
+#define TK_ANY 91
+#define TK_BITAND 92
+#define TK_BITOR 93
+#define TK_LSHIFT 94
+#define TK_RSHIFT 95
+#define TK_PLUS 96
+#define TK_MINUS 97
+#define TK_STAR 98
+#define TK_SLASH 99
+#define TK_REM 100
+#define TK_CONCAT 101
+#define TK_COLLATE 102
+#define TK_BITNOT 103
+#define TK_ON 104
+#define TK_INDEXED 105
+#define TK_STRING 106
+#define TK_JOIN_KW 107
+#define TK_CONSTRAINT 108
+#define TK_DEFAULT 109
+#define TK_NULL 110
+#define TK_PRIMARY 111
+#define TK_UNIQUE 112
+#define TK_CHECK 113
+#define TK_REFERENCES 114
+#define TK_AUTOINCR 115
+#define TK_INSERT 116
+#define TK_DELETE 117
+#define TK_UPDATE 118
+#define TK_SET 119
+#define TK_DEFERRABLE 120
+#define TK_FOREIGN 121
+#define TK_DROP 122
+#define TK_UNION 123
+#define TK_ALL 124
+#define TK_EXCEPT 125
+#define TK_INTERSECT 126
+#define TK_SELECT 127
+#define TK_VALUES 128
+#define TK_DISTINCT 129
+#define TK_DOT 130
+#define TK_FROM 131
+#define TK_JOIN 132
+#define TK_USING 133
+#define TK_ORDER 134
+#define TK_GROUP 135
+#define TK_HAVING 136
+#define TK_LIMIT 137
+#define TK_WHERE 138
+#define TK_RETURNING 139
+#define TK_INTO 140
+#define TK_NOTHING 141
+#define TK_FLOAT 142
+#define TK_BLOB 143
+#define TK_INTEGER 144
+#define TK_VARIABLE 145
+#define TK_CASE 146
+#define TK_WHEN 147
+#define TK_THEN 148
+#define TK_ELSE 149
+#define TK_INDEX 150
+#define TK_ALTER 151
+#define TK_ADD 152
+#define TK_COLUMN 153
+#define TK_AGG_FUNCTION 154
+#define TK_AGG_COLUMN 155
+#define TK_TRUEFALSE 156
+#define TK_ISNOT 157
+#define TK_FUNCTION 158
+#define TK_UMINUS 159
+#define TK_UPLUS 160
+#define TK_TRUTH 161
+#define TK_REGISTER 162
+#define TK_VECTOR 163
+#define TK_SELECT_COLUMN 164
+#define TK_IF_NULL_ROW 165
+#define TK_ASTERISK 166
+#define TK_SPAN 167
+#define TK_SPACE 168
+#define TK_ILLEGAL 169
#endif
/**************** End token definitions ***************************************/
@@ -155261,25 +157450,27 @@ static void updateDeleteLimitError(
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned short int
-#define YYNOCODE 281
+#define YYNOCODE 287
#define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 90
+#define YYWILDCARD 91
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
- IdList* yy14;
- TriggerStep* yy39;
- Upsert* yy90;
- struct TrigEvent yy168;
- int yy222;
- Expr* yy244;
- ExprList* yy328;
- Select* yy341;
- const char* yy386;
- SrcList* yy475;
- struct {int value; int mask;} yy501;
- With* yy523;
+ Expr* yy62;
+ IdList* yy76;
+ int yy116;
+ const char* yy224;
+ SrcList* yy315;
+ ExprList* yy336;
+ Upsert* yy402;
+ Cte* yy403;
+ struct TrigEvent yy440;
+ TriggerStep* yy441;
+ Select* yy457;
+ u8 yy518;
+ struct {int value; int mask;} yy523;
+ With* yy535;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -155295,18 +157486,18 @@ typedef union {
#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
#define sqlite3ParserCTX_STORE yypParser->pParse=pParse;
#define YYFALLBACK 1
-#define YYNSTATE 498
-#define YYNRULE 344
-#define YYNRULE_WITH_ACTION 285
-#define YYNTOKEN 168
-#define YY_MAX_SHIFT 497
-#define YY_MIN_SHIFTREDUCE 716
-#define YY_MAX_SHIFTREDUCE 1059
-#define YY_ERROR_ACTION 1060
-#define YY_ACCEPT_ACTION 1061
-#define YY_NO_ACTION 1062
-#define YY_MIN_REDUCE 1063
-#define YY_MAX_REDUCE 1406
+#define YYNSTATE 515
+#define YYNRULE 357
+#define YYNRULE_WITH_ACTION 297
+#define YYNTOKEN 170
+#define YY_MAX_SHIFT 514
+#define YY_MIN_SHIFTREDUCE 738
+#define YY_MAX_SHIFTREDUCE 1094
+#define YY_ERROR_ACTION 1095
+#define YY_ACCEPT_ACTION 1096
+#define YY_NO_ACTION 1097
+#define YY_MIN_REDUCE 1098
+#define YY_MAX_REDUCE 1454
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@@ -155373,511 +157564,527 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1678)
+#define YY_ACTTAB_COUNT (1728)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 101, 98, 187, 101, 98, 187, 1368, 1130, 492, 1109,
- /* 10 */ 172, 172, 462, 1092, 1102, 492, 357, 1130, 336, 1402,
- /* 20 */ 343, 1329, 350, 345, 325, 234, 1373, 326, 847, 778,
- /* 30 */ 58, 58, 416, 357, 12, 12, 848, 43, 43, 463,
- /* 40 */ 85, 108, 109, 99, 1037, 1037, 914, 917, 907, 907,
- /* 50 */ 106, 106, 107, 107, 107, 107, 342, 1057, 108, 109,
- /* 60 */ 99, 1037, 1037, 914, 917, 907, 907, 106, 106, 107,
- /* 70 */ 107, 107, 107, 239, 239, 101, 98, 187, 101, 98,
- /* 80 */ 187, 957, 101, 98, 187, 489, 110, 162, 329, 215,
- /* 90 */ 184, 105, 105, 105, 105, 104, 104, 103, 103, 103,
- /* 100 */ 102, 389, 389, 357, 107, 107, 107, 107, 105, 105,
- /* 110 */ 105, 105, 104, 104, 103, 103, 103, 102, 389, 107,
- /* 120 */ 107, 107, 107, 100, 147, 1014, 366, 1058, 108, 109,
- /* 130 */ 99, 1037, 1037, 914, 917, 907, 907, 106, 106, 107,
- /* 140 */ 107, 107, 107, 105, 105, 105, 105, 104, 104, 103,
- /* 150 */ 103, 103, 102, 389, 68, 486, 486, 486, 105, 105,
- /* 160 */ 105, 105, 104, 104, 103, 103, 103, 102, 389, 261,
- /* 170 */ 483, 357, 1014, 1015, 1016, 91, 69, 89, 105, 105,
- /* 180 */ 105, 105, 104, 104, 103, 103, 103, 102, 389, 407,
- /* 190 */ 285, 996, 1400, 357, 269, 1400, 108, 109, 99, 1037,
- /* 200 */ 1037, 914, 917, 907, 907, 106, 106, 107, 107, 107,
- /* 210 */ 107, 104, 104, 103, 103, 103, 102, 389, 108, 109,
- /* 220 */ 99, 1037, 1037, 914, 917, 907, 907, 106, 106, 107,
- /* 230 */ 107, 107, 107, 105, 105, 105, 105, 104, 104, 103,
- /* 240 */ 103, 103, 102, 389, 407, 285, 105, 105, 105, 105,
- /* 250 */ 104, 104, 103, 103, 103, 102, 389, 103, 103, 103,
- /* 260 */ 102, 389, 994, 357, 397, 102, 389, 299, 105, 105,
- /* 270 */ 105, 105, 104, 104, 103, 103, 103, 102, 389, 876,
- /* 280 */ 357, 397, 396, 490, 445, 803, 803, 147, 108, 109,
- /* 290 */ 99, 1037, 1037, 914, 917, 907, 907, 106, 106, 107,
- /* 300 */ 107, 107, 107, 342, 995, 108, 109, 99, 1037, 1037,
- /* 310 */ 914, 917, 907, 907, 106, 106, 107, 107, 107, 107,
- /* 320 */ 310, 283, 207, 87, 297, 444, 441, 440, 312, 492,
- /* 330 */ 309, 1014, 261, 483, 1095, 439, 112, 172, 105, 105,
- /* 340 */ 105, 105, 104, 104, 103, 103, 103, 102, 389, 356,
- /* 350 */ 397, 59, 59, 163, 1094, 105, 105, 105, 105, 104,
- /* 360 */ 104, 103, 103, 103, 102, 389, 366, 904, 904, 915,
- /* 370 */ 918, 253, 357, 253, 1058, 129, 753, 366, 1014, 1015,
- /* 380 */ 1016, 207, 1135, 1135, 444, 441, 440, 474, 292, 357,
- /* 390 */ 295, 1014, 267, 746, 439, 1374, 464, 108, 109, 99,
- /* 400 */ 1037, 1037, 914, 917, 907, 907, 106, 106, 107, 107,
- /* 410 */ 107, 107, 354, 353, 108, 109, 99, 1037, 1037, 914,
- /* 420 */ 917, 907, 907, 106, 106, 107, 107, 107, 107, 414,
- /* 430 */ 399, 978, 908, 147, 246, 436, 1133, 1133, 1014, 1015,
- /* 440 */ 1016, 347, 431, 1014, 431, 247, 979, 105, 105, 105,
- /* 450 */ 105, 104, 104, 103, 103, 103, 102, 389, 154, 731,
- /* 460 */ 398, 1165, 980, 211, 105, 105, 105, 105, 104, 104,
- /* 470 */ 103, 103, 103, 102, 389, 239, 239, 1293, 261, 483,
- /* 480 */ 8, 357, 492, 789, 260, 895, 1328, 489, 1292, 214,
- /* 490 */ 1014, 1015, 1016, 355, 312, 790, 1014, 181, 357, 1014,
- /* 500 */ 491, 245, 881, 412, 59, 59, 108, 109, 99, 1037,
- /* 510 */ 1037, 914, 917, 907, 907, 106, 106, 107, 107, 107,
- /* 520 */ 107, 405, 362, 108, 109, 99, 1037, 1037, 914, 917,
- /* 530 */ 907, 907, 106, 106, 107, 107, 107, 107, 302, 813,
- /* 540 */ 474, 131, 276, 1014, 1015, 1016, 1014, 1015, 1016, 473,
- /* 550 */ 268, 959, 937, 1014, 421, 959, 105, 105, 105, 105,
- /* 560 */ 104, 104, 103, 103, 103, 102, 389, 4, 168, 1298,
- /* 570 */ 834, 324, 492, 105, 105, 105, 105, 104, 104, 103,
- /* 580 */ 103, 103, 102, 389, 239, 239, 1298, 1300, 426, 1285,
- /* 590 */ 357, 492, 261, 483, 9, 9, 489, 387, 387, 387,
- /* 600 */ 1014, 1015, 1016, 386, 385, 1014, 273, 357, 275, 368,
- /* 610 */ 312, 82, 173, 59, 59, 108, 109, 99, 1037, 1037,
- /* 620 */ 914, 917, 907, 907, 106, 106, 107, 107, 107, 107,
- /* 630 */ 361, 832, 108, 109, 99, 1037, 1037, 914, 917, 907,
- /* 640 */ 907, 106, 106, 107, 107, 107, 107, 468, 1044, 474,
- /* 650 */ 1044, 211, 1014, 1015, 1016, 1298, 1018, 128, 453, 281,
- /* 660 */ 185, 1141, 431, 1081, 328, 105, 105, 105, 105, 104,
- /* 670 */ 104, 103, 103, 103, 102, 389, 808, 274, 492, 420,
- /* 680 */ 492, 807, 105, 105, 105, 105, 104, 104, 103, 103,
- /* 690 */ 103, 102, 389, 239, 239, 239, 239, 239, 239, 357,
- /* 700 */ 9, 9, 9, 9, 1018, 489, 1142, 489, 425, 489,
- /* 710 */ 362, 1014, 422, 420, 186, 373, 357, 375, 414, 876,
- /* 720 */ 90, 431, 456, 1014, 108, 109, 99, 1037, 1037, 914,
- /* 730 */ 917, 907, 907, 106, 106, 107, 107, 107, 107, 832,
- /* 740 */ 1336, 108, 97, 99, 1037, 1037, 914, 917, 907, 907,
- /* 750 */ 106, 106, 107, 107, 107, 107, 239, 239, 1014, 1015,
- /* 760 */ 1016, 283, 402, 271, 2, 394, 1113, 1014, 489, 431,
- /* 770 */ 1014, 1015, 1016, 248, 105, 105, 105, 105, 104, 104,
- /* 780 */ 103, 103, 103, 102, 389, 833, 769, 459, 420, 492,
- /* 790 */ 249, 105, 105, 105, 105, 104, 104, 103, 103, 103,
- /* 800 */ 102, 389, 1014, 414, 71, 233, 233, 282, 357, 492,
- /* 810 */ 1227, 9, 9, 1138, 1014, 1015, 1016, 489, 448, 392,
- /* 820 */ 991, 239, 239, 344, 431, 357, 252, 192, 770, 1084,
- /* 830 */ 363, 59, 59, 489, 109, 99, 1037, 1037, 914, 917,
- /* 840 */ 907, 907, 106, 106, 107, 107, 107, 107, 492, 1014,
- /* 850 */ 1015, 1016, 99, 1037, 1037, 914, 917, 907, 907, 106,
- /* 860 */ 106, 107, 107, 107, 107, 996, 1401, 469, 290, 1401,
- /* 870 */ 44, 44, 377, 492, 465, 250, 492, 94, 484, 370,
- /* 880 */ 3, 313, 251, 105, 105, 105, 105, 104, 104, 103,
- /* 890 */ 103, 103, 102, 389, 487, 11, 11, 1112, 9, 9,
- /* 900 */ 105, 105, 105, 105, 104, 104, 103, 103, 103, 102,
- /* 910 */ 389, 492, 477, 471, 312, 181, 8, 492, 390, 374,
- /* 920 */ 1061, 1, 1, 497, 1063, 894, 492, 94, 484, 262,
- /* 930 */ 3, 123, 481, 59, 59, 194, 994, 492, 1143, 59,
- /* 940 */ 59, 887, 147, 126, 487, 886, 239, 239, 33, 33,
- /* 950 */ 894, 236, 393, 5, 832, 218, 92, 92, 489, 45,
- /* 960 */ 45, 130, 466, 93, 409, 390, 494, 493, 390, 384,
- /* 970 */ 886, 492, 239, 239, 492, 388, 886, 886, 888, 1227,
- /* 980 */ 978, 741, 481, 452, 489, 171, 873, 261, 483, 1227,
- /* 990 */ 406, 1035, 756, 46, 46, 979, 47, 47, 195, 1147,
- /* 1000 */ 894, 886, 886, 888, 889, 19, 92, 92, 812, 808,
- /* 1010 */ 489, 980, 313, 93, 807, 390, 494, 493, 94, 484,
- /* 1020 */ 886, 3, 176, 492, 962, 962, 428, 391, 847, 741,
- /* 1030 */ 86, 484, 480, 3, 475, 487, 848, 186, 492, 1035,
- /* 1040 */ 756, 492, 418, 492, 1227, 59, 59, 487, 371, 454,
- /* 1050 */ 381, 886, 886, 888, 889, 19, 492, 1333, 372, 390,
- /* 1060 */ 39, 39, 832, 48, 48, 49, 49, 944, 239, 239,
- /* 1070 */ 492, 390, 13, 481, 240, 240, 190, 492, 50, 50,
- /* 1080 */ 489, 474, 266, 239, 239, 481, 489, 210, 209, 208,
- /* 1090 */ 476, 894, 34, 34, 241, 489, 455, 92, 92, 35,
- /* 1100 */ 35, 485, 363, 894, 93, 492, 390, 494, 493, 92,
- /* 1110 */ 92, 886, 408, 382, 492, 944, 93, 492, 390, 494,
- /* 1120 */ 493, 1227, 1052, 886, 1348, 1004, 243, 36, 36, 492,
- /* 1130 */ 419, 340, 340, 339, 228, 337, 38, 38, 728, 51,
- /* 1140 */ 51, 492, 886, 886, 888, 889, 19, 261, 483, 749,
- /* 1150 */ 1178, 52, 52, 265, 886, 886, 888, 889, 19, 1004,
- /* 1160 */ 243, 264, 1177, 53, 53, 340, 340, 339, 228, 337,
- /* 1170 */ 492, 379, 728, 1349, 497, 1063, 303, 719, 720, 721,
- /* 1180 */ 262, 894, 123, 401, 492, 238, 184, 265, 22, 1143,
- /* 1190 */ 427, 492, 10, 10, 191, 264, 749, 887, 84, 492,
- /* 1200 */ 1339, 886, 140, 492, 1361, 142, 54, 54, 492, 364,
- /* 1210 */ 148, 768, 767, 114, 114, 492, 127, 277, 28, 492,
- /* 1220 */ 23, 55, 55, 239, 239, 40, 40, 956, 191, 956,
- /* 1230 */ 56, 56, 886, 886, 888, 489, 140, 57, 57, 142,
- /* 1240 */ 447, 41, 41, 280, 1317, 358, 84, 492, 1034, 195,
- /* 1250 */ 261, 483, 1014, 492, 878, 413, 376, 217, 217, 492,
- /* 1260 */ 775, 776, 225, 242, 311, 450, 306, 449, 212, 135,
- /* 1270 */ 135, 492, 1316, 395, 302, 136, 136, 415, 391, 358,
- /* 1280 */ 217, 64, 64, 492, 261, 483, 492, 218, 423, 760,
- /* 1290 */ 386, 385, 492, 42, 42, 492, 850, 851, 1041, 1014,
- /* 1300 */ 1015, 1016, 492, 1043, 492, 60, 60, 395, 115, 115,
- /* 1310 */ 492, 1042, 890, 287, 61, 61, 492, 116, 116, 492,
- /* 1320 */ 955, 492, 955, 1035, 117, 117, 113, 113, 492, 1174,
- /* 1330 */ 1111, 492, 134, 134, 492, 1044, 492, 1044, 133, 133,
- /* 1340 */ 492, 121, 121, 120, 120, 492, 286, 492, 479, 84,
- /* 1350 */ 118, 118, 291, 119, 119, 176, 63, 63, 65, 65,
- /* 1360 */ 890, 437, 62, 62, 213, 294, 296, 32, 32, 37,
- /* 1370 */ 37, 1035, 300, 298, 940, 84, 841, 213, 805, 217,
- /* 1380 */ 739, 96, 806, 125, 1126, 96, 1110, 305, 7, 314,
- /* 1390 */ 315, 1186, 1226, 1161, 1172, 258, 478, 1232, 432, 1091,
- /* 1400 */ 231, 1083, 1072, 1071, 1073, 1355, 174, 270, 189, 1158,
- /* 1410 */ 341, 317, 279, 319, 321, 178, 1219, 417, 284, 482,
- /* 1420 */ 182, 400, 334, 272, 323, 177, 1358, 1052, 1049, 220,
- /* 1430 */ 71, 150, 442, 308, 67, 365, 1289, 70, 1109, 1288,
- /* 1440 */ 411, 160, 82, 1216, 145, 403, 1294, 404, 25, 435,
- /* 1450 */ 197, 201, 348, 26, 424, 152, 76, 430, 232, 203,
- /* 1460 */ 155, 156, 157, 158, 1222, 1211, 164, 1305, 1208, 289,
- /* 1470 */ 169, 293, 204, 346, 410, 433, 1074, 349, 205, 1283,
- /* 1480 */ 451, 351, 1129, 1128, 1127, 378, 78, 1372, 1120, 352,
- /* 1490 */ 760, 1371, 1099, 380, 81, 307, 1098, 1097, 1119, 467,
- /* 1500 */ 1370, 458, 1169, 316, 461, 1170, 219, 318, 383, 1168,
- /* 1510 */ 6, 320, 327, 256, 1269, 1167, 88, 257, 259, 111,
- /* 1520 */ 1193, 322, 1192, 472, 83, 226, 1009, 1080, 470, 24,
- /* 1530 */ 495, 227, 230, 331, 1151, 332, 330, 333, 496, 229,
- /* 1540 */ 1069, 137, 1064, 1321, 1322, 1320, 124, 138, 254, 175,
- /* 1550 */ 263, 1319, 188, 244, 122, 954, 179, 952, 870, 151,
- /* 1560 */ 180, 139, 141, 193, 66, 153, 792, 278, 359, 196,
- /* 1570 */ 968, 159, 874, 143, 367, 72, 161, 369, 73, 74,
- /* 1580 */ 144, 971, 75, 198, 967, 199, 149, 132, 360, 14,
- /* 1590 */ 200, 288, 1046, 960, 217, 429, 166, 202, 27, 730,
- /* 1600 */ 165, 309, 434, 206, 301, 438, 167, 77, 15, 16,
- /* 1610 */ 758, 443, 304, 79, 255, 146, 893, 771, 892, 446,
- /* 1620 */ 920, 999, 80, 29, 457, 1000, 30, 460, 183, 235,
- /* 1630 */ 237, 170, 835, 216, 96, 935, 84, 921, 840, 17,
- /* 1640 */ 919, 923, 977, 924, 976, 18, 221, 222, 20, 31,
- /* 1650 */ 488, 891, 740, 95, 338, 21, 1005, 335, 1062, 802,
- /* 1660 */ 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 223, 1062,
- /* 1670 */ 1062, 1062, 1062, 1062, 224, 1363, 1062, 1362,
+ /* 0 */ 102, 99, 194, 102, 99, 194, 1127, 479, 1165, 509,
+ /* 10 */ 1144, 503, 503, 503, 240, 240, 371, 413, 1165, 1415,
+ /* 20 */ 1340, 1371, 339, 241, 1130, 340, 506, 1137, 869, 12,
+ /* 30 */ 12, 58, 58, 371, 413, 412, 870, 1340, 1342, 480,
+ /* 40 */ 86, 109, 110, 100, 1072, 1072, 943, 946, 936, 936,
+ /* 50 */ 107, 107, 108, 108, 108, 108, 1170, 1170, 109, 110,
+ /* 60 */ 100, 1072, 1072, 943, 946, 936, 936, 107, 107, 108,
+ /* 70 */ 108, 108, 108, 246, 246, 102, 99, 194, 102, 99,
+ /* 80 */ 194, 113, 102, 99, 194, 506, 111, 1168, 1168, 222,
+ /* 90 */ 191, 343, 106, 106, 106, 106, 105, 105, 104, 104,
+ /* 100 */ 104, 103, 406, 371, 434, 413, 406, 1048, 1340, 106,
+ /* 110 */ 106, 106, 106, 105, 105, 104, 104, 104, 103, 406,
+ /* 120 */ 108, 108, 108, 108, 101, 425, 299, 124, 109, 110,
+ /* 130 */ 100, 1072, 1072, 943, 946, 936, 936, 107, 107, 108,
+ /* 140 */ 108, 108, 108, 106, 106, 106, 106, 105, 105, 104,
+ /* 150 */ 104, 104, 103, 406, 68, 1048, 1049, 1050, 368, 367,
+ /* 160 */ 106, 106, 106, 106, 105, 105, 104, 104, 104, 103,
+ /* 170 */ 406, 371, 243, 275, 500, 854, 69, 254, 375, 106,
+ /* 180 */ 106, 106, 106, 105, 105, 104, 104, 104, 103, 406,
+ /* 190 */ 71, 1048, 434, 371, 1048, 436, 109, 110, 100, 1072,
+ /* 200 */ 1072, 943, 946, 936, 936, 107, 107, 108, 108, 108,
+ /* 210 */ 108, 105, 105, 104, 104, 104, 103, 406, 109, 110,
+ /* 220 */ 100, 1072, 1072, 943, 946, 936, 936, 107, 107, 108,
+ /* 230 */ 108, 108, 108, 104, 104, 104, 103, 406, 509, 1048,
+ /* 240 */ 1049, 1050, 1048, 1049, 1050, 753, 1129, 106, 106, 106,
+ /* 250 */ 106, 105, 105, 104, 104, 104, 103, 406, 445, 193,
+ /* 260 */ 43, 43, 442, 1048, 371, 259, 856, 282, 313, 106,
+ /* 270 */ 106, 106, 106, 105, 105, 104, 104, 104, 103, 406,
+ /* 280 */ 108, 108, 108, 108, 854, 933, 933, 944, 947, 109,
+ /* 290 */ 110, 100, 1072, 1072, 943, 946, 936, 936, 107, 107,
+ /* 300 */ 108, 108, 108, 108, 835, 215, 124, 423, 464, 461,
+ /* 310 */ 460, 1048, 1049, 1050, 356, 1092, 180, 434, 459, 165,
+ /* 320 */ 106, 106, 106, 106, 105, 105, 104, 104, 104, 103,
+ /* 330 */ 406, 103, 406, 371, 414, 1048, 440, 465, 430, 966,
+ /* 340 */ 106, 106, 106, 106, 105, 105, 104, 104, 104, 103,
+ /* 350 */ 406, 937, 275, 500, 1335, 771, 1269, 1048, 109, 110,
+ /* 360 */ 100, 1072, 1072, 943, 946, 936, 936, 107, 107, 108,
+ /* 370 */ 108, 108, 108, 182, 403, 402, 509, 1327, 509, 404,
+ /* 380 */ 404, 404, 1076, 1048, 1049, 1050, 1093, 1078, 923, 492,
+ /* 390 */ 262, 329, 172, 252, 905, 1077, 1450, 357, 59, 59,
+ /* 400 */ 59, 59, 124, 771, 916, 1048, 1049, 1050, 915, 106,
+ /* 410 */ 106, 106, 106, 105, 105, 104, 104, 104, 103, 406,
+ /* 420 */ 1079, 175, 1079, 246, 246, 386, 371, 246, 246, 350,
+ /* 430 */ 775, 1421, 258, 364, 486, 506, 491, 297, 134, 506,
+ /* 440 */ 915, 915, 917, 371, 509, 493, 451, 768, 275, 500,
+ /* 450 */ 508, 109, 110, 100, 1072, 1072, 943, 946, 936, 936,
+ /* 460 */ 107, 107, 108, 108, 108, 108, 44, 44, 109, 110,
+ /* 470 */ 100, 1072, 1072, 943, 946, 936, 936, 107, 107, 108,
+ /* 480 */ 108, 108, 108, 1007, 1182, 403, 402, 986, 175, 456,
+ /* 490 */ 379, 991, 991, 448, 1048, 506, 275, 500, 1008, 1393,
+ /* 500 */ 359, 13, 106, 106, 106, 106, 105, 105, 104, 104,
+ /* 510 */ 104, 103, 406, 507, 1009, 825, 825, 219, 175, 106,
+ /* 520 */ 106, 106, 106, 105, 105, 104, 104, 104, 103, 406,
+ /* 530 */ 370, 1079, 381, 1079, 1269, 811, 371, 509, 188, 381,
+ /* 540 */ 924, 382, 1048, 1049, 1050, 215, 409, 812, 464, 461,
+ /* 550 */ 460, 338, 267, 371, 267, 440, 327, 910, 459, 59,
+ /* 560 */ 59, 109, 110, 100, 1072, 1072, 943, 946, 936, 936,
+ /* 570 */ 107, 107, 108, 108, 108, 108, 434, 376, 109, 110,
+ /* 580 */ 100, 1072, 1072, 943, 946, 936, 936, 107, 107, 108,
+ /* 590 */ 108, 108, 108, 316, 390, 491, 425, 299, 1026, 1448,
+ /* 600 */ 284, 509, 1448, 387, 481, 509, 361, 255, 263, 741,
+ /* 610 */ 742, 743, 106, 106, 106, 106, 105, 105, 104, 104,
+ /* 620 */ 104, 103, 406, 59, 59, 509, 166, 11, 11, 106,
+ /* 630 */ 106, 106, 106, 105, 105, 104, 104, 104, 103, 406,
+ /* 640 */ 246, 246, 246, 246, 509, 8, 371, 9, 9, 264,
+ /* 650 */ 1148, 296, 506, 83, 506, 329, 1119, 377, 440, 491,
+ /* 660 */ 329, 485, 384, 371, 1048, 381, 32, 32, 490, 432,
+ /* 670 */ 1024, 109, 110, 100, 1072, 1072, 943, 946, 936, 936,
+ /* 680 */ 107, 107, 108, 108, 108, 108, 509, 192, 109, 110,
+ /* 690 */ 100, 1072, 1072, 943, 946, 936, 936, 107, 107, 108,
+ /* 700 */ 108, 108, 108, 1007, 342, 395, 311, 136, 45, 45,
+ /* 710 */ 317, 1377, 1048, 1049, 1050, 509, 174, 1048, 1008, 502,
+ /* 720 */ 377, 424, 106, 106, 106, 106, 105, 105, 104, 104,
+ /* 730 */ 104, 103, 406, 257, 1009, 356, 1025, 59, 59, 106,
+ /* 740 */ 106, 106, 106, 105, 105, 104, 104, 104, 103, 406,
+ /* 750 */ 1395, 1038, 250, 509, 265, 497, 1048, 354, 354, 353,
+ /* 760 */ 235, 351, 1379, 1394, 750, 1048, 1049, 1050, 1393, 923,
+ /* 770 */ 306, 126, 309, 491, 467, 9, 9, 410, 88, 280,
+ /* 780 */ 1026, 1449, 473, 1375, 1449, 916, 5, 279, 225, 915,
+ /* 790 */ 389, 392, 855, 509, 4, 91, 509, 232, 249, 325,
+ /* 800 */ 470, 320, 469, 220, 1048, 1049, 1050, 1093, 1420, 316,
+ /* 810 */ 8, 800, 371, 509, 219, 9, 9, 176, 9, 9,
+ /* 820 */ 199, 915, 915, 917, 1069, 218, 217, 216, 145, 371,
+ /* 830 */ 391, 122, 1048, 266, 281, 59, 59, 109, 110, 100,
+ /* 840 */ 1072, 1072, 943, 946, 936, 936, 107, 107, 108, 108,
+ /* 850 */ 108, 108, 1024, 509, 109, 110, 100, 1072, 1072, 943,
+ /* 860 */ 946, 936, 936, 107, 107, 108, 108, 108, 108, 275,
+ /* 870 */ 500, 401, 372, 1069, 376, 33, 33, 275, 500, 451,
+ /* 880 */ 1048, 1049, 1050, 1176, 451, 1116, 441, 1048, 106, 106,
+ /* 890 */ 106, 106, 105, 105, 104, 104, 104, 103, 406, 476,
+ /* 900 */ 2, 411, 129, 509, 327, 106, 106, 106, 106, 105,
+ /* 910 */ 105, 104, 104, 104, 103, 406, 1269, 246, 246, 246,
+ /* 920 */ 246, 509, 371, 1370, 869, 9, 9, 1147, 1334, 506,
+ /* 930 */ 22, 506, 870, 246, 246, 1048, 1049, 1050, 1048, 371,
+ /* 940 */ 488, 1213, 398, 59, 59, 506, 494, 109, 98, 100,
+ /* 950 */ 1072, 1072, 943, 946, 936, 936, 107, 107, 108, 108,
+ /* 960 */ 108, 108, 23, 854, 472, 110, 100, 1072, 1072, 943,
+ /* 970 */ 946, 936, 936, 107, 107, 108, 108, 108, 108, 405,
+ /* 980 */ 246, 246, 329, 905, 289, 388, 1048, 1049, 1050, 1212,
+ /* 990 */ 830, 509, 506, 329, 451, 829, 419, 451, 106, 106,
+ /* 1000 */ 106, 106, 105, 105, 104, 104, 104, 103, 406, 1382,
+ /* 1010 */ 791, 509, 188, 46, 46, 106, 106, 106, 106, 105,
+ /* 1020 */ 105, 104, 104, 104, 103, 406, 297, 420, 285, 133,
+ /* 1030 */ 415, 509, 371, 47, 47, 509, 1269, 417, 1177, 225,
+ /* 1040 */ 135, 1173, 468, 247, 247, 988, 369, 193, 286, 988,
+ /* 1050 */ 288, 509, 792, 48, 48, 506, 451, 49, 49, 100,
+ /* 1060 */ 1072, 1072, 943, 946, 936, 936, 107, 107, 108, 108,
+ /* 1070 */ 108, 108, 854, 50, 50, 1069, 509, 1021, 95, 501,
+ /* 1080 */ 358, 3, 446, 1200, 509, 1096, 1, 1, 514, 1098,
+ /* 1090 */ 1393, 1269, 1052, 85, 276, 504, 127, 393, 34, 34,
+ /* 1100 */ 304, 1393, 290, 1178, 509, 447, 35, 35, 106, 106,
+ /* 1110 */ 106, 106, 105, 105, 104, 104, 104, 103, 406, 407,
+ /* 1120 */ 183, 287, 378, 152, 1069, 1068, 36, 36, 482, 95,
+ /* 1130 */ 501, 509, 3, 498, 509, 418, 438, 246, 246, 509,
+ /* 1140 */ 92, 1052, 90, 124, 369, 474, 504, 95, 501, 506,
+ /* 1150 */ 3, 509, 923, 38, 38, 1146, 39, 39, 93, 93,
+ /* 1160 */ 399, 51, 51, 203, 504, 94, 427, 407, 511, 510,
+ /* 1170 */ 407, 200, 915, 52, 52, 369, 509, 431, 509, 246,
+ /* 1180 */ 246, 245, 191, 778, 498, 782, 369, 274, 407, 275,
+ /* 1190 */ 500, 506, 475, 198, 408, 132, 369, 28, 53, 53,
+ /* 1200 */ 10, 10, 498, 923, 915, 915, 917, 918, 19, 93,
+ /* 1210 */ 93, 834, 72, 179, 790, 789, 94, 483, 407, 511,
+ /* 1220 */ 510, 923, 985, 915, 985, 439, 509, 93, 93, 509,
+ /* 1230 */ 830, 509, 778, 183, 94, 829, 407, 511, 510, 1087,
+ /* 1240 */ 509, 915, 509, 426, 87, 501, 509, 3, 54, 54,
+ /* 1250 */ 251, 115, 115, 55, 55, 915, 915, 917, 918, 19,
+ /* 1260 */ 131, 504, 40, 40, 56, 56, 294, 509, 57, 57,
+ /* 1270 */ 797, 798, 973, 915, 915, 917, 918, 19, 428, 295,
+ /* 1280 */ 202, 509, 85, 278, 509, 407, 509, 1038, 250, 41,
+ /* 1290 */ 41, 509, 324, 354, 354, 353, 235, 351, 763, 498,
+ /* 1300 */ 750, 260, 323, 140, 140, 509, 141, 141, 64, 64,
+ /* 1310 */ 478, 1359, 919, 42, 42, 280, 907, 509, 923, 224,
+ /* 1320 */ 984, 973, 984, 279, 93, 93, 1358, 60, 60, 509,
+ /* 1330 */ 248, 94, 509, 407, 511, 510, 509, 272, 915, 116,
+ /* 1340 */ 116, 1396, 514, 1098, 872, 873, 433, 763, 276, 224,
+ /* 1350 */ 127, 61, 61, 452, 117, 117, 199, 1178, 118, 118,
+ /* 1360 */ 435, 919, 509, 224, 145, 827, 509, 122, 97, 443,
+ /* 1370 */ 915, 915, 917, 918, 19, 301, 509, 300, 509, 1209,
+ /* 1380 */ 85, 1030, 509, 457, 114, 114, 221, 509, 139, 139,
+ /* 1390 */ 305, 246, 246, 308, 314, 310, 509, 85, 138, 138,
+ /* 1400 */ 123, 123, 312, 506, 121, 121, 509, 1161, 372, 119,
+ /* 1410 */ 119, 1145, 509, 275, 500, 319, 509, 203, 120, 120,
+ /* 1420 */ 509, 969, 509, 328, 221, 1221, 1268, 863, 63, 63,
+ /* 1430 */ 224, 1196, 238, 761, 65, 65, 130, 411, 62, 62,
+ /* 1440 */ 1207, 1408, 31, 31, 37, 37, 495, 1274, 408, 828,
+ /* 1450 */ 496, 1126, 97, 1118, 1107, 1106, 1108, 1402, 177, 1193,
+ /* 1460 */ 331, 333, 7, 335, 185, 355, 197, 1255, 253, 1250,
+ /* 1470 */ 1243, 292, 189, 416, 437, 462, 293, 1405, 256, 261,
+ /* 1480 */ 1260, 298, 184, 1144, 322, 1331, 1330, 154, 1087, 195,
+ /* 1490 */ 348, 1084, 337, 380, 227, 1259, 71, 362, 181, 163,
+ /* 1500 */ 150, 421, 156, 422, 455, 205, 83, 158, 159, 160,
+ /* 1510 */ 360, 161, 1264, 499, 444, 167, 209, 77, 450, 1256,
+ /* 1520 */ 25, 429, 239, 171, 211, 1262, 307, 1261, 1336, 363,
+ /* 1530 */ 1325, 453, 67, 70, 212, 365, 1109, 213, 471, 394,
+ /* 1540 */ 1164, 79, 1155, 1419, 1163, 26, 782, 1162, 1134, 396,
+ /* 1550 */ 321, 1418, 366, 1133, 397, 484, 1132, 1204, 82, 1417,
+ /* 1560 */ 330, 226, 332, 1154, 326, 400, 1205, 270, 271, 6,
+ /* 1570 */ 1347, 1203, 303, 1311, 341, 89, 334, 273, 1202, 336,
+ /* 1580 */ 112, 489, 84, 487, 233, 1115, 24, 1043, 512, 477,
+ /* 1590 */ 234, 237, 236, 513, 1104, 1099, 373, 345, 1186, 344,
+ /* 1600 */ 374, 346, 347, 186, 1363, 153, 142, 1364, 1228, 1227,
+ /* 1610 */ 128, 1362, 178, 143, 268, 144, 1361, 277, 187, 196,
+ /* 1620 */ 66, 125, 983, 981, 283, 155, 146, 1068, 157, 814,
+ /* 1630 */ 201, 204, 291, 997, 162, 147, 148, 383, 73, 385,
+ /* 1640 */ 164, 74, 75, 76, 149, 1000, 206, 996, 207, 137,
+ /* 1650 */ 14, 208, 302, 989, 168, 1081, 224, 210, 449, 169,
+ /* 1660 */ 27, 752, 323, 214, 454, 458, 463, 780, 170, 78,
+ /* 1670 */ 15, 151, 315, 16, 318, 466, 80, 29, 269, 922,
+ /* 1680 */ 793, 921, 949, 81, 1032, 242, 190, 1031, 244, 862,
+ /* 1690 */ 173, 857, 97, 85, 223, 964, 950, 17, 18, 948,
+ /* 1700 */ 952, 1006, 953, 1005, 229, 228, 20, 30, 352, 920,
+ /* 1710 */ 762, 96, 21, 230, 505, 349, 1039, 1097, 824, 1097,
+ /* 1720 */ 1097, 1097, 1097, 1097, 1097, 231, 1410, 1409,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 251, 252, 253, 251, 252, 253, 196, 204, 175, 206,
- /* 10 */ 175, 175, 175, 197, 204, 175, 16, 214, 183, 278,
- /* 20 */ 279, 272, 187, 187, 200, 194, 20, 200, 28, 23,
- /* 30 */ 197, 198, 175, 16, 197, 198, 36, 197, 198, 186,
+ /* 0 */ 255, 256, 257, 255, 256, 257, 199, 177, 206, 177,
+ /* 10 */ 208, 193, 194, 195, 222, 223, 16, 177, 216, 198,
+ /* 20 */ 177, 276, 202, 196, 199, 202, 234, 206, 28, 199,
+ /* 30 */ 200, 199, 200, 16, 194, 195, 36, 194, 195, 188,
/* 40 */ 23, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- /* 50 */ 50, 51, 52, 53, 54, 55, 19, 20, 41, 42,
+ /* 50 */ 50, 51, 52, 53, 54, 55, 218, 219, 41, 42,
/* 60 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 70 */ 53, 54, 55, 220, 221, 251, 252, 253, 251, 252,
- /* 80 */ 253, 8, 251, 252, 253, 232, 69, 19, 255, 236,
- /* 90 */ 237, 91, 92, 93, 94, 95, 96, 97, 98, 99,
- /* 100 */ 100, 101, 101, 16, 52, 53, 54, 55, 91, 92,
- /* 110 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 52,
- /* 120 */ 53, 54, 55, 56, 81, 57, 175, 90, 41, 42,
+ /* 70 */ 53, 54, 55, 222, 223, 255, 256, 257, 255, 256,
+ /* 80 */ 257, 19, 255, 256, 257, 234, 69, 218, 219, 238,
+ /* 90 */ 239, 259, 92, 93, 94, 95, 96, 97, 98, 99,
+ /* 100 */ 100, 101, 102, 16, 177, 265, 102, 57, 265, 92,
+ /* 110 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 120 */ 52, 53, 54, 55, 56, 117, 118, 81, 41, 42,
/* 130 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 140 */ 53, 54, 55, 91, 92, 93, 94, 95, 96, 97,
- /* 150 */ 98, 99, 100, 101, 67, 191, 192, 193, 91, 92,
- /* 160 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 126,
- /* 170 */ 127, 16, 104, 105, 106, 145, 21, 147, 91, 92,
- /* 180 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 116,
- /* 190 */ 117, 19, 20, 16, 243, 23, 41, 42, 43, 44,
+ /* 140 */ 53, 54, 55, 92, 93, 94, 95, 96, 97, 98,
+ /* 150 */ 99, 100, 101, 102, 67, 105, 106, 107, 96, 97,
+ /* 160 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ /* 170 */ 102, 16, 20, 127, 128, 23, 21, 250, 182, 92,
+ /* 180 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 190 */ 140, 57, 177, 16, 57, 177, 41, 42, 43, 44,
/* 200 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 210 */ 55, 95, 96, 97, 98, 99, 100, 101, 41, 42,
+ /* 210 */ 55, 96, 97, 98, 99, 100, 101, 102, 41, 42,
/* 220 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 230 */ 53, 54, 55, 91, 92, 93, 94, 95, 96, 97,
- /* 240 */ 98, 99, 100, 101, 116, 117, 91, 92, 93, 94,
- /* 250 */ 95, 96, 97, 98, 99, 100, 101, 97, 98, 99,
- /* 260 */ 100, 101, 90, 16, 175, 100, 101, 20, 91, 92,
- /* 270 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 73,
- /* 280 */ 16, 192, 193, 122, 20, 124, 125, 81, 41, 42,
- /* 290 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 300 */ 53, 54, 55, 19, 20, 41, 42, 43, 44, 45,
- /* 310 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 320 */ 109, 115, 107, 146, 13, 110, 111, 112, 175, 175,
- /* 330 */ 119, 57, 126, 127, 197, 120, 19, 175, 91, 92,
- /* 340 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 187,
- /* 350 */ 261, 197, 198, 19, 197, 91, 92, 93, 94, 95,
- /* 360 */ 96, 97, 98, 99, 100, 101, 175, 44, 45, 46,
- /* 370 */ 47, 209, 16, 211, 90, 222, 20, 175, 104, 105,
- /* 380 */ 106, 107, 216, 217, 110, 111, 112, 233, 77, 16,
- /* 390 */ 79, 57, 175, 20, 120, 211, 242, 41, 42, 43,
- /* 400 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 410 */ 54, 55, 95, 96, 41, 42, 43, 44, 45, 46,
- /* 420 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 175,
- /* 430 */ 248, 9, 109, 81, 243, 16, 216, 217, 104, 105,
- /* 440 */ 106, 186, 175, 57, 175, 243, 24, 91, 92, 93,
- /* 450 */ 94, 95, 96, 97, 98, 99, 100, 101, 72, 18,
- /* 460 */ 108, 238, 40, 44, 91, 92, 93, 94, 95, 96,
- /* 470 */ 97, 98, 99, 100, 101, 220, 221, 260, 126, 127,
- /* 480 */ 194, 16, 175, 61, 225, 20, 219, 232, 219, 23,
- /* 490 */ 104, 105, 106, 234, 175, 73, 57, 23, 16, 57,
- /* 500 */ 175, 247, 20, 248, 197, 198, 41, 42, 43, 44,
- /* 510 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 520 */ 55, 80, 103, 41, 42, 43, 44, 45, 46, 47,
- /* 530 */ 48, 49, 50, 51, 52, 53, 54, 55, 119, 97,
- /* 540 */ 233, 222, 13, 104, 105, 106, 104, 105, 106, 242,
- /* 550 */ 186, 26, 111, 57, 268, 30, 91, 92, 93, 94,
- /* 560 */ 95, 96, 97, 98, 99, 100, 101, 19, 72, 175,
- /* 570 */ 131, 175, 175, 91, 92, 93, 94, 95, 96, 97,
- /* 580 */ 98, 99, 100, 101, 220, 221, 192, 193, 63, 148,
- /* 590 */ 16, 175, 126, 127, 197, 198, 232, 191, 192, 193,
- /* 600 */ 104, 105, 106, 95, 96, 57, 77, 16, 79, 212,
- /* 610 */ 175, 137, 21, 197, 198, 41, 42, 43, 44, 45,
- /* 620 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 630 */ 180, 23, 41, 42, 43, 44, 45, 46, 47, 48,
- /* 640 */ 49, 50, 51, 52, 53, 54, 55, 175, 140, 233,
- /* 650 */ 142, 44, 104, 105, 106, 261, 57, 222, 242, 186,
- /* 660 */ 175, 186, 175, 186, 175, 91, 92, 93, 94, 95,
- /* 670 */ 96, 97, 98, 99, 100, 101, 123, 148, 175, 175,
- /* 680 */ 175, 128, 91, 92, 93, 94, 95, 96, 97, 98,
- /* 690 */ 99, 100, 101, 220, 221, 220, 221, 220, 221, 16,
- /* 700 */ 197, 198, 197, 198, 105, 232, 219, 232, 258, 232,
- /* 710 */ 103, 57, 262, 175, 106, 212, 16, 212, 175, 73,
- /* 720 */ 146, 175, 186, 57, 41, 42, 43, 44, 45, 46,
- /* 730 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 131,
- /* 740 */ 175, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- /* 750 */ 50, 51, 52, 53, 54, 55, 220, 221, 104, 105,
- /* 760 */ 106, 115, 116, 117, 19, 219, 207, 57, 232, 175,
- /* 770 */ 104, 105, 106, 269, 91, 92, 93, 94, 95, 96,
- /* 780 */ 97, 98, 99, 100, 101, 131, 32, 186, 175, 175,
- /* 790 */ 247, 91, 92, 93, 94, 95, 96, 97, 98, 99,
- /* 800 */ 100, 101, 57, 175, 138, 220, 221, 269, 16, 175,
- /* 810 */ 175, 197, 198, 219, 104, 105, 106, 232, 64, 273,
- /* 820 */ 20, 220, 221, 23, 175, 16, 212, 21, 74, 189,
- /* 830 */ 190, 197, 198, 232, 42, 43, 44, 45, 46, 47,
- /* 840 */ 48, 49, 50, 51, 52, 53, 54, 55, 175, 104,
- /* 850 */ 105, 106, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 860 */ 51, 52, 53, 54, 55, 19, 20, 233, 219, 23,
- /* 870 */ 197, 198, 118, 175, 16, 247, 175, 16, 17, 244,
- /* 880 */ 19, 175, 269, 91, 92, 93, 94, 95, 96, 97,
- /* 890 */ 98, 99, 100, 101, 33, 197, 198, 207, 197, 198,
- /* 900 */ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
- /* 910 */ 101, 175, 186, 212, 175, 23, 194, 175, 57, 213,
- /* 920 */ 168, 169, 170, 171, 172, 89, 175, 16, 17, 177,
- /* 930 */ 19, 179, 71, 197, 198, 129, 90, 175, 186, 197,
- /* 940 */ 198, 105, 81, 19, 33, 109, 220, 221, 197, 198,
- /* 950 */ 89, 20, 175, 19, 23, 21, 95, 96, 232, 197,
- /* 960 */ 198, 222, 104, 102, 117, 104, 105, 106, 57, 233,
- /* 970 */ 109, 175, 220, 221, 175, 233, 140, 141, 142, 175,
- /* 980 */ 9, 57, 71, 97, 232, 263, 139, 126, 127, 175,
- /* 990 */ 268, 57, 57, 197, 198, 24, 197, 198, 246, 221,
- /* 1000 */ 89, 140, 141, 142, 143, 144, 95, 96, 97, 123,
- /* 1010 */ 232, 40, 175, 102, 128, 104, 105, 106, 16, 17,
- /* 1020 */ 109, 19, 130, 175, 115, 116, 117, 275, 28, 105,
- /* 1030 */ 16, 17, 61, 19, 186, 33, 36, 106, 175, 105,
- /* 1040 */ 105, 175, 16, 175, 175, 197, 198, 33, 244, 186,
- /* 1050 */ 213, 140, 141, 142, 143, 144, 175, 175, 244, 57,
- /* 1060 */ 197, 198, 131, 197, 198, 197, 198, 57, 220, 221,
- /* 1070 */ 175, 57, 19, 71, 220, 221, 12, 175, 197, 198,
- /* 1080 */ 232, 233, 175, 220, 221, 71, 232, 115, 116, 117,
- /* 1090 */ 242, 89, 197, 198, 19, 232, 233, 95, 96, 197,
- /* 1100 */ 198, 189, 190, 89, 102, 175, 104, 105, 106, 95,
- /* 1110 */ 96, 109, 59, 244, 175, 105, 102, 175, 104, 105,
- /* 1120 */ 106, 175, 58, 109, 0, 1, 2, 197, 198, 175,
- /* 1130 */ 104, 7, 8, 9, 10, 11, 197, 198, 14, 197,
- /* 1140 */ 198, 175, 140, 141, 142, 143, 144, 126, 127, 57,
- /* 1150 */ 175, 197, 198, 29, 140, 141, 142, 143, 144, 1,
- /* 1160 */ 2, 37, 175, 197, 198, 7, 8, 9, 10, 11,
- /* 1170 */ 175, 16, 14, 170, 171, 172, 21, 4, 5, 6,
- /* 1180 */ 177, 89, 179, 175, 175, 236, 237, 29, 19, 186,
- /* 1190 */ 244, 175, 197, 198, 70, 37, 104, 105, 23, 175,
- /* 1200 */ 175, 109, 78, 175, 129, 81, 197, 198, 175, 276,
- /* 1210 */ 277, 108, 109, 197, 198, 175, 19, 175, 21, 175,
- /* 1220 */ 51, 197, 198, 220, 221, 197, 198, 140, 70, 142,
- /* 1230 */ 197, 198, 140, 141, 142, 232, 78, 197, 198, 81,
- /* 1240 */ 85, 197, 198, 20, 175, 121, 23, 175, 23, 246,
- /* 1250 */ 126, 127, 57, 175, 20, 20, 101, 23, 23, 175,
- /* 1260 */ 4, 5, 107, 108, 109, 110, 111, 112, 113, 197,
- /* 1270 */ 198, 175, 175, 149, 119, 197, 198, 20, 275, 121,
- /* 1280 */ 23, 197, 198, 175, 126, 127, 175, 21, 175, 114,
- /* 1290 */ 95, 96, 175, 197, 198, 175, 83, 84, 103, 104,
- /* 1300 */ 105, 106, 175, 108, 175, 197, 198, 149, 197, 198,
- /* 1310 */ 175, 116, 57, 175, 197, 198, 175, 197, 198, 175,
- /* 1320 */ 140, 175, 142, 57, 197, 198, 197, 198, 175, 175,
- /* 1330 */ 207, 175, 197, 198, 175, 140, 175, 142, 197, 198,
- /* 1340 */ 175, 197, 198, 197, 198, 175, 20, 175, 217, 23,
- /* 1350 */ 197, 198, 175, 197, 198, 130, 197, 198, 197, 198,
- /* 1360 */ 105, 20, 197, 198, 23, 175, 175, 197, 198, 197,
- /* 1370 */ 198, 105, 20, 175, 20, 23, 20, 23, 20, 23,
- /* 1380 */ 20, 23, 20, 23, 175, 23, 175, 175, 224, 175,
- /* 1390 */ 175, 175, 175, 175, 175, 235, 175, 175, 265, 175,
- /* 1400 */ 264, 175, 175, 175, 175, 175, 223, 226, 274, 235,
- /* 1410 */ 173, 235, 270, 235, 235, 195, 227, 270, 226, 257,
- /* 1420 */ 210, 239, 226, 239, 239, 224, 178, 58, 35, 129,
- /* 1430 */ 138, 274, 201, 200, 271, 182, 200, 271, 206, 200,
- /* 1440 */ 103, 19, 137, 250, 41, 15, 260, 182, 249, 15,
- /* 1450 */ 181, 181, 250, 249, 182, 215, 145, 60, 182, 181,
- /* 1460 */ 218, 218, 218, 218, 215, 227, 215, 267, 227, 266,
- /* 1470 */ 19, 182, 181, 227, 227, 202, 182, 227, 181, 227,
- /* 1480 */ 103, 202, 199, 199, 199, 62, 19, 205, 208, 202,
- /* 1490 */ 114, 205, 199, 101, 103, 199, 201, 199, 208, 132,
- /* 1500 */ 199, 202, 241, 240, 202, 241, 182, 240, 82, 241,
- /* 1510 */ 19, 240, 182, 259, 254, 241, 145, 259, 256, 136,
- /* 1520 */ 245, 240, 245, 133, 135, 22, 10, 185, 134, 23,
- /* 1530 */ 184, 176, 3, 229, 231, 228, 230, 227, 174, 176,
- /* 1540 */ 174, 188, 174, 194, 194, 194, 203, 188, 203, 19,
- /* 1550 */ 150, 194, 12, 88, 13, 20, 195, 20, 127, 138,
- /* 1560 */ 195, 188, 118, 21, 194, 130, 17, 13, 280, 132,
- /* 1570 */ 1, 130, 139, 118, 59, 51, 138, 34, 51, 51,
- /* 1580 */ 118, 104, 51, 31, 1, 129, 277, 2, 280, 19,
- /* 1590 */ 103, 148, 75, 68, 23, 38, 103, 129, 21, 17,
- /* 1600 */ 68, 119, 16, 113, 20, 67, 19, 19, 19, 19,
- /* 1610 */ 57, 67, 21, 19, 67, 34, 20, 25, 20, 86,
- /* 1620 */ 20, 20, 23, 19, 21, 20, 19, 21, 129, 20,
- /* 1630 */ 20, 19, 131, 31, 23, 20, 23, 20, 104, 31,
- /* 1640 */ 20, 20, 20, 8, 20, 31, 23, 19, 19, 19,
- /* 1650 */ 23, 20, 20, 19, 12, 19, 1, 20, 281, 123,
- /* 1660 */ 281, 281, 281, 281, 281, 281, 281, 281, 129, 281,
- /* 1670 */ 281, 281, 281, 281, 129, 129, 281, 129, 281, 281,
- /* 1680 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1690 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1700 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1710 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1720 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1730 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1740 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1750 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1760 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1770 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1780 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1790 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1800 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1810 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1820 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1830 */ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- /* 1840 */ 281, 281, 281, 281, 281, 281,
+ /* 230 */ 53, 54, 55, 98, 99, 100, 101, 102, 177, 105,
+ /* 240 */ 106, 107, 105, 106, 107, 18, 199, 92, 93, 94,
+ /* 250 */ 95, 96, 97, 98, 99, 100, 101, 102, 262, 107,
+ /* 260 */ 199, 200, 266, 57, 16, 250, 132, 177, 20, 92,
+ /* 270 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 280 */ 52, 53, 54, 55, 132, 44, 45, 46, 47, 41,
+ /* 290 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ /* 300 */ 52, 53, 54, 55, 98, 108, 81, 80, 111, 112,
+ /* 310 */ 113, 105, 106, 107, 19, 20, 139, 177, 121, 19,
+ /* 320 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ /* 330 */ 102, 101, 102, 16, 109, 57, 177, 20, 104, 112,
+ /* 340 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ /* 350 */ 102, 110, 127, 128, 264, 57, 177, 57, 41, 42,
+ /* 360 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 370 */ 53, 54, 55, 139, 96, 97, 177, 150, 177, 193,
+ /* 380 */ 194, 195, 104, 105, 106, 107, 91, 109, 90, 188,
+ /* 390 */ 250, 177, 23, 188, 73, 117, 282, 283, 199, 200,
+ /* 400 */ 199, 200, 81, 105, 106, 105, 106, 107, 110, 92,
+ /* 410 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 420 */ 142, 177, 144, 222, 223, 246, 16, 222, 223, 185,
+ /* 430 */ 20, 213, 273, 189, 235, 234, 235, 116, 224, 234,
+ /* 440 */ 142, 143, 144, 16, 177, 244, 177, 20, 127, 128,
+ /* 450 */ 177, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ /* 460 */ 50, 51, 52, 53, 54, 55, 199, 200, 41, 42,
+ /* 470 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 480 */ 53, 54, 55, 9, 223, 96, 97, 8, 177, 16,
+ /* 490 */ 221, 116, 117, 118, 57, 234, 127, 128, 24, 285,
+ /* 500 */ 189, 19, 92, 93, 94, 95, 96, 97, 98, 99,
+ /* 510 */ 100, 101, 102, 123, 40, 125, 126, 44, 177, 92,
+ /* 520 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 530 */ 189, 142, 177, 144, 177, 61, 16, 177, 23, 177,
+ /* 540 */ 20, 59, 105, 106, 107, 108, 277, 73, 111, 112,
+ /* 550 */ 113, 177, 211, 16, 213, 177, 177, 20, 121, 199,
+ /* 560 */ 200, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ /* 570 */ 50, 51, 52, 53, 54, 55, 177, 104, 41, 42,
+ /* 580 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 590 */ 53, 54, 55, 120, 215, 235, 117, 118, 19, 20,
+ /* 600 */ 245, 177, 23, 246, 244, 177, 188, 245, 188, 4,
+ /* 610 */ 5, 6, 92, 93, 94, 95, 96, 97, 98, 99,
+ /* 620 */ 100, 101, 102, 199, 200, 177, 19, 199, 200, 92,
+ /* 630 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 640 */ 222, 223, 222, 223, 177, 196, 16, 199, 200, 250,
+ /* 650 */ 209, 273, 234, 138, 234, 177, 191, 192, 177, 235,
+ /* 660 */ 177, 177, 214, 16, 57, 177, 199, 200, 244, 251,
+ /* 670 */ 91, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ /* 680 */ 50, 51, 52, 53, 54, 55, 177, 177, 41, 42,
+ /* 690 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 700 */ 53, 54, 55, 9, 177, 16, 13, 224, 199, 200,
+ /* 710 */ 21, 177, 105, 106, 107, 177, 267, 57, 24, 191,
+ /* 720 */ 192, 272, 92, 93, 94, 95, 96, 97, 98, 99,
+ /* 730 */ 100, 101, 102, 245, 40, 19, 20, 199, 200, 92,
+ /* 740 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 750 */ 0, 1, 2, 177, 273, 61, 57, 7, 8, 9,
+ /* 760 */ 10, 11, 177, 285, 14, 105, 106, 107, 285, 90,
+ /* 770 */ 77, 72, 79, 235, 85, 199, 200, 177, 148, 29,
+ /* 780 */ 19, 20, 244, 177, 23, 106, 19, 37, 21, 110,
+ /* 790 */ 214, 102, 132, 177, 19, 148, 177, 108, 109, 110,
+ /* 800 */ 111, 112, 113, 114, 105, 106, 107, 91, 20, 120,
+ /* 810 */ 196, 23, 16, 177, 44, 199, 200, 21, 199, 200,
+ /* 820 */ 70, 142, 143, 144, 57, 116, 117, 118, 78, 16,
+ /* 830 */ 214, 81, 57, 214, 177, 199, 200, 41, 42, 43,
+ /* 840 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 850 */ 54, 55, 91, 177, 41, 42, 43, 44, 45, 46,
+ /* 860 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 127,
+ /* 870 */ 128, 235, 122, 106, 104, 199, 200, 127, 128, 177,
+ /* 880 */ 105, 106, 107, 188, 177, 188, 272, 57, 92, 93,
+ /* 890 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 188,
+ /* 900 */ 19, 151, 72, 177, 177, 92, 93, 94, 95, 96,
+ /* 910 */ 97, 98, 99, 100, 101, 102, 177, 222, 223, 222,
+ /* 920 */ 223, 177, 16, 221, 28, 199, 200, 209, 221, 234,
+ /* 930 */ 19, 234, 36, 222, 223, 105, 106, 107, 57, 16,
+ /* 940 */ 214, 177, 215, 199, 200, 234, 188, 41, 42, 43,
+ /* 950 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 960 */ 54, 55, 51, 23, 98, 42, 43, 44, 45, 46,
+ /* 970 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 235,
+ /* 980 */ 222, 223, 177, 73, 13, 246, 105, 106, 107, 177,
+ /* 990 */ 124, 177, 234, 177, 177, 129, 177, 177, 92, 93,
+ /* 1000 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 177,
+ /* 1010 */ 32, 177, 23, 199, 200, 92, 93, 94, 95, 96,
+ /* 1020 */ 97, 98, 99, 100, 101, 102, 116, 117, 118, 224,
+ /* 1030 */ 251, 177, 16, 199, 200, 177, 177, 227, 221, 21,
+ /* 1040 */ 224, 221, 64, 222, 223, 26, 236, 107, 77, 30,
+ /* 1050 */ 79, 177, 74, 199, 200, 234, 177, 199, 200, 43,
+ /* 1060 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 1070 */ 54, 55, 132, 199, 200, 57, 177, 20, 16, 17,
+ /* 1080 */ 23, 19, 63, 240, 177, 170, 171, 172, 173, 174,
+ /* 1090 */ 285, 177, 57, 23, 179, 33, 181, 119, 199, 200,
+ /* 1100 */ 221, 285, 177, 188, 177, 246, 199, 200, 92, 93,
+ /* 1110 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 57,
+ /* 1120 */ 131, 150, 280, 281, 106, 23, 199, 200, 16, 16,
+ /* 1130 */ 17, 177, 19, 71, 177, 227, 16, 222, 223, 177,
+ /* 1140 */ 147, 106, 149, 81, 236, 188, 33, 16, 17, 234,
+ /* 1150 */ 19, 177, 90, 199, 200, 209, 199, 200, 96, 97,
+ /* 1160 */ 246, 199, 200, 248, 33, 103, 227, 105, 106, 107,
+ /* 1170 */ 57, 21, 110, 199, 200, 236, 177, 227, 177, 222,
+ /* 1180 */ 223, 238, 239, 57, 71, 115, 236, 227, 57, 127,
+ /* 1190 */ 128, 234, 235, 12, 279, 19, 236, 21, 199, 200,
+ /* 1200 */ 199, 200, 71, 90, 142, 143, 144, 145, 146, 96,
+ /* 1210 */ 97, 98, 138, 139, 109, 110, 103, 105, 105, 106,
+ /* 1220 */ 107, 90, 142, 110, 144, 105, 177, 96, 97, 177,
+ /* 1230 */ 124, 177, 106, 131, 103, 129, 105, 106, 107, 58,
+ /* 1240 */ 177, 110, 177, 118, 16, 17, 177, 19, 199, 200,
+ /* 1250 */ 89, 199, 200, 199, 200, 142, 143, 144, 145, 146,
+ /* 1260 */ 19, 33, 199, 200, 199, 200, 141, 177, 199, 200,
+ /* 1270 */ 4, 5, 57, 142, 143, 144, 145, 146, 118, 20,
+ /* 1280 */ 130, 177, 23, 122, 177, 57, 177, 1, 2, 199,
+ /* 1290 */ 200, 177, 110, 7, 8, 9, 10, 11, 57, 71,
+ /* 1300 */ 14, 141, 120, 199, 200, 177, 199, 200, 199, 200,
+ /* 1310 */ 16, 177, 57, 199, 200, 29, 20, 177, 90, 23,
+ /* 1320 */ 142, 106, 144, 37, 96, 97, 177, 199, 200, 177,
+ /* 1330 */ 19, 103, 177, 105, 106, 107, 177, 237, 110, 199,
+ /* 1340 */ 200, 172, 173, 174, 83, 84, 20, 106, 179, 23,
+ /* 1350 */ 181, 199, 200, 269, 199, 200, 70, 188, 199, 200,
+ /* 1360 */ 20, 106, 177, 23, 78, 20, 177, 81, 23, 177,
+ /* 1370 */ 142, 143, 144, 145, 146, 177, 177, 20, 177, 177,
+ /* 1380 */ 23, 87, 177, 20, 199, 200, 23, 177, 199, 200,
+ /* 1390 */ 177, 222, 223, 177, 20, 177, 177, 23, 199, 200,
+ /* 1400 */ 199, 200, 177, 234, 199, 200, 177, 177, 122, 199,
+ /* 1410 */ 200, 177, 177, 127, 128, 177, 177, 248, 199, 200,
+ /* 1420 */ 177, 20, 177, 177, 23, 177, 177, 20, 199, 200,
+ /* 1430 */ 23, 177, 268, 20, 199, 200, 23, 151, 199, 200,
+ /* 1440 */ 177, 130, 199, 200, 199, 200, 177, 177, 279, 20,
+ /* 1450 */ 219, 177, 23, 177, 177, 177, 177, 177, 225, 237,
+ /* 1460 */ 237, 237, 226, 237, 197, 175, 278, 253, 228, 249,
+ /* 1470 */ 249, 274, 212, 241, 274, 203, 229, 180, 241, 229,
+ /* 1480 */ 253, 228, 226, 208, 202, 202, 202, 278, 58, 278,
+ /* 1490 */ 228, 35, 241, 184, 130, 253, 140, 253, 139, 19,
+ /* 1500 */ 41, 15, 217, 184, 15, 183, 138, 220, 220, 220,
+ /* 1510 */ 229, 220, 217, 261, 184, 217, 183, 147, 60, 254,
+ /* 1520 */ 252, 229, 184, 19, 183, 254, 184, 254, 264, 229,
+ /* 1530 */ 229, 204, 275, 275, 183, 204, 184, 183, 104, 62,
+ /* 1540 */ 201, 19, 210, 207, 201, 252, 115, 201, 201, 21,
+ /* 1550 */ 201, 207, 204, 203, 102, 133, 201, 243, 104, 201,
+ /* 1560 */ 242, 184, 242, 210, 204, 82, 243, 263, 263, 19,
+ /* 1570 */ 271, 243, 270, 258, 184, 147, 242, 260, 243, 242,
+ /* 1580 */ 137, 134, 136, 135, 22, 187, 23, 10, 186, 286,
+ /* 1590 */ 178, 3, 178, 176, 176, 176, 284, 231, 233, 232,
+ /* 1600 */ 284, 230, 229, 197, 196, 281, 190, 196, 247, 247,
+ /* 1610 */ 205, 196, 19, 190, 205, 190, 196, 152, 197, 12,
+ /* 1620 */ 196, 13, 20, 20, 128, 140, 119, 23, 131, 17,
+ /* 1630 */ 21, 133, 13, 1, 131, 119, 119, 59, 51, 34,
+ /* 1640 */ 140, 51, 51, 51, 119, 105, 31, 1, 130, 2,
+ /* 1650 */ 19, 104, 150, 68, 68, 75, 23, 130, 38, 104,
+ /* 1660 */ 21, 17, 120, 114, 16, 67, 67, 57, 19, 19,
+ /* 1670 */ 19, 34, 20, 19, 21, 86, 19, 19, 67, 20,
+ /* 1680 */ 25, 20, 20, 23, 20, 20, 130, 87, 20, 105,
+ /* 1690 */ 19, 132, 23, 23, 31, 20, 20, 31, 31, 20,
+ /* 1700 */ 20, 20, 8, 20, 19, 23, 19, 19, 12, 20,
+ /* 1710 */ 20, 19, 19, 130, 23, 20, 1, 287, 124, 287,
+ /* 1720 */ 287, 287, 287, 287, 287, 130, 130, 130, 287, 287,
+ /* 1730 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1740 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1750 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1760 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1770 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1780 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1790 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1800 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1810 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1820 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1830 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1840 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1850 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1860 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1870 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1880 */ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ /* 1890 */ 287, 287, 287, 287, 287, 287, 287, 287,
};
-#define YY_SHIFT_COUNT (497)
+#define YY_SHIFT_COUNT (514)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (1655)
+#define YY_SHIFT_MAX (1715)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 1158, 1124, 861, 861, 43, 1002, 1002, 1002, 206, 0,
- /* 10 */ 0, 87, 683, 1002, 1002, 1002, 1002, 1002, 1002, 1002,
- /* 20 */ 1002, 1002, 1195, 1195, 274, 352, 43, 43, 43, 43,
- /* 30 */ 43, 43, 17, 155, 247, 264, 356, 373, 465, 482,
- /* 40 */ 177, 574, 591, 683, 683, 683, 683, 683, 683, 683,
- /* 50 */ 683, 683, 683, 683, 683, 683, 683, 683, 683, 683,
- /* 60 */ 683, 700, 683, 792, 809, 809, 911, 1002, 1002, 1002,
- /* 70 */ 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002,
- /* 80 */ 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002,
- /* 90 */ 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1014,
- /* 100 */ 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002,
- /* 110 */ 1002, 1002, 1002, 67, 52, 52, 52, 52, 52, 142,
- /* 120 */ 116, 160, 710, 441, 419, 508, 508, 710, 466, 466,
- /* 130 */ 466, 466, 128, 165, 1, 1678, 1678, 1155, 1155, 1155,
- /* 140 */ 666, 68, 386, 68, 68, 422, 422, 496, 172, 846,
- /* 150 */ 710, 710, 710, 710, 710, 710, 710, 710, 710, 710,
- /* 160 */ 710, 710, 710, 710, 710, 710, 710, 710, 710, 710,
- /* 170 */ 710, 73, 599, 599, 1021, 1678, 1678, 1678, 1092, 836,
- /* 180 */ 836, 334, 215, 442, 548, 439, 654, 745, 710, 710,
- /* 190 */ 710, 710, 710, 710, 710, 646, 710, 710, 710, 710,
- /* 200 */ 710, 710, 710, 710, 710, 710, 710, 710, 754, 754,
- /* 210 */ 754, 710, 710, 710, 710, 931, 710, 710, 710, 934,
- /* 220 */ 710, 710, 971, 710, 710, 710, 710, 710, 710, 710,
- /* 230 */ 710, 909, 525, 161, 1266, 1266, 1266, 1266, 608, 161,
- /* 240 */ 161, 886, 317, 1173, 1064, 892, 858, 858, 1026, 474,
- /* 250 */ 892, 1026, 1175, 6, 607, 1000, 1000, 1000, 858, 30,
- /* 260 */ 1225, 553, 1197, 1369, 1393, 1393, 1300, 1292, 1337, 1422,
- /* 270 */ 1305, 1403, 1305, 1430, 1430, 1430, 1430, 1300, 1434, 1305,
- /* 280 */ 1305, 1337, 1422, 1403, 1305, 1403, 1305, 1300, 1434, 1311,
- /* 290 */ 1397, 1300, 1434, 1451, 1300, 1434, 1300, 1434, 1451, 1377,
- /* 300 */ 1377, 1377, 1423, 1467, 1467, 1451, 1377, 1376, 1377, 1423,
- /* 310 */ 1377, 1377, 1451, 1392, 1392, 1451, 1367, 1391, 1367, 1391,
- /* 320 */ 1367, 1391, 1367, 1391, 1300, 1426, 1426, 1491, 1300, 1371,
- /* 330 */ 1383, 1390, 1389, 1394, 1305, 1503, 1506, 1516, 1516, 1529,
- /* 340 */ 1529, 1529, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678,
- /* 350 */ 1678, 1678, 1678, 1678, 1678, 1678, 1678, 323, 529, 37,
- /* 360 */ 284, 311, 972, 924, 800, 1169, 806, 847, 1223, 1053,
- /* 370 */ 1234, 1235, 1257, 1326, 1341, 1352, 935, 1103, 1256, 211,
- /* 380 */ 1010, 1354, 1356, 1213, 1358, 1087, 1180, 1360, 1362, 1255,
- /* 390 */ 1075, 1530, 1400, 1540, 1465, 1541, 1535, 1537, 1431, 1421,
- /* 400 */ 1444, 1542, 1435, 1549, 1437, 1554, 1569, 1441, 1433, 1455,
- /* 410 */ 1515, 1543, 1438, 1524, 1527, 1528, 1531, 1462, 1477, 1552,
- /* 420 */ 1456, 1583, 1585, 1570, 1487, 1443, 1525, 1571, 1532, 1517,
- /* 430 */ 1557, 1468, 1493, 1577, 1582, 1586, 1482, 1490, 1587, 1538,
- /* 440 */ 1588, 1589, 1584, 1590, 1544, 1553, 1591, 1533, 1592, 1594,
- /* 450 */ 1547, 1581, 1596, 1598, 1600, 1599, 1601, 1604, 1603, 1605,
- /* 460 */ 1607, 1606, 1499, 1609, 1610, 1534, 1602, 1612, 1501, 1611,
- /* 470 */ 1608, 1613, 1614, 1615, 1611, 1617, 1620, 1621, 1622, 1623,
- /* 480 */ 1624, 1628, 1635, 1629, 1630, 1631, 1632, 1634, 1636, 1627,
- /* 490 */ 1536, 1539, 1545, 1546, 1548, 1637, 1642, 1655,
+ /* 0 */ 1286, 750, 1062, 1062, 46, 1131, 1131, 1131, 321, 0,
+ /* 10 */ 0, 87, 813, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
+ /* 20 */ 1131, 1131, 278, 278, 437, 225, 46, 46, 46, 46,
+ /* 30 */ 46, 17, 155, 177, 248, 317, 410, 427, 520, 537,
+ /* 40 */ 630, 647, 796, 813, 813, 813, 813, 813, 813, 813,
+ /* 50 */ 813, 813, 813, 813, 813, 813, 813, 813, 813, 813,
+ /* 60 */ 813, 906, 813, 923, 1016, 1016, 1113, 1131, 1131, 1131,
+ /* 70 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
+ /* 80 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
+ /* 90 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
+ /* 100 */ 1228, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
+ /* 110 */ 1131, 1131, 1131, 1131, 68, 228, 228, 228, 228, 228,
+ /* 120 */ 51, 115, 699, 135, 830, 137, 137, 227, 473, 137,
+ /* 130 */ 389, 389, 137, 369, 369, 369, 369, 8, 230, 4,
+ /* 140 */ 1728, 1728, 689, 689, 689, 50, 300, 300, 300, 300,
+ /* 150 */ 474, 474, 579, 761, 137, 137, 137, 137, 137, 137,
+ /* 160 */ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ /* 170 */ 137, 137, 137, 137, 479, 1035, 1035, 742, 1728, 1728,
+ /* 180 */ 1728, 1728, 1728, 1728, 1728, 298, 679, 679, 607, 197,
+ /* 190 */ 206, 775, 134, 660, 881, 137, 137, 137, 137, 137,
+ /* 200 */ 137, 137, 137, 910, 137, 137, 137, 137, 137, 137,
+ /* 210 */ 137, 137, 137, 137, 137, 137, 978, 978, 978, 137,
+ /* 220 */ 137, 137, 152, 137, 137, 137, 767, 137, 137, 694,
+ /* 230 */ 137, 137, 137, 137, 137, 137, 137, 137, 375, 1019,
+ /* 240 */ 390, 1018, 1018, 1018, 1018, 940, 390, 390, 866, 62,
+ /* 250 */ 605, 1181, 234, 1074, 989, 1112, 1074, 1112, 1120, 515,
+ /* 260 */ 234, 234, 515, 234, 989, 1120, 1070, 788, 770, 896,
+ /* 270 */ 896, 896, 1112, 993, 1102, 1106, 1176, 1430, 1430, 1456,
+ /* 280 */ 1456, 1364, 1356, 1359, 1480, 1459, 1486, 1486, 1486, 1486,
+ /* 290 */ 1364, 1489, 1368, 1359, 1359, 1368, 1480, 1459, 1368, 1459,
+ /* 300 */ 1368, 1364, 1489, 1370, 1458, 1364, 1489, 1504, 1364, 1489,
+ /* 310 */ 1364, 1489, 1504, 1434, 1434, 1434, 1477, 1522, 1522, 1504,
+ /* 320 */ 1434, 1431, 1434, 1477, 1434, 1434, 1528, 1452, 1452, 1504,
+ /* 330 */ 1422, 1454, 1422, 1454, 1422, 1454, 1422, 1454, 1364, 1483,
+ /* 340 */ 1483, 1550, 1364, 1428, 1443, 1447, 1446, 1448, 1368, 1562,
+ /* 350 */ 1563, 1577, 1577, 1588, 1588, 1588, 1728, 1728, 1728, 1728,
+ /* 360 */ 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+ /* 370 */ 1728, 241, 971, 295, 716, 693, 709, 1241, 1057, 1161,
+ /* 380 */ 911, 1150, 1125, 1160, 1259, 482, 1296, 1326, 1340, 1357,
+ /* 390 */ 1363, 1374, 1126, 1105, 1266, 1182, 1294, 1215, 1401, 1407,
+ /* 400 */ 1261, 1345, 1080, 1178, 1413, 1429, 1255, 1311, 1593, 1465,
+ /* 410 */ 1607, 1608, 1602, 1603, 1496, 1485, 1507, 1604, 1604, 1609,
+ /* 420 */ 1497, 1612, 1498, 1619, 1632, 1503, 1516, 1604, 1517, 1578,
+ /* 430 */ 1605, 1604, 1500, 1587, 1590, 1591, 1592, 1525, 1540, 1615,
+ /* 440 */ 1518, 1646, 1647, 1631, 1547, 1502, 1585, 1633, 1586, 1580,
+ /* 450 */ 1620, 1527, 1555, 1639, 1644, 1648, 1542, 1549, 1649, 1598,
+ /* 460 */ 1650, 1651, 1652, 1654, 1599, 1610, 1653, 1589, 1655, 1657,
+ /* 470 */ 1611, 1637, 1659, 1661, 1662, 1660, 1664, 1658, 1600, 1556,
+ /* 480 */ 1665, 1668, 1584, 1663, 1671, 1559, 1669, 1666, 1670, 1667,
+ /* 490 */ 1675, 1669, 1676, 1679, 1680, 1681, 1682, 1683, 1685, 1694,
+ /* 500 */ 1687, 1688, 1689, 1690, 1692, 1693, 1691, 1594, 1583, 1595,
+ /* 510 */ 1596, 1597, 1695, 1696, 1715,
};
-#define YY_REDUCE_COUNT (356)
-#define YY_REDUCE_MIN (-259)
-#define YY_REDUCE_MAX (1373)
+#define YY_REDUCE_COUNT (370)
+#define YY_REDUCE_MIN (-255)
+#define YY_REDUCE_MAX (1425)
static const short yy_reduce_ofst[] = {
- /* 0 */ 752, 1003, 848, 863, -147, 154, 307, 416, 255, -176,
- /* 10 */ -173, -251, -169, 397, 503, 505, 614, 634, 701, -167,
- /* 20 */ 736, 742, 89, 394, 162, 364, 473, 475, 477, 536,
- /* 30 */ 601, 726, -248, -248, -248, -248, -248, -248, -248, -248,
- /* 40 */ -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
- /* 50 */ -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
- /* 60 */ -248, -248, -248, -248, -248, -248, -163, -160, 673, 698,
- /* 70 */ 751, 762, 796, 799, 866, 868, 881, 895, 902, 930,
- /* 80 */ 939, 942, 954, 966, 995, 1009, 1016, 1024, 1028, 1033,
- /* 90 */ 1040, 1044, 1072, 1078, 1084, 1096, 1108, 1111, 1117, 1120,
- /* 100 */ 1127, 1129, 1135, 1141, 1144, 1146, 1153, 1156, 1159, 1161,
- /* 110 */ 1165, 1170, 1172, -248, -248, -248, -248, -248, -248, -248,
- /* 120 */ -248, -248, 546, 450, -197, -36, 406, -165, 585, 854,
- /* 130 */ 585, 854, 722, -248, -248, -248, -248, -190, -190, -190,
- /* 140 */ 217, 254, 153, 543, 628, 166, 220, 319, -259, -259,
- /* 150 */ -164, -49, 191, 202, 435, 267, 269, 487, 594, 504,
- /* 160 */ 635, 538, 804, 814, 613, 946, 649, 706, 739, 837,
- /* 170 */ 869, 286, 640, 912, 778, 933, 949, 259, -184, 137,
- /* 180 */ 157, -143, 184, 325, 396, 472, 485, 489, 565, 777,
- /* 190 */ 882, 907, 975, 987, 1008, 182, 1025, 1042, 1069, 1097,
- /* 200 */ 1113, 1138, 1154, 1177, 1190, 1191, 1198, 1209, 559, 690,
- /* 210 */ 1123, 1211, 1212, 1214, 1215, 223, 1216, 1217, 1218, 1160,
- /* 220 */ 1219, 1221, 1131, 1222, 325, 1224, 1226, 1227, 1228, 1229,
- /* 230 */ 1230, 1133, 1136, 1183, 1174, 1176, 1178, 1179, 223, 1183,
- /* 240 */ 1183, 1164, 1220, 1237, 1134, 1181, 1182, 1184, 1142, 1189,
- /* 250 */ 1192, 1147, 1231, 1210, 1232, 1233, 1236, 1239, 1185, 1162,
- /* 260 */ 1196, 1201, 1248, 1157, 1163, 1166, 1253, 1186, 1193, 1199,
- /* 270 */ 1238, 1240, 1241, 1242, 1243, 1244, 1245, 1265, 1269, 1246,
- /* 280 */ 1247, 1202, 1204, 1249, 1250, 1251, 1252, 1272, 1270, 1200,
- /* 290 */ 1203, 1276, 1278, 1273, 1289, 1291, 1294, 1297, 1279, 1283,
- /* 300 */ 1284, 1285, 1280, 1282, 1286, 1287, 1293, 1295, 1296, 1290,
- /* 310 */ 1298, 1301, 1299, 1254, 1258, 1302, 1261, 1263, 1264, 1267,
- /* 320 */ 1268, 1271, 1274, 1281, 1324, 1275, 1277, 1260, 1330, 1262,
- /* 330 */ 1303, 1306, 1304, 1307, 1310, 1342, 1346, 1355, 1363, 1364,
- /* 340 */ 1366, 1368, 1288, 1308, 1309, 1353, 1349, 1350, 1351, 1357,
- /* 350 */ 1359, 1343, 1345, 1361, 1365, 1370, 1373,
+ /* 0 */ 915, 1169, 201, 957, -149, 360, 424, 538, 418, -180,
+ /* 10 */ -177, -255, -173, 448, 576, 616, 619, 199, 726, -168,
+ /* 20 */ 636, 744, -160, -157, 341, 205, 420, 695, 697, 711,
+ /* 30 */ 758, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+ /* 40 */ -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+ /* 50 */ -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+ /* 60 */ -252, -252, -252, -252, -252, -252, -170, 61, 267, 428,
+ /* 70 */ 467, 509, 676, 814, 834, 854, 858, 874, 899, 907,
+ /* 80 */ 927, 954, 962, 974, 999, 1001, 1049, 1052, 1054, 1063,
+ /* 90 */ 1065, 1069, 1090, 1104, 1107, 1109, 1114, 1128, 1140, 1152,
+ /* 100 */ 1155, 1159, 1185, 1189, 1199, 1201, 1205, 1210, 1219, 1229,
+ /* 110 */ 1235, 1239, 1243, 1245, -252, -252, -252, -252, -252, -252,
+ /* 120 */ -252, -252, 214, -252, 483, 269, 805, -4, -198, 816,
+ /* 130 */ -182, 186, 244, -208, 821, -208, 821, 449, -252, -252,
+ /* 140 */ -252, -252, -179, -179, -179, 90, -73, 15, 140, 399,
+ /* 150 */ -162, -131, 114, 114, 311, 355, 362, 488, 702, 707,
+ /* 160 */ 817, 820, 159, 179, 378, 357, 739, 481, 859, 879,
+ /* 170 */ 379, 727, 478, 914, 614, 465, 528, 261, 842, 810,
+ /* 180 */ 908, 939, 950, 943, 960, -193, -175, 47, 18, 218,
+ /* 190 */ 273, 374, 484, 510, 527, 534, 585, 600, 606, 657,
+ /* 200 */ 764, 812, 819, 779, 832, 925, 1134, 1149, 1192, 1198,
+ /* 210 */ 1202, 1213, 1216, 1218, 1225, 1230, 441, 718, 946, 1234,
+ /* 220 */ 1238, 1246, 843, 1248, 1249, 1254, 1100, 1263, 1269, 1231,
+ /* 230 */ 1270, 273, 1274, 1276, 1277, 1278, 1279, 1280, 1084, 1164,
+ /* 240 */ 1233, 1222, 1223, 1224, 1226, 843, 1233, 1233, 1236, 1267,
+ /* 250 */ 1290, 1188, 1214, 1220, 1240, 1232, 1221, 1237, 1197, 1247,
+ /* 260 */ 1227, 1242, 1250, 1244, 1253, 1200, 1272, 1260, 1275, 1282,
+ /* 270 */ 1283, 1284, 1251, 1252, 1262, 1256, 1297, 1209, 1211, 1257,
+ /* 280 */ 1258, 1309, 1264, 1265, 1268, 1285, 1287, 1288, 1289, 1291,
+ /* 290 */ 1319, 1322, 1281, 1271, 1273, 1292, 1293, 1295, 1300, 1298,
+ /* 300 */ 1301, 1330, 1333, 1299, 1302, 1338, 1341, 1327, 1342, 1351,
+ /* 310 */ 1352, 1354, 1331, 1339, 1343, 1346, 1332, 1336, 1344, 1348,
+ /* 320 */ 1347, 1350, 1349, 1353, 1355, 1358, 1303, 1304, 1305, 1360,
+ /* 330 */ 1314, 1318, 1323, 1320, 1328, 1334, 1335, 1337, 1377, 1361,
+ /* 340 */ 1362, 1315, 1390, 1317, 1365, 1367, 1366, 1371, 1373, 1398,
+ /* 350 */ 1402, 1412, 1414, 1417, 1418, 1419, 1312, 1316, 1324, 1416,
+ /* 360 */ 1408, 1411, 1415, 1420, 1423, 1405, 1409, 1406, 1421, 1424,
+ /* 370 */ 1425,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1406, 1406, 1278, 1060, 1166, 1278, 1278, 1278, 1060, 1196,
- /* 10 */ 1196, 1331, 1089, 1060, 1060, 1060, 1060, 1060, 1060, 1277,
- /* 20 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 30 */ 1060, 1060, 1205, 1060, 1060, 1060, 1060, 1060, 1279, 1280,
- /* 40 */ 1060, 1060, 1060, 1330, 1332, 1295, 1215, 1214, 1213, 1212,
- /* 50 */ 1313, 1183, 1210, 1203, 1207, 1273, 1274, 1272, 1276, 1280,
- /* 60 */ 1279, 1060, 1206, 1244, 1258, 1243, 1060, 1060, 1060, 1060,
- /* 70 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 80 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 90 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 100 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 110 */ 1060, 1060, 1060, 1252, 1257, 1263, 1256, 1253, 1246, 1245,
- /* 120 */ 1247, 1248, 1060, 1079, 1131, 1060, 1060, 1060, 1345, 1344,
- /* 130 */ 1060, 1060, 1089, 1249, 1250, 1260, 1259, 1334, 1360, 1359,
- /* 140 */ 1296, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 150 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 160 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 170 */ 1060, 1089, 1085, 1085, 1060, 1340, 1166, 1157, 1060, 1060,
- /* 180 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 190 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 200 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 210 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1162,
- /* 220 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 230 */ 1354, 1060, 1308, 1145, 1162, 1162, 1162, 1162, 1164, 1146,
- /* 240 */ 1144, 1156, 1090, 1065, 1398, 1163, 1185, 1185, 1395, 1209,
- /* 250 */ 1163, 1395, 1106, 1376, 1101, 1196, 1196, 1196, 1185, 1275,
- /* 260 */ 1163, 1156, 1060, 1398, 1397, 1397, 1171, 1296, 1218, 1224,
- /* 270 */ 1209, 1134, 1209, 1140, 1140, 1140, 1140, 1171, 1076, 1209,
- /* 280 */ 1209, 1218, 1224, 1134, 1209, 1134, 1209, 1171, 1076, 1312,
- /* 290 */ 1392, 1171, 1076, 1286, 1171, 1076, 1171, 1076, 1286, 1132,
- /* 300 */ 1132, 1132, 1121, 1060, 1060, 1286, 1132, 1106, 1132, 1121,
- /* 310 */ 1132, 1132, 1286, 1290, 1290, 1286, 1189, 1184, 1189, 1184,
- /* 320 */ 1189, 1184, 1189, 1184, 1171, 1199, 1199, 1281, 1171, 1060,
- /* 330 */ 1204, 1190, 1202, 1200, 1209, 1082, 1124, 1357, 1357, 1353,
- /* 340 */ 1353, 1353, 1403, 1403, 1340, 1369, 1089, 1089, 1089, 1089,
- /* 350 */ 1369, 1108, 1108, 1090, 1090, 1089, 1369, 1060, 1060, 1060,
- /* 360 */ 1060, 1060, 1060, 1364, 1060, 1297, 1175, 1060, 1060, 1060,
- /* 370 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 380 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 390 */ 1229, 1337, 1060, 1060, 1335, 1060, 1060, 1060, 1060, 1060,
- /* 400 */ 1060, 1176, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 410 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 420 */ 1394, 1060, 1060, 1060, 1060, 1060, 1060, 1311, 1310, 1060,
- /* 430 */ 1060, 1173, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 440 */ 1060, 1060, 1060, 1060, 1060, 1104, 1060, 1060, 1060, 1060,
- /* 450 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
- /* 460 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1201,
- /* 470 */ 1060, 1191, 1060, 1060, 1385, 1060, 1060, 1060, 1060, 1060,
- /* 480 */ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1380,
- /* 490 */ 1148, 1231, 1060, 1230, 1234, 1060, 1070, 1060,
+ /* 0 */ 1454, 1454, 1320, 1095, 1201, 1320, 1320, 1320, 1095, 1231,
+ /* 10 */ 1231, 1373, 1124, 1095, 1095, 1095, 1095, 1095, 1095, 1319,
+ /* 20 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 30 */ 1095, 1240, 1095, 1247, 1095, 1095, 1095, 1095, 1321, 1322,
+ /* 40 */ 1095, 1095, 1095, 1372, 1374, 1337, 1254, 1253, 1252, 1251,
+ /* 50 */ 1355, 1218, 1245, 1238, 1242, 1315, 1316, 1314, 1318, 1322,
+ /* 60 */ 1321, 1095, 1241, 1286, 1300, 1285, 1095, 1095, 1095, 1095,
+ /* 70 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 80 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 90 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 100 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 110 */ 1095, 1095, 1095, 1095, 1294, 1299, 1305, 1298, 1295, 1288,
+ /* 120 */ 1287, 1289, 1095, 1290, 1095, 1095, 1095, 1114, 1166, 1095,
+ /* 130 */ 1095, 1095, 1095, 1388, 1387, 1095, 1095, 1124, 1291, 1292,
+ /* 140 */ 1302, 1301, 1376, 1407, 1406, 1338, 1095, 1095, 1095, 1095,
+ /* 150 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 160 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 170 */ 1095, 1095, 1095, 1095, 1124, 1120, 1120, 1095, 1383, 1192,
+ /* 180 */ 1192, 1192, 1192, 1201, 1192, 1095, 1095, 1095, 1095, 1095,
+ /* 190 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 200 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 210 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 220 */ 1095, 1095, 1095, 1095, 1095, 1095, 1197, 1095, 1095, 1095,
+ /* 230 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1401, 1095, 1350,
+ /* 240 */ 1180, 1197, 1197, 1197, 1197, 1199, 1181, 1179, 1191, 1125,
+ /* 250 */ 1100, 1446, 1257, 1246, 1198, 1220, 1246, 1220, 1443, 1244,
+ /* 260 */ 1257, 1257, 1244, 1257, 1198, 1443, 1141, 1423, 1136, 1231,
+ /* 270 */ 1231, 1231, 1220, 1317, 1198, 1191, 1095, 1446, 1446, 1445,
+ /* 280 */ 1445, 1206, 1338, 1430, 1266, 1169, 1175, 1175, 1175, 1175,
+ /* 290 */ 1206, 1111, 1244, 1430, 1430, 1244, 1266, 1169, 1244, 1169,
+ /* 300 */ 1244, 1206, 1111, 1354, 1440, 1206, 1111, 1328, 1206, 1111,
+ /* 310 */ 1206, 1111, 1328, 1167, 1167, 1167, 1156, 1095, 1095, 1328,
+ /* 320 */ 1167, 1141, 1167, 1156, 1167, 1167, 1095, 1332, 1332, 1328,
+ /* 330 */ 1224, 1219, 1224, 1219, 1224, 1219, 1224, 1219, 1206, 1234,
+ /* 340 */ 1234, 1323, 1206, 1095, 1239, 1225, 1237, 1235, 1244, 1117,
+ /* 350 */ 1159, 1404, 1404, 1400, 1400, 1400, 1451, 1451, 1383, 1416,
+ /* 360 */ 1124, 1124, 1124, 1124, 1416, 1143, 1143, 1125, 1125, 1124,
+ /* 370 */ 1416, 1095, 1095, 1095, 1095, 1095, 1095, 1411, 1095, 1378,
+ /* 380 */ 1339, 1210, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 390 */ 1095, 1095, 1095, 1095, 1095, 1095, 1389, 1095, 1095, 1095,
+ /* 400 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1271, 1380, 1095,
+ /* 410 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1248, 1249, 1211,
+ /* 420 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1263, 1095, 1095,
+ /* 430 */ 1095, 1258, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 440 */ 1442, 1095, 1095, 1095, 1095, 1095, 1095, 1353, 1352, 1095,
+ /* 450 */ 1095, 1208, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 460 */ 1095, 1095, 1095, 1095, 1095, 1139, 1095, 1095, 1095, 1095,
+ /* 470 */ 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 480 */ 1095, 1095, 1095, 1095, 1095, 1095, 1236, 1095, 1226, 1095,
+ /* 490 */ 1095, 1433, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ /* 500 */ 1095, 1095, 1095, 1095, 1095, 1095, 1427, 1183, 1273, 1095,
+ /* 510 */ 1272, 1276, 1095, 1105, 1095,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -155984,6 +158191,7 @@ static const YYCODETYPE yyFallback[] = {
57, /* LAST => ID */
57, /* GENERATED => ID */
57, /* ALWAYS => ID */
+ 57, /* MATERIALIZED => ID */
57, /* REINDEX => ID */
57, /* RENAME => ID */
57, /* CTIME_KW => ID */
@@ -156035,6 +158243,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* HAVING => nothing */
0, /* LIMIT => nothing */
0, /* WHERE => nothing */
+ 0, /* RETURNING => nothing */
0, /* INTO => nothing */
0, /* NOTHING => nothing */
0, /* FLOAT => nothing */
@@ -156240,200 +158449,206 @@ static const char *const yyTokenName[] = {
/* 84 */ "LAST",
/* 85 */ "GENERATED",
/* 86 */ "ALWAYS",
- /* 87 */ "REINDEX",
- /* 88 */ "RENAME",
- /* 89 */ "CTIME_KW",
- /* 90 */ "ANY",
- /* 91 */ "BITAND",
- /* 92 */ "BITOR",
- /* 93 */ "LSHIFT",
- /* 94 */ "RSHIFT",
- /* 95 */ "PLUS",
- /* 96 */ "MINUS",
- /* 97 */ "STAR",
- /* 98 */ "SLASH",
- /* 99 */ "REM",
- /* 100 */ "CONCAT",
- /* 101 */ "COLLATE",
- /* 102 */ "BITNOT",
- /* 103 */ "ON",
- /* 104 */ "INDEXED",
- /* 105 */ "STRING",
- /* 106 */ "JOIN_KW",
- /* 107 */ "CONSTRAINT",
- /* 108 */ "DEFAULT",
- /* 109 */ "NULL",
- /* 110 */ "PRIMARY",
- /* 111 */ "UNIQUE",
- /* 112 */ "CHECK",
- /* 113 */ "REFERENCES",
- /* 114 */ "AUTOINCR",
- /* 115 */ "INSERT",
- /* 116 */ "DELETE",
- /* 117 */ "UPDATE",
- /* 118 */ "SET",
- /* 119 */ "DEFERRABLE",
- /* 120 */ "FOREIGN",
- /* 121 */ "DROP",
- /* 122 */ "UNION",
- /* 123 */ "ALL",
- /* 124 */ "EXCEPT",
- /* 125 */ "INTERSECT",
- /* 126 */ "SELECT",
- /* 127 */ "VALUES",
- /* 128 */ "DISTINCT",
- /* 129 */ "DOT",
- /* 130 */ "FROM",
- /* 131 */ "JOIN",
- /* 132 */ "USING",
- /* 133 */ "ORDER",
- /* 134 */ "GROUP",
- /* 135 */ "HAVING",
- /* 136 */ "LIMIT",
- /* 137 */ "WHERE",
- /* 138 */ "INTO",
- /* 139 */ "NOTHING",
- /* 140 */ "FLOAT",
- /* 141 */ "BLOB",
- /* 142 */ "INTEGER",
- /* 143 */ "VARIABLE",
- /* 144 */ "CASE",
- /* 145 */ "WHEN",
- /* 146 */ "THEN",
- /* 147 */ "ELSE",
- /* 148 */ "INDEX",
- /* 149 */ "ALTER",
- /* 150 */ "ADD",
- /* 151 */ "COLUMN",
- /* 152 */ "AGG_FUNCTION",
- /* 153 */ "AGG_COLUMN",
- /* 154 */ "TRUEFALSE",
- /* 155 */ "ISNOT",
- /* 156 */ "FUNCTION",
- /* 157 */ "UMINUS",
- /* 158 */ "UPLUS",
- /* 159 */ "TRUTH",
- /* 160 */ "REGISTER",
- /* 161 */ "VECTOR",
- /* 162 */ "SELECT_COLUMN",
- /* 163 */ "IF_NULL_ROW",
- /* 164 */ "ASTERISK",
- /* 165 */ "SPAN",
- /* 166 */ "SPACE",
- /* 167 */ "ILLEGAL",
- /* 168 */ "input",
- /* 169 */ "cmdlist",
- /* 170 */ "ecmd",
- /* 171 */ "cmdx",
- /* 172 */ "cmd",
- /* 173 */ "transtype",
- /* 174 */ "trans_opt",
- /* 175 */ "nm",
- /* 176 */ "savepoint_opt",
- /* 177 */ "create_table",
- /* 178 */ "create_table_args",
- /* 179 */ "createkw",
- /* 180 */ "temp",
- /* 181 */ "ifnotexists",
- /* 182 */ "dbnm",
- /* 183 */ "columnlist",
- /* 184 */ "conslist_opt",
- /* 185 */ "table_options",
- /* 186 */ "select",
- /* 187 */ "columnname",
- /* 188 */ "carglist",
- /* 189 */ "typetoken",
- /* 190 */ "typename",
- /* 191 */ "signed",
- /* 192 */ "plus_num",
- /* 193 */ "minus_num",
- /* 194 */ "scanpt",
- /* 195 */ "scantok",
- /* 196 */ "ccons",
- /* 197 */ "term",
- /* 198 */ "expr",
- /* 199 */ "onconf",
- /* 200 */ "sortorder",
- /* 201 */ "autoinc",
- /* 202 */ "eidlist_opt",
- /* 203 */ "refargs",
- /* 204 */ "defer_subclause",
- /* 205 */ "generated",
- /* 206 */ "refarg",
- /* 207 */ "refact",
- /* 208 */ "init_deferred_pred_opt",
- /* 209 */ "conslist",
- /* 210 */ "tconscomma",
- /* 211 */ "tcons",
- /* 212 */ "sortlist",
- /* 213 */ "eidlist",
- /* 214 */ "defer_subclause_opt",
- /* 215 */ "orconf",
- /* 216 */ "resolvetype",
- /* 217 */ "raisetype",
- /* 218 */ "ifexists",
- /* 219 */ "fullname",
- /* 220 */ "selectnowith",
- /* 221 */ "oneselect",
- /* 222 */ "wqlist",
- /* 223 */ "multiselect_op",
- /* 224 */ "distinct",
- /* 225 */ "selcollist",
- /* 226 */ "from",
- /* 227 */ "where_opt",
- /* 228 */ "groupby_opt",
- /* 229 */ "having_opt",
- /* 230 */ "orderby_opt",
- /* 231 */ "limit_opt",
- /* 232 */ "values",
- /* 233 */ "nexprlist",
- /* 234 */ "sclp",
- /* 235 */ "as",
- /* 236 */ "seltablist",
- /* 237 */ "stl_prefix",
- /* 238 */ "joinop",
- /* 239 */ "indexed_opt",
- /* 240 */ "on_opt",
- /* 241 */ "using_opt",
- /* 242 */ "exprlist",
- /* 243 */ "xfullname",
- /* 244 */ "idlist",
- /* 245 */ "nulls",
- /* 246 */ "with",
- /* 247 */ "setlist",
- /* 248 */ "insert_cmd",
- /* 249 */ "idlist_opt",
- /* 250 */ "upsert",
- /* 251 */ "likeop",
- /* 252 */ "between_op",
- /* 253 */ "in_op",
- /* 254 */ "paren_exprlist",
- /* 255 */ "case_operand",
- /* 256 */ "case_exprlist",
- /* 257 */ "case_else",
- /* 258 */ "uniqueflag",
- /* 259 */ "collate",
- /* 260 */ "vinto",
- /* 261 */ "nmnum",
- /* 262 */ "trigger_decl",
- /* 263 */ "trigger_cmd_list",
- /* 264 */ "trigger_time",
- /* 265 */ "trigger_event",
- /* 266 */ "foreach_clause",
- /* 267 */ "when_clause",
- /* 268 */ "trigger_cmd",
- /* 269 */ "trnm",
- /* 270 */ "tridxby",
- /* 271 */ "database_kw_opt",
- /* 272 */ "key_opt",
- /* 273 */ "add_column_fullname",
- /* 274 */ "kwcolumn_opt",
- /* 275 */ "create_vtab",
- /* 276 */ "vtabarglist",
- /* 277 */ "vtabarg",
- /* 278 */ "vtabargtoken",
- /* 279 */ "lp",
- /* 280 */ "anylist",
+ /* 87 */ "MATERIALIZED",
+ /* 88 */ "REINDEX",
+ /* 89 */ "RENAME",
+ /* 90 */ "CTIME_KW",
+ /* 91 */ "ANY",
+ /* 92 */ "BITAND",
+ /* 93 */ "BITOR",
+ /* 94 */ "LSHIFT",
+ /* 95 */ "RSHIFT",
+ /* 96 */ "PLUS",
+ /* 97 */ "MINUS",
+ /* 98 */ "STAR",
+ /* 99 */ "SLASH",
+ /* 100 */ "REM",
+ /* 101 */ "CONCAT",
+ /* 102 */ "COLLATE",
+ /* 103 */ "BITNOT",
+ /* 104 */ "ON",
+ /* 105 */ "INDEXED",
+ /* 106 */ "STRING",
+ /* 107 */ "JOIN_KW",
+ /* 108 */ "CONSTRAINT",
+ /* 109 */ "DEFAULT",
+ /* 110 */ "NULL",
+ /* 111 */ "PRIMARY",
+ /* 112 */ "UNIQUE",
+ /* 113 */ "CHECK",
+ /* 114 */ "REFERENCES",
+ /* 115 */ "AUTOINCR",
+ /* 116 */ "INSERT",
+ /* 117 */ "DELETE",
+ /* 118 */ "UPDATE",
+ /* 119 */ "SET",
+ /* 120 */ "DEFERRABLE",
+ /* 121 */ "FOREIGN",
+ /* 122 */ "DROP",
+ /* 123 */ "UNION",
+ /* 124 */ "ALL",
+ /* 125 */ "EXCEPT",
+ /* 126 */ "INTERSECT",
+ /* 127 */ "SELECT",
+ /* 128 */ "VALUES",
+ /* 129 */ "DISTINCT",
+ /* 130 */ "DOT",
+ /* 131 */ "FROM",
+ /* 132 */ "JOIN",
+ /* 133 */ "USING",
+ /* 134 */ "ORDER",
+ /* 135 */ "GROUP",
+ /* 136 */ "HAVING",
+ /* 137 */ "LIMIT",
+ /* 138 */ "WHERE",
+ /* 139 */ "RETURNING",
+ /* 140 */ "INTO",
+ /* 141 */ "NOTHING",
+ /* 142 */ "FLOAT",
+ /* 143 */ "BLOB",
+ /* 144 */ "INTEGER",
+ /* 145 */ "VARIABLE",
+ /* 146 */ "CASE",
+ /* 147 */ "WHEN",
+ /* 148 */ "THEN",
+ /* 149 */ "ELSE",
+ /* 150 */ "INDEX",
+ /* 151 */ "ALTER",
+ /* 152 */ "ADD",
+ /* 153 */ "COLUMN",
+ /* 154 */ "AGG_FUNCTION",
+ /* 155 */ "AGG_COLUMN",
+ /* 156 */ "TRUEFALSE",
+ /* 157 */ "ISNOT",
+ /* 158 */ "FUNCTION",
+ /* 159 */ "UMINUS",
+ /* 160 */ "UPLUS",
+ /* 161 */ "TRUTH",
+ /* 162 */ "REGISTER",
+ /* 163 */ "VECTOR",
+ /* 164 */ "SELECT_COLUMN",
+ /* 165 */ "IF_NULL_ROW",
+ /* 166 */ "ASTERISK",
+ /* 167 */ "SPAN",
+ /* 168 */ "SPACE",
+ /* 169 */ "ILLEGAL",
+ /* 170 */ "input",
+ /* 171 */ "cmdlist",
+ /* 172 */ "ecmd",
+ /* 173 */ "cmdx",
+ /* 174 */ "cmd",
+ /* 175 */ "transtype",
+ /* 176 */ "trans_opt",
+ /* 177 */ "nm",
+ /* 178 */ "savepoint_opt",
+ /* 179 */ "create_table",
+ /* 180 */ "create_table_args",
+ /* 181 */ "createkw",
+ /* 182 */ "temp",
+ /* 183 */ "ifnotexists",
+ /* 184 */ "dbnm",
+ /* 185 */ "columnlist",
+ /* 186 */ "conslist_opt",
+ /* 187 */ "table_options",
+ /* 188 */ "select",
+ /* 189 */ "columnname",
+ /* 190 */ "carglist",
+ /* 191 */ "typetoken",
+ /* 192 */ "typename",
+ /* 193 */ "signed",
+ /* 194 */ "plus_num",
+ /* 195 */ "minus_num",
+ /* 196 */ "scanpt",
+ /* 197 */ "scantok",
+ /* 198 */ "ccons",
+ /* 199 */ "term",
+ /* 200 */ "expr",
+ /* 201 */ "onconf",
+ /* 202 */ "sortorder",
+ /* 203 */ "autoinc",
+ /* 204 */ "eidlist_opt",
+ /* 205 */ "refargs",
+ /* 206 */ "defer_subclause",
+ /* 207 */ "generated",
+ /* 208 */ "refarg",
+ /* 209 */ "refact",
+ /* 210 */ "init_deferred_pred_opt",
+ /* 211 */ "conslist",
+ /* 212 */ "tconscomma",
+ /* 213 */ "tcons",
+ /* 214 */ "sortlist",
+ /* 215 */ "eidlist",
+ /* 216 */ "defer_subclause_opt",
+ /* 217 */ "orconf",
+ /* 218 */ "resolvetype",
+ /* 219 */ "raisetype",
+ /* 220 */ "ifexists",
+ /* 221 */ "fullname",
+ /* 222 */ "selectnowith",
+ /* 223 */ "oneselect",
+ /* 224 */ "wqlist",
+ /* 225 */ "multiselect_op",
+ /* 226 */ "distinct",
+ /* 227 */ "selcollist",
+ /* 228 */ "from",
+ /* 229 */ "where_opt",
+ /* 230 */ "groupby_opt",
+ /* 231 */ "having_opt",
+ /* 232 */ "orderby_opt",
+ /* 233 */ "limit_opt",
+ /* 234 */ "values",
+ /* 235 */ "nexprlist",
+ /* 236 */ "sclp",
+ /* 237 */ "as",
+ /* 238 */ "seltablist",
+ /* 239 */ "stl_prefix",
+ /* 240 */ "joinop",
+ /* 241 */ "indexed_opt",
+ /* 242 */ "on_opt",
+ /* 243 */ "using_opt",
+ /* 244 */ "exprlist",
+ /* 245 */ "xfullname",
+ /* 246 */ "idlist",
+ /* 247 */ "nulls",
+ /* 248 */ "with",
+ /* 249 */ "where_opt_ret",
+ /* 250 */ "setlist",
+ /* 251 */ "insert_cmd",
+ /* 252 */ "idlist_opt",
+ /* 253 */ "upsert",
+ /* 254 */ "returning",
+ /* 255 */ "likeop",
+ /* 256 */ "between_op",
+ /* 257 */ "in_op",
+ /* 258 */ "paren_exprlist",
+ /* 259 */ "case_operand",
+ /* 260 */ "case_exprlist",
+ /* 261 */ "case_else",
+ /* 262 */ "uniqueflag",
+ /* 263 */ "collate",
+ /* 264 */ "vinto",
+ /* 265 */ "nmnum",
+ /* 266 */ "trigger_decl",
+ /* 267 */ "trigger_cmd_list",
+ /* 268 */ "trigger_time",
+ /* 269 */ "trigger_event",
+ /* 270 */ "foreach_clause",
+ /* 271 */ "when_clause",
+ /* 272 */ "trigger_cmd",
+ /* 273 */ "trnm",
+ /* 274 */ "tridxby",
+ /* 275 */ "database_kw_opt",
+ /* 276 */ "key_opt",
+ /* 277 */ "add_column_fullname",
+ /* 278 */ "kwcolumn_opt",
+ /* 279 */ "create_vtab",
+ /* 280 */ "vtabarglist",
+ /* 281 */ "vtabarg",
+ /* 282 */ "vtabargtoken",
+ /* 283 */ "lp",
+ /* 284 */ "anylist",
+ /* 285 */ "wqitem",
+ /* 286 */ "wqas",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -156586,205 +158801,218 @@ static const char *const yyRuleName[] = {
/* 142 */ "limit_opt ::= LIMIT expr",
/* 143 */ "limit_opt ::= LIMIT expr OFFSET expr",
/* 144 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 145 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt",
+ /* 145 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret",
/* 146 */ "where_opt ::=",
/* 147 */ "where_opt ::= WHERE expr",
- /* 148 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt",
- /* 149 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 150 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
- /* 151 */ "setlist ::= nm EQ expr",
- /* 152 */ "setlist ::= LP idlist RP EQ expr",
- /* 153 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
- /* 154 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
- /* 155 */ "upsert ::=",
- /* 156 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
- /* 157 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
- /* 158 */ "upsert ::= ON CONFLICT DO NOTHING",
- /* 159 */ "insert_cmd ::= INSERT orconf",
- /* 160 */ "insert_cmd ::= REPLACE",
- /* 161 */ "idlist_opt ::=",
- /* 162 */ "idlist_opt ::= LP idlist RP",
- /* 163 */ "idlist ::= idlist COMMA nm",
- /* 164 */ "idlist ::= nm",
- /* 165 */ "expr ::= LP expr RP",
- /* 166 */ "expr ::= ID|INDEXED",
- /* 167 */ "expr ::= JOIN_KW",
- /* 168 */ "expr ::= nm DOT nm",
- /* 169 */ "expr ::= nm DOT nm DOT nm",
- /* 170 */ "term ::= NULL|FLOAT|BLOB",
- /* 171 */ "term ::= STRING",
- /* 172 */ "term ::= INTEGER",
- /* 173 */ "expr ::= VARIABLE",
- /* 174 */ "expr ::= expr COLLATE ID|STRING",
- /* 175 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 176 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
- /* 177 */ "expr ::= ID|INDEXED LP STAR RP",
- /* 178 */ "term ::= CTIME_KW",
- /* 179 */ "expr ::= LP nexprlist COMMA expr RP",
- /* 180 */ "expr ::= expr AND expr",
- /* 181 */ "expr ::= expr OR expr",
- /* 182 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 183 */ "expr ::= expr EQ|NE expr",
- /* 184 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 185 */ "expr ::= expr PLUS|MINUS expr",
- /* 186 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 187 */ "expr ::= expr CONCAT expr",
- /* 188 */ "likeop ::= NOT LIKE_KW|MATCH",
- /* 189 */ "expr ::= expr likeop expr",
- /* 190 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 191 */ "expr ::= expr ISNULL|NOTNULL",
- /* 192 */ "expr ::= expr NOT NULL",
- /* 193 */ "expr ::= expr IS expr",
- /* 194 */ "expr ::= expr IS NOT expr",
- /* 195 */ "expr ::= NOT expr",
- /* 196 */ "expr ::= BITNOT expr",
- /* 197 */ "expr ::= PLUS|MINUS expr",
- /* 198 */ "between_op ::= BETWEEN",
- /* 199 */ "between_op ::= NOT BETWEEN",
- /* 200 */ "expr ::= expr between_op expr AND expr",
- /* 201 */ "in_op ::= IN",
- /* 202 */ "in_op ::= NOT IN",
- /* 203 */ "expr ::= expr in_op LP exprlist RP",
- /* 204 */ "expr ::= LP select RP",
- /* 205 */ "expr ::= expr in_op LP select RP",
- /* 206 */ "expr ::= expr in_op nm dbnm paren_exprlist",
- /* 207 */ "expr ::= EXISTS LP select RP",
- /* 208 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 209 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 210 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 211 */ "case_else ::= ELSE expr",
- /* 212 */ "case_else ::=",
- /* 213 */ "case_operand ::= expr",
- /* 214 */ "case_operand ::=",
- /* 215 */ "exprlist ::=",
- /* 216 */ "nexprlist ::= nexprlist COMMA expr",
- /* 217 */ "nexprlist ::= expr",
- /* 218 */ "paren_exprlist ::=",
- /* 219 */ "paren_exprlist ::= LP exprlist RP",
- /* 220 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
- /* 221 */ "uniqueflag ::= UNIQUE",
- /* 222 */ "uniqueflag ::=",
- /* 223 */ "eidlist_opt ::=",
- /* 224 */ "eidlist_opt ::= LP eidlist RP",
- /* 225 */ "eidlist ::= eidlist COMMA nm collate sortorder",
- /* 226 */ "eidlist ::= nm collate sortorder",
- /* 227 */ "collate ::=",
- /* 228 */ "collate ::= COLLATE ID|STRING",
- /* 229 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 230 */ "cmd ::= VACUUM vinto",
- /* 231 */ "cmd ::= VACUUM nm vinto",
- /* 232 */ "vinto ::= INTO expr",
- /* 233 */ "vinto ::=",
- /* 234 */ "cmd ::= PRAGMA nm dbnm",
- /* 235 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 236 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 237 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 238 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 239 */ "plus_num ::= PLUS INTEGER|FLOAT",
- /* 240 */ "minus_num ::= MINUS INTEGER|FLOAT",
- /* 241 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 242 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 243 */ "trigger_time ::= BEFORE|AFTER",
- /* 244 */ "trigger_time ::= INSTEAD OF",
- /* 245 */ "trigger_time ::=",
- /* 246 */ "trigger_event ::= DELETE|INSERT",
- /* 247 */ "trigger_event ::= UPDATE",
- /* 248 */ "trigger_event ::= UPDATE OF idlist",
- /* 249 */ "when_clause ::=",
- /* 250 */ "when_clause ::= WHEN expr",
- /* 251 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 252 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 253 */ "trnm ::= nm DOT nm",
- /* 254 */ "tridxby ::= INDEXED BY nm",
- /* 255 */ "tridxby ::= NOT INDEXED",
- /* 256 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
- /* 257 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
- /* 258 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
- /* 259 */ "trigger_cmd ::= scanpt select scanpt",
- /* 260 */ "expr ::= RAISE LP IGNORE RP",
- /* 261 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 262 */ "raisetype ::= ROLLBACK",
- /* 263 */ "raisetype ::= ABORT",
- /* 264 */ "raisetype ::= FAIL",
- /* 265 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 266 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 267 */ "cmd ::= DETACH database_kw_opt expr",
- /* 268 */ "key_opt ::=",
- /* 269 */ "key_opt ::= KEY expr",
- /* 270 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 271 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
- /* 272 */ "add_column_fullname ::= fullname",
- /* 273 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
- /* 274 */ "cmd ::= create_vtab",
- /* 275 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 276 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 277 */ "vtabarg ::=",
- /* 278 */ "vtabargtoken ::= ANY",
- /* 279 */ "vtabargtoken ::= lp anylist RP",
- /* 280 */ "lp ::= LP",
- /* 281 */ "with ::= WITH wqlist",
- /* 282 */ "with ::= WITH RECURSIVE wqlist",
- /* 283 */ "wqlist ::= nm eidlist_opt AS LP select RP",
- /* 284 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
- /* 285 */ "input ::= cmdlist",
- /* 286 */ "cmdlist ::= cmdlist ecmd",
- /* 287 */ "cmdlist ::= ecmd",
- /* 288 */ "ecmd ::= SEMI",
- /* 289 */ "ecmd ::= cmdx SEMI",
- /* 290 */ "trans_opt ::=",
- /* 291 */ "trans_opt ::= TRANSACTION",
- /* 292 */ "trans_opt ::= TRANSACTION nm",
- /* 293 */ "savepoint_opt ::= SAVEPOINT",
- /* 294 */ "savepoint_opt ::=",
- /* 295 */ "cmd ::= create_table create_table_args",
- /* 296 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 297 */ "columnlist ::= columnname carglist",
- /* 298 */ "nm ::= ID|INDEXED",
- /* 299 */ "nm ::= STRING",
- /* 300 */ "nm ::= JOIN_KW",
- /* 301 */ "typetoken ::= typename",
- /* 302 */ "typename ::= ID|STRING",
- /* 303 */ "signed ::= plus_num",
- /* 304 */ "signed ::= minus_num",
- /* 305 */ "carglist ::= carglist ccons",
- /* 306 */ "carglist ::=",
- /* 307 */ "ccons ::= NULL onconf",
- /* 308 */ "ccons ::= GENERATED ALWAYS AS generated",
- /* 309 */ "ccons ::= AS generated",
- /* 310 */ "conslist_opt ::= COMMA conslist",
- /* 311 */ "conslist ::= conslist tconscomma tcons",
- /* 312 */ "conslist ::= tcons",
- /* 313 */ "tconscomma ::=",
- /* 314 */ "defer_subclause_opt ::= defer_subclause",
- /* 315 */ "resolvetype ::= raisetype",
- /* 316 */ "selectnowith ::= oneselect",
- /* 317 */ "oneselect ::= values",
- /* 318 */ "sclp ::= selcollist COMMA",
- /* 319 */ "as ::= ID|STRING",
- /* 320 */ "expr ::= term",
- /* 321 */ "likeop ::= LIKE_KW|MATCH",
- /* 322 */ "exprlist ::= nexprlist",
- /* 323 */ "nmnum ::= plus_num",
- /* 324 */ "nmnum ::= nm",
- /* 325 */ "nmnum ::= ON",
- /* 326 */ "nmnum ::= DELETE",
- /* 327 */ "nmnum ::= DEFAULT",
- /* 328 */ "plus_num ::= INTEGER|FLOAT",
- /* 329 */ "foreach_clause ::=",
- /* 330 */ "foreach_clause ::= FOR EACH ROW",
- /* 331 */ "trnm ::= nm",
- /* 332 */ "tridxby ::=",
- /* 333 */ "database_kw_opt ::= DATABASE",
- /* 334 */ "database_kw_opt ::=",
- /* 335 */ "kwcolumn_opt ::=",
- /* 336 */ "kwcolumn_opt ::= COLUMNKW",
- /* 337 */ "vtabarglist ::= vtabarg",
- /* 338 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 339 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 340 */ "anylist ::=",
- /* 341 */ "anylist ::= anylist LP anylist RP",
- /* 342 */ "anylist ::= anylist ANY",
- /* 343 */ "with ::=",
+ /* 148 */ "where_opt_ret ::=",
+ /* 149 */ "where_opt_ret ::= WHERE expr",
+ /* 150 */ "where_opt_ret ::= RETURNING selcollist",
+ /* 151 */ "where_opt_ret ::= WHERE expr RETURNING selcollist",
+ /* 152 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret",
+ /* 153 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 154 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
+ /* 155 */ "setlist ::= nm EQ expr",
+ /* 156 */ "setlist ::= LP idlist RP EQ expr",
+ /* 157 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
+ /* 158 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning",
+ /* 159 */ "upsert ::=",
+ /* 160 */ "upsert ::= RETURNING selcollist",
+ /* 161 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert",
+ /* 162 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert",
+ /* 163 */ "upsert ::= ON CONFLICT DO NOTHING returning",
+ /* 164 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning",
+ /* 165 */ "returning ::= RETURNING selcollist",
+ /* 166 */ "insert_cmd ::= INSERT orconf",
+ /* 167 */ "insert_cmd ::= REPLACE",
+ /* 168 */ "idlist_opt ::=",
+ /* 169 */ "idlist_opt ::= LP idlist RP",
+ /* 170 */ "idlist ::= idlist COMMA nm",
+ /* 171 */ "idlist ::= nm",
+ /* 172 */ "expr ::= LP expr RP",
+ /* 173 */ "expr ::= ID|INDEXED",
+ /* 174 */ "expr ::= JOIN_KW",
+ /* 175 */ "expr ::= nm DOT nm",
+ /* 176 */ "expr ::= nm DOT nm DOT nm",
+ /* 177 */ "term ::= NULL|FLOAT|BLOB",
+ /* 178 */ "term ::= STRING",
+ /* 179 */ "term ::= INTEGER",
+ /* 180 */ "expr ::= VARIABLE",
+ /* 181 */ "expr ::= expr COLLATE ID|STRING",
+ /* 182 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 183 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
+ /* 184 */ "expr ::= ID|INDEXED LP STAR RP",
+ /* 185 */ "term ::= CTIME_KW",
+ /* 186 */ "expr ::= LP nexprlist COMMA expr RP",
+ /* 187 */ "expr ::= expr AND expr",
+ /* 188 */ "expr ::= expr OR expr",
+ /* 189 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 190 */ "expr ::= expr EQ|NE expr",
+ /* 191 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 192 */ "expr ::= expr PLUS|MINUS expr",
+ /* 193 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 194 */ "expr ::= expr CONCAT expr",
+ /* 195 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 196 */ "expr ::= expr likeop expr",
+ /* 197 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 198 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 199 */ "expr ::= expr NOT NULL",
+ /* 200 */ "expr ::= expr IS expr",
+ /* 201 */ "expr ::= expr IS NOT expr",
+ /* 202 */ "expr ::= NOT expr",
+ /* 203 */ "expr ::= BITNOT expr",
+ /* 204 */ "expr ::= PLUS|MINUS expr",
+ /* 205 */ "between_op ::= BETWEEN",
+ /* 206 */ "between_op ::= NOT BETWEEN",
+ /* 207 */ "expr ::= expr between_op expr AND expr",
+ /* 208 */ "in_op ::= IN",
+ /* 209 */ "in_op ::= NOT IN",
+ /* 210 */ "expr ::= expr in_op LP exprlist RP",
+ /* 211 */ "expr ::= LP select RP",
+ /* 212 */ "expr ::= expr in_op LP select RP",
+ /* 213 */ "expr ::= expr in_op nm dbnm paren_exprlist",
+ /* 214 */ "expr ::= EXISTS LP select RP",
+ /* 215 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 216 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 217 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 218 */ "case_else ::= ELSE expr",
+ /* 219 */ "case_else ::=",
+ /* 220 */ "case_operand ::= expr",
+ /* 221 */ "case_operand ::=",
+ /* 222 */ "exprlist ::=",
+ /* 223 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 224 */ "nexprlist ::= expr",
+ /* 225 */ "paren_exprlist ::=",
+ /* 226 */ "paren_exprlist ::= LP exprlist RP",
+ /* 227 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
+ /* 228 */ "uniqueflag ::= UNIQUE",
+ /* 229 */ "uniqueflag ::=",
+ /* 230 */ "eidlist_opt ::=",
+ /* 231 */ "eidlist_opt ::= LP eidlist RP",
+ /* 232 */ "eidlist ::= eidlist COMMA nm collate sortorder",
+ /* 233 */ "eidlist ::= nm collate sortorder",
+ /* 234 */ "collate ::=",
+ /* 235 */ "collate ::= COLLATE ID|STRING",
+ /* 236 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 237 */ "cmd ::= VACUUM vinto",
+ /* 238 */ "cmd ::= VACUUM nm vinto",
+ /* 239 */ "vinto ::= INTO expr",
+ /* 240 */ "vinto ::=",
+ /* 241 */ "cmd ::= PRAGMA nm dbnm",
+ /* 242 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 243 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 244 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 245 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 246 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 247 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 248 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 249 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 250 */ "trigger_time ::= BEFORE|AFTER",
+ /* 251 */ "trigger_time ::= INSTEAD OF",
+ /* 252 */ "trigger_time ::=",
+ /* 253 */ "trigger_event ::= DELETE|INSERT",
+ /* 254 */ "trigger_event ::= UPDATE",
+ /* 255 */ "trigger_event ::= UPDATE OF idlist",
+ /* 256 */ "when_clause ::=",
+ /* 257 */ "when_clause ::= WHEN expr",
+ /* 258 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 259 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 260 */ "trnm ::= nm DOT nm",
+ /* 261 */ "tridxby ::= INDEXED BY nm",
+ /* 262 */ "tridxby ::= NOT INDEXED",
+ /* 263 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
+ /* 264 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
+ /* 265 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
+ /* 266 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 267 */ "expr ::= RAISE LP IGNORE RP",
+ /* 268 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 269 */ "raisetype ::= ROLLBACK",
+ /* 270 */ "raisetype ::= ABORT",
+ /* 271 */ "raisetype ::= FAIL",
+ /* 272 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 273 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 274 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 275 */ "key_opt ::=",
+ /* 276 */ "key_opt ::= KEY expr",
+ /* 277 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 278 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 279 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm",
+ /* 280 */ "add_column_fullname ::= fullname",
+ /* 281 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
+ /* 282 */ "cmd ::= create_vtab",
+ /* 283 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 284 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 285 */ "vtabarg ::=",
+ /* 286 */ "vtabargtoken ::= ANY",
+ /* 287 */ "vtabargtoken ::= lp anylist RP",
+ /* 288 */ "lp ::= LP",
+ /* 289 */ "with ::= WITH wqlist",
+ /* 290 */ "with ::= WITH RECURSIVE wqlist",
+ /* 291 */ "wqas ::= AS",
+ /* 292 */ "wqas ::= AS MATERIALIZED",
+ /* 293 */ "wqas ::= AS NOT MATERIALIZED",
+ /* 294 */ "wqitem ::= nm eidlist_opt wqas LP select RP",
+ /* 295 */ "wqlist ::= wqitem",
+ /* 296 */ "wqlist ::= wqlist COMMA wqitem",
+ /* 297 */ "input ::= cmdlist",
+ /* 298 */ "cmdlist ::= cmdlist ecmd",
+ /* 299 */ "cmdlist ::= ecmd",
+ /* 300 */ "ecmd ::= SEMI",
+ /* 301 */ "ecmd ::= cmdx SEMI",
+ /* 302 */ "trans_opt ::=",
+ /* 303 */ "trans_opt ::= TRANSACTION",
+ /* 304 */ "trans_opt ::= TRANSACTION nm",
+ /* 305 */ "savepoint_opt ::= SAVEPOINT",
+ /* 306 */ "savepoint_opt ::=",
+ /* 307 */ "cmd ::= create_table create_table_args",
+ /* 308 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 309 */ "columnlist ::= columnname carglist",
+ /* 310 */ "nm ::= ID|INDEXED",
+ /* 311 */ "nm ::= STRING",
+ /* 312 */ "nm ::= JOIN_KW",
+ /* 313 */ "typetoken ::= typename",
+ /* 314 */ "typename ::= ID|STRING",
+ /* 315 */ "signed ::= plus_num",
+ /* 316 */ "signed ::= minus_num",
+ /* 317 */ "carglist ::= carglist ccons",
+ /* 318 */ "carglist ::=",
+ /* 319 */ "ccons ::= NULL onconf",
+ /* 320 */ "ccons ::= GENERATED ALWAYS AS generated",
+ /* 321 */ "ccons ::= AS generated",
+ /* 322 */ "conslist_opt ::= COMMA conslist",
+ /* 323 */ "conslist ::= conslist tconscomma tcons",
+ /* 324 */ "conslist ::= tcons",
+ /* 325 */ "tconscomma ::=",
+ /* 326 */ "defer_subclause_opt ::= defer_subclause",
+ /* 327 */ "resolvetype ::= raisetype",
+ /* 328 */ "selectnowith ::= oneselect",
+ /* 329 */ "oneselect ::= values",
+ /* 330 */ "sclp ::= selcollist COMMA",
+ /* 331 */ "as ::= ID|STRING",
+ /* 332 */ "returning ::=",
+ /* 333 */ "expr ::= term",
+ /* 334 */ "likeop ::= LIKE_KW|MATCH",
+ /* 335 */ "exprlist ::= nexprlist",
+ /* 336 */ "nmnum ::= plus_num",
+ /* 337 */ "nmnum ::= nm",
+ /* 338 */ "nmnum ::= ON",
+ /* 339 */ "nmnum ::= DELETE",
+ /* 340 */ "nmnum ::= DEFAULT",
+ /* 341 */ "plus_num ::= INTEGER|FLOAT",
+ /* 342 */ "foreach_clause ::=",
+ /* 343 */ "foreach_clause ::= FOR EACH ROW",
+ /* 344 */ "trnm ::= nm",
+ /* 345 */ "tridxby ::=",
+ /* 346 */ "database_kw_opt ::= DATABASE",
+ /* 347 */ "database_kw_opt ::=",
+ /* 348 */ "kwcolumn_opt ::=",
+ /* 349 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 350 */ "vtabarglist ::= vtabarg",
+ /* 351 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 352 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 353 */ "anylist ::=",
+ /* 354 */ "anylist ::= anylist LP anylist RP",
+ /* 355 */ "anylist ::= anylist ANY",
+ /* 356 */ "with ::=",
};
#endif /* NDEBUG */
@@ -156910,74 +159138,75 @@ static void yy_destructor(
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
- case 186: /* select */
- case 220: /* selectnowith */
- case 221: /* oneselect */
- case 232: /* values */
+ case 188: /* select */
+ case 222: /* selectnowith */
+ case 223: /* oneselect */
+ case 234: /* values */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy341));
+sqlite3SelectDelete(pParse->db, (yypminor->yy457));
}
break;
- case 197: /* term */
- case 198: /* expr */
- case 227: /* where_opt */
- case 229: /* having_opt */
- case 240: /* on_opt */
- case 255: /* case_operand */
- case 257: /* case_else */
- case 260: /* vinto */
- case 267: /* when_clause */
- case 272: /* key_opt */
+ case 199: /* term */
+ case 200: /* expr */
+ case 229: /* where_opt */
+ case 231: /* having_opt */
+ case 242: /* on_opt */
+ case 249: /* where_opt_ret */
+ case 259: /* case_operand */
+ case 261: /* case_else */
+ case 264: /* vinto */
+ case 271: /* when_clause */
+ case 276: /* key_opt */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy244));
+sqlite3ExprDelete(pParse->db, (yypminor->yy62));
}
break;
- case 202: /* eidlist_opt */
- case 212: /* sortlist */
- case 213: /* eidlist */
- case 225: /* selcollist */
- case 228: /* groupby_opt */
- case 230: /* orderby_opt */
- case 233: /* nexprlist */
- case 234: /* sclp */
- case 242: /* exprlist */
- case 247: /* setlist */
- case 254: /* paren_exprlist */
- case 256: /* case_exprlist */
+ case 204: /* eidlist_opt */
+ case 214: /* sortlist */
+ case 215: /* eidlist */
+ case 227: /* selcollist */
+ case 230: /* groupby_opt */
+ case 232: /* orderby_opt */
+ case 235: /* nexprlist */
+ case 236: /* sclp */
+ case 244: /* exprlist */
+ case 250: /* setlist */
+ case 258: /* paren_exprlist */
+ case 260: /* case_exprlist */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy328));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy336));
}
break;
- case 219: /* fullname */
- case 226: /* from */
- case 236: /* seltablist */
- case 237: /* stl_prefix */
- case 243: /* xfullname */
+ case 221: /* fullname */
+ case 228: /* from */
+ case 238: /* seltablist */
+ case 239: /* stl_prefix */
+ case 245: /* xfullname */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy475));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy315));
}
break;
- case 222: /* wqlist */
+ case 224: /* wqlist */
{
-sqlite3WithDelete(pParse->db, (yypminor->yy523));
+sqlite3WithDelete(pParse->db, (yypminor->yy535));
}
break;
- case 241: /* using_opt */
- case 244: /* idlist */
- case 249: /* idlist_opt */
+ case 243: /* using_opt */
+ case 246: /* idlist */
+ case 252: /* idlist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy14));
+sqlite3IdListDelete(pParse->db, (yypminor->yy76));
}
break;
- case 263: /* trigger_cmd_list */
- case 268: /* trigger_cmd */
+ case 267: /* trigger_cmd_list */
+ case 272: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy39));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy441));
}
break;
- case 265: /* trigger_event */
+ case 269: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy168).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy440).b);
}
break;
/********* End destructor definitions *****************************************/
@@ -157268,350 +159497,363 @@ static void yy_shift(
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
- 171, /* (0) cmdx ::= cmd */
- 172, /* (1) cmd ::= BEGIN transtype trans_opt */
- 173, /* (2) transtype ::= */
- 173, /* (3) transtype ::= DEFERRED */
- 173, /* (4) transtype ::= IMMEDIATE */
- 173, /* (5) transtype ::= EXCLUSIVE */
- 172, /* (6) cmd ::= COMMIT|END trans_opt */
- 172, /* (7) cmd ::= ROLLBACK trans_opt */
- 172, /* (8) cmd ::= SAVEPOINT nm */
- 172, /* (9) cmd ::= RELEASE savepoint_opt nm */
- 172, /* (10) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
- 177, /* (11) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
- 179, /* (12) createkw ::= CREATE */
- 181, /* (13) ifnotexists ::= */
- 181, /* (14) ifnotexists ::= IF NOT EXISTS */
- 180, /* (15) temp ::= TEMP */
- 180, /* (16) temp ::= */
- 178, /* (17) create_table_args ::= LP columnlist conslist_opt RP table_options */
- 178, /* (18) create_table_args ::= AS select */
- 185, /* (19) table_options ::= */
- 185, /* (20) table_options ::= WITHOUT nm */
- 187, /* (21) columnname ::= nm typetoken */
- 189, /* (22) typetoken ::= */
- 189, /* (23) typetoken ::= typename LP signed RP */
- 189, /* (24) typetoken ::= typename LP signed COMMA signed RP */
- 190, /* (25) typename ::= typename ID|STRING */
- 194, /* (26) scanpt ::= */
- 195, /* (27) scantok ::= */
- 196, /* (28) ccons ::= CONSTRAINT nm */
- 196, /* (29) ccons ::= DEFAULT scantok term */
- 196, /* (30) ccons ::= DEFAULT LP expr RP */
- 196, /* (31) ccons ::= DEFAULT PLUS scantok term */
- 196, /* (32) ccons ::= DEFAULT MINUS scantok term */
- 196, /* (33) ccons ::= DEFAULT scantok ID|INDEXED */
- 196, /* (34) ccons ::= NOT NULL onconf */
- 196, /* (35) ccons ::= PRIMARY KEY sortorder onconf autoinc */
- 196, /* (36) ccons ::= UNIQUE onconf */
- 196, /* (37) ccons ::= CHECK LP expr RP */
- 196, /* (38) ccons ::= REFERENCES nm eidlist_opt refargs */
- 196, /* (39) ccons ::= defer_subclause */
- 196, /* (40) ccons ::= COLLATE ID|STRING */
- 205, /* (41) generated ::= LP expr RP */
- 205, /* (42) generated ::= LP expr RP ID */
- 201, /* (43) autoinc ::= */
- 201, /* (44) autoinc ::= AUTOINCR */
- 203, /* (45) refargs ::= */
- 203, /* (46) refargs ::= refargs refarg */
- 206, /* (47) refarg ::= MATCH nm */
- 206, /* (48) refarg ::= ON INSERT refact */
- 206, /* (49) refarg ::= ON DELETE refact */
- 206, /* (50) refarg ::= ON UPDATE refact */
- 207, /* (51) refact ::= SET NULL */
- 207, /* (52) refact ::= SET DEFAULT */
- 207, /* (53) refact ::= CASCADE */
- 207, /* (54) refact ::= RESTRICT */
- 207, /* (55) refact ::= NO ACTION */
- 204, /* (56) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- 204, /* (57) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- 208, /* (58) init_deferred_pred_opt ::= */
- 208, /* (59) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- 208, /* (60) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- 184, /* (61) conslist_opt ::= */
- 210, /* (62) tconscomma ::= COMMA */
- 211, /* (63) tcons ::= CONSTRAINT nm */
- 211, /* (64) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- 211, /* (65) tcons ::= UNIQUE LP sortlist RP onconf */
- 211, /* (66) tcons ::= CHECK LP expr RP onconf */
- 211, /* (67) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- 214, /* (68) defer_subclause_opt ::= */
- 199, /* (69) onconf ::= */
- 199, /* (70) onconf ::= ON CONFLICT resolvetype */
- 215, /* (71) orconf ::= */
- 215, /* (72) orconf ::= OR resolvetype */
- 216, /* (73) resolvetype ::= IGNORE */
- 216, /* (74) resolvetype ::= REPLACE */
- 172, /* (75) cmd ::= DROP TABLE ifexists fullname */
- 218, /* (76) ifexists ::= IF EXISTS */
- 218, /* (77) ifexists ::= */
- 172, /* (78) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- 172, /* (79) cmd ::= DROP VIEW ifexists fullname */
- 172, /* (80) cmd ::= select */
- 186, /* (81) select ::= WITH wqlist selectnowith */
- 186, /* (82) select ::= WITH RECURSIVE wqlist selectnowith */
- 186, /* (83) select ::= selectnowith */
- 220, /* (84) selectnowith ::= selectnowith multiselect_op oneselect */
- 223, /* (85) multiselect_op ::= UNION */
- 223, /* (86) multiselect_op ::= UNION ALL */
- 223, /* (87) multiselect_op ::= EXCEPT|INTERSECT */
- 221, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- 232, /* (89) values ::= VALUES LP nexprlist RP */
- 232, /* (90) values ::= values COMMA LP nexprlist RP */
- 224, /* (91) distinct ::= DISTINCT */
- 224, /* (92) distinct ::= ALL */
- 224, /* (93) distinct ::= */
- 234, /* (94) sclp ::= */
- 225, /* (95) selcollist ::= sclp scanpt expr scanpt as */
- 225, /* (96) selcollist ::= sclp scanpt STAR */
- 225, /* (97) selcollist ::= sclp scanpt nm DOT STAR */
- 235, /* (98) as ::= AS nm */
- 235, /* (99) as ::= */
- 226, /* (100) from ::= */
- 226, /* (101) from ::= FROM seltablist */
- 237, /* (102) stl_prefix ::= seltablist joinop */
- 237, /* (103) stl_prefix ::= */
- 236, /* (104) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- 236, /* (105) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- 236, /* (106) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- 236, /* (107) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- 182, /* (108) dbnm ::= */
- 182, /* (109) dbnm ::= DOT nm */
- 219, /* (110) fullname ::= nm */
- 219, /* (111) fullname ::= nm DOT nm */
- 243, /* (112) xfullname ::= nm */
- 243, /* (113) xfullname ::= nm DOT nm */
- 243, /* (114) xfullname ::= nm DOT nm AS nm */
- 243, /* (115) xfullname ::= nm AS nm */
- 238, /* (116) joinop ::= COMMA|JOIN */
- 238, /* (117) joinop ::= JOIN_KW JOIN */
- 238, /* (118) joinop ::= JOIN_KW nm JOIN */
- 238, /* (119) joinop ::= JOIN_KW nm nm JOIN */
- 240, /* (120) on_opt ::= ON expr */
- 240, /* (121) on_opt ::= */
- 239, /* (122) indexed_opt ::= */
- 239, /* (123) indexed_opt ::= INDEXED BY nm */
- 239, /* (124) indexed_opt ::= NOT INDEXED */
- 241, /* (125) using_opt ::= USING LP idlist RP */
- 241, /* (126) using_opt ::= */
- 230, /* (127) orderby_opt ::= */
- 230, /* (128) orderby_opt ::= ORDER BY sortlist */
- 212, /* (129) sortlist ::= sortlist COMMA expr sortorder nulls */
- 212, /* (130) sortlist ::= expr sortorder nulls */
- 200, /* (131) sortorder ::= ASC */
- 200, /* (132) sortorder ::= DESC */
- 200, /* (133) sortorder ::= */
- 245, /* (134) nulls ::= NULLS FIRST */
- 245, /* (135) nulls ::= NULLS LAST */
- 245, /* (136) nulls ::= */
- 228, /* (137) groupby_opt ::= */
- 228, /* (138) groupby_opt ::= GROUP BY nexprlist */
- 229, /* (139) having_opt ::= */
- 229, /* (140) having_opt ::= HAVING expr */
- 231, /* (141) limit_opt ::= */
- 231, /* (142) limit_opt ::= LIMIT expr */
- 231, /* (143) limit_opt ::= LIMIT expr OFFSET expr */
- 231, /* (144) limit_opt ::= LIMIT expr COMMA expr */
- 172, /* (145) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
- 227, /* (146) where_opt ::= */
- 227, /* (147) where_opt ::= WHERE expr */
- 172, /* (148) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt */
- 247, /* (149) setlist ::= setlist COMMA nm EQ expr */
- 247, /* (150) setlist ::= setlist COMMA LP idlist RP EQ expr */
- 247, /* (151) setlist ::= nm EQ expr */
- 247, /* (152) setlist ::= LP idlist RP EQ expr */
- 172, /* (153) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- 172, /* (154) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- 250, /* (155) upsert ::= */
- 250, /* (156) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- 250, /* (157) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- 250, /* (158) upsert ::= ON CONFLICT DO NOTHING */
- 248, /* (159) insert_cmd ::= INSERT orconf */
- 248, /* (160) insert_cmd ::= REPLACE */
- 249, /* (161) idlist_opt ::= */
- 249, /* (162) idlist_opt ::= LP idlist RP */
- 244, /* (163) idlist ::= idlist COMMA nm */
- 244, /* (164) idlist ::= nm */
- 198, /* (165) expr ::= LP expr RP */
- 198, /* (166) expr ::= ID|INDEXED */
- 198, /* (167) expr ::= JOIN_KW */
- 198, /* (168) expr ::= nm DOT nm */
- 198, /* (169) expr ::= nm DOT nm DOT nm */
- 197, /* (170) term ::= NULL|FLOAT|BLOB */
- 197, /* (171) term ::= STRING */
- 197, /* (172) term ::= INTEGER */
- 198, /* (173) expr ::= VARIABLE */
- 198, /* (174) expr ::= expr COLLATE ID|STRING */
- 198, /* (175) expr ::= CAST LP expr AS typetoken RP */
- 198, /* (176) expr ::= ID|INDEXED LP distinct exprlist RP */
- 198, /* (177) expr ::= ID|INDEXED LP STAR RP */
- 197, /* (178) term ::= CTIME_KW */
- 198, /* (179) expr ::= LP nexprlist COMMA expr RP */
- 198, /* (180) expr ::= expr AND expr */
- 198, /* (181) expr ::= expr OR expr */
- 198, /* (182) expr ::= expr LT|GT|GE|LE expr */
- 198, /* (183) expr ::= expr EQ|NE expr */
- 198, /* (184) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- 198, /* (185) expr ::= expr PLUS|MINUS expr */
- 198, /* (186) expr ::= expr STAR|SLASH|REM expr */
- 198, /* (187) expr ::= expr CONCAT expr */
- 251, /* (188) likeop ::= NOT LIKE_KW|MATCH */
- 198, /* (189) expr ::= expr likeop expr */
- 198, /* (190) expr ::= expr likeop expr ESCAPE expr */
- 198, /* (191) expr ::= expr ISNULL|NOTNULL */
- 198, /* (192) expr ::= expr NOT NULL */
- 198, /* (193) expr ::= expr IS expr */
- 198, /* (194) expr ::= expr IS NOT expr */
- 198, /* (195) expr ::= NOT expr */
- 198, /* (196) expr ::= BITNOT expr */
- 198, /* (197) expr ::= PLUS|MINUS expr */
- 252, /* (198) between_op ::= BETWEEN */
- 252, /* (199) between_op ::= NOT BETWEEN */
- 198, /* (200) expr ::= expr between_op expr AND expr */
- 253, /* (201) in_op ::= IN */
- 253, /* (202) in_op ::= NOT IN */
- 198, /* (203) expr ::= expr in_op LP exprlist RP */
- 198, /* (204) expr ::= LP select RP */
- 198, /* (205) expr ::= expr in_op LP select RP */
- 198, /* (206) expr ::= expr in_op nm dbnm paren_exprlist */
- 198, /* (207) expr ::= EXISTS LP select RP */
- 198, /* (208) expr ::= CASE case_operand case_exprlist case_else END */
- 256, /* (209) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- 256, /* (210) case_exprlist ::= WHEN expr THEN expr */
- 257, /* (211) case_else ::= ELSE expr */
- 257, /* (212) case_else ::= */
- 255, /* (213) case_operand ::= expr */
- 255, /* (214) case_operand ::= */
- 242, /* (215) exprlist ::= */
- 233, /* (216) nexprlist ::= nexprlist COMMA expr */
- 233, /* (217) nexprlist ::= expr */
- 254, /* (218) paren_exprlist ::= */
- 254, /* (219) paren_exprlist ::= LP exprlist RP */
- 172, /* (220) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- 258, /* (221) uniqueflag ::= UNIQUE */
- 258, /* (222) uniqueflag ::= */
- 202, /* (223) eidlist_opt ::= */
- 202, /* (224) eidlist_opt ::= LP eidlist RP */
- 213, /* (225) eidlist ::= eidlist COMMA nm collate sortorder */
- 213, /* (226) eidlist ::= nm collate sortorder */
- 259, /* (227) collate ::= */
- 259, /* (228) collate ::= COLLATE ID|STRING */
- 172, /* (229) cmd ::= DROP INDEX ifexists fullname */
- 172, /* (230) cmd ::= VACUUM vinto */
- 172, /* (231) cmd ::= VACUUM nm vinto */
- 260, /* (232) vinto ::= INTO expr */
- 260, /* (233) vinto ::= */
- 172, /* (234) cmd ::= PRAGMA nm dbnm */
- 172, /* (235) cmd ::= PRAGMA nm dbnm EQ nmnum */
- 172, /* (236) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- 172, /* (237) cmd ::= PRAGMA nm dbnm EQ minus_num */
- 172, /* (238) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- 192, /* (239) plus_num ::= PLUS INTEGER|FLOAT */
- 193, /* (240) minus_num ::= MINUS INTEGER|FLOAT */
- 172, /* (241) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- 262, /* (242) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- 264, /* (243) trigger_time ::= BEFORE|AFTER */
- 264, /* (244) trigger_time ::= INSTEAD OF */
- 264, /* (245) trigger_time ::= */
- 265, /* (246) trigger_event ::= DELETE|INSERT */
- 265, /* (247) trigger_event ::= UPDATE */
- 265, /* (248) trigger_event ::= UPDATE OF idlist */
- 267, /* (249) when_clause ::= */
- 267, /* (250) when_clause ::= WHEN expr */
- 263, /* (251) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- 263, /* (252) trigger_cmd_list ::= trigger_cmd SEMI */
- 269, /* (253) trnm ::= nm DOT nm */
- 270, /* (254) tridxby ::= INDEXED BY nm */
- 270, /* (255) tridxby ::= NOT INDEXED */
- 268, /* (256) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
- 268, /* (257) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- 268, /* (258) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- 268, /* (259) trigger_cmd ::= scanpt select scanpt */
- 198, /* (260) expr ::= RAISE LP IGNORE RP */
- 198, /* (261) expr ::= RAISE LP raisetype COMMA nm RP */
- 217, /* (262) raisetype ::= ROLLBACK */
- 217, /* (263) raisetype ::= ABORT */
- 217, /* (264) raisetype ::= FAIL */
- 172, /* (265) cmd ::= DROP TRIGGER ifexists fullname */
- 172, /* (266) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- 172, /* (267) cmd ::= DETACH database_kw_opt expr */
- 272, /* (268) key_opt ::= */
- 272, /* (269) key_opt ::= KEY expr */
- 172, /* (270) cmd ::= ALTER TABLE fullname RENAME TO nm */
- 172, /* (271) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- 273, /* (272) add_column_fullname ::= fullname */
- 172, /* (273) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- 172, /* (274) cmd ::= create_vtab */
- 172, /* (275) cmd ::= create_vtab LP vtabarglist RP */
- 275, /* (276) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 277, /* (277) vtabarg ::= */
- 278, /* (278) vtabargtoken ::= ANY */
- 278, /* (279) vtabargtoken ::= lp anylist RP */
- 279, /* (280) lp ::= LP */
- 246, /* (281) with ::= WITH wqlist */
- 246, /* (282) with ::= WITH RECURSIVE wqlist */
- 222, /* (283) wqlist ::= nm eidlist_opt AS LP select RP */
- 222, /* (284) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- 168, /* (285) input ::= cmdlist */
- 169, /* (286) cmdlist ::= cmdlist ecmd */
- 169, /* (287) cmdlist ::= ecmd */
- 170, /* (288) ecmd ::= SEMI */
- 170, /* (289) ecmd ::= cmdx SEMI */
- 174, /* (290) trans_opt ::= */
- 174, /* (291) trans_opt ::= TRANSACTION */
- 174, /* (292) trans_opt ::= TRANSACTION nm */
- 176, /* (293) savepoint_opt ::= SAVEPOINT */
- 176, /* (294) savepoint_opt ::= */
- 172, /* (295) cmd ::= create_table create_table_args */
- 183, /* (296) columnlist ::= columnlist COMMA columnname carglist */
- 183, /* (297) columnlist ::= columnname carglist */
- 175, /* (298) nm ::= ID|INDEXED */
- 175, /* (299) nm ::= STRING */
- 175, /* (300) nm ::= JOIN_KW */
- 189, /* (301) typetoken ::= typename */
- 190, /* (302) typename ::= ID|STRING */
- 191, /* (303) signed ::= plus_num */
- 191, /* (304) signed ::= minus_num */
- 188, /* (305) carglist ::= carglist ccons */
- 188, /* (306) carglist ::= */
- 196, /* (307) ccons ::= NULL onconf */
- 196, /* (308) ccons ::= GENERATED ALWAYS AS generated */
- 196, /* (309) ccons ::= AS generated */
- 184, /* (310) conslist_opt ::= COMMA conslist */
- 209, /* (311) conslist ::= conslist tconscomma tcons */
- 209, /* (312) conslist ::= tcons */
- 210, /* (313) tconscomma ::= */
- 214, /* (314) defer_subclause_opt ::= defer_subclause */
- 216, /* (315) resolvetype ::= raisetype */
- 220, /* (316) selectnowith ::= oneselect */
- 221, /* (317) oneselect ::= values */
- 234, /* (318) sclp ::= selcollist COMMA */
- 235, /* (319) as ::= ID|STRING */
- 198, /* (320) expr ::= term */
- 251, /* (321) likeop ::= LIKE_KW|MATCH */
- 242, /* (322) exprlist ::= nexprlist */
- 261, /* (323) nmnum ::= plus_num */
- 261, /* (324) nmnum ::= nm */
- 261, /* (325) nmnum ::= ON */
- 261, /* (326) nmnum ::= DELETE */
- 261, /* (327) nmnum ::= DEFAULT */
- 192, /* (328) plus_num ::= INTEGER|FLOAT */
- 266, /* (329) foreach_clause ::= */
- 266, /* (330) foreach_clause ::= FOR EACH ROW */
- 269, /* (331) trnm ::= nm */
- 270, /* (332) tridxby ::= */
- 271, /* (333) database_kw_opt ::= DATABASE */
- 271, /* (334) database_kw_opt ::= */
- 274, /* (335) kwcolumn_opt ::= */
- 274, /* (336) kwcolumn_opt ::= COLUMNKW */
- 276, /* (337) vtabarglist ::= vtabarg */
- 276, /* (338) vtabarglist ::= vtabarglist COMMA vtabarg */
- 277, /* (339) vtabarg ::= vtabarg vtabargtoken */
- 280, /* (340) anylist ::= */
- 280, /* (341) anylist ::= anylist LP anylist RP */
- 280, /* (342) anylist ::= anylist ANY */
- 246, /* (343) with ::= */
+ 173, /* (0) cmdx ::= cmd */
+ 174, /* (1) cmd ::= BEGIN transtype trans_opt */
+ 175, /* (2) transtype ::= */
+ 175, /* (3) transtype ::= DEFERRED */
+ 175, /* (4) transtype ::= IMMEDIATE */
+ 175, /* (5) transtype ::= EXCLUSIVE */
+ 174, /* (6) cmd ::= COMMIT|END trans_opt */
+ 174, /* (7) cmd ::= ROLLBACK trans_opt */
+ 174, /* (8) cmd ::= SAVEPOINT nm */
+ 174, /* (9) cmd ::= RELEASE savepoint_opt nm */
+ 174, /* (10) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ 179, /* (11) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ 181, /* (12) createkw ::= CREATE */
+ 183, /* (13) ifnotexists ::= */
+ 183, /* (14) ifnotexists ::= IF NOT EXISTS */
+ 182, /* (15) temp ::= TEMP */
+ 182, /* (16) temp ::= */
+ 180, /* (17) create_table_args ::= LP columnlist conslist_opt RP table_options */
+ 180, /* (18) create_table_args ::= AS select */
+ 187, /* (19) table_options ::= */
+ 187, /* (20) table_options ::= WITHOUT nm */
+ 189, /* (21) columnname ::= nm typetoken */
+ 191, /* (22) typetoken ::= */
+ 191, /* (23) typetoken ::= typename LP signed RP */
+ 191, /* (24) typetoken ::= typename LP signed COMMA signed RP */
+ 192, /* (25) typename ::= typename ID|STRING */
+ 196, /* (26) scanpt ::= */
+ 197, /* (27) scantok ::= */
+ 198, /* (28) ccons ::= CONSTRAINT nm */
+ 198, /* (29) ccons ::= DEFAULT scantok term */
+ 198, /* (30) ccons ::= DEFAULT LP expr RP */
+ 198, /* (31) ccons ::= DEFAULT PLUS scantok term */
+ 198, /* (32) ccons ::= DEFAULT MINUS scantok term */
+ 198, /* (33) ccons ::= DEFAULT scantok ID|INDEXED */
+ 198, /* (34) ccons ::= NOT NULL onconf */
+ 198, /* (35) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ 198, /* (36) ccons ::= UNIQUE onconf */
+ 198, /* (37) ccons ::= CHECK LP expr RP */
+ 198, /* (38) ccons ::= REFERENCES nm eidlist_opt refargs */
+ 198, /* (39) ccons ::= defer_subclause */
+ 198, /* (40) ccons ::= COLLATE ID|STRING */
+ 207, /* (41) generated ::= LP expr RP */
+ 207, /* (42) generated ::= LP expr RP ID */
+ 203, /* (43) autoinc ::= */
+ 203, /* (44) autoinc ::= AUTOINCR */
+ 205, /* (45) refargs ::= */
+ 205, /* (46) refargs ::= refargs refarg */
+ 208, /* (47) refarg ::= MATCH nm */
+ 208, /* (48) refarg ::= ON INSERT refact */
+ 208, /* (49) refarg ::= ON DELETE refact */
+ 208, /* (50) refarg ::= ON UPDATE refact */
+ 209, /* (51) refact ::= SET NULL */
+ 209, /* (52) refact ::= SET DEFAULT */
+ 209, /* (53) refact ::= CASCADE */
+ 209, /* (54) refact ::= RESTRICT */
+ 209, /* (55) refact ::= NO ACTION */
+ 206, /* (56) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ 206, /* (57) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 210, /* (58) init_deferred_pred_opt ::= */
+ 210, /* (59) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ 210, /* (60) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 186, /* (61) conslist_opt ::= */
+ 212, /* (62) tconscomma ::= COMMA */
+ 213, /* (63) tcons ::= CONSTRAINT nm */
+ 213, /* (64) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ 213, /* (65) tcons ::= UNIQUE LP sortlist RP onconf */
+ 213, /* (66) tcons ::= CHECK LP expr RP onconf */
+ 213, /* (67) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 216, /* (68) defer_subclause_opt ::= */
+ 201, /* (69) onconf ::= */
+ 201, /* (70) onconf ::= ON CONFLICT resolvetype */
+ 217, /* (71) orconf ::= */
+ 217, /* (72) orconf ::= OR resolvetype */
+ 218, /* (73) resolvetype ::= IGNORE */
+ 218, /* (74) resolvetype ::= REPLACE */
+ 174, /* (75) cmd ::= DROP TABLE ifexists fullname */
+ 220, /* (76) ifexists ::= IF EXISTS */
+ 220, /* (77) ifexists ::= */
+ 174, /* (78) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ 174, /* (79) cmd ::= DROP VIEW ifexists fullname */
+ 174, /* (80) cmd ::= select */
+ 188, /* (81) select ::= WITH wqlist selectnowith */
+ 188, /* (82) select ::= WITH RECURSIVE wqlist selectnowith */
+ 188, /* (83) select ::= selectnowith */
+ 222, /* (84) selectnowith ::= selectnowith multiselect_op oneselect */
+ 225, /* (85) multiselect_op ::= UNION */
+ 225, /* (86) multiselect_op ::= UNION ALL */
+ 225, /* (87) multiselect_op ::= EXCEPT|INTERSECT */
+ 223, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ 234, /* (89) values ::= VALUES LP nexprlist RP */
+ 234, /* (90) values ::= values COMMA LP nexprlist RP */
+ 226, /* (91) distinct ::= DISTINCT */
+ 226, /* (92) distinct ::= ALL */
+ 226, /* (93) distinct ::= */
+ 236, /* (94) sclp ::= */
+ 227, /* (95) selcollist ::= sclp scanpt expr scanpt as */
+ 227, /* (96) selcollist ::= sclp scanpt STAR */
+ 227, /* (97) selcollist ::= sclp scanpt nm DOT STAR */
+ 237, /* (98) as ::= AS nm */
+ 237, /* (99) as ::= */
+ 228, /* (100) from ::= */
+ 228, /* (101) from ::= FROM seltablist */
+ 239, /* (102) stl_prefix ::= seltablist joinop */
+ 239, /* (103) stl_prefix ::= */
+ 238, /* (104) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ 238, /* (105) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ 238, /* (106) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ 238, /* (107) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ 184, /* (108) dbnm ::= */
+ 184, /* (109) dbnm ::= DOT nm */
+ 221, /* (110) fullname ::= nm */
+ 221, /* (111) fullname ::= nm DOT nm */
+ 245, /* (112) xfullname ::= nm */
+ 245, /* (113) xfullname ::= nm DOT nm */
+ 245, /* (114) xfullname ::= nm DOT nm AS nm */
+ 245, /* (115) xfullname ::= nm AS nm */
+ 240, /* (116) joinop ::= COMMA|JOIN */
+ 240, /* (117) joinop ::= JOIN_KW JOIN */
+ 240, /* (118) joinop ::= JOIN_KW nm JOIN */
+ 240, /* (119) joinop ::= JOIN_KW nm nm JOIN */
+ 242, /* (120) on_opt ::= ON expr */
+ 242, /* (121) on_opt ::= */
+ 241, /* (122) indexed_opt ::= */
+ 241, /* (123) indexed_opt ::= INDEXED BY nm */
+ 241, /* (124) indexed_opt ::= NOT INDEXED */
+ 243, /* (125) using_opt ::= USING LP idlist RP */
+ 243, /* (126) using_opt ::= */
+ 232, /* (127) orderby_opt ::= */
+ 232, /* (128) orderby_opt ::= ORDER BY sortlist */
+ 214, /* (129) sortlist ::= sortlist COMMA expr sortorder nulls */
+ 214, /* (130) sortlist ::= expr sortorder nulls */
+ 202, /* (131) sortorder ::= ASC */
+ 202, /* (132) sortorder ::= DESC */
+ 202, /* (133) sortorder ::= */
+ 247, /* (134) nulls ::= NULLS FIRST */
+ 247, /* (135) nulls ::= NULLS LAST */
+ 247, /* (136) nulls ::= */
+ 230, /* (137) groupby_opt ::= */
+ 230, /* (138) groupby_opt ::= GROUP BY nexprlist */
+ 231, /* (139) having_opt ::= */
+ 231, /* (140) having_opt ::= HAVING expr */
+ 233, /* (141) limit_opt ::= */
+ 233, /* (142) limit_opt ::= LIMIT expr */
+ 233, /* (143) limit_opt ::= LIMIT expr OFFSET expr */
+ 233, /* (144) limit_opt ::= LIMIT expr COMMA expr */
+ 174, /* (145) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
+ 229, /* (146) where_opt ::= */
+ 229, /* (147) where_opt ::= WHERE expr */
+ 249, /* (148) where_opt_ret ::= */
+ 249, /* (149) where_opt_ret ::= WHERE expr */
+ 249, /* (150) where_opt_ret ::= RETURNING selcollist */
+ 249, /* (151) where_opt_ret ::= WHERE expr RETURNING selcollist */
+ 174, /* (152) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
+ 250, /* (153) setlist ::= setlist COMMA nm EQ expr */
+ 250, /* (154) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ 250, /* (155) setlist ::= nm EQ expr */
+ 250, /* (156) setlist ::= LP idlist RP EQ expr */
+ 174, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ 174, /* (158) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
+ 253, /* (159) upsert ::= */
+ 253, /* (160) upsert ::= RETURNING selcollist */
+ 253, /* (161) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+ 253, /* (162) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+ 253, /* (163) upsert ::= ON CONFLICT DO NOTHING returning */
+ 253, /* (164) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+ 254, /* (165) returning ::= RETURNING selcollist */
+ 251, /* (166) insert_cmd ::= INSERT orconf */
+ 251, /* (167) insert_cmd ::= REPLACE */
+ 252, /* (168) idlist_opt ::= */
+ 252, /* (169) idlist_opt ::= LP idlist RP */
+ 246, /* (170) idlist ::= idlist COMMA nm */
+ 246, /* (171) idlist ::= nm */
+ 200, /* (172) expr ::= LP expr RP */
+ 200, /* (173) expr ::= ID|INDEXED */
+ 200, /* (174) expr ::= JOIN_KW */
+ 200, /* (175) expr ::= nm DOT nm */
+ 200, /* (176) expr ::= nm DOT nm DOT nm */
+ 199, /* (177) term ::= NULL|FLOAT|BLOB */
+ 199, /* (178) term ::= STRING */
+ 199, /* (179) term ::= INTEGER */
+ 200, /* (180) expr ::= VARIABLE */
+ 200, /* (181) expr ::= expr COLLATE ID|STRING */
+ 200, /* (182) expr ::= CAST LP expr AS typetoken RP */
+ 200, /* (183) expr ::= ID|INDEXED LP distinct exprlist RP */
+ 200, /* (184) expr ::= ID|INDEXED LP STAR RP */
+ 199, /* (185) term ::= CTIME_KW */
+ 200, /* (186) expr ::= LP nexprlist COMMA expr RP */
+ 200, /* (187) expr ::= expr AND expr */
+ 200, /* (188) expr ::= expr OR expr */
+ 200, /* (189) expr ::= expr LT|GT|GE|LE expr */
+ 200, /* (190) expr ::= expr EQ|NE expr */
+ 200, /* (191) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ 200, /* (192) expr ::= expr PLUS|MINUS expr */
+ 200, /* (193) expr ::= expr STAR|SLASH|REM expr */
+ 200, /* (194) expr ::= expr CONCAT expr */
+ 255, /* (195) likeop ::= NOT LIKE_KW|MATCH */
+ 200, /* (196) expr ::= expr likeop expr */
+ 200, /* (197) expr ::= expr likeop expr ESCAPE expr */
+ 200, /* (198) expr ::= expr ISNULL|NOTNULL */
+ 200, /* (199) expr ::= expr NOT NULL */
+ 200, /* (200) expr ::= expr IS expr */
+ 200, /* (201) expr ::= expr IS NOT expr */
+ 200, /* (202) expr ::= NOT expr */
+ 200, /* (203) expr ::= BITNOT expr */
+ 200, /* (204) expr ::= PLUS|MINUS expr */
+ 256, /* (205) between_op ::= BETWEEN */
+ 256, /* (206) between_op ::= NOT BETWEEN */
+ 200, /* (207) expr ::= expr between_op expr AND expr */
+ 257, /* (208) in_op ::= IN */
+ 257, /* (209) in_op ::= NOT IN */
+ 200, /* (210) expr ::= expr in_op LP exprlist RP */
+ 200, /* (211) expr ::= LP select RP */
+ 200, /* (212) expr ::= expr in_op LP select RP */
+ 200, /* (213) expr ::= expr in_op nm dbnm paren_exprlist */
+ 200, /* (214) expr ::= EXISTS LP select RP */
+ 200, /* (215) expr ::= CASE case_operand case_exprlist case_else END */
+ 260, /* (216) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ 260, /* (217) case_exprlist ::= WHEN expr THEN expr */
+ 261, /* (218) case_else ::= ELSE expr */
+ 261, /* (219) case_else ::= */
+ 259, /* (220) case_operand ::= expr */
+ 259, /* (221) case_operand ::= */
+ 244, /* (222) exprlist ::= */
+ 235, /* (223) nexprlist ::= nexprlist COMMA expr */
+ 235, /* (224) nexprlist ::= expr */
+ 258, /* (225) paren_exprlist ::= */
+ 258, /* (226) paren_exprlist ::= LP exprlist RP */
+ 174, /* (227) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ 262, /* (228) uniqueflag ::= UNIQUE */
+ 262, /* (229) uniqueflag ::= */
+ 204, /* (230) eidlist_opt ::= */
+ 204, /* (231) eidlist_opt ::= LP eidlist RP */
+ 215, /* (232) eidlist ::= eidlist COMMA nm collate sortorder */
+ 215, /* (233) eidlist ::= nm collate sortorder */
+ 263, /* (234) collate ::= */
+ 263, /* (235) collate ::= COLLATE ID|STRING */
+ 174, /* (236) cmd ::= DROP INDEX ifexists fullname */
+ 174, /* (237) cmd ::= VACUUM vinto */
+ 174, /* (238) cmd ::= VACUUM nm vinto */
+ 264, /* (239) vinto ::= INTO expr */
+ 264, /* (240) vinto ::= */
+ 174, /* (241) cmd ::= PRAGMA nm dbnm */
+ 174, /* (242) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ 174, /* (243) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ 174, /* (244) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ 174, /* (245) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ 194, /* (246) plus_num ::= PLUS INTEGER|FLOAT */
+ 195, /* (247) minus_num ::= MINUS INTEGER|FLOAT */
+ 174, /* (248) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ 266, /* (249) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ 268, /* (250) trigger_time ::= BEFORE|AFTER */
+ 268, /* (251) trigger_time ::= INSTEAD OF */
+ 268, /* (252) trigger_time ::= */
+ 269, /* (253) trigger_event ::= DELETE|INSERT */
+ 269, /* (254) trigger_event ::= UPDATE */
+ 269, /* (255) trigger_event ::= UPDATE OF idlist */
+ 271, /* (256) when_clause ::= */
+ 271, /* (257) when_clause ::= WHEN expr */
+ 267, /* (258) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ 267, /* (259) trigger_cmd_list ::= trigger_cmd SEMI */
+ 273, /* (260) trnm ::= nm DOT nm */
+ 274, /* (261) tridxby ::= INDEXED BY nm */
+ 274, /* (262) tridxby ::= NOT INDEXED */
+ 272, /* (263) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+ 272, /* (264) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ 272, /* (265) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ 272, /* (266) trigger_cmd ::= scanpt select scanpt */
+ 200, /* (267) expr ::= RAISE LP IGNORE RP */
+ 200, /* (268) expr ::= RAISE LP raisetype COMMA nm RP */
+ 219, /* (269) raisetype ::= ROLLBACK */
+ 219, /* (270) raisetype ::= ABORT */
+ 219, /* (271) raisetype ::= FAIL */
+ 174, /* (272) cmd ::= DROP TRIGGER ifexists fullname */
+ 174, /* (273) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ 174, /* (274) cmd ::= DETACH database_kw_opt expr */
+ 276, /* (275) key_opt ::= */
+ 276, /* (276) key_opt ::= KEY expr */
+ 174, /* (277) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ 174, /* (278) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ 174, /* (279) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+ 277, /* (280) add_column_fullname ::= fullname */
+ 174, /* (281) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ 174, /* (282) cmd ::= create_vtab */
+ 174, /* (283) cmd ::= create_vtab LP vtabarglist RP */
+ 279, /* (284) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 281, /* (285) vtabarg ::= */
+ 282, /* (286) vtabargtoken ::= ANY */
+ 282, /* (287) vtabargtoken ::= lp anylist RP */
+ 283, /* (288) lp ::= LP */
+ 248, /* (289) with ::= WITH wqlist */
+ 248, /* (290) with ::= WITH RECURSIVE wqlist */
+ 286, /* (291) wqas ::= AS */
+ 286, /* (292) wqas ::= AS MATERIALIZED */
+ 286, /* (293) wqas ::= AS NOT MATERIALIZED */
+ 285, /* (294) wqitem ::= nm eidlist_opt wqas LP select RP */
+ 224, /* (295) wqlist ::= wqitem */
+ 224, /* (296) wqlist ::= wqlist COMMA wqitem */
+ 170, /* (297) input ::= cmdlist */
+ 171, /* (298) cmdlist ::= cmdlist ecmd */
+ 171, /* (299) cmdlist ::= ecmd */
+ 172, /* (300) ecmd ::= SEMI */
+ 172, /* (301) ecmd ::= cmdx SEMI */
+ 176, /* (302) trans_opt ::= */
+ 176, /* (303) trans_opt ::= TRANSACTION */
+ 176, /* (304) trans_opt ::= TRANSACTION nm */
+ 178, /* (305) savepoint_opt ::= SAVEPOINT */
+ 178, /* (306) savepoint_opt ::= */
+ 174, /* (307) cmd ::= create_table create_table_args */
+ 185, /* (308) columnlist ::= columnlist COMMA columnname carglist */
+ 185, /* (309) columnlist ::= columnname carglist */
+ 177, /* (310) nm ::= ID|INDEXED */
+ 177, /* (311) nm ::= STRING */
+ 177, /* (312) nm ::= JOIN_KW */
+ 191, /* (313) typetoken ::= typename */
+ 192, /* (314) typename ::= ID|STRING */
+ 193, /* (315) signed ::= plus_num */
+ 193, /* (316) signed ::= minus_num */
+ 190, /* (317) carglist ::= carglist ccons */
+ 190, /* (318) carglist ::= */
+ 198, /* (319) ccons ::= NULL onconf */
+ 198, /* (320) ccons ::= GENERATED ALWAYS AS generated */
+ 198, /* (321) ccons ::= AS generated */
+ 186, /* (322) conslist_opt ::= COMMA conslist */
+ 211, /* (323) conslist ::= conslist tconscomma tcons */
+ 211, /* (324) conslist ::= tcons */
+ 212, /* (325) tconscomma ::= */
+ 216, /* (326) defer_subclause_opt ::= defer_subclause */
+ 218, /* (327) resolvetype ::= raisetype */
+ 222, /* (328) selectnowith ::= oneselect */
+ 223, /* (329) oneselect ::= values */
+ 236, /* (330) sclp ::= selcollist COMMA */
+ 237, /* (331) as ::= ID|STRING */
+ 254, /* (332) returning ::= */
+ 200, /* (333) expr ::= term */
+ 255, /* (334) likeop ::= LIKE_KW|MATCH */
+ 244, /* (335) exprlist ::= nexprlist */
+ 265, /* (336) nmnum ::= plus_num */
+ 265, /* (337) nmnum ::= nm */
+ 265, /* (338) nmnum ::= ON */
+ 265, /* (339) nmnum ::= DELETE */
+ 265, /* (340) nmnum ::= DEFAULT */
+ 194, /* (341) plus_num ::= INTEGER|FLOAT */
+ 270, /* (342) foreach_clause ::= */
+ 270, /* (343) foreach_clause ::= FOR EACH ROW */
+ 273, /* (344) trnm ::= nm */
+ 274, /* (345) tridxby ::= */
+ 275, /* (346) database_kw_opt ::= DATABASE */
+ 275, /* (347) database_kw_opt ::= */
+ 278, /* (348) kwcolumn_opt ::= */
+ 278, /* (349) kwcolumn_opt ::= COLUMNKW */
+ 280, /* (350) vtabarglist ::= vtabarg */
+ 280, /* (351) vtabarglist ::= vtabarglist COMMA vtabarg */
+ 281, /* (352) vtabarg ::= vtabarg vtabargtoken */
+ 284, /* (353) anylist ::= */
+ 284, /* (354) anylist ::= anylist LP anylist RP */
+ 284, /* (355) anylist ::= anylist ANY */
+ 248, /* (356) with ::= */
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
@@ -157762,205 +160004,218 @@ static const signed char yyRuleInfoNRhs[] = {
-2, /* (142) limit_opt ::= LIMIT expr */
-4, /* (143) limit_opt ::= LIMIT expr OFFSET expr */
-4, /* (144) limit_opt ::= LIMIT expr COMMA expr */
- -6, /* (145) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ -6, /* (145) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
0, /* (146) where_opt ::= */
-2, /* (147) where_opt ::= WHERE expr */
- -9, /* (148) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt */
- -5, /* (149) setlist ::= setlist COMMA nm EQ expr */
- -7, /* (150) setlist ::= setlist COMMA LP idlist RP EQ expr */
- -3, /* (151) setlist ::= nm EQ expr */
- -5, /* (152) setlist ::= LP idlist RP EQ expr */
- -7, /* (153) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- -7, /* (154) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- 0, /* (155) upsert ::= */
- -11, /* (156) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- -8, /* (157) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- -4, /* (158) upsert ::= ON CONFLICT DO NOTHING */
- -2, /* (159) insert_cmd ::= INSERT orconf */
- -1, /* (160) insert_cmd ::= REPLACE */
- 0, /* (161) idlist_opt ::= */
- -3, /* (162) idlist_opt ::= LP idlist RP */
- -3, /* (163) idlist ::= idlist COMMA nm */
- -1, /* (164) idlist ::= nm */
- -3, /* (165) expr ::= LP expr RP */
- -1, /* (166) expr ::= ID|INDEXED */
- -1, /* (167) expr ::= JOIN_KW */
- -3, /* (168) expr ::= nm DOT nm */
- -5, /* (169) expr ::= nm DOT nm DOT nm */
- -1, /* (170) term ::= NULL|FLOAT|BLOB */
- -1, /* (171) term ::= STRING */
- -1, /* (172) term ::= INTEGER */
- -1, /* (173) expr ::= VARIABLE */
- -3, /* (174) expr ::= expr COLLATE ID|STRING */
- -6, /* (175) expr ::= CAST LP expr AS typetoken RP */
- -5, /* (176) expr ::= ID|INDEXED LP distinct exprlist RP */
- -4, /* (177) expr ::= ID|INDEXED LP STAR RP */
- -1, /* (178) term ::= CTIME_KW */
- -5, /* (179) expr ::= LP nexprlist COMMA expr RP */
- -3, /* (180) expr ::= expr AND expr */
- -3, /* (181) expr ::= expr OR expr */
- -3, /* (182) expr ::= expr LT|GT|GE|LE expr */
- -3, /* (183) expr ::= expr EQ|NE expr */
- -3, /* (184) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- -3, /* (185) expr ::= expr PLUS|MINUS expr */
- -3, /* (186) expr ::= expr STAR|SLASH|REM expr */
- -3, /* (187) expr ::= expr CONCAT expr */
- -2, /* (188) likeop ::= NOT LIKE_KW|MATCH */
- -3, /* (189) expr ::= expr likeop expr */
- -5, /* (190) expr ::= expr likeop expr ESCAPE expr */
- -2, /* (191) expr ::= expr ISNULL|NOTNULL */
- -3, /* (192) expr ::= expr NOT NULL */
- -3, /* (193) expr ::= expr IS expr */
- -4, /* (194) expr ::= expr IS NOT expr */
- -2, /* (195) expr ::= NOT expr */
- -2, /* (196) expr ::= BITNOT expr */
- -2, /* (197) expr ::= PLUS|MINUS expr */
- -1, /* (198) between_op ::= BETWEEN */
- -2, /* (199) between_op ::= NOT BETWEEN */
- -5, /* (200) expr ::= expr between_op expr AND expr */
- -1, /* (201) in_op ::= IN */
- -2, /* (202) in_op ::= NOT IN */
- -5, /* (203) expr ::= expr in_op LP exprlist RP */
- -3, /* (204) expr ::= LP select RP */
- -5, /* (205) expr ::= expr in_op LP select RP */
- -5, /* (206) expr ::= expr in_op nm dbnm paren_exprlist */
- -4, /* (207) expr ::= EXISTS LP select RP */
- -5, /* (208) expr ::= CASE case_operand case_exprlist case_else END */
- -5, /* (209) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- -4, /* (210) case_exprlist ::= WHEN expr THEN expr */
- -2, /* (211) case_else ::= ELSE expr */
- 0, /* (212) case_else ::= */
- -1, /* (213) case_operand ::= expr */
- 0, /* (214) case_operand ::= */
- 0, /* (215) exprlist ::= */
- -3, /* (216) nexprlist ::= nexprlist COMMA expr */
- -1, /* (217) nexprlist ::= expr */
- 0, /* (218) paren_exprlist ::= */
- -3, /* (219) paren_exprlist ::= LP exprlist RP */
- -12, /* (220) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- -1, /* (221) uniqueflag ::= UNIQUE */
- 0, /* (222) uniqueflag ::= */
- 0, /* (223) eidlist_opt ::= */
- -3, /* (224) eidlist_opt ::= LP eidlist RP */
- -5, /* (225) eidlist ::= eidlist COMMA nm collate sortorder */
- -3, /* (226) eidlist ::= nm collate sortorder */
- 0, /* (227) collate ::= */
- -2, /* (228) collate ::= COLLATE ID|STRING */
- -4, /* (229) cmd ::= DROP INDEX ifexists fullname */
- -2, /* (230) cmd ::= VACUUM vinto */
- -3, /* (231) cmd ::= VACUUM nm vinto */
- -2, /* (232) vinto ::= INTO expr */
- 0, /* (233) vinto ::= */
- -3, /* (234) cmd ::= PRAGMA nm dbnm */
- -5, /* (235) cmd ::= PRAGMA nm dbnm EQ nmnum */
- -6, /* (236) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- -5, /* (237) cmd ::= PRAGMA nm dbnm EQ minus_num */
- -6, /* (238) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- -2, /* (239) plus_num ::= PLUS INTEGER|FLOAT */
- -2, /* (240) minus_num ::= MINUS INTEGER|FLOAT */
- -5, /* (241) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- -11, /* (242) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- -1, /* (243) trigger_time ::= BEFORE|AFTER */
- -2, /* (244) trigger_time ::= INSTEAD OF */
- 0, /* (245) trigger_time ::= */
- -1, /* (246) trigger_event ::= DELETE|INSERT */
- -1, /* (247) trigger_event ::= UPDATE */
- -3, /* (248) trigger_event ::= UPDATE OF idlist */
- 0, /* (249) when_clause ::= */
- -2, /* (250) when_clause ::= WHEN expr */
- -3, /* (251) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- -2, /* (252) trigger_cmd_list ::= trigger_cmd SEMI */
- -3, /* (253) trnm ::= nm DOT nm */
- -3, /* (254) tridxby ::= INDEXED BY nm */
- -2, /* (255) tridxby ::= NOT INDEXED */
- -9, /* (256) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
- -8, /* (257) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- -6, /* (258) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- -3, /* (259) trigger_cmd ::= scanpt select scanpt */
- -4, /* (260) expr ::= RAISE LP IGNORE RP */
- -6, /* (261) expr ::= RAISE LP raisetype COMMA nm RP */
- -1, /* (262) raisetype ::= ROLLBACK */
- -1, /* (263) raisetype ::= ABORT */
- -1, /* (264) raisetype ::= FAIL */
- -4, /* (265) cmd ::= DROP TRIGGER ifexists fullname */
- -6, /* (266) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- -3, /* (267) cmd ::= DETACH database_kw_opt expr */
- 0, /* (268) key_opt ::= */
- -2, /* (269) key_opt ::= KEY expr */
- -6, /* (270) cmd ::= ALTER TABLE fullname RENAME TO nm */
- -7, /* (271) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- -1, /* (272) add_column_fullname ::= fullname */
- -8, /* (273) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- -1, /* (274) cmd ::= create_vtab */
- -4, /* (275) cmd ::= create_vtab LP vtabarglist RP */
- -8, /* (276) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 0, /* (277) vtabarg ::= */
- -1, /* (278) vtabargtoken ::= ANY */
- -3, /* (279) vtabargtoken ::= lp anylist RP */
- -1, /* (280) lp ::= LP */
- -2, /* (281) with ::= WITH wqlist */
- -3, /* (282) with ::= WITH RECURSIVE wqlist */
- -6, /* (283) wqlist ::= nm eidlist_opt AS LP select RP */
- -8, /* (284) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- -1, /* (285) input ::= cmdlist */
- -2, /* (286) cmdlist ::= cmdlist ecmd */
- -1, /* (287) cmdlist ::= ecmd */
- -1, /* (288) ecmd ::= SEMI */
- -2, /* (289) ecmd ::= cmdx SEMI */
- 0, /* (290) trans_opt ::= */
- -1, /* (291) trans_opt ::= TRANSACTION */
- -2, /* (292) trans_opt ::= TRANSACTION nm */
- -1, /* (293) savepoint_opt ::= SAVEPOINT */
- 0, /* (294) savepoint_opt ::= */
- -2, /* (295) cmd ::= create_table create_table_args */
- -4, /* (296) columnlist ::= columnlist COMMA columnname carglist */
- -2, /* (297) columnlist ::= columnname carglist */
- -1, /* (298) nm ::= ID|INDEXED */
- -1, /* (299) nm ::= STRING */
- -1, /* (300) nm ::= JOIN_KW */
- -1, /* (301) typetoken ::= typename */
- -1, /* (302) typename ::= ID|STRING */
- -1, /* (303) signed ::= plus_num */
- -1, /* (304) signed ::= minus_num */
- -2, /* (305) carglist ::= carglist ccons */
- 0, /* (306) carglist ::= */
- -2, /* (307) ccons ::= NULL onconf */
- -4, /* (308) ccons ::= GENERATED ALWAYS AS generated */
- -2, /* (309) ccons ::= AS generated */
- -2, /* (310) conslist_opt ::= COMMA conslist */
- -3, /* (311) conslist ::= conslist tconscomma tcons */
- -1, /* (312) conslist ::= tcons */
- 0, /* (313) tconscomma ::= */
- -1, /* (314) defer_subclause_opt ::= defer_subclause */
- -1, /* (315) resolvetype ::= raisetype */
- -1, /* (316) selectnowith ::= oneselect */
- -1, /* (317) oneselect ::= values */
- -2, /* (318) sclp ::= selcollist COMMA */
- -1, /* (319) as ::= ID|STRING */
- -1, /* (320) expr ::= term */
- -1, /* (321) likeop ::= LIKE_KW|MATCH */
- -1, /* (322) exprlist ::= nexprlist */
- -1, /* (323) nmnum ::= plus_num */
- -1, /* (324) nmnum ::= nm */
- -1, /* (325) nmnum ::= ON */
- -1, /* (326) nmnum ::= DELETE */
- -1, /* (327) nmnum ::= DEFAULT */
- -1, /* (328) plus_num ::= INTEGER|FLOAT */
- 0, /* (329) foreach_clause ::= */
- -3, /* (330) foreach_clause ::= FOR EACH ROW */
- -1, /* (331) trnm ::= nm */
- 0, /* (332) tridxby ::= */
- -1, /* (333) database_kw_opt ::= DATABASE */
- 0, /* (334) database_kw_opt ::= */
- 0, /* (335) kwcolumn_opt ::= */
- -1, /* (336) kwcolumn_opt ::= COLUMNKW */
- -1, /* (337) vtabarglist ::= vtabarg */
- -3, /* (338) vtabarglist ::= vtabarglist COMMA vtabarg */
- -2, /* (339) vtabarg ::= vtabarg vtabargtoken */
- 0, /* (340) anylist ::= */
- -4, /* (341) anylist ::= anylist LP anylist RP */
- -2, /* (342) anylist ::= anylist ANY */
- 0, /* (343) with ::= */
+ 0, /* (148) where_opt_ret ::= */
+ -2, /* (149) where_opt_ret ::= WHERE expr */
+ -2, /* (150) where_opt_ret ::= RETURNING selcollist */
+ -4, /* (151) where_opt_ret ::= WHERE expr RETURNING selcollist */
+ -9, /* (152) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
+ -5, /* (153) setlist ::= setlist COMMA nm EQ expr */
+ -7, /* (154) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ -3, /* (155) setlist ::= nm EQ expr */
+ -5, /* (156) setlist ::= LP idlist RP EQ expr */
+ -7, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ -8, /* (158) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
+ 0, /* (159) upsert ::= */
+ -2, /* (160) upsert ::= RETURNING selcollist */
+ -12, /* (161) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+ -9, /* (162) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+ -5, /* (163) upsert ::= ON CONFLICT DO NOTHING returning */
+ -8, /* (164) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+ -2, /* (165) returning ::= RETURNING selcollist */
+ -2, /* (166) insert_cmd ::= INSERT orconf */
+ -1, /* (167) insert_cmd ::= REPLACE */
+ 0, /* (168) idlist_opt ::= */
+ -3, /* (169) idlist_opt ::= LP idlist RP */
+ -3, /* (170) idlist ::= idlist COMMA nm */
+ -1, /* (171) idlist ::= nm */
+ -3, /* (172) expr ::= LP expr RP */
+ -1, /* (173) expr ::= ID|INDEXED */
+ -1, /* (174) expr ::= JOIN_KW */
+ -3, /* (175) expr ::= nm DOT nm */
+ -5, /* (176) expr ::= nm DOT nm DOT nm */
+ -1, /* (177) term ::= NULL|FLOAT|BLOB */
+ -1, /* (178) term ::= STRING */
+ -1, /* (179) term ::= INTEGER */
+ -1, /* (180) expr ::= VARIABLE */
+ -3, /* (181) expr ::= expr COLLATE ID|STRING */
+ -6, /* (182) expr ::= CAST LP expr AS typetoken RP */
+ -5, /* (183) expr ::= ID|INDEXED LP distinct exprlist RP */
+ -4, /* (184) expr ::= ID|INDEXED LP STAR RP */
+ -1, /* (185) term ::= CTIME_KW */
+ -5, /* (186) expr ::= LP nexprlist COMMA expr RP */
+ -3, /* (187) expr ::= expr AND expr */
+ -3, /* (188) expr ::= expr OR expr */
+ -3, /* (189) expr ::= expr LT|GT|GE|LE expr */
+ -3, /* (190) expr ::= expr EQ|NE expr */
+ -3, /* (191) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ -3, /* (192) expr ::= expr PLUS|MINUS expr */
+ -3, /* (193) expr ::= expr STAR|SLASH|REM expr */
+ -3, /* (194) expr ::= expr CONCAT expr */
+ -2, /* (195) likeop ::= NOT LIKE_KW|MATCH */
+ -3, /* (196) expr ::= expr likeop expr */
+ -5, /* (197) expr ::= expr likeop expr ESCAPE expr */
+ -2, /* (198) expr ::= expr ISNULL|NOTNULL */
+ -3, /* (199) expr ::= expr NOT NULL */
+ -3, /* (200) expr ::= expr IS expr */
+ -4, /* (201) expr ::= expr IS NOT expr */
+ -2, /* (202) expr ::= NOT expr */
+ -2, /* (203) expr ::= BITNOT expr */
+ -2, /* (204) expr ::= PLUS|MINUS expr */
+ -1, /* (205) between_op ::= BETWEEN */
+ -2, /* (206) between_op ::= NOT BETWEEN */
+ -5, /* (207) expr ::= expr between_op expr AND expr */
+ -1, /* (208) in_op ::= IN */
+ -2, /* (209) in_op ::= NOT IN */
+ -5, /* (210) expr ::= expr in_op LP exprlist RP */
+ -3, /* (211) expr ::= LP select RP */
+ -5, /* (212) expr ::= expr in_op LP select RP */
+ -5, /* (213) expr ::= expr in_op nm dbnm paren_exprlist */
+ -4, /* (214) expr ::= EXISTS LP select RP */
+ -5, /* (215) expr ::= CASE case_operand case_exprlist case_else END */
+ -5, /* (216) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ -4, /* (217) case_exprlist ::= WHEN expr THEN expr */
+ -2, /* (218) case_else ::= ELSE expr */
+ 0, /* (219) case_else ::= */
+ -1, /* (220) case_operand ::= expr */
+ 0, /* (221) case_operand ::= */
+ 0, /* (222) exprlist ::= */
+ -3, /* (223) nexprlist ::= nexprlist COMMA expr */
+ -1, /* (224) nexprlist ::= expr */
+ 0, /* (225) paren_exprlist ::= */
+ -3, /* (226) paren_exprlist ::= LP exprlist RP */
+ -12, /* (227) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ -1, /* (228) uniqueflag ::= UNIQUE */
+ 0, /* (229) uniqueflag ::= */
+ 0, /* (230) eidlist_opt ::= */
+ -3, /* (231) eidlist_opt ::= LP eidlist RP */
+ -5, /* (232) eidlist ::= eidlist COMMA nm collate sortorder */
+ -3, /* (233) eidlist ::= nm collate sortorder */
+ 0, /* (234) collate ::= */
+ -2, /* (235) collate ::= COLLATE ID|STRING */
+ -4, /* (236) cmd ::= DROP INDEX ifexists fullname */
+ -2, /* (237) cmd ::= VACUUM vinto */
+ -3, /* (238) cmd ::= VACUUM nm vinto */
+ -2, /* (239) vinto ::= INTO expr */
+ 0, /* (240) vinto ::= */
+ -3, /* (241) cmd ::= PRAGMA nm dbnm */
+ -5, /* (242) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ -6, /* (243) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ -5, /* (244) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ -6, /* (245) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ -2, /* (246) plus_num ::= PLUS INTEGER|FLOAT */
+ -2, /* (247) minus_num ::= MINUS INTEGER|FLOAT */
+ -5, /* (248) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ -11, /* (249) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ -1, /* (250) trigger_time ::= BEFORE|AFTER */
+ -2, /* (251) trigger_time ::= INSTEAD OF */
+ 0, /* (252) trigger_time ::= */
+ -1, /* (253) trigger_event ::= DELETE|INSERT */
+ -1, /* (254) trigger_event ::= UPDATE */
+ -3, /* (255) trigger_event ::= UPDATE OF idlist */
+ 0, /* (256) when_clause ::= */
+ -2, /* (257) when_clause ::= WHEN expr */
+ -3, /* (258) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ -2, /* (259) trigger_cmd_list ::= trigger_cmd SEMI */
+ -3, /* (260) trnm ::= nm DOT nm */
+ -3, /* (261) tridxby ::= INDEXED BY nm */
+ -2, /* (262) tridxby ::= NOT INDEXED */
+ -9, /* (263) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+ -8, /* (264) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ -6, /* (265) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ -3, /* (266) trigger_cmd ::= scanpt select scanpt */
+ -4, /* (267) expr ::= RAISE LP IGNORE RP */
+ -6, /* (268) expr ::= RAISE LP raisetype COMMA nm RP */
+ -1, /* (269) raisetype ::= ROLLBACK */
+ -1, /* (270) raisetype ::= ABORT */
+ -1, /* (271) raisetype ::= FAIL */
+ -4, /* (272) cmd ::= DROP TRIGGER ifexists fullname */
+ -6, /* (273) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ -3, /* (274) cmd ::= DETACH database_kw_opt expr */
+ 0, /* (275) key_opt ::= */
+ -2, /* (276) key_opt ::= KEY expr */
+ -6, /* (277) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ -7, /* (278) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ -6, /* (279) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+ -1, /* (280) add_column_fullname ::= fullname */
+ -8, /* (281) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ -1, /* (282) cmd ::= create_vtab */
+ -4, /* (283) cmd ::= create_vtab LP vtabarglist RP */
+ -8, /* (284) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 0, /* (285) vtabarg ::= */
+ -1, /* (286) vtabargtoken ::= ANY */
+ -3, /* (287) vtabargtoken ::= lp anylist RP */
+ -1, /* (288) lp ::= LP */
+ -2, /* (289) with ::= WITH wqlist */
+ -3, /* (290) with ::= WITH RECURSIVE wqlist */
+ -1, /* (291) wqas ::= AS */
+ -2, /* (292) wqas ::= AS MATERIALIZED */
+ -3, /* (293) wqas ::= AS NOT MATERIALIZED */
+ -6, /* (294) wqitem ::= nm eidlist_opt wqas LP select RP */
+ -1, /* (295) wqlist ::= wqitem */
+ -3, /* (296) wqlist ::= wqlist COMMA wqitem */
+ -1, /* (297) input ::= cmdlist */
+ -2, /* (298) cmdlist ::= cmdlist ecmd */
+ -1, /* (299) cmdlist ::= ecmd */
+ -1, /* (300) ecmd ::= SEMI */
+ -2, /* (301) ecmd ::= cmdx SEMI */
+ 0, /* (302) trans_opt ::= */
+ -1, /* (303) trans_opt ::= TRANSACTION */
+ -2, /* (304) trans_opt ::= TRANSACTION nm */
+ -1, /* (305) savepoint_opt ::= SAVEPOINT */
+ 0, /* (306) savepoint_opt ::= */
+ -2, /* (307) cmd ::= create_table create_table_args */
+ -4, /* (308) columnlist ::= columnlist COMMA columnname carglist */
+ -2, /* (309) columnlist ::= columnname carglist */
+ -1, /* (310) nm ::= ID|INDEXED */
+ -1, /* (311) nm ::= STRING */
+ -1, /* (312) nm ::= JOIN_KW */
+ -1, /* (313) typetoken ::= typename */
+ -1, /* (314) typename ::= ID|STRING */
+ -1, /* (315) signed ::= plus_num */
+ -1, /* (316) signed ::= minus_num */
+ -2, /* (317) carglist ::= carglist ccons */
+ 0, /* (318) carglist ::= */
+ -2, /* (319) ccons ::= NULL onconf */
+ -4, /* (320) ccons ::= GENERATED ALWAYS AS generated */
+ -2, /* (321) ccons ::= AS generated */
+ -2, /* (322) conslist_opt ::= COMMA conslist */
+ -3, /* (323) conslist ::= conslist tconscomma tcons */
+ -1, /* (324) conslist ::= tcons */
+ 0, /* (325) tconscomma ::= */
+ -1, /* (326) defer_subclause_opt ::= defer_subclause */
+ -1, /* (327) resolvetype ::= raisetype */
+ -1, /* (328) selectnowith ::= oneselect */
+ -1, /* (329) oneselect ::= values */
+ -2, /* (330) sclp ::= selcollist COMMA */
+ -1, /* (331) as ::= ID|STRING */
+ 0, /* (332) returning ::= */
+ -1, /* (333) expr ::= term */
+ -1, /* (334) likeop ::= LIKE_KW|MATCH */
+ -1, /* (335) exprlist ::= nexprlist */
+ -1, /* (336) nmnum ::= plus_num */
+ -1, /* (337) nmnum ::= nm */
+ -1, /* (338) nmnum ::= ON */
+ -1, /* (339) nmnum ::= DELETE */
+ -1, /* (340) nmnum ::= DEFAULT */
+ -1, /* (341) plus_num ::= INTEGER|FLOAT */
+ 0, /* (342) foreach_clause ::= */
+ -3, /* (343) foreach_clause ::= FOR EACH ROW */
+ -1, /* (344) trnm ::= nm */
+ 0, /* (345) tridxby ::= */
+ -1, /* (346) database_kw_opt ::= DATABASE */
+ 0, /* (347) database_kw_opt ::= */
+ 0, /* (348) kwcolumn_opt ::= */
+ -1, /* (349) kwcolumn_opt ::= COLUMNKW */
+ -1, /* (350) vtabarglist ::= vtabarg */
+ -3, /* (351) vtabarglist ::= vtabarglist COMMA vtabarg */
+ -2, /* (352) vtabarg ::= vtabarg vtabargtoken */
+ 0, /* (353) anylist ::= */
+ -4, /* (354) anylist ::= anylist LP anylist RP */
+ -2, /* (355) anylist ::= anylist ANY */
+ 0, /* (356) with ::= */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -157990,55 +160245,6 @@ static YYACTIONTYPE yy_reduce(
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
- assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
-#ifndef NDEBUG
- if( yyTraceFILE ){
- yysize = yyRuleInfoNRhs[yyruleno];
- if( yysize ){
- fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
- yyTracePrompt,
- yyruleno, yyRuleName[yyruleno],
- yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
- yymsp[yysize].stateno);
- }else{
- fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
- yyTracePrompt, yyruleno, yyRuleName[yyruleno],
- yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
- }
- }
-#endif /* NDEBUG */
-
- /* Check that the stack is large enough to grow by a single entry
- ** if the RHS of the rule is empty. This ensures that there is room
- ** enough on the stack to push the LHS value */
- if( yyRuleInfoNRhs[yyruleno]==0 ){
-#ifdef YYTRACKMAXSTACKDEPTH
- if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
- yypParser->yyhwm++;
- assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
- }
-#endif
-#if YYSTACKDEPTH>0
- if( yypParser->yytos>=yypParser->yystackEnd ){
- yyStackOverflow(yypParser);
- /* The call to yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
-#else
- if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
- if( yyGrowStack(yypParser) ){
- yyStackOverflow(yypParser);
- /* The call to yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
- yymsp = yypParser->yytos;
- }
-#endif
- }
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
@@ -158055,15 +160261,15 @@ static YYACTIONTYPE yy_reduce(
{ sqlite3FinishCoding(pParse); }
break;
case 1: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy222);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy116);}
break;
case 2: /* transtype ::= */
-{yymsp[1].minor.yy222 = TK_DEFERRED;}
+{yymsp[1].minor.yy116 = TK_DEFERRED;}
break;
case 3: /* transtype ::= DEFERRED */
case 4: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==4);
case 5: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==5);
-{yymsp[0].minor.yy222 = yymsp[0].major; /*A-overwrites-X*/}
+{yymsp[0].minor.yy116 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 6: /* cmd ::= COMMIT|END trans_opt */
case 7: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==7);
@@ -158086,7 +160292,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 11: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy222,0,0,yymsp[-2].minor.yy222);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy116,0,0,yymsp[-2].minor.yy116);
}
break;
case 12: /* createkw ::= CREATE */
@@ -158100,33 +160306,33 @@ static YYACTIONTYPE yy_reduce(
case 68: /* defer_subclause_opt ::= */ yytestcase(yyruleno==68);
case 77: /* ifexists ::= */ yytestcase(yyruleno==77);
case 93: /* distinct ::= */ yytestcase(yyruleno==93);
- case 227: /* collate ::= */ yytestcase(yyruleno==227);
-{yymsp[1].minor.yy222 = 0;}
+ case 234: /* collate ::= */ yytestcase(yyruleno==234);
+{yymsp[1].minor.yy116 = 0;}
break;
case 14: /* ifnotexists ::= IF NOT EXISTS */
-{yymsp[-2].minor.yy222 = 1;}
+{yymsp[-2].minor.yy116 = 1;}
break;
case 15: /* temp ::= TEMP */
case 44: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==44);
-{yymsp[0].minor.yy222 = 1;}
+{yymsp[0].minor.yy116 = 1;}
break;
case 17: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
{
- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy222,0);
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy116,0);
}
break;
case 18: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy341);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy341);
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy457);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy457);
}
break;
case 20: /* table_options ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
- yymsp[-1].minor.yy222 = TF_WithoutRowid | TF_NoVisibleRowid;
+ yymsp[-1].minor.yy116 = TF_WithoutRowid | TF_NoVisibleRowid;
}else{
- yymsp[-1].minor.yy222 = 0;
+ yymsp[-1].minor.yy116 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
@@ -158155,7 +160361,7 @@ static YYACTIONTYPE yy_reduce(
case 26: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
- yymsp[1].minor.yy386 = yyLookaheadToken.z;
+ yymsp[1].minor.yy224 = yyLookaheadToken.z;
}
break;
case 27: /* scantok ::= */
@@ -158169,17 +160375,17 @@ static YYACTIONTYPE yy_reduce(
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
case 29: /* ccons ::= DEFAULT scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy244,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy62,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 30: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy244,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy62,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
case 31: /* ccons ::= DEFAULT PLUS scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy244,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy62,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 32: /* ccons ::= DEFAULT MINUS scantok term */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy244, 0);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy62, 0);
sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);
}
break;
@@ -158194,176 +160400,158 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 34: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy222);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy116);}
break;
case 35: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy222,yymsp[0].minor.yy222,yymsp[-2].minor.yy222);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy116,yymsp[0].minor.yy116,yymsp[-2].minor.yy116);}
break;
case 36: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy222,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy116,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 37: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy244,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy62,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
break;
case 38: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy328,yymsp[0].minor.yy222);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy336,yymsp[0].minor.yy116);}
break;
case 39: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy222);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy116);}
break;
case 40: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 41: /* generated ::= LP expr RP */
-{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy244,0);}
+{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy62,0);}
break;
case 42: /* generated ::= LP expr RP ID */
-{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy244,&yymsp[0].minor.yy0);}
+{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy62,&yymsp[0].minor.yy0);}
break;
case 45: /* refargs ::= */
-{ yymsp[1].minor.yy222 = OE_None*0x0101; /* EV: R-19803-45884 */}
+{ yymsp[1].minor.yy116 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
case 46: /* refargs ::= refargs refarg */
-{ yymsp[-1].minor.yy222 = (yymsp[-1].minor.yy222 & ~yymsp[0].minor.yy501.mask) | yymsp[0].minor.yy501.value; }
+{ yymsp[-1].minor.yy116 = (yymsp[-1].minor.yy116 & ~yymsp[0].minor.yy523.mask) | yymsp[0].minor.yy523.value; }
break;
case 47: /* refarg ::= MATCH nm */
-{ yymsp[-1].minor.yy501.value = 0; yymsp[-1].minor.yy501.mask = 0x000000; }
+{ yymsp[-1].minor.yy523.value = 0; yymsp[-1].minor.yy523.mask = 0x000000; }
break;
case 48: /* refarg ::= ON INSERT refact */
-{ yymsp[-2].minor.yy501.value = 0; yymsp[-2].minor.yy501.mask = 0x000000; }
+{ yymsp[-2].minor.yy523.value = 0; yymsp[-2].minor.yy523.mask = 0x000000; }
break;
case 49: /* refarg ::= ON DELETE refact */
-{ yymsp[-2].minor.yy501.value = yymsp[0].minor.yy222; yymsp[-2].minor.yy501.mask = 0x0000ff; }
+{ yymsp[-2].minor.yy523.value = yymsp[0].minor.yy116; yymsp[-2].minor.yy523.mask = 0x0000ff; }
break;
case 50: /* refarg ::= ON UPDATE refact */
-{ yymsp[-2].minor.yy501.value = yymsp[0].minor.yy222<<8; yymsp[-2].minor.yy501.mask = 0x00ff00; }
+{ yymsp[-2].minor.yy523.value = yymsp[0].minor.yy116<<8; yymsp[-2].minor.yy523.mask = 0x00ff00; }
break;
case 51: /* refact ::= SET NULL */
-{ yymsp[-1].minor.yy222 = OE_SetNull; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy116 = OE_SetNull; /* EV: R-33326-45252 */}
break;
case 52: /* refact ::= SET DEFAULT */
-{ yymsp[-1].minor.yy222 = OE_SetDflt; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy116 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
case 53: /* refact ::= CASCADE */
-{ yymsp[0].minor.yy222 = OE_Cascade; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy116 = OE_Cascade; /* EV: R-33326-45252 */}
break;
case 54: /* refact ::= RESTRICT */
-{ yymsp[0].minor.yy222 = OE_Restrict; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy116 = OE_Restrict; /* EV: R-33326-45252 */}
break;
case 55: /* refact ::= NO ACTION */
-{ yymsp[-1].minor.yy222 = OE_None; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy116 = OE_None; /* EV: R-33326-45252 */}
break;
case 56: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-{yymsp[-2].minor.yy222 = 0;}
+{yymsp[-2].minor.yy116 = 0;}
break;
case 57: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 72: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==72);
- case 159: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==159);
-{yymsp[-1].minor.yy222 = yymsp[0].minor.yy222;}
+ case 166: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==166);
+{yymsp[-1].minor.yy116 = yymsp[0].minor.yy116;}
break;
case 59: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 76: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==76);
- case 199: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==199);
- case 202: /* in_op ::= NOT IN */ yytestcase(yyruleno==202);
- case 228: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==228);
-{yymsp[-1].minor.yy222 = 1;}
+ case 206: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==206);
+ case 209: /* in_op ::= NOT IN */ yytestcase(yyruleno==209);
+ case 235: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==235);
+{yymsp[-1].minor.yy116 = 1;}
break;
case 60: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-{yymsp[-1].minor.yy222 = 0;}
+{yymsp[-1].minor.yy116 = 0;}
break;
case 62: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
case 64: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy328,yymsp[0].minor.yy222,yymsp[-2].minor.yy222,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy336,yymsp[0].minor.yy116,yymsp[-2].minor.yy116,0);}
break;
case 65: /* tcons ::= UNIQUE LP sortlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy328,yymsp[0].minor.yy222,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy336,yymsp[0].minor.yy116,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 66: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy244,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy62,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
break;
case 67: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy328, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy328, yymsp[-1].minor.yy222);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy222);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy336, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy336, yymsp[-1].minor.yy116);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy116);
}
break;
case 69: /* onconf ::= */
case 71: /* orconf ::= */ yytestcase(yyruleno==71);
-{yymsp[1].minor.yy222 = OE_Default;}
+{yymsp[1].minor.yy116 = OE_Default;}
break;
case 70: /* onconf ::= ON CONFLICT resolvetype */
-{yymsp[-2].minor.yy222 = yymsp[0].minor.yy222;}
+{yymsp[-2].minor.yy116 = yymsp[0].minor.yy116;}
break;
case 73: /* resolvetype ::= IGNORE */
-{yymsp[0].minor.yy222 = OE_Ignore;}
+{yymsp[0].minor.yy116 = OE_Ignore;}
break;
case 74: /* resolvetype ::= REPLACE */
- case 160: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==160);
-{yymsp[0].minor.yy222 = OE_Replace;}
+ case 167: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==167);
+{yymsp[0].minor.yy116 = OE_Replace;}
break;
case 75: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy475, 0, yymsp[-1].minor.yy222);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy315, 0, yymsp[-1].minor.yy116);
}
break;
case 78: /* 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.yy328, yymsp[0].minor.yy341, yymsp[-7].minor.yy222, yymsp[-5].minor.yy222);
+ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy336, yymsp[0].minor.yy457, yymsp[-7].minor.yy116, yymsp[-5].minor.yy116);
}
break;
case 79: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy475, 1, yymsp[-1].minor.yy222);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy315, 1, yymsp[-1].minor.yy116);
}
break;
case 80: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy341, &dest);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy341);
+ sqlite3Select(pParse, yymsp[0].minor.yy457, &dest);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy457);
}
break;
case 81: /* select ::= WITH wqlist selectnowith */
-{
- Select *p = yymsp[0].minor.yy341;
- if( p ){
- p->pWith = yymsp[-1].minor.yy523;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy523);
- }
- yymsp[-2].minor.yy341 = p;
-}
+{yymsp[-2].minor.yy457 = attachWithToSelect(pParse,yymsp[0].minor.yy457,yymsp[-1].minor.yy535);}
break;
case 82: /* select ::= WITH RECURSIVE wqlist selectnowith */
-{
- Select *p = yymsp[0].minor.yy341;
- if( p ){
- p->pWith = yymsp[-1].minor.yy523;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy523);
- }
- yymsp[-3].minor.yy341 = p;
-}
+{yymsp[-3].minor.yy457 = attachWithToSelect(pParse,yymsp[0].minor.yy457,yymsp[-1].minor.yy535);}
break;
case 83: /* select ::= selectnowith */
{
- Select *p = yymsp[0].minor.yy341;
+ Select *p = yymsp[0].minor.yy457;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
- yymsp[0].minor.yy341 = p; /*A-overwrites-X*/
+ yymsp[0].minor.yy457 = p; /*A-overwrites-X*/
}
break;
case 84: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
- Select *pRhs = yymsp[0].minor.yy341;
- Select *pLhs = yymsp[-2].minor.yy341;
+ Select *pRhs = yymsp[0].minor.yy457;
+ Select *pLhs = yymsp[-2].minor.yy457;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
@@ -158373,73 +160561,73 @@ static YYACTIONTYPE yy_reduce(
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
- pRhs->op = (u8)yymsp[-1].minor.yy222;
+ pRhs->op = (u8)yymsp[-1].minor.yy116;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->selFlags &= ~SF_MultiValue;
- if( yymsp[-1].minor.yy222!=TK_ALL ) pParse->hasCompound = 1;
+ if( yymsp[-1].minor.yy116!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
}
- yymsp[-2].minor.yy341 = pRhs;
+ yymsp[-2].minor.yy457 = pRhs;
}
break;
case 85: /* multiselect_op ::= UNION */
case 87: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==87);
-{yymsp[0].minor.yy222 = yymsp[0].major; /*A-overwrites-OP*/}
+{yymsp[0].minor.yy116 = yymsp[0].major; /*A-overwrites-OP*/}
break;
case 86: /* multiselect_op ::= UNION ALL */
-{yymsp[-1].minor.yy222 = TK_ALL;}
+{yymsp[-1].minor.yy116 = TK_ALL;}
break;
case 88: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yymsp[-8].minor.yy341 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy328,yymsp[-5].minor.yy475,yymsp[-4].minor.yy244,yymsp[-3].minor.yy328,yymsp[-2].minor.yy244,yymsp[-1].minor.yy328,yymsp[-7].minor.yy222,yymsp[0].minor.yy244);
+ yymsp[-8].minor.yy457 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy336,yymsp[-5].minor.yy315,yymsp[-4].minor.yy62,yymsp[-3].minor.yy336,yymsp[-2].minor.yy62,yymsp[-1].minor.yy336,yymsp[-7].minor.yy116,yymsp[0].minor.yy62);
}
break;
case 89: /* values ::= VALUES LP nexprlist RP */
{
- yymsp[-3].minor.yy341 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy328,0,0,0,0,0,SF_Values,0);
+ yymsp[-3].minor.yy457 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy336,0,0,0,0,0,SF_Values,0);
}
break;
case 90: /* values ::= values COMMA LP nexprlist RP */
{
- Select *pRight, *pLeft = yymsp[-4].minor.yy341;
- pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy328,0,0,0,0,0,SF_Values|SF_MultiValue,0);
+ Select *pRight, *pLeft = yymsp[-4].minor.yy457;
+ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy336,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
pRight->pPrior = pLeft;
- yymsp[-4].minor.yy341 = pRight;
+ yymsp[-4].minor.yy457 = pRight;
}else{
- yymsp[-4].minor.yy341 = pLeft;
+ yymsp[-4].minor.yy457 = pLeft;
}
}
break;
case 91: /* distinct ::= DISTINCT */
-{yymsp[0].minor.yy222 = SF_Distinct;}
+{yymsp[0].minor.yy116 = SF_Distinct;}
break;
case 92: /* distinct ::= ALL */
-{yymsp[0].minor.yy222 = SF_All;}
+{yymsp[0].minor.yy116 = SF_All;}
break;
case 94: /* sclp ::= */
case 127: /* orderby_opt ::= */ yytestcase(yyruleno==127);
case 137: /* groupby_opt ::= */ yytestcase(yyruleno==137);
- case 215: /* exprlist ::= */ yytestcase(yyruleno==215);
- case 218: /* paren_exprlist ::= */ yytestcase(yyruleno==218);
- case 223: /* eidlist_opt ::= */ yytestcase(yyruleno==223);
-{yymsp[1].minor.yy328 = 0;}
+ case 222: /* exprlist ::= */ yytestcase(yyruleno==222);
+ case 225: /* paren_exprlist ::= */ yytestcase(yyruleno==225);
+ case 230: /* eidlist_opt ::= */ yytestcase(yyruleno==230);
+{yymsp[1].minor.yy336 = 0;}
break;
case 95: /* selcollist ::= sclp scanpt expr scanpt as */
{
- yymsp[-4].minor.yy328 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy328, yymsp[-2].minor.yy244);
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy328, &yymsp[0].minor.yy0, 1);
- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy328,yymsp[-3].minor.yy386,yymsp[-1].minor.yy386);
+ yymsp[-4].minor.yy336 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy336, yymsp[-2].minor.yy62);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy336, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy336,yymsp[-3].minor.yy224,yymsp[-1].minor.yy224);
}
break;
case 96: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
- yymsp[-2].minor.yy328 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy328, p);
+ yymsp[-2].minor.yy336 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy336, p);
}
break;
case 97: /* selcollist ::= sclp scanpt nm DOT STAR */
@@ -158447,56 +160635,56 @@ static YYACTIONTYPE yy_reduce(
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- yymsp[-4].minor.yy328 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy328, pDot);
+ yymsp[-4].minor.yy336 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy336, pDot);
}
break;
case 98: /* as ::= AS nm */
case 109: /* dbnm ::= DOT nm */ yytestcase(yyruleno==109);
- case 239: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==239);
- case 240: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==240);
+ case 246: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==246);
+ case 247: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==247);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
case 100: /* from ::= */
case 103: /* stl_prefix ::= */ yytestcase(yyruleno==103);
-{yymsp[1].minor.yy475 = 0;}
+{yymsp[1].minor.yy315 = 0;}
break;
case 101: /* from ::= FROM seltablist */
{
- yymsp[-1].minor.yy475 = yymsp[0].minor.yy475;
- sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy475);
+ yymsp[-1].minor.yy315 = yymsp[0].minor.yy315;
+ sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy315);
}
break;
case 102: /* stl_prefix ::= seltablist joinop */
{
- if( ALWAYS(yymsp[-1].minor.yy475 && yymsp[-1].minor.yy475->nSrc>0) ) yymsp[-1].minor.yy475->a[yymsp[-1].minor.yy475->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy222;
+ if( ALWAYS(yymsp[-1].minor.yy315 && yymsp[-1].minor.yy315->nSrc>0) ) yymsp[-1].minor.yy315->a[yymsp[-1].minor.yy315->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy116;
}
break;
case 104: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
- yymsp[-6].minor.yy475 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy475,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy244,yymsp[0].minor.yy14);
- sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy475, &yymsp[-2].minor.yy0);
+ yymsp[-6].minor.yy315 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy315,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy62,yymsp[0].minor.yy76);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy315, &yymsp[-2].minor.yy0);
}
break;
case 105: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
{
- yymsp[-8].minor.yy475 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy475,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy244,yymsp[0].minor.yy14);
- sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy475, yymsp[-4].minor.yy328);
+ yymsp[-8].minor.yy315 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy315,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy62,yymsp[0].minor.yy76);
+ sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy315, yymsp[-4].minor.yy336);
}
break;
case 106: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
- yymsp[-6].minor.yy475 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy475,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy341,yymsp[-1].minor.yy244,yymsp[0].minor.yy14);
+ yymsp[-6].minor.yy315 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy315,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy457,yymsp[-1].minor.yy62,yymsp[0].minor.yy76);
}
break;
case 107: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
- if( yymsp[-6].minor.yy475==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy244==0 && yymsp[0].minor.yy14==0 ){
- yymsp[-6].minor.yy475 = yymsp[-4].minor.yy475;
- }else if( yymsp[-4].minor.yy475->nSrc==1 ){
- yymsp[-6].minor.yy475 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy475,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy244,yymsp[0].minor.yy14);
- if( yymsp[-6].minor.yy475 ){
- struct SrcList_item *pNew = &yymsp[-6].minor.yy475->a[yymsp[-6].minor.yy475->nSrc-1];
- struct SrcList_item *pOld = yymsp[-4].minor.yy475->a;
+ if( yymsp[-6].minor.yy315==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy62==0 && yymsp[0].minor.yy76==0 ){
+ yymsp[-6].minor.yy315 = yymsp[-4].minor.yy315;
+ }else if( yymsp[-4].minor.yy315->nSrc==1 ){
+ yymsp[-6].minor.yy315 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy315,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy62,yymsp[0].minor.yy76);
+ if( yymsp[-6].minor.yy315 ){
+ SrcItem *pNew = &yymsp[-6].minor.yy315->a[yymsp[-6].minor.yy315->nSrc-1];
+ SrcItem *pOld = yymsp[-4].minor.yy315->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
@@ -158509,12 +160697,12 @@ static YYACTIONTYPE yy_reduce(
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy475);
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy315);
}else{
Select *pSubquery;
- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy475);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy475,0,0,0,0,SF_NestedFrom,0);
- yymsp[-6].minor.yy475 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy475,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy244,yymsp[0].minor.yy14);
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy315);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy315,0,0,0,0,SF_NestedFrom,0);
+ yymsp[-6].minor.yy315 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy315,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy62,yymsp[0].minor.yy76);
}
}
break;
@@ -158524,63 +160712,65 @@ static YYACTIONTYPE yy_reduce(
break;
case 110: /* fullname ::= nm */
{
- yylhsminor.yy475 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
- if( IN_RENAME_OBJECT && yylhsminor.yy475 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy475->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy315 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy315 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy315->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[0].minor.yy475 = yylhsminor.yy475;
+ yymsp[0].minor.yy315 = yylhsminor.yy315;
break;
case 111: /* fullname ::= nm DOT nm */
{
- yylhsminor.yy475 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- if( IN_RENAME_OBJECT && yylhsminor.yy475 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy475->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy315 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy315 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy315->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[-2].minor.yy475 = yylhsminor.yy475;
+ yymsp[-2].minor.yy315 = yylhsminor.yy315;
break;
case 112: /* xfullname ::= nm */
-{yymsp[0].minor.yy475 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy315 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
break;
case 113: /* xfullname ::= nm DOT nm */
-{yymsp[-2].minor.yy475 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[-2].minor.yy315 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 114: /* xfullname ::= nm DOT nm AS nm */
{
- yymsp[-4].minor.yy475 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
- if( yymsp[-4].minor.yy475 ) yymsp[-4].minor.yy475->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-4].minor.yy315 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
+ if( yymsp[-4].minor.yy315 ) yymsp[-4].minor.yy315->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 115: /* xfullname ::= nm AS nm */
{
- yymsp[-2].minor.yy475 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
- if( yymsp[-2].minor.yy475 ) yymsp[-2].minor.yy475->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-2].minor.yy315 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
+ if( yymsp[-2].minor.yy315 ) yymsp[-2].minor.yy315->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 116: /* joinop ::= COMMA|JOIN */
-{ yymsp[0].minor.yy222 = JT_INNER; }
+{ yymsp[0].minor.yy116 = JT_INNER; }
break;
case 117: /* joinop ::= JOIN_KW JOIN */
-{yymsp[-1].minor.yy222 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
+{yymsp[-1].minor.yy116 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
case 118: /* joinop ::= JOIN_KW nm JOIN */
-{yymsp[-2].minor.yy222 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
+{yymsp[-2].minor.yy116 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
case 119: /* joinop ::= JOIN_KW nm nm JOIN */
-{yymsp[-3].minor.yy222 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
+{yymsp[-3].minor.yy116 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
case 120: /* on_opt ::= ON expr */
case 140: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==140);
case 147: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==147);
- case 211: /* case_else ::= ELSE expr */ yytestcase(yyruleno==211);
- case 232: /* vinto ::= INTO expr */ yytestcase(yyruleno==232);
-{yymsp[-1].minor.yy244 = yymsp[0].minor.yy244;}
+ case 149: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==149);
+ case 218: /* case_else ::= ELSE expr */ yytestcase(yyruleno==218);
+ case 239: /* vinto ::= INTO expr */ yytestcase(yyruleno==239);
+{yymsp[-1].minor.yy62 = yymsp[0].minor.yy62;}
break;
case 121: /* on_opt ::= */
case 139: /* having_opt ::= */ yytestcase(yyruleno==139);
case 141: /* limit_opt ::= */ yytestcase(yyruleno==141);
case 146: /* where_opt ::= */ yytestcase(yyruleno==146);
- case 212: /* case_else ::= */ yytestcase(yyruleno==212);
- case 214: /* case_operand ::= */ yytestcase(yyruleno==214);
- case 233: /* vinto ::= */ yytestcase(yyruleno==233);
-{yymsp[1].minor.yy244 = 0;}
+ case 148: /* where_opt_ret ::= */ yytestcase(yyruleno==148);
+ case 219: /* case_else ::= */ yytestcase(yyruleno==219);
+ case 221: /* case_operand ::= */ yytestcase(yyruleno==221);
+ case 240: /* vinto ::= */ yytestcase(yyruleno==240);
+{yymsp[1].minor.yy62 = 0;}
break;
case 123: /* indexed_opt ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
@@ -158589,129 +160779,144 @@ static YYACTIONTYPE yy_reduce(
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
case 125: /* using_opt ::= USING LP idlist RP */
-{yymsp[-3].minor.yy14 = yymsp[-1].minor.yy14;}
+{yymsp[-3].minor.yy76 = yymsp[-1].minor.yy76;}
break;
case 126: /* using_opt ::= */
- case 161: /* idlist_opt ::= */ yytestcase(yyruleno==161);
-{yymsp[1].minor.yy14 = 0;}
+ case 168: /* idlist_opt ::= */ yytestcase(yyruleno==168);
+{yymsp[1].minor.yy76 = 0;}
break;
case 128: /* orderby_opt ::= ORDER BY sortlist */
case 138: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==138);
-{yymsp[-2].minor.yy328 = yymsp[0].minor.yy328;}
+{yymsp[-2].minor.yy336 = yymsp[0].minor.yy336;}
break;
case 129: /* sortlist ::= sortlist COMMA expr sortorder nulls */
{
- yymsp[-4].minor.yy328 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy328,yymsp[-2].minor.yy244);
- sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy328,yymsp[-1].minor.yy222,yymsp[0].minor.yy222);
+ yymsp[-4].minor.yy336 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy336,yymsp[-2].minor.yy62);
+ sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy336,yymsp[-1].minor.yy116,yymsp[0].minor.yy116);
}
break;
case 130: /* sortlist ::= expr sortorder nulls */
{
- yymsp[-2].minor.yy328 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy244); /*A-overwrites-Y*/
- sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy328,yymsp[-1].minor.yy222,yymsp[0].minor.yy222);
+ yymsp[-2].minor.yy336 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy62); /*A-overwrites-Y*/
+ sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy336,yymsp[-1].minor.yy116,yymsp[0].minor.yy116);
}
break;
case 131: /* sortorder ::= ASC */
-{yymsp[0].minor.yy222 = SQLITE_SO_ASC;}
+{yymsp[0].minor.yy116 = SQLITE_SO_ASC;}
break;
case 132: /* sortorder ::= DESC */
-{yymsp[0].minor.yy222 = SQLITE_SO_DESC;}
+{yymsp[0].minor.yy116 = SQLITE_SO_DESC;}
break;
case 133: /* sortorder ::= */
case 136: /* nulls ::= */ yytestcase(yyruleno==136);
-{yymsp[1].minor.yy222 = SQLITE_SO_UNDEFINED;}
+{yymsp[1].minor.yy116 = SQLITE_SO_UNDEFINED;}
break;
case 134: /* nulls ::= NULLS FIRST */
-{yymsp[-1].minor.yy222 = SQLITE_SO_ASC;}
+{yymsp[-1].minor.yy116 = SQLITE_SO_ASC;}
break;
case 135: /* nulls ::= NULLS LAST */
-{yymsp[-1].minor.yy222 = SQLITE_SO_DESC;}
+{yymsp[-1].minor.yy116 = SQLITE_SO_DESC;}
break;
case 142: /* limit_opt ::= LIMIT expr */
-{yymsp[-1].minor.yy244 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy244,0);}
+{yymsp[-1].minor.yy62 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy62,0);}
break;
case 143: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yymsp[-3].minor.yy244 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy244,yymsp[0].minor.yy244);}
+{yymsp[-3].minor.yy62 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy62,yymsp[0].minor.yy62);}
break;
case 144: /* limit_opt ::= LIMIT expr COMMA expr */
-{yymsp[-3].minor.yy244 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy244,yymsp[-2].minor.yy244);}
+{yymsp[-3].minor.yy62 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy62,yymsp[-2].minor.yy62);}
break;
- case 145: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ case 145: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy475, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy475,yymsp[0].minor.yy244,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy315, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy315,yymsp[0].minor.yy62,0,0);
}
break;
- case 148: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt */
+ case 150: /* where_opt_ret ::= RETURNING selcollist */
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy336); yymsp[-1].minor.yy62 = 0;}
+ break;
+ case 151: /* where_opt_ret ::= WHERE expr RETURNING selcollist */
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy336); yymsp[-3].minor.yy62 = yymsp[-2].minor.yy62;}
+ break;
+ case 152: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy475, &yymsp[-4].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy328,"set list");
- yymsp[-5].minor.yy475 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy475, yymsp[-1].minor.yy475);
- sqlite3Update(pParse,yymsp[-5].minor.yy475,yymsp[-2].minor.yy328,yymsp[0].minor.yy244,yymsp[-6].minor.yy222,0,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy315, &yymsp[-4].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy336,"set list");
+ yymsp[-5].minor.yy315 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy315, yymsp[-1].minor.yy315);
+ sqlite3Update(pParse,yymsp[-5].minor.yy315,yymsp[-2].minor.yy336,yymsp[0].minor.yy62,yymsp[-6].minor.yy116,0,0,0);
}
break;
- case 149: /* setlist ::= setlist COMMA nm EQ expr */
+ case 153: /* setlist ::= setlist COMMA nm EQ expr */
{
- yymsp[-4].minor.yy328 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy328, yymsp[0].minor.yy244);
- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy328, &yymsp[-2].minor.yy0, 1);
+ yymsp[-4].minor.yy336 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy336, yymsp[0].minor.yy62);
+ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy336, &yymsp[-2].minor.yy0, 1);
}
break;
- case 150: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
+ case 154: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
- yymsp[-6].minor.yy328 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy328, yymsp[-3].minor.yy14, yymsp[0].minor.yy244);
+ yymsp[-6].minor.yy336 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy336, yymsp[-3].minor.yy76, yymsp[0].minor.yy62);
}
break;
- case 151: /* setlist ::= nm EQ expr */
+ case 155: /* setlist ::= nm EQ expr */
{
- yylhsminor.yy328 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy244);
- sqlite3ExprListSetName(pParse, yylhsminor.yy328, &yymsp[-2].minor.yy0, 1);
+ yylhsminor.yy336 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy62);
+ sqlite3ExprListSetName(pParse, yylhsminor.yy336, &yymsp[-2].minor.yy0, 1);
}
- yymsp[-2].minor.yy328 = yylhsminor.yy328;
+ yymsp[-2].minor.yy336 = yylhsminor.yy336;
break;
- case 152: /* setlist ::= LP idlist RP EQ expr */
+ case 156: /* setlist ::= LP idlist RP EQ expr */
{
- yymsp[-4].minor.yy328 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy14, yymsp[0].minor.yy244);
+ yymsp[-4].minor.yy336 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy76, yymsp[0].minor.yy62);
}
break;
- case 153: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ case 157: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy475, yymsp[-1].minor.yy341, yymsp[-2].minor.yy14, yymsp[-5].minor.yy222, yymsp[0].minor.yy90);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy315, yymsp[-1].minor.yy457, yymsp[-2].minor.yy76, yymsp[-5].minor.yy116, yymsp[0].minor.yy402);
}
break;
- case 154: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ case 158: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy475, 0, yymsp[-2].minor.yy14, yymsp[-5].minor.yy222, 0);
+ sqlite3Insert(pParse, yymsp[-4].minor.yy315, 0, yymsp[-3].minor.yy76, yymsp[-6].minor.yy116, 0);
}
break;
- case 155: /* upsert ::= */
-{ yymsp[1].minor.yy90 = 0; }
+ case 159: /* upsert ::= */
+{ yymsp[1].minor.yy402 = 0; }
+ break;
+ case 160: /* upsert ::= RETURNING selcollist */
+{ yymsp[-1].minor.yy402 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy336); }
+ break;
+ case 161: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+{ yymsp[-11].minor.yy402 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy336,yymsp[-6].minor.yy62,yymsp[-2].minor.yy336,yymsp[-1].minor.yy62,yymsp[0].minor.yy402);}
+ break;
+ case 162: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+{ yymsp[-8].minor.yy402 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy336,yymsp[-3].minor.yy62,0,0,yymsp[0].minor.yy402); }
break;
- case 156: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
-{ yymsp[-10].minor.yy90 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy328,yymsp[-5].minor.yy244,yymsp[-1].minor.yy328,yymsp[0].minor.yy244);}
+ case 163: /* upsert ::= ON CONFLICT DO NOTHING returning */
+{ yymsp[-4].minor.yy402 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
break;
- case 157: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
-{ yymsp[-7].minor.yy90 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy328,yymsp[-2].minor.yy244,0,0); }
+ case 164: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+{ yymsp[-7].minor.yy402 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy336,yymsp[-1].minor.yy62,0);}
break;
- case 158: /* upsert ::= ON CONFLICT DO NOTHING */
-{ yymsp[-3].minor.yy90 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
+ case 165: /* returning ::= RETURNING selcollist */
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy336);}
break;
- case 162: /* idlist_opt ::= LP idlist RP */
-{yymsp[-2].minor.yy14 = yymsp[-1].minor.yy14;}
+ case 169: /* idlist_opt ::= LP idlist RP */
+{yymsp[-2].minor.yy76 = yymsp[-1].minor.yy76;}
break;
- case 163: /* idlist ::= idlist COMMA nm */
-{yymsp[-2].minor.yy14 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy14,&yymsp[0].minor.yy0);}
+ case 170: /* idlist ::= idlist COMMA nm */
+{yymsp[-2].minor.yy76 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy76,&yymsp[0].minor.yy0);}
break;
- case 164: /* idlist ::= nm */
-{yymsp[0].minor.yy14 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+ case 171: /* idlist ::= nm */
+{yymsp[0].minor.yy76 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
- case 165: /* expr ::= LP expr RP */
-{yymsp[-2].minor.yy244 = yymsp[-1].minor.yy244;}
+ case 172: /* expr ::= LP expr RP */
+{yymsp[-2].minor.yy62 = yymsp[-1].minor.yy62;}
break;
- case 166: /* expr ::= ID|INDEXED */
- case 167: /* expr ::= JOIN_KW */ yytestcase(yyruleno==167);
-{yymsp[0].minor.yy244=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 173: /* expr ::= ID|INDEXED */
+ case 174: /* expr ::= JOIN_KW */ yytestcase(yyruleno==174);
+{yymsp[0].minor.yy62=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 168: /* expr ::= nm DOT nm */
+ case 175: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
@@ -158719,11 +160924,11 @@ static YYACTIONTYPE yy_reduce(
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0);
}
- yylhsminor.yy244 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
+ yylhsminor.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
- yymsp[-2].minor.yy244 = yylhsminor.yy244;
+ yymsp[-2].minor.yy62 = yylhsminor.yy62;
break;
- case 169: /* expr ::= nm DOT nm DOT nm */
+ case 176: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
@@ -158733,26 +160938,26 @@ static YYACTIONTYPE yy_reduce(
sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0);
}
- yylhsminor.yy244 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
+ yylhsminor.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
- yymsp[-4].minor.yy244 = yylhsminor.yy244;
+ yymsp[-4].minor.yy62 = yylhsminor.yy62;
break;
- case 170: /* term ::= NULL|FLOAT|BLOB */
- case 171: /* term ::= STRING */ yytestcase(yyruleno==171);
-{yymsp[0].minor.yy244=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 177: /* term ::= NULL|FLOAT|BLOB */
+ case 178: /* term ::= STRING */ yytestcase(yyruleno==178);
+{yymsp[0].minor.yy62=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 172: /* term ::= INTEGER */
+ case 179: /* term ::= INTEGER */
{
- yylhsminor.yy244 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
+ yylhsminor.yy62 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
}
- yymsp[0].minor.yy244 = yylhsminor.yy244;
+ yymsp[0].minor.yy62 = yylhsminor.yy62;
break;
- case 173: /* expr ::= VARIABLE */
+ case 180: /* 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.yy244 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy244, n);
+ yymsp[0].minor.yy62 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy62, 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
@@ -158761,145 +160966,145 @@ static YYACTIONTYPE yy_reduce(
assert( t.n>=2 );
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
- yymsp[0].minor.yy244 = 0;
+ yymsp[0].minor.yy62 = 0;
}else{
- yymsp[0].minor.yy244 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( yymsp[0].minor.yy244 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy244->iTable);
+ yymsp[0].minor.yy62 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
+ if( yymsp[0].minor.yy62 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy62->iTable);
}
}
}
break;
- case 174: /* expr ::= expr COLLATE ID|STRING */
+ case 181: /* expr ::= expr COLLATE ID|STRING */
{
- yymsp[-2].minor.yy244 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy244, &yymsp[0].minor.yy0, 1);
+ yymsp[-2].minor.yy62 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy62, &yymsp[0].minor.yy0, 1);
}
break;
- case 175: /* expr ::= CAST LP expr AS typetoken RP */
+ case 182: /* expr ::= CAST LP expr AS typetoken RP */
{
- yymsp[-5].minor.yy244 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy244, yymsp[-3].minor.yy244, 0);
+ yymsp[-5].minor.yy62 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy62, yymsp[-3].minor.yy62, 0);
}
break;
- case 176: /* expr ::= ID|INDEXED LP distinct exprlist RP */
+ case 183: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
- yylhsminor.yy244 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy328, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy222);
+ yylhsminor.yy62 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy336, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy116);
}
- yymsp[-4].minor.yy244 = yylhsminor.yy244;
+ yymsp[-4].minor.yy62 = yylhsminor.yy62;
break;
- case 177: /* expr ::= ID|INDEXED LP STAR RP */
+ case 184: /* expr ::= ID|INDEXED LP STAR RP */
{
- yylhsminor.yy244 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
+ yylhsminor.yy62 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
}
- yymsp[-3].minor.yy244 = yylhsminor.yy244;
+ yymsp[-3].minor.yy62 = yylhsminor.yy62;
break;
- case 178: /* term ::= CTIME_KW */
+ case 185: /* term ::= CTIME_KW */
{
- yylhsminor.yy244 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
+ yylhsminor.yy62 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
- yymsp[0].minor.yy244 = yylhsminor.yy244;
+ yymsp[0].minor.yy62 = yylhsminor.yy62;
break;
- case 179: /* expr ::= LP nexprlist COMMA expr RP */
+ case 186: /* expr ::= LP nexprlist COMMA expr RP */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy328, yymsp[-1].minor.yy244);
- yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( yymsp[-4].minor.yy244 ){
- yymsp[-4].minor.yy244->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy336, yymsp[-1].minor.yy62);
+ yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( yymsp[-4].minor.yy62 ){
+ yymsp[-4].minor.yy62->x.pList = pList;
if( ALWAYS(pList->nExpr) ){
- yymsp[-4].minor.yy244->flags |= pList->a[0].pExpr->flags & EP_Propagate;
+ yymsp[-4].minor.yy62->flags |= pList->a[0].pExpr->flags & EP_Propagate;
}
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
}
break;
- case 180: /* expr ::= expr AND expr */
-{yymsp[-2].minor.yy244=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy244,yymsp[0].minor.yy244);}
+ case 187: /* expr ::= expr AND expr */
+{yymsp[-2].minor.yy62=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy62,yymsp[0].minor.yy62);}
break;
- case 181: /* expr ::= expr OR expr */
- case 182: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==182);
- case 183: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==183);
- case 184: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==184);
- case 185: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==185);
- case 186: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==186);
- case 187: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==187);
-{yymsp[-2].minor.yy244=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy244,yymsp[0].minor.yy244);}
+ case 188: /* expr ::= expr OR expr */
+ case 189: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==189);
+ case 190: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==190);
+ case 191: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==191);
+ case 192: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==192);
+ case 193: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==193);
+ case 194: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==194);
+{yymsp[-2].minor.yy62=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy62,yymsp[0].minor.yy62);}
break;
- case 188: /* likeop ::= NOT LIKE_KW|MATCH */
+ case 195: /* 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*/}
break;
- case 189: /* expr ::= expr likeop expr */
+ case 196: /* expr ::= expr likeop expr */
{
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy244);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy244);
- yymsp[-2].minor.yy244 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
- if( bNot ) yymsp[-2].minor.yy244 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy244, 0);
- if( yymsp[-2].minor.yy244 ) yymsp[-2].minor.yy244->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy62);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy62);
+ yymsp[-2].minor.yy62 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ if( bNot ) yymsp[-2].minor.yy62 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy62, 0);
+ if( yymsp[-2].minor.yy62 ) yymsp[-2].minor.yy62->flags |= EP_InfixFunc;
}
break;
- case 190: /* expr ::= expr likeop expr ESCAPE expr */
+ case 197: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy244);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy244);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy244);
- yymsp[-4].minor.yy244 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
- if( bNot ) yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy244, 0);
- if( yymsp[-4].minor.yy244 ) yymsp[-4].minor.yy244->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy62);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62);
+ yymsp[-4].minor.yy62 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
+ if( bNot ) yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy62, 0);
+ if( yymsp[-4].minor.yy62 ) yymsp[-4].minor.yy62->flags |= EP_InfixFunc;
}
break;
- case 191: /* expr ::= expr ISNULL|NOTNULL */
-{yymsp[-1].minor.yy244 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy244,0);}
+ case 198: /* expr ::= expr ISNULL|NOTNULL */
+{yymsp[-1].minor.yy62 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy62,0);}
break;
- case 192: /* expr ::= expr NOT NULL */
-{yymsp[-2].minor.yy244 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy244,0);}
+ case 199: /* expr ::= expr NOT NULL */
+{yymsp[-2].minor.yy62 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy62,0);}
break;
- case 193: /* expr ::= expr IS expr */
+ case 200: /* expr ::= expr IS expr */
{
- yymsp[-2].minor.yy244 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy244,yymsp[0].minor.yy244);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy244, yymsp[-2].minor.yy244, TK_ISNULL);
+ yymsp[-2].minor.yy62 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy62,yymsp[0].minor.yy62);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy62, yymsp[-2].minor.yy62, TK_ISNULL);
}
break;
- case 194: /* expr ::= expr IS NOT expr */
+ case 201: /* expr ::= expr IS NOT expr */
{
- yymsp[-3].minor.yy244 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy244,yymsp[0].minor.yy244);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy244, yymsp[-3].minor.yy244, TK_NOTNULL);
+ yymsp[-3].minor.yy62 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy62,yymsp[0].minor.yy62);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy62, yymsp[-3].minor.yy62, TK_NOTNULL);
}
break;
- case 195: /* expr ::= NOT expr */
- case 196: /* expr ::= BITNOT expr */ yytestcase(yyruleno==196);
-{yymsp[-1].minor.yy244 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy244, 0);/*A-overwrites-B*/}
+ case 202: /* expr ::= NOT expr */
+ case 203: /* expr ::= BITNOT expr */ yytestcase(yyruleno==203);
+{yymsp[-1].minor.yy62 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy62, 0);/*A-overwrites-B*/}
break;
- case 197: /* expr ::= PLUS|MINUS expr */
+ case 204: /* expr ::= PLUS|MINUS expr */
{
- yymsp[-1].minor.yy244 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy244, 0);
+ yymsp[-1].minor.yy62 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy62, 0);
/*A-overwrites-B*/
}
break;
- case 198: /* between_op ::= BETWEEN */
- case 201: /* in_op ::= IN */ yytestcase(yyruleno==201);
-{yymsp[0].minor.yy222 = 0;}
+ case 205: /* between_op ::= BETWEEN */
+ case 208: /* in_op ::= IN */ yytestcase(yyruleno==208);
+{yymsp[0].minor.yy116 = 0;}
break;
- case 200: /* expr ::= expr between_op expr AND expr */
+ case 207: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy244);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy244);
- yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy244, 0);
- if( yymsp[-4].minor.yy244 ){
- yymsp[-4].minor.yy244->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62);
+ yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy62, 0);
+ if( yymsp[-4].minor.yy62 ){
+ yymsp[-4].minor.yy62->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy222 ) yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy244, 0);
+ if( yymsp[-3].minor.yy116 ) yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy62, 0);
}
break;
- case 203: /* expr ::= expr in_op LP exprlist RP */
+ case 210: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy328==0 ){
+ if( yymsp[-1].minor.yy336==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -158908,197 +161113,197 @@ static YYACTIONTYPE yy_reduce(
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy244);
- yymsp[-4].minor.yy244 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy222 ? "1" : "0");
- }else if( yymsp[-1].minor.yy328->nExpr==1 && sqlite3ExprIsConstant(yymsp[-1].minor.yy328->a[0].pExpr) ){
- Expr *pRHS = yymsp[-1].minor.yy328->a[0].pExpr;
- yymsp[-1].minor.yy328->a[0].pExpr = 0;
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy328);
+ sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy62);
+ yymsp[-4].minor.yy62 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy116 ? "1" : "0");
+ }else if( yymsp[-1].minor.yy336->nExpr==1 && sqlite3ExprIsConstant(yymsp[-1].minor.yy336->a[0].pExpr) ){
+ Expr *pRHS = yymsp[-1].minor.yy336->a[0].pExpr;
+ yymsp[-1].minor.yy336->a[0].pExpr = 0;
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy336);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
- yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy244, pRHS);
- if( yymsp[-3].minor.yy222 ) yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy244, 0);
+ yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy62, pRHS);
+ if( yymsp[-3].minor.yy116 ) yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy62, 0);
}else{
- yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy244, 0);
- if( yymsp[-4].minor.yy244 ){
- yymsp[-4].minor.yy244->x.pList = yymsp[-1].minor.yy328;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy244);
+ yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0);
+ if( yymsp[-4].minor.yy62 ){
+ yymsp[-4].minor.yy62->x.pList = yymsp[-1].minor.yy336;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy62);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy328);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy336);
}
- if( yymsp[-3].minor.yy222 ) yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy244, 0);
+ if( yymsp[-3].minor.yy116 ) yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy62, 0);
}
}
break;
- case 204: /* expr ::= LP select RP */
+ case 211: /* expr ::= LP select RP */
{
- yymsp[-2].minor.yy244 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy244, yymsp[-1].minor.yy341);
+ yymsp[-2].minor.yy62 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy62, yymsp[-1].minor.yy457);
}
break;
- case 205: /* expr ::= expr in_op LP select RP */
+ case 212: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy244, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy244, yymsp[-1].minor.yy341);
- if( yymsp[-3].minor.yy222 ) yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy244, 0);
+ yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy62, yymsp[-1].minor.yy457);
+ if( yymsp[-3].minor.yy116 ) yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy62, 0);
}
break;
- case 206: /* expr ::= expr in_op nm dbnm paren_exprlist */
+ case 213: /* 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.yy328 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy328);
- yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy244, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy244, pSelect);
- if( yymsp[-3].minor.yy222 ) yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy244, 0);
+ if( yymsp[0].minor.yy336 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy336);
+ yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy62, pSelect);
+ if( yymsp[-3].minor.yy116 ) yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy62, 0);
}
break;
- case 207: /* expr ::= EXISTS LP select RP */
+ case 214: /* expr ::= EXISTS LP select RP */
{
Expr *p;
- p = yymsp[-3].minor.yy244 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy341);
+ p = yymsp[-3].minor.yy62 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
+ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy457);
}
break;
- case 208: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 215: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yymsp[-4].minor.yy244 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy244, 0);
- if( yymsp[-4].minor.yy244 ){
- yymsp[-4].minor.yy244->x.pList = yymsp[-1].minor.yy244 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy328,yymsp[-1].minor.yy244) : yymsp[-2].minor.yy328;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy244);
+ yymsp[-4].minor.yy62 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy62, 0);
+ if( yymsp[-4].minor.yy62 ){
+ yymsp[-4].minor.yy62->x.pList = yymsp[-1].minor.yy62 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy336,yymsp[-1].minor.yy62) : yymsp[-2].minor.yy336;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy62);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy328);
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy244);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy336);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy62);
}
}
break;
- case 209: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 216: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yymsp[-4].minor.yy328 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy328, yymsp[-2].minor.yy244);
- yymsp[-4].minor.yy328 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy328, yymsp[0].minor.yy244);
+ yymsp[-4].minor.yy336 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy336, yymsp[-2].minor.yy62);
+ yymsp[-4].minor.yy336 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy336, yymsp[0].minor.yy62);
}
break;
- case 210: /* case_exprlist ::= WHEN expr THEN expr */
+ case 217: /* case_exprlist ::= WHEN expr THEN expr */
{
- yymsp[-3].minor.yy328 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy244);
- yymsp[-3].minor.yy328 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy328, yymsp[0].minor.yy244);
+ yymsp[-3].minor.yy336 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62);
+ yymsp[-3].minor.yy336 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy336, yymsp[0].minor.yy62);
}
break;
- case 213: /* case_operand ::= expr */
-{yymsp[0].minor.yy244 = yymsp[0].minor.yy244; /*A-overwrites-X*/}
+ case 220: /* case_operand ::= expr */
+{yymsp[0].minor.yy62 = yymsp[0].minor.yy62; /*A-overwrites-X*/}
break;
- case 216: /* nexprlist ::= nexprlist COMMA expr */
-{yymsp[-2].minor.yy328 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy328,yymsp[0].minor.yy244);}
+ case 223: /* nexprlist ::= nexprlist COMMA expr */
+{yymsp[-2].minor.yy336 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy336,yymsp[0].minor.yy62);}
break;
- case 217: /* nexprlist ::= expr */
-{yymsp[0].minor.yy328 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy244); /*A-overwrites-Y*/}
+ case 224: /* nexprlist ::= expr */
+{yymsp[0].minor.yy336 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy62); /*A-overwrites-Y*/}
break;
- case 219: /* paren_exprlist ::= LP exprlist RP */
- case 224: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==224);
-{yymsp[-2].minor.yy328 = yymsp[-1].minor.yy328;}
+ case 226: /* paren_exprlist ::= LP exprlist RP */
+ case 231: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==231);
+{yymsp[-2].minor.yy336 = yymsp[-1].minor.yy336;}
break;
- case 220: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ case 227: /* 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.yy328, yymsp[-10].minor.yy222,
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy244, SQLITE_SO_ASC, yymsp[-8].minor.yy222, SQLITE_IDXTYPE_APPDEF);
+ sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy336, yymsp[-10].minor.yy116,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy62, SQLITE_SO_ASC, yymsp[-8].minor.yy116, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
}
break;
- case 221: /* uniqueflag ::= UNIQUE */
- case 263: /* raisetype ::= ABORT */ yytestcase(yyruleno==263);
-{yymsp[0].minor.yy222 = OE_Abort;}
+ case 228: /* uniqueflag ::= UNIQUE */
+ case 270: /* raisetype ::= ABORT */ yytestcase(yyruleno==270);
+{yymsp[0].minor.yy116 = OE_Abort;}
break;
- case 222: /* uniqueflag ::= */
-{yymsp[1].minor.yy222 = OE_None;}
+ case 229: /* uniqueflag ::= */
+{yymsp[1].minor.yy116 = OE_None;}
break;
- case 225: /* eidlist ::= eidlist COMMA nm collate sortorder */
+ case 232: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
- yymsp[-4].minor.yy328 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy328, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy222, yymsp[0].minor.yy222);
+ yymsp[-4].minor.yy336 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy336, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy116, yymsp[0].minor.yy116);
}
break;
- case 226: /* eidlist ::= nm collate sortorder */
+ case 233: /* eidlist ::= nm collate sortorder */
{
- yymsp[-2].minor.yy328 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy222, yymsp[0].minor.yy222); /*A-overwrites-Y*/
+ yymsp[-2].minor.yy336 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy116, yymsp[0].minor.yy116); /*A-overwrites-Y*/
}
break;
- case 229: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy475, yymsp[-1].minor.yy222);}
+ case 236: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy315, yymsp[-1].minor.yy116);}
break;
- case 230: /* cmd ::= VACUUM vinto */
-{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy244);}
+ case 237: /* cmd ::= VACUUM vinto */
+{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy62);}
break;
- case 231: /* cmd ::= VACUUM nm vinto */
-{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy244);}
+ case 238: /* cmd ::= VACUUM nm vinto */
+{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy62);}
break;
- case 234: /* cmd ::= PRAGMA nm dbnm */
+ case 241: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 235: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 242: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 236: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 243: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 237: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 244: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 238: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 245: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 241: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 248: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
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.yy39, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy441, &all);
}
break;
- case 242: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 249: /* 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.yy222, yymsp[-4].minor.yy168.a, yymsp[-4].minor.yy168.b, yymsp[-2].minor.yy475, yymsp[0].minor.yy244, yymsp[-10].minor.yy222, yymsp[-8].minor.yy222);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy116, yymsp[-4].minor.yy440.a, yymsp[-4].minor.yy440.b, yymsp[-2].minor.yy315, yymsp[0].minor.yy62, yymsp[-10].minor.yy116, yymsp[-8].minor.yy116);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
- case 243: /* trigger_time ::= BEFORE|AFTER */
-{ yymsp[0].minor.yy222 = yymsp[0].major; /*A-overwrites-X*/ }
+ case 250: /* trigger_time ::= BEFORE|AFTER */
+{ yymsp[0].minor.yy116 = yymsp[0].major; /*A-overwrites-X*/ }
break;
- case 244: /* trigger_time ::= INSTEAD OF */
-{ yymsp[-1].minor.yy222 = TK_INSTEAD;}
+ case 251: /* trigger_time ::= INSTEAD OF */
+{ yymsp[-1].minor.yy116 = TK_INSTEAD;}
break;
- case 245: /* trigger_time ::= */
-{ yymsp[1].minor.yy222 = TK_BEFORE; }
+ case 252: /* trigger_time ::= */
+{ yymsp[1].minor.yy116 = TK_BEFORE; }
break;
- case 246: /* trigger_event ::= DELETE|INSERT */
- case 247: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==247);
-{yymsp[0].minor.yy168.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy168.b = 0;}
+ case 253: /* trigger_event ::= DELETE|INSERT */
+ case 254: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==254);
+{yymsp[0].minor.yy440.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy440.b = 0;}
break;
- case 248: /* trigger_event ::= UPDATE OF idlist */
-{yymsp[-2].minor.yy168.a = TK_UPDATE; yymsp[-2].minor.yy168.b = yymsp[0].minor.yy14;}
+ case 255: /* trigger_event ::= UPDATE OF idlist */
+{yymsp[-2].minor.yy440.a = TK_UPDATE; yymsp[-2].minor.yy440.b = yymsp[0].minor.yy76;}
break;
- case 249: /* when_clause ::= */
- case 268: /* key_opt ::= */ yytestcase(yyruleno==268);
-{ yymsp[1].minor.yy244 = 0; }
+ case 256: /* when_clause ::= */
+ case 275: /* key_opt ::= */ yytestcase(yyruleno==275);
+{ yymsp[1].minor.yy62 = 0; }
break;
- case 250: /* when_clause ::= WHEN expr */
- case 269: /* key_opt ::= KEY expr */ yytestcase(yyruleno==269);
-{ yymsp[-1].minor.yy244 = yymsp[0].minor.yy244; }
+ case 257: /* when_clause ::= WHEN expr */
+ case 276: /* key_opt ::= KEY expr */ yytestcase(yyruleno==276);
+{ yymsp[-1].minor.yy62 = yymsp[0].minor.yy62; }
break;
- case 251: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 258: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy39!=0 );
- yymsp[-2].minor.yy39->pLast->pNext = yymsp[-1].minor.yy39;
- yymsp[-2].minor.yy39->pLast = yymsp[-1].minor.yy39;
+ assert( yymsp[-2].minor.yy441!=0 );
+ yymsp[-2].minor.yy441->pLast->pNext = yymsp[-1].minor.yy441;
+ yymsp[-2].minor.yy441->pLast = yymsp[-1].minor.yy441;
}
break;
- case 252: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 259: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy39!=0 );
- yymsp[-1].minor.yy39->pLast = yymsp[-1].minor.yy39;
+ assert( yymsp[-1].minor.yy441!=0 );
+ yymsp[-1].minor.yy441->pLast = yymsp[-1].minor.yy441;
}
break;
- case 253: /* trnm ::= nm DOT nm */
+ case 260: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
@@ -159106,190 +161311,210 @@ static YYACTIONTYPE yy_reduce(
"statements within triggers");
}
break;
- case 254: /* tridxby ::= INDEXED BY nm */
+ case 261: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 255: /* tridxby ::= NOT INDEXED */
+ case 262: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 256: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
-{yylhsminor.yy39 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy475, yymsp[-3].minor.yy328, yymsp[-1].minor.yy244, yymsp[-7].minor.yy222, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy386);}
- yymsp[-8].minor.yy39 = yylhsminor.yy39;
+ case 263: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+{yylhsminor.yy441 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy315, yymsp[-3].minor.yy336, yymsp[-1].minor.yy62, yymsp[-7].minor.yy116, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy224);}
+ yymsp[-8].minor.yy441 = yylhsminor.yy441;
break;
- case 257: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ case 264: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
- yylhsminor.yy39 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy14,yymsp[-2].minor.yy341,yymsp[-6].minor.yy222,yymsp[-1].minor.yy90,yymsp[-7].minor.yy386,yymsp[0].minor.yy386);/*yylhsminor.yy39-overwrites-yymsp[-6].minor.yy222*/
+ yylhsminor.yy441 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy76,yymsp[-2].minor.yy457,yymsp[-6].minor.yy116,yymsp[-1].minor.yy402,yymsp[-7].minor.yy224,yymsp[0].minor.yy224);/*yylhsminor.yy441-overwrites-yymsp[-6].minor.yy116*/
}
- yymsp[-7].minor.yy39 = yylhsminor.yy39;
+ yymsp[-7].minor.yy441 = yylhsminor.yy441;
break;
- case 258: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-{yylhsminor.yy39 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy244, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy386);}
- yymsp[-5].minor.yy39 = yylhsminor.yy39;
+ case 265: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+{yylhsminor.yy441 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy62, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy224);}
+ yymsp[-5].minor.yy441 = yylhsminor.yy441;
break;
- case 259: /* trigger_cmd ::= scanpt select scanpt */
-{yylhsminor.yy39 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy341, yymsp[-2].minor.yy386, yymsp[0].minor.yy386); /*yylhsminor.yy39-overwrites-yymsp[-1].minor.yy341*/}
- yymsp[-2].minor.yy39 = yylhsminor.yy39;
+ case 266: /* trigger_cmd ::= scanpt select scanpt */
+{yylhsminor.yy441 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy457, yymsp[-2].minor.yy224, yymsp[0].minor.yy224); /*yylhsminor.yy441-overwrites-yymsp[-1].minor.yy457*/}
+ yymsp[-2].minor.yy441 = yylhsminor.yy441;
break;
- case 260: /* expr ::= RAISE LP IGNORE RP */
+ case 267: /* expr ::= RAISE LP IGNORE RP */
{
- yymsp[-3].minor.yy244 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( yymsp[-3].minor.yy244 ){
- yymsp[-3].minor.yy244->affExpr = OE_Ignore;
+ yymsp[-3].minor.yy62 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
+ if( yymsp[-3].minor.yy62 ){
+ yymsp[-3].minor.yy62->affExpr = OE_Ignore;
}
}
break;
- case 261: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 268: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yymsp[-5].minor.yy244 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
- if( yymsp[-5].minor.yy244 ) {
- yymsp[-5].minor.yy244->affExpr = (char)yymsp[-3].minor.yy222;
+ yymsp[-5].minor.yy62 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
+ if( yymsp[-5].minor.yy62 ) {
+ yymsp[-5].minor.yy62->affExpr = (char)yymsp[-3].minor.yy116;
}
}
break;
- case 262: /* raisetype ::= ROLLBACK */
-{yymsp[0].minor.yy222 = OE_Rollback;}
+ case 269: /* raisetype ::= ROLLBACK */
+{yymsp[0].minor.yy116 = OE_Rollback;}
break;
- case 264: /* raisetype ::= FAIL */
-{yymsp[0].minor.yy222 = OE_Fail;}
+ case 271: /* raisetype ::= FAIL */
+{yymsp[0].minor.yy116 = OE_Fail;}
break;
- case 265: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 272: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy475,yymsp[-1].minor.yy222);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy315,yymsp[-1].minor.yy116);
}
break;
- case 266: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 273: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy244, yymsp[-1].minor.yy244, yymsp[0].minor.yy244);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, yymsp[0].minor.yy62);
}
break;
- case 267: /* cmd ::= DETACH database_kw_opt expr */
+ case 274: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy244);
+ sqlite3Detach(pParse, yymsp[0].minor.yy62);
}
break;
- case 270: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 277: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy475,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy315,&yymsp[0].minor.yy0);
}
break;
- case 271: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 278: /* 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 272: /* add_column_fullname ::= fullname */
+ case 279: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+{
+ sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy315, &yymsp[0].minor.yy0);
+}
+ break;
+ case 280: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy475);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy315);
}
break;
- case 273: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ case 281: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
- sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy475, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
+ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy315, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 274: /* cmd ::= create_vtab */
+ case 282: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 275: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 283: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 276: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 284: /* 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.yy222);
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy116);
}
break;
- case 277: /* vtabarg ::= */
+ case 285: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 278: /* vtabargtoken ::= ANY */
- case 279: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==279);
- case 280: /* lp ::= LP */ yytestcase(yyruleno==280);
+ case 286: /* vtabargtoken ::= ANY */
+ case 287: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==287);
+ case 288: /* lp ::= LP */ yytestcase(yyruleno==288);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 281: /* with ::= WITH wqlist */
- case 282: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==282);
-{ sqlite3WithPush(pParse, yymsp[0].minor.yy523, 1); }
+ case 289: /* with ::= WITH wqlist */
+ case 290: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==290);
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy535, 1); }
+ break;
+ case 291: /* wqas ::= AS */
+{yymsp[0].minor.yy518 = M10d_Any;}
+ break;
+ case 292: /* wqas ::= AS MATERIALIZED */
+{yymsp[-1].minor.yy518 = M10d_Yes;}
+ break;
+ case 293: /* wqas ::= AS NOT MATERIALIZED */
+{yymsp[-2].minor.yy518 = M10d_No;}
+ break;
+ case 294: /* wqitem ::= nm eidlist_opt wqas LP select RP */
+{
+ yymsp[-5].minor.yy403 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy336, yymsp[-1].minor.yy457, yymsp[-3].minor.yy518); /*A-overwrites-X*/
+}
break;
- case 283: /* wqlist ::= nm eidlist_opt AS LP select RP */
+ case 295: /* wqlist ::= wqitem */
{
- yymsp[-5].minor.yy523 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy328, yymsp[-1].minor.yy341); /*A-overwrites-X*/
+ yymsp[0].minor.yy535 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy403); /*A-overwrites-X*/
}
break;
- case 284: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ case 296: /* wqlist ::= wqlist COMMA wqitem */
{
- yymsp[-7].minor.yy523 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy523, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy328, yymsp[-1].minor.yy341);
+ yymsp[-2].minor.yy535 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy535, yymsp[0].minor.yy403);
}
break;
default:
- /* (285) input ::= cmdlist */ yytestcase(yyruleno==285);
- /* (286) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==286);
- /* (287) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=287);
- /* (288) ecmd ::= SEMI */ yytestcase(yyruleno==288);
- /* (289) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==289);
- /* (290) trans_opt ::= */ yytestcase(yyruleno==290);
- /* (291) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==291);
- /* (292) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==292);
- /* (293) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==293);
- /* (294) savepoint_opt ::= */ yytestcase(yyruleno==294);
- /* (295) cmd ::= create_table create_table_args */ yytestcase(yyruleno==295);
- /* (296) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==296);
- /* (297) columnlist ::= columnname carglist */ yytestcase(yyruleno==297);
- /* (298) nm ::= ID|INDEXED */ yytestcase(yyruleno==298);
- /* (299) nm ::= STRING */ yytestcase(yyruleno==299);
- /* (300) nm ::= JOIN_KW */ yytestcase(yyruleno==300);
- /* (301) typetoken ::= typename */ yytestcase(yyruleno==301);
- /* (302) typename ::= ID|STRING */ yytestcase(yyruleno==302);
- /* (303) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=303);
- /* (304) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=304);
- /* (305) carglist ::= carglist ccons */ yytestcase(yyruleno==305);
- /* (306) carglist ::= */ yytestcase(yyruleno==306);
- /* (307) ccons ::= NULL onconf */ yytestcase(yyruleno==307);
- /* (308) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==308);
- /* (309) ccons ::= AS generated */ yytestcase(yyruleno==309);
- /* (310) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==310);
- /* (311) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==311);
- /* (312) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=312);
- /* (313) tconscomma ::= */ yytestcase(yyruleno==313);
- /* (314) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=314);
- /* (315) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=315);
- /* (316) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=316);
- /* (317) oneselect ::= values */ yytestcase(yyruleno==317);
- /* (318) sclp ::= selcollist COMMA */ yytestcase(yyruleno==318);
- /* (319) as ::= ID|STRING */ yytestcase(yyruleno==319);
- /* (320) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=320);
- /* (321) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==321);
- /* (322) exprlist ::= nexprlist */ yytestcase(yyruleno==322);
- /* (323) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=323);
- /* (324) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=324);
- /* (325) nmnum ::= ON */ yytestcase(yyruleno==325);
- /* (326) nmnum ::= DELETE */ yytestcase(yyruleno==326);
- /* (327) nmnum ::= DEFAULT */ yytestcase(yyruleno==327);
- /* (328) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==328);
- /* (329) foreach_clause ::= */ yytestcase(yyruleno==329);
- /* (330) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==330);
- /* (331) trnm ::= nm */ yytestcase(yyruleno==331);
- /* (332) tridxby ::= */ yytestcase(yyruleno==332);
- /* (333) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==333);
- /* (334) database_kw_opt ::= */ yytestcase(yyruleno==334);
- /* (335) kwcolumn_opt ::= */ yytestcase(yyruleno==335);
- /* (336) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==336);
- /* (337) vtabarglist ::= vtabarg */ yytestcase(yyruleno==337);
- /* (338) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==338);
- /* (339) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==339);
- /* (340) anylist ::= */ yytestcase(yyruleno==340);
- /* (341) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==341);
- /* (342) anylist ::= anylist ANY */ yytestcase(yyruleno==342);
- /* (343) with ::= */ yytestcase(yyruleno==343);
+ /* (297) input ::= cmdlist */ yytestcase(yyruleno==297);
+ /* (298) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==298);
+ /* (299) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=299);
+ /* (300) ecmd ::= SEMI */ yytestcase(yyruleno==300);
+ /* (301) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==301);
+ /* (302) trans_opt ::= */ yytestcase(yyruleno==302);
+ /* (303) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==303);
+ /* (304) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==304);
+ /* (305) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==305);
+ /* (306) savepoint_opt ::= */ yytestcase(yyruleno==306);
+ /* (307) cmd ::= create_table create_table_args */ yytestcase(yyruleno==307);
+ /* (308) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==308);
+ /* (309) columnlist ::= columnname carglist */ yytestcase(yyruleno==309);
+ /* (310) nm ::= ID|INDEXED */ yytestcase(yyruleno==310);
+ /* (311) nm ::= STRING */ yytestcase(yyruleno==311);
+ /* (312) nm ::= JOIN_KW */ yytestcase(yyruleno==312);
+ /* (313) typetoken ::= typename */ yytestcase(yyruleno==313);
+ /* (314) typename ::= ID|STRING */ yytestcase(yyruleno==314);
+ /* (315) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=315);
+ /* (316) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=316);
+ /* (317) carglist ::= carglist ccons */ yytestcase(yyruleno==317);
+ /* (318) carglist ::= */ yytestcase(yyruleno==318);
+ /* (319) ccons ::= NULL onconf */ yytestcase(yyruleno==319);
+ /* (320) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==320);
+ /* (321) ccons ::= AS generated */ yytestcase(yyruleno==321);
+ /* (322) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==322);
+ /* (323) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==323);
+ /* (324) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=324);
+ /* (325) tconscomma ::= */ yytestcase(yyruleno==325);
+ /* (326) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=326);
+ /* (327) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=327);
+ /* (328) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=328);
+ /* (329) oneselect ::= values */ yytestcase(yyruleno==329);
+ /* (330) sclp ::= selcollist COMMA */ yytestcase(yyruleno==330);
+ /* (331) as ::= ID|STRING */ yytestcase(yyruleno==331);
+ /* (332) returning ::= */ yytestcase(yyruleno==332);
+ /* (333) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=333);
+ /* (334) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==334);
+ /* (335) exprlist ::= nexprlist */ yytestcase(yyruleno==335);
+ /* (336) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=336);
+ /* (337) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=337);
+ /* (338) nmnum ::= ON */ yytestcase(yyruleno==338);
+ /* (339) nmnum ::= DELETE */ yytestcase(yyruleno==339);
+ /* (340) nmnum ::= DEFAULT */ yytestcase(yyruleno==340);
+ /* (341) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==341);
+ /* (342) foreach_clause ::= */ yytestcase(yyruleno==342);
+ /* (343) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==343);
+ /* (344) trnm ::= nm */ yytestcase(yyruleno==344);
+ /* (345) tridxby ::= */ yytestcase(yyruleno==345);
+ /* (346) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==346);
+ /* (347) database_kw_opt ::= */ yytestcase(yyruleno==347);
+ /* (348) kwcolumn_opt ::= */ yytestcase(yyruleno==348);
+ /* (349) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==349);
+ /* (350) vtabarglist ::= vtabarg */ yytestcase(yyruleno==350);
+ /* (351) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==351);
+ /* (352) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==352);
+ /* (353) anylist ::= */ yytestcase(yyruleno==353);
+ /* (354) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==354);
+ /* (355) anylist ::= anylist ANY */ yytestcase(yyruleno==355);
+ /* (356) with ::= */ yytestcase(yyruleno==356);
break;
/********** End reduce actions ************************************************/
};
@@ -159441,12 +161666,56 @@ SQLITE_PRIVATE void sqlite3Parser(
}
#endif
- do{
+ while(1){ /* Exit by "break" */
+ assert( yypParser->yytos>=yypParser->yystack );
assert( yyact==yypParser->yytos->stateno );
yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
- yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
- yyminor sqlite3ParserCTX_PARAM);
+ unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
+ assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ int yysize = yyRuleInfoNRhs[yyruleno];
+ if( yysize ){
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
+ yyTracePrompt,
+ yyruleno, yyRuleName[yyruleno],
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
+ yypParser->yytos[yysize].stateno);
+ }else{
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
+ yyTracePrompt, yyruleno, yyRuleName[yyruleno],
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
+ }
+ }
+#endif /* NDEBUG */
+
+ /* Check that the stack is large enough to grow by a single entry
+ ** if the RHS of the rule is empty. This ensures that there is room
+ ** enough on the stack to push the LHS value */
+ if( yyRuleInfoNRhs[yyruleno]==0 ){
+#ifdef YYTRACKMAXSTACKDEPTH
+ if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
+ yypParser->yyhwm++;
+ assert( yypParser->yyhwm ==
+ (int)(yypParser->yytos - yypParser->yystack));
+ }
+#endif
+#if YYSTACKDEPTH>0
+ if( yypParser->yytos>=yypParser->yystackEnd ){
+ yyStackOverflow(yypParser);
+ break;
+ }
+#else
+ if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
+ if( yyGrowStack(yypParser) ){
+ yyStackOverflow(yypParser);
+ break;
+ }
+ }
+#endif
+ }
+ yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor sqlite3ParserCTX_PARAM);
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
@@ -159559,7 +161828,7 @@ SQLITE_PRIVATE void sqlite3Parser(
break;
#endif
}
- }while( yypParser->yytos>yypParser->yystack );
+ }
#ifndef NDEBUG
if( yyTraceFILE ){
yyStackEntry *i;
@@ -159620,8 +161889,8 @@ SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){
** all of them need to be used within the switch.
*/
#define CC_X 0 /* The letter 'x', or start of BLOB literal */
-#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
-#define CC_ID 2 /* unicode characters usable in IDs */
+#define CC_KYWD0 1 /* First letter of a keyword */
+#define CC_KYWD 2 /* Alphabetics or '_'. Usable in a keyword */
#define CC_DIGIT 3 /* Digits */
#define CC_DOLLAR 4 /* '$' */
#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
@@ -159646,20 +161915,21 @@ SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){
#define CC_AND 24 /* '&' */
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
-#define CC_ILLEGAL 27 /* Illegal character */
-#define CC_NUL 28 /* 0x00 */
+#define CC_ID 27 /* unicode characters usable in IDs */
+#define CC_ILLEGAL 28 /* Illegal character */
+#define CC_NUL 29 /* 0x00 */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* 0x */ 29, 28, 28, 28, 28, 28, 28, 28, 28, 7, 7, 28, 7, 7, 28, 28,
+/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
+/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
+/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28,
/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -159671,22 +161941,22 @@ static const unsigned char aiClass[] = {
#endif
#ifdef SQLITE_EBCDIC
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10,
-/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27,
-/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6,
-/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8,
-/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27,
-/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27,
+/* 0x */ 29, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 7, 7, 28, 28,
+/* 1x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 2x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 3x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 4x */ 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 12, 17, 20, 10,
+/* 5x */ 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 15, 4, 21, 18, 19, 28,
+/* 6x */ 11, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 23, 22, 2, 13, 6,
+/* 7x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 8, 5, 5, 5, 8, 14, 8,
+/* 8x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* 9x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Ax */ 28, 25, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
+/* Bx */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 9, 28, 28, 28, 28, 28,
+/* Cx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Dx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Ex */ 28, 28, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
+/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 28, 28, 28, 28, 28, 28,
#endif
};
@@ -159751,19 +162021,19 @@ const unsigned char ebcdicToAscii[] = {
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
-/* Hash score: 189 */
-/* zKWText[] encodes 838 bytes of keyword text in 562 bytes */
+/* Hash score: 193 */
+/* zKWText[] encodes 861 bytes of keyword text in 581 bytes */
/* BEFOREIGNOREFERENCESCAPEACHECKEYISNULLSAVEPOINTERSECTABLEFTHEN */
/* DESCONSTRAINTOFFSETRANSACTIONOTNULLIKELSELECTRIGGERAISEXCEPT */
/* EMPORARYWITHOUTERELEASEXCLUSIVEXISTSATTACHAVINGROUPDATEBEGIN */
/* STEADDATABASEBETWEENATURALTERECURSIVECASCADEFERRABLECASE */
/* COLLATECREATECURRENT_DATEDELETEDETACHIMMEDIATEJOINDEXEDEFAULT */
-/* MATCHPRAGMABORTVALUESVIRTUALWAYSWHENWHEREGEXPRIMARYAFTERENAME */
-/* ANDEFERREDISTINCTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
-/* CURRENT_TIMESTAMPDROPFAILASTFIRSTFROMFULLIMITGENERATEDGLOBYIF */
-/* INNEREPLACEINSERTORDERESTRICTRIGHTROLLBACKROWSUNIONUNIQUEUSING */
-/* VACUUMVIEWINITIALLY */
-static const char zKWText[561] = {
+/* MATCHPRAGMATERIALIZEDEFERREDISTINCTVALUESVIRTUALWAYSWHENWHERE */
+/* GEXPRIMARYABORTAFTERENAMEANDROPAUTOINCREMENTCASTCOLUMNCOMMIT */
+/* CONFLICTCROSSCURRENT_TIMESTAMPFAILASTFIRSTFROMFULLIMIT */
+/* GENERATEDGLOBYIFINNEREPLACEINSERTORDERESTRICTRETURNINGRIGHT */
+/* ROLLBACKROWSUNIONUNIQUEUSINGVACUUMVIEWINITIALLY */
+static const char zKWText[580] = {
'B','E','F','O','R','E','I','G','N','O','R','E','F','E','R','E','N','C',
'E','S','C','A','P','E','A','C','H','E','C','K','E','Y','I','S','N','U',
'L','L','S','A','V','E','P','O','I','N','T','E','R','S','E','C','T','A',
@@ -159781,79 +162051,80 @@ static const char zKWText[561] = {
'U','R','R','E','N','T','_','D','A','T','E','D','E','L','E','T','E','D',
'E','T','A','C','H','I','M','M','E','D','I','A','T','E','J','O','I','N',
'D','E','X','E','D','E','F','A','U','L','T','M','A','T','C','H','P','R',
- 'A','G','M','A','B','O','R','T','V','A','L','U','E','S','V','I','R','T',
- 'U','A','L','W','A','Y','S','W','H','E','N','W','H','E','R','E','G','E',
- 'X','P','R','I','M','A','R','Y','A','F','T','E','R','E','N','A','M','E',
- 'A','N','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','A',
- 'U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C','O',
- 'L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C','T',
- 'C','R','O','S','S','C','U','R','R','E','N','T','_','T','I','M','E','S',
- 'T','A','M','P','D','R','O','P','F','A','I','L','A','S','T','F','I','R',
- 'S','T','F','R','O','M','F','U','L','L','I','M','I','T','G','E','N','E',
- 'R','A','T','E','D','G','L','O','B','Y','I','F','I','N','N','E','R','E',
- 'P','L','A','C','E','I','N','S','E','R','T','O','R','D','E','R','E','S',
- 'T','R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K',
- 'R','O','W','S','U','N','I','O','N','U','N','I','Q','U','E','U','S','I',
- 'N','G','V','A','C','U','U','M','V','I','E','W','I','N','I','T','I','A',
- 'L','L','Y',
+ 'A','G','M','A','T','E','R','I','A','L','I','Z','E','D','E','F','E','R',
+ 'R','E','D','I','S','T','I','N','C','T','V','A','L','U','E','S','V','I',
+ 'R','T','U','A','L','W','A','Y','S','W','H','E','N','W','H','E','R','E',
+ 'G','E','X','P','R','I','M','A','R','Y','A','B','O','R','T','A','F','T',
+ 'E','R','E','N','A','M','E','A','N','D','R','O','P','A','U','T','O','I',
+ 'N','C','R','E','M','E','N','T','C','A','S','T','C','O','L','U','M','N',
+ 'C','O','M','M','I','T','C','O','N','F','L','I','C','T','C','R','O','S',
+ 'S','C','U','R','R','E','N','T','_','T','I','M','E','S','T','A','M','P',
+ 'F','A','I','L','A','S','T','F','I','R','S','T','F','R','O','M','F','U',
+ 'L','L','I','M','I','T','G','E','N','E','R','A','T','E','D','G','L','O',
+ 'B','Y','I','F','I','N','N','E','R','E','P','L','A','C','E','I','N','S',
+ 'E','R','T','O','R','D','E','R','E','S','T','R','I','C','T','R','E','T',
+ 'U','R','N','I','N','G','R','I','G','H','T','R','O','L','L','B','A','C',
+ 'K','R','O','W','S','U','N','I','O','N','U','N','I','Q','U','E','U','S',
+ 'I','N','G','V','A','C','U','U','M','V','I','E','W','I','N','I','T','I',
+ 'A','L','L','Y',
};
/* aKWHash[i] is the hash value for the i-th keyword */
static const unsigned char aKWHash[127] = {
- 112, 88, 116, 68, 0, 38, 0, 0, 76, 0, 73, 0, 0,
- 22, 4, 0, 51, 0, 24, 79, 23, 109, 117, 33, 0, 0,
- 122, 0, 31, 114, 0, 81, 90, 0, 1, 0, 0, 63, 64,
- 0, 62, 7, 0, 0, 85, 82, 0, 118, 98, 0, 0, 44,
- 0, 86, 61, 0, 53, 0, 66, 46, 17, 0, 6, 107, 32,
- 93, 102, 0, 125, 87, 55, 124, 50, 8, 48, 0, 45, 0,
- 3, 36, 0, 96, 0, 0, 0, 92, 2, 94, 83, 104, 0,
- 19, 103, 0, 75, 0, 54, 111, 108, 35, 0, 121, 74, 69,
- 28, 39, 105, 0, 0, 91, 20, 58, 113, 0, 13, 0, 0,
- 26, 0, 80, 29, 30, 0, 14, 56, 0, 49,
+ 113, 78, 118, 68, 0, 38, 0, 0, 79, 0, 73, 0, 0,
+ 22, 4, 0, 51, 0, 24, 82, 23, 75, 119, 33, 0, 0,
+ 124, 0, 31, 115, 0, 84, 92, 0, 1, 0, 0, 63, 64,
+ 0, 62, 7, 0, 0, 89, 85, 0, 120, 100, 0, 0, 44,
+ 0, 76, 61, 0, 53, 0, 66, 46, 17, 0, 6, 108, 32,
+ 95, 103, 0, 127, 77, 55, 126, 50, 8, 48, 0, 45, 0,
+ 3, 36, 0, 98, 0, 0, 0, 94, 2, 96, 87, 105, 0,
+ 19, 104, 0, 86, 0, 54, 112, 109, 35, 0, 123, 74, 69,
+ 28, 39, 106, 0, 0, 93, 20, 58, 114, 0, 13, 0, 0,
+ 116, 0, 83, 29, 30, 0, 14, 56, 0, 49,
};
/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0
** then the i-th keyword has no more hash collisions. Otherwise,
** the next keyword with the same hash is aKWHash[i]-1. */
-static const unsigned char aKWNext[125] = {
- 0, 89, 97, 0, 0, 18, 0, 25, 0, 21, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 115, 0, 0,
- 0, 0, 110, 0, 119, 0, 0, 0, 0, 0, 0, 0, 101,
- 0, 43, 0, 0, 37, 72, 0, 0, 71, 120, 0, 70, 0,
+static const unsigned char aKWNext[127] = {
+ 0, 91, 99, 0, 0, 18, 0, 25, 0, 21, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 117, 0, 0,
+ 0, 0, 111, 0, 121, 0, 0, 0, 0, 0, 0, 0, 102,
+ 0, 43, 0, 0, 37, 72, 0, 0, 71, 122, 0, 70, 0,
0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 59, 0, 0,
- 123, 60, 0, 10, 0, 0, 0, 0, 0, 0, 40, 5, 0,
- 0, 0, 16, 0, 57, 0, 52, 0, 99, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 65, 9, 95, 15, 0, 78, 100,
- 0, 0, 0, 84, 0, 0, 41, 0, 42, 0, 0, 34, 0,
- 67, 77, 0, 11, 12, 106, 0, 0,
+ 125, 60, 0, 10, 0, 0, 0, 0, 0, 110, 0, 90, 0,
+ 40, 5, 0, 0, 0, 16, 0, 0, 57, 0, 52, 9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 65, 97, 15, 0, 81,
+ 101, 0, 0, 0, 88, 0, 0, 41, 0, 42, 0, 26, 0,
+ 34, 0, 67, 80, 0, 11, 12, 107, 0, 0,
};
/* aKWLen[i] is the length (in bytes) of the i-th keyword */
-static const unsigned char aKWLen[125] = {
+static const unsigned char aKWLen[127] = {
6, 7, 3, 6, 10, 6, 4, 5, 3, 6, 5, 9, 9,
5, 4, 4, 3, 4, 10, 4, 6, 2, 3, 11, 6, 2,
7, 3, 2, 4, 4, 4, 6, 7, 5, 6, 9, 4, 2,
7, 4, 5, 7, 9, 6, 6, 6, 5, 6, 5, 7, 3,
8, 2, 7, 7, 5, 9, 7, 3, 10, 4, 7, 6, 12,
- 6, 6, 9, 4, 7, 5, 7, 5, 6, 5, 6, 7, 6,
- 4, 5, 6, 7, 5, 6, 3, 8, 8, 2, 13, 2, 2,
- 4, 6, 6, 8, 5, 17, 12, 4, 4, 4, 5, 4, 4,
- 5, 9, 4, 2, 2, 5, 7, 6, 5, 8, 5, 8, 4,
- 3, 5, 6, 5, 6, 4, 9, 3,
+ 6, 6, 9, 4, 7, 5, 7, 5, 6, 12, 8, 8, 2,
+ 6, 7, 6, 4, 5, 6, 7, 5, 5, 6, 3, 4, 13,
+ 2, 2, 4, 6, 6, 8, 5, 17, 12, 4, 4, 5, 4,
+ 4, 5, 9, 4, 2, 2, 5, 7, 6, 5, 8, 9, 5,
+ 8, 4, 3, 5, 6, 5, 6, 4, 9, 3,
};
/* aKWOffset[i] is the index into zKWText[] of the start of
** the text for the i-th keyword. */
-static const unsigned short int aKWOffset[125] = {
+static const unsigned short int aKWOffset[127] = {
0, 2, 2, 6, 10, 18, 23, 25, 29, 32, 34, 38, 44,
52, 55, 58, 60, 62, 65, 72, 75, 75, 78, 80, 85, 89,
90, 90, 90, 93, 96, 99, 101, 106, 112, 116, 121, 121, 125,
130, 130, 134, 138, 144, 152, 158, 163, 168, 171, 177, 180, 185,
187, 192, 195, 201, 206, 210, 219, 220, 224, 234, 238, 245, 251,
- 263, 269, 275, 284, 286, 286, 292, 299, 304, 309, 314, 320, 325,
- 331, 335, 338, 343, 350, 354, 360, 362, 369, 370, 377, 379, 381,
- 390, 394, 400, 406, 414, 419, 419, 436, 440, 443, 447, 452, 456,
- 459, 464, 473, 476, 478, 480, 484, 491, 497, 501, 509, 514, 522,
- 522, 526, 531, 537, 542, 548, 552, 557,
+ 263, 269, 275, 284, 286, 286, 292, 299, 304, 308, 319, 326, 327,
+ 334, 340, 345, 351, 355, 358, 363, 370, 375, 379, 385, 387, 391,
+ 393, 395, 404, 408, 414, 420, 428, 433, 433, 450, 453, 457, 462,
+ 466, 469, 474, 483, 486, 488, 490, 494, 501, 507, 511, 519, 528,
+ 533, 541, 541, 545, 550, 556, 561, 567, 571, 576,
};
/* aKWCode[i] is the parser symbol code for the i-th keyword */
-static const unsigned char aKWCode[125] = {
+static const unsigned char aKWCode[127] = {
TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_REFERENCES,
TK_ESCAPE, TK_EACH, TK_CHECK, TK_KEY, TK_ISNULL,
TK_NULLS, TK_SAVEPOINT, TK_INTERSECT, TK_TABLE, TK_JOIN_KW,
@@ -159868,17 +162139,18 @@ static const unsigned char aKWCode[125] = {
TK_JOIN_KW, TK_ALTER, TK_RECURSIVE, TK_CASCADE, TK_ASC,
TK_DEFERRABLE, TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW,
TK_DELETE, TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INDEXED,
- TK_INDEX, TK_DEFAULT, TK_MATCH, TK_PRAGMA, TK_ABORT,
- TK_VALUES, TK_VIRTUAL, TK_ALWAYS, TK_WHEN, TK_WHERE,
- TK_LIKE_KW, TK_PRIMARY, TK_AFTER, TK_RENAME, TK_AND,
- TK_DEFERRED, TK_DISTINCT, TK_IS, TK_AUTOINCR, TK_TO,
- TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT,
- TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_DROP, TK_FAIL,
- TK_LAST, TK_FIRST, TK_FROM, TK_JOIN_KW, TK_LIMIT,
- TK_GENERATED, TK_LIKE_KW, TK_BY, TK_IF, TK_JOIN_KW,
- TK_REPLACE, TK_INSERT, TK_ORDER, TK_RESTRICT, TK_JOIN_KW,
- TK_ROLLBACK, TK_ROWS, TK_ROW, TK_UNION, TK_UNIQUE,
- TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL,
+ TK_INDEX, TK_DEFAULT, TK_MATCH, TK_PRAGMA, TK_MATERIALIZED,
+ TK_DEFERRED, TK_DISTINCT, TK_IS, TK_VALUES, TK_VIRTUAL,
+ TK_ALWAYS, TK_WHEN, TK_WHERE, TK_LIKE_KW, TK_PRIMARY,
+ TK_ABORT, TK_AFTER, TK_RENAME, TK_AND, TK_DROP,
+ TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW,
+ TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW,
+ TK_FAIL, TK_LAST, TK_FIRST, TK_FROM, TK_JOIN_KW,
+ TK_LIMIT, TK_GENERATED, TK_LIKE_KW, TK_BY, TK_IF,
+ TK_JOIN_KW, TK_REPLACE, TK_INSERT, TK_ORDER, TK_RESTRICT,
+ TK_RETURNING, TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, TK_ROW,
+ TK_UNION, TK_UNIQUE, TK_USING, TK_VACUUM, TK_VIEW,
+ TK_INITIALLY, TK_ALL,
};
/* Hash table decoded:
** 0: INSERT
@@ -159902,7 +162174,7 @@ static const unsigned char aKWCode[125] = {
** 18: TRANSACTION RIGHT
** 19: WHEN
** 20: SET HAVING
-** 21: IF
+** 21: MATERIALIZED IF
** 22: ROWS
** 23: SELECT
** 24:
@@ -159998,7 +162270,7 @@ static const unsigned char aKWCode[125] = {
** 114: INTERSECT
** 115:
** 116:
-** 117: ON
+** 117: RETURNING ON
** 118:
** 119: WHERE
** 120: NO INNER
@@ -160016,7 +162288,7 @@ static int keywordCode(const char *z, int n, int *pType){
int i, j;
const char *zKW;
if( n>=2 ){
- i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127;
+ i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127;
for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){
if( aKWLen[i]!=n ) continue;
zKW = &zKWText[aKWOffset[i]];
@@ -160107,57 +162379,59 @@ static int keywordCode(const char *z, int n, int *pType){
testcase( i==71 ); /* DEFAULT */
testcase( i==72 ); /* MATCH */
testcase( i==73 ); /* PRAGMA */
- testcase( i==74 ); /* ABORT */
- testcase( i==75 ); /* VALUES */
- testcase( i==76 ); /* VIRTUAL */
- testcase( i==77 ); /* ALWAYS */
- testcase( i==78 ); /* WHEN */
- testcase( i==79 ); /* WHERE */
- testcase( i==80 ); /* REGEXP */
- testcase( i==81 ); /* PRIMARY */
- testcase( i==82 ); /* AFTER */
- testcase( i==83 ); /* RENAME */
- testcase( i==84 ); /* AND */
- testcase( i==85 ); /* DEFERRED */
- testcase( i==86 ); /* DISTINCT */
- testcase( i==87 ); /* IS */
- testcase( i==88 ); /* AUTOINCREMENT */
- testcase( i==89 ); /* TO */
- testcase( i==90 ); /* IN */
- testcase( i==91 ); /* CAST */
- testcase( i==92 ); /* COLUMN */
- testcase( i==93 ); /* COMMIT */
- testcase( i==94 ); /* CONFLICT */
- testcase( i==95 ); /* CROSS */
- testcase( i==96 ); /* CURRENT_TIMESTAMP */
- testcase( i==97 ); /* CURRENT_TIME */
- testcase( i==98 ); /* DROP */
- testcase( i==99 ); /* FAIL */
- testcase( i==100 ); /* LAST */
- testcase( i==101 ); /* FIRST */
- testcase( i==102 ); /* FROM */
- testcase( i==103 ); /* FULL */
- testcase( i==104 ); /* LIMIT */
- testcase( i==105 ); /* GENERATED */
- testcase( i==106 ); /* GLOB */
- testcase( i==107 ); /* BY */
- testcase( i==108 ); /* IF */
- testcase( i==109 ); /* INNER */
- testcase( i==110 ); /* REPLACE */
- testcase( i==111 ); /* INSERT */
- testcase( i==112 ); /* ORDER */
- testcase( i==113 ); /* RESTRICT */
- testcase( i==114 ); /* RIGHT */
- testcase( i==115 ); /* ROLLBACK */
- testcase( i==116 ); /* ROWS */
- testcase( i==117 ); /* ROW */
- testcase( i==118 ); /* UNION */
- testcase( i==119 ); /* UNIQUE */
- testcase( i==120 ); /* USING */
- testcase( i==121 ); /* VACUUM */
- testcase( i==122 ); /* VIEW */
- testcase( i==123 ); /* INITIALLY */
- testcase( i==124 ); /* ALL */
+ testcase( i==74 ); /* MATERIALIZED */
+ testcase( i==75 ); /* DEFERRED */
+ testcase( i==76 ); /* DISTINCT */
+ testcase( i==77 ); /* IS */
+ testcase( i==78 ); /* VALUES */
+ testcase( i==79 ); /* VIRTUAL */
+ testcase( i==80 ); /* ALWAYS */
+ testcase( i==81 ); /* WHEN */
+ testcase( i==82 ); /* WHERE */
+ testcase( i==83 ); /* REGEXP */
+ testcase( i==84 ); /* PRIMARY */
+ testcase( i==85 ); /* ABORT */
+ testcase( i==86 ); /* AFTER */
+ testcase( i==87 ); /* RENAME */
+ testcase( i==88 ); /* AND */
+ testcase( i==89 ); /* DROP */
+ testcase( i==90 ); /* AUTOINCREMENT */
+ testcase( i==91 ); /* TO */
+ testcase( i==92 ); /* IN */
+ testcase( i==93 ); /* CAST */
+ testcase( i==94 ); /* COLUMN */
+ testcase( i==95 ); /* COMMIT */
+ testcase( i==96 ); /* CONFLICT */
+ testcase( i==97 ); /* CROSS */
+ testcase( i==98 ); /* CURRENT_TIMESTAMP */
+ testcase( i==99 ); /* CURRENT_TIME */
+ testcase( i==100 ); /* FAIL */
+ testcase( i==101 ); /* LAST */
+ testcase( i==102 ); /* FIRST */
+ testcase( i==103 ); /* FROM */
+ testcase( i==104 ); /* FULL */
+ testcase( i==105 ); /* LIMIT */
+ testcase( i==106 ); /* GENERATED */
+ testcase( i==107 ); /* GLOB */
+ testcase( i==108 ); /* BY */
+ testcase( i==109 ); /* IF */
+ testcase( i==110 ); /* INNER */
+ testcase( i==111 ); /* REPLACE */
+ testcase( i==112 ); /* INSERT */
+ testcase( i==113 ); /* ORDER */
+ testcase( i==114 ); /* RESTRICT */
+ testcase( i==115 ); /* RETURNING */
+ testcase( i==116 ); /* RIGHT */
+ testcase( i==117 ); /* ROLLBACK */
+ testcase( i==118 ); /* ROWS */
+ testcase( i==119 ); /* ROW */
+ testcase( i==120 ); /* UNION */
+ testcase( i==121 ); /* UNIQUE */
+ testcase( i==122 ); /* USING */
+ testcase( i==123 ); /* VACUUM */
+ testcase( i==124 ); /* VIEW */
+ testcase( i==125 ); /* INITIALLY */
+ testcase( i==126 ); /* ALL */
*pType = aKWCode[i];
break;
}
@@ -160169,7 +162443,7 @@ SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){
keywordCode((char*)z, n, &id);
return id;
}
-#define SQLITE_N_KEYWORD 125
+#define SQLITE_N_KEYWORD 127
SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){
if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;
*pzName = zKWText + aKWOffset[i];
@@ -160538,7 +162812,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
- case CC_KYWD: {
+ case CC_KYWD0: {
for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
if( IdChar(z[i]) ){
/* This token started out using characters that can appear in keywords,
@@ -160568,6 +162842,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
+ case CC_KYWD:
case CC_ID: {
i = 1;
break;
@@ -160750,19 +163025,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
if( !IN_RENAME_OBJECT ){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
-
- if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
sqlite3DbFree(db, pParse->pVList);
- while( pParse->pAinc ){
- AutoincInfo *p = pParse->pAinc;
- pParse->pAinc = p->pNext;
- sqlite3DbFreeNN(db, p);
- }
- while( pParse->pZombieTab ){
- Table *p = pParse->pZombieTab;
- pParse->pZombieTab = p->pNextZombie;
- sqlite3DeleteTable(db, p);
- }
db->pParse = pParse->pParentParse;
pParse->pParentParse = 0;
assert( nErr==0 || pParse->rc!=SQLITE_OK );
@@ -163669,7 +165932,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
return SQLITE_OK;
#else
int rc; /* Return code */
- int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
+ int iDb; /* Schema to checkpoint */
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
@@ -163692,6 +165955,8 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
sqlite3_mutex_enter(db->mutex);
if( zDb && zDb[0] ){
iDb = sqlite3FindDbName(db, zDb);
+ }else{
+ iDb = SQLITE_MAX_DB; /* This means process all schemas */
}
if( iDb<0 ){
rc = SQLITE_ERROR;
@@ -163740,7 +166005,7 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
** associated with the specific b-tree being checkpointed is taken by
** this function while the checkpoint is running.
**
-** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
+** If iDb is passed SQLITE_MAX_DB then all attached databases are
** checkpointed. If an error is encountered it is returned immediately -
** no attempt is made to checkpoint any remaining databases.
**
@@ -163755,9 +166020,11 @@ SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog
assert( sqlite3_mutex_held(db->mutex) );
assert( !pnLog || *pnLog==-1 );
assert( !pnCkpt || *pnCkpt==-1 );
+ testcase( iDb==SQLITE_MAX_ATTACHED ); /* See forum post a006d86f72 */
+ testcase( iDb==SQLITE_MAX_DB );
for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
- if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
+ if( i==iDb || iDb==SQLITE_MAX_DB ){
rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt);
pnLog = 0;
pnCkpt = 0;
@@ -165375,7 +167642,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
sqlite3 *db = va_arg(ap, sqlite3*);
- db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
+ db->dbOptFlags = va_arg(ap, u32);
break;
}
@@ -165550,7 +167817,26 @@ SQLITE_API int sqlite3_test_control(int op, ...){
break;
}
-
+ /* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
+ **
+ ** "ptr" is a pointer to a u32.
+ **
+ ** op==0 Store the current sqlite3SelectTrace in *ptr
+ ** op==1 Set sqlite3SelectTrace to the value *ptr
+ ** op==3 Store the current sqlite3WhereTrace in *ptr
+ ** op==3 Set sqlite3WhereTrace to the value *ptr
+ */
+ case SQLITE_TESTCTRL_TRACEFLAGS: {
+ int opTrace = va_arg(ap, int);
+ u32 *ptr = va_arg(ap, u32*);
+ switch( opTrace ){
+ case 0: *ptr = sqlite3SelectTrace; break;
+ case 1: sqlite3SelectTrace = *ptr; break;
+ case 2: *ptr = sqlite3WhereTrace; break;
+ case 3: sqlite3WhereTrace = *ptr; break;
+ }
+ break;
+ }
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
@@ -169120,7 +171406,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
@@ -169136,8 +171422,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -169190,20 +171476,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
@@ -172435,9 +174721,9 @@ static int fts3EvalNearTrim(
);
if( res ){
nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
- if( nNew>=0 ){
+ assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 );
+ if( nNew>=0 && nNew<=pPhrase->doclist.nList ){
assert( pPhrase->doclist.pList[nNew]=='\0' );
- assert( nNew<=pPhrase->doclist.nList && nNew>0 );
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
pPhrase->doclist.nList = nNew;
}
@@ -174371,6 +176657,11 @@ static int getNextNode(
if( *zInput=='(' ){
int nConsumed = 0;
pParse->nNest++;
+#if !defined(SQLITE_MAX_EXPR_DEPTH)
+ if( pParse->nNest>1000 ) return SQLITE_ERROR;
+#elif SQLITE_MAX_EXPR_DEPTH>0
+ if( pParse->nNest>SQLITE_MAX_EXPR_DEPTH ) return SQLITE_ERROR;
+#endif
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
@@ -179442,8 +181733,8 @@ static int fts3PrefixCompress(
int nNext /* Size of buffer zNext in bytes */
){
int n;
- UNUSED_PARAMETER(nNext);
- for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
+ for(n=0; n<nPrev && n<nNext && zPrev[n]==zNext[n]; n++);
+ assert_fts3_nc( n<nNext );
return n;
}
@@ -181774,17 +184065,20 @@ static int fts3IncrmergeLoad(
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
if( rc==SQLITE_OK ){
- memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ assert_fts3_nc( reader.term.n>0 || reader.aNode==0 );
+ if( reader.term.n>0 ){
+ memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ }
pNode->key.n = reader.term.n;
if( i>0 ){
char *aBlock = 0;
int nBlock = 0;
pNode = &pWriter->aNodeWriter[i-1];
pNode->iBlock = reader.iChild;
- rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
+ rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0);
blobGrowBuffer(&pNode->block,
MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
- );
+ );
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aBlock, nBlock);
pNode->block.n = nBlock;
@@ -185272,6 +187566,7 @@ static int unicodeOpen(
pCsr->aInput = (const unsigned char *)aInput;
if( aInput==0 ){
pCsr->nInput = 0;
+ pCsr->aInput = (const unsigned char*)"";
}else if( nInput<0 ){
pCsr->nInput = (int)strlen(aInput);
}else{
@@ -201027,22 +203322,24 @@ static int rbuVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
#endif
assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
- if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){
- /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from
- ** taking this lock also prevents any checkpoints from occurring.
- ** todo: really, it's not clear why this might occur, as
- ** wal_autocheckpoint ought to be turned off. */
+ if( pRbu && (
+ pRbu->eStage==RBU_STAGE_OAL
+ || pRbu->eStage==RBU_STAGE_MOVE
+ || pRbu->eStage==RBU_STAGE_DONE
+ )){
+ /* Prevent SQLite from taking a shm-lock on the target file when it
+ ** is supplying heap memory to the upper layer in place of *-shm
+ ** segments. */
if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY;
}else{
int bCapture = 0;
if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){
bCapture = 1;
}
-
if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
if( bCapture && rc==SQLITE_OK ){
- pRbu->mLock |= (1 << ofst);
+ pRbu->mLock |= ((1<<n) - 1) << ofst;
}
}
}
@@ -202829,6 +205126,7 @@ struct sqlite3_session {
int rc; /* Non-zero if an error has occurred */
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
+ i64 nMalloc; /* Number of bytes of data allocated */
sqlite3_value *pZeroBlob; /* Value containing X'' */
sqlite3_session *pNext; /* Next session object on same db. */
SessionTable *pTable; /* List of attached tables */
@@ -202871,6 +205169,7 @@ struct sqlite3_changeset_iter {
SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */
int bPatchset; /* True if this is a patchset */
int bInvert; /* True to invert changeset */
+ int bSkipEmpty; /* Skip noop UPDATE changes */
int rc; /* Iterator error code */
sqlite3_stmt *pConflict; /* Points to conflicting row, if any */
char *zTab; /* Current table */
@@ -203212,6 +205511,26 @@ static int sessionSerializeValue(
return SQLITE_OK;
}
+/*
+** Allocate and return a pointer to a buffer nByte bytes in size. If
+** pSession is not NULL, increase the sqlite3_session.nMalloc variable
+** by the number of bytes allocated.
+*/
+static void *sessionMalloc64(sqlite3_session *pSession, i64 nByte){
+ void *pRet = sqlite3_malloc64(nByte);
+ if( pSession ) pSession->nMalloc += sqlite3_msize(pRet);
+ return pRet;
+}
+
+/*
+** Free buffer pFree, which must have been allocated by an earlier
+** call to sessionMalloc64(). If pSession is not NULL, decrease the
+** sqlite3_session.nMalloc counter by the number of bytes freed.
+*/
+static void sessionFree(sqlite3_session *pSession, void *pFree){
+ if( pSession ) pSession->nMalloc -= sqlite3_msize(pFree);
+ sqlite3_free(pFree);
+}
/*
** This macro is used to calculate hash key values for data structures. In
@@ -203679,13 +205998,19 @@ static int sessionPreupdateEqual(
** Growing the hash table in this case is a performance optimization only,
** it is not required for correct operation.
*/
-static int sessionGrowHash(int bPatchset, SessionTable *pTab){
+static int sessionGrowHash(
+ sqlite3_session *pSession, /* For memory accounting. May be NULL */
+ int bPatchset,
+ SessionTable *pTab
+){
if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){
int i;
SessionChange **apNew;
sqlite3_int64 nNew = 2*(sqlite3_int64)(pTab->nChange ? pTab->nChange : 128);
- apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew);
+ apNew = (SessionChange**)sessionMalloc64(
+ pSession, sizeof(SessionChange*) * nNew
+ );
if( apNew==0 ){
if( pTab->nChange==0 ){
return SQLITE_ERROR;
@@ -203706,7 +206031,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
}
}
- sqlite3_free(pTab->apChange);
+ sessionFree(pSession, pTab->apChange);
pTab->nChange = nNew;
pTab->apChange = apNew;
}
@@ -203740,6 +206065,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
** be freed using sqlite3_free() by the caller
*/
static int sessionTableInfo(
+ sqlite3_session *pSession, /* For memory accounting. May be NULL */
sqlite3 *db, /* Database connection */
const char *zDb, /* Name of attached database (e.g. "main") */
const char *zThis, /* Table name */
@@ -203794,7 +206120,7 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
- pAlloc = sqlite3_malloc64(nByte);
+ pAlloc = sessionMalloc64(pSession, nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
}
@@ -203837,7 +206163,7 @@ static int sessionTableInfo(
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
- sqlite3_free(azCol);
+ sessionFree(pSession, azCol);
}
sqlite3_finalize(pStmt);
return rc;
@@ -203859,7 +206185,7 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
if( pTab->nCol==0 ){
u8 *abPK;
assert( pTab->azCol==0 || pTab->abPK==0 );
- pSession->rc = sessionTableInfo(pSession->db, pSession->zDb,
+ pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
);
if( pSession->rc==SQLITE_OK ){
@@ -203950,7 +206276,7 @@ static void sessionPreupdateOneChange(
}
/* Grow the hash table if required */
- if( sessionGrowHash(0, pTab) ){
+ if( sessionGrowHash(pSession, 0, pTab) ){
pSession->rc = SQLITE_NOMEM;
return;
}
@@ -204017,7 +206343,7 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
- pChange = (SessionChange *)sqlite3_malloc64(nByte);
+ pChange = (SessionChange *)sessionMalloc64(pSession, nByte);
if( !pChange ){
rc = SQLITE_NOMEM;
goto error_out;
@@ -204390,7 +206716,7 @@ SQLITE_API int sqlite3session_diff(
int nCol; /* Columns in zFrom.zTbl */
u8 *abPK;
const char **azCol = 0;
- rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
+ rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
if( rc==SQLITE_OK ){
if( pTo->nCol!=nCol ){
bMismatch = 1;
@@ -204488,7 +206814,7 @@ SQLITE_API int sqlite3session_create(
** Free the list of table objects passed as the first argument. The contents
** of the changed-rows hash tables are also deleted.
*/
-static void sessionDeleteTable(SessionTable *pList){
+static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){
SessionTable *pNext;
SessionTable *pTab;
@@ -204500,12 +206826,12 @@ static void sessionDeleteTable(SessionTable *pList){
SessionChange *pNextChange;
for(p=pTab->apChange[i]; p; p=pNextChange){
pNextChange = p->pNext;
- sqlite3_free(p);
+ sessionFree(pSession, p);
}
}
- sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */
- sqlite3_free(pTab->apChange);
- sqlite3_free(pTab);
+ sessionFree(pSession, (char*)pTab->azCol); /* cast works around VC++ bug */
+ sessionFree(pSession, pTab->apChange);
+ sessionFree(pSession, pTab);
}
}
@@ -204533,9 +206859,11 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession){
/* Delete all attached table objects. And the contents of their
** associated hash-tables. */
- sessionDeleteTable(pSession->pTable);
+ sessionDeleteTable(pSession, pSession->pTable);
- /* Free the session object itself. */
+ /* Assert that all allocations have been freed and then free the
+ ** session object itself. */
+ assert( pSession->nMalloc==0 );
sqlite3_free(pSession);
}
@@ -204582,7 +206910,8 @@ SQLITE_API int sqlite3session_attach(
if( !pTab ){
/* Allocate new SessionTable object. */
- pTab = (SessionTable *)sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
+ int nByte = sizeof(SessionTable) + nName + 1;
+ pTab = (SessionTable*)sessionMalloc64(pSession, nByte);
if( !pTab ){
rc = SQLITE_NOMEM;
}else{
@@ -205179,7 +207508,7 @@ static int sessionGenerateChangeset(
int nNoop; /* Size of buffer after writing tbl header */
/* Check the table schema is still Ok. */
- rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK);
+ rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK);
if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
rc = SQLITE_SCHEMA;
}
@@ -205355,6 +207684,13 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession){
}
/*
+** Return the amount of heap memory in use.
+*/
+SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
+ return pSession->nMalloc;
+}
+
+/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
static int sessionChangesetStart(
@@ -205363,7 +207699,8 @@ static int sessionChangesetStart(
void *pIn,
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset, /* Pointer to buffer containing changeset */
- int bInvert /* True to invert changeset */
+ int bInvert, /* True to invert changeset */
+ int bSkipEmpty /* True to skip empty UPDATE changes */
){
sqlite3_changeset_iter *pRet; /* Iterator to return */
int nByte; /* Number of bytes to allocate for iterator */
@@ -205384,6 +207721,7 @@ static int sessionChangesetStart(
pRet->in.pIn = pIn;
pRet->in.bEof = (xInput ? 0 : 1);
pRet->bInvert = bInvert;
+ pRet->bSkipEmpty = bSkipEmpty;
/* Populate the output variable and return success. */
*pp = pRet;
@@ -205398,7 +207736,7 @@ SQLITE_API int sqlite3changeset_start(
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset /* Pointer to buffer containing changeset */
){
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0, 0);
}
SQLITE_API int sqlite3changeset_start_v2(
sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
@@ -205407,7 +207745,7 @@ SQLITE_API int sqlite3changeset_start_v2(
int flags
){
int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert, 0);
}
/*
@@ -205418,7 +207756,7 @@ SQLITE_API int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
){
- return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0, 0);
}
SQLITE_API int sqlite3changeset_start_v2_strm(
sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
@@ -205427,7 +207765,7 @@ SQLITE_API int sqlite3changeset_start_v2_strm(
int flags
){
int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
- return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert, 0);
}
/*
@@ -205553,11 +207891,14 @@ static int sessionReadRecord(
SessionInput *pIn, /* Input data */
int nCol, /* Number of values in record */
u8 *abPK, /* Array of primary key flags, or NULL */
- sqlite3_value **apOut /* Write values to this array */
+ sqlite3_value **apOut, /* Write values to this array */
+ int *pbEmpty
){
int i; /* Used to iterate through columns */
int rc = SQLITE_OK;
+ assert( pbEmpty==0 || *pbEmpty==0 );
+ if( pbEmpty ) *pbEmpty = 1;
for(i=0; i<nCol && rc==SQLITE_OK; i++){
int eType = 0; /* Type of value (SQLITE_NULL, TEXT etc.) */
if( abPK && abPK[i]==0 ) continue;
@@ -205569,6 +207910,7 @@ static int sessionReadRecord(
eType = pIn->aData[pIn->iNext++];
assert( apOut[i]==0 );
if( eType ){
+ if( pbEmpty ) *pbEmpty = 0;
apOut[i] = sqlite3ValueNew(0);
if( !apOut[i] ) rc = SQLITE_NOMEM;
}
@@ -205748,31 +208090,27 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
}
/*
-** Advance the changeset iterator to the next change.
+** Advance the changeset iterator to the next change. The differences between
+** this function and sessionChangesetNext() are that
**
-** If both paRec and pnRec are NULL, then this function works like the public
-** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the
-** sqlite3changeset_new() and old() APIs may be used to query for values.
-**
-** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
-** record is written to *paRec before returning and the number of bytes in
-** the record to *pnRec.
+** * If pbEmpty is not NULL and the change is a no-op UPDATE (an UPDATE
+** that modifies no columns), this function sets (*pbEmpty) to 1.
**
-** Either way, this function returns SQLITE_ROW if the iterator is
-** successfully advanced to the next change in the changeset, an SQLite
-** error code if an error occurs, or SQLITE_DONE if there are no further
-** changes in the changeset.
+** * If the iterator is configured to skip no-op UPDATEs,
+** sessionChangesetNext() does that. This function does not.
*/
-static int sessionChangesetNext(
+static int sessionChangesetNextOne(
sqlite3_changeset_iter *p, /* Changeset iterator */
u8 **paRec, /* If non-NULL, store record pointer here */
int *pnRec, /* If non-NULL, store size of record here */
- int *pbNew /* If non-NULL, true if new table */
+ int *pbNew, /* If non-NULL, true if new table */
+ int *pbEmpty
){
int i;
u8 op;
assert( (paRec==0 && pnRec==0) || (paRec && pnRec) );
+ assert( pbEmpty==0 || *pbEmpty==0 );
/* If the iterator is in the error-state, return immediately. */
if( p->rc!=SQLITE_OK ) return p->rc;
@@ -205845,13 +208183,13 @@ static int sessionChangesetNext(
/* If this is an UPDATE or DELETE, read the old.* record. */
if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){
u8 *abPK = p->bPatchset ? p->abPK : 0;
- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld);
+ p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld, 0);
if( p->rc!=SQLITE_OK ) return p->rc;
}
/* If this is an INSERT or UPDATE, read the new.* record. */
if( p->op!=SQLITE_DELETE ){
- p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew);
+ p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew, pbEmpty);
if( p->rc!=SQLITE_OK ) return p->rc;
}
@@ -205879,6 +208217,37 @@ static int sessionChangesetNext(
}
/*
+** Advance the changeset iterator to the next change.
+**
+** If both paRec and pnRec are NULL, then this function works like the public
+** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the
+** sqlite3changeset_new() and old() APIs may be used to query for values.
+**
+** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
+** record is written to *paRec before returning and the number of bytes in
+** the record to *pnRec.
+**
+** Either way, this function returns SQLITE_ROW if the iterator is
+** successfully advanced to the next change in the changeset, an SQLite
+** error code if an error occurs, or SQLITE_DONE if there are no further
+** changes in the changeset.
+*/
+static int sessionChangesetNext(
+ sqlite3_changeset_iter *p, /* Changeset iterator */
+ u8 **paRec, /* If non-NULL, store record pointer here */
+ int *pnRec, /* If non-NULL, store size of record here */
+ int *pbNew /* If non-NULL, true if new table */
+){
+ int bEmpty;
+ int rc;
+ do {
+ bEmpty = 0;
+ rc = sessionChangesetNextOne(p, paRec, pnRec, pbNew, &bEmpty);
+ }while( rc==SQLITE_ROW && p->bSkipEmpty && bEmpty);
+ return rc;
+}
+
+/*
** Advance an iterator created by sqlite3changeset_start() to the next
** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE
** or SQLITE_CORRUPT.
@@ -206150,9 +208519,9 @@ static int sessionChangesetInvert(
/* Read the old.* and new.* records for the update change. */
pInput->iNext += 2;
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]);
+ rc = sessionReadRecord(pInput, nCol, 0, &apVal[0], 0);
if( rc==SQLITE_OK ){
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]);
+ rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol], 0);
}
/* Write the new old.* record. Consists of the PK columns from the
@@ -206253,16 +208622,25 @@ SQLITE_API int sqlite3changeset_invert_strm(
return rc;
}
+
+typedef struct SessionUpdate SessionUpdate;
+struct SessionUpdate {
+ sqlite3_stmt *pStmt;
+ u32 *aMask;
+ SessionUpdate *pNext;
+};
+
typedef struct SessionApplyCtx SessionApplyCtx;
struct SessionApplyCtx {
sqlite3 *db;
sqlite3_stmt *pDelete; /* DELETE statement */
- sqlite3_stmt *pUpdate; /* UPDATE statement */
sqlite3_stmt *pInsert; /* INSERT statement */
sqlite3_stmt *pSelect; /* SELECT statement */
int nCol; /* Size of azCol[] and abPK[] arrays */
const char **azCol; /* Array of column names */
u8 *abPK; /* Boolean array - true if column is in PK */
+ u32 *aUpdateMask; /* Used by sessionUpdateFind */
+ SessionUpdate *pUp;
int bStat1; /* True if table is sqlite_stat1 */
int bDeferConstraints; /* True to defer constraints */
int bInvertConstraints; /* Invert when iterating constraints buffer */
@@ -206272,6 +208650,167 @@ struct SessionApplyCtx {
u8 bRebase; /* True to collect rebase information */
};
+/* Number of prepared UPDATE statements to cache. */
+#define SESSION_UPDATE_CACHE_SZ 12
+
+/*
+** Find a prepared UPDATE statement suitable for the UPDATE step currently
+** being visited by the iterator. The UPDATE is of the form:
+**
+** UPDATE tbl SET col = ?, col2 = ? WHERE pk1 IS ? AND pk2 IS ?
+*/
+static int sessionUpdateFind(
+ sqlite3_changeset_iter *pIter,
+ SessionApplyCtx *p,
+ int bPatchset,
+ sqlite3_stmt **ppStmt
+){
+ int rc = SQLITE_OK;
+ SessionUpdate *pUp = 0;
+ int nCol = pIter->nCol;
+ int nU32 = (pIter->nCol+33)/32;
+ int ii;
+
+ if( p->aUpdateMask==0 ){
+ p->aUpdateMask = sqlite3_malloc(nU32*sizeof(u32));
+ if( p->aUpdateMask==0 ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ memset(p->aUpdateMask, 0, nU32*sizeof(u32));
+ rc = SQLITE_CORRUPT;
+ for(ii=0; ii<pIter->nCol; ii++){
+ if( sessionChangesetNew(pIter, ii) ){
+ p->aUpdateMask[ii/32] |= (1<<(ii%32));
+ rc = SQLITE_OK;
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ if( bPatchset ) p->aUpdateMask[nCol/32] |= (1<<(nCol%32));
+
+ if( p->pUp ){
+ int nUp = 0;
+ SessionUpdate **pp = &p->pUp;
+ while( 1 ){
+ nUp++;
+ if( 0==memcmp(p->aUpdateMask, (*pp)->aMask, nU32*sizeof(u32)) ){
+ pUp = *pp;
+ *pp = pUp->pNext;
+ pUp->pNext = p->pUp;
+ p->pUp = pUp;
+ break;
+ }
+
+ if( (*pp)->pNext ){
+ pp = &(*pp)->pNext;
+ }else{
+ if( nUp>=SESSION_UPDATE_CACHE_SZ ){
+ sqlite3_finalize((*pp)->pStmt);
+ sqlite3_free(*pp);
+ *pp = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ if( pUp==0 ){
+ int nByte = sizeof(SessionUpdate) * nU32*sizeof(u32);
+ int bStat1 = (sqlite3_stricmp(pIter->zTab, "sqlite_stat1")==0);
+ pUp = (SessionUpdate*)sqlite3_malloc(nByte);
+ if( pUp==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ const char *zSep = "";
+ SessionBuffer buf;
+
+ memset(&buf, 0, sizeof(buf));
+ pUp->aMask = (u32*)&pUp[1];
+ memcpy(pUp->aMask, p->aUpdateMask, nU32*sizeof(u32));
+
+ sessionAppendStr(&buf, "UPDATE main.", &rc);
+ sessionAppendIdent(&buf, pIter->zTab, &rc);
+ sessionAppendStr(&buf, " SET ", &rc);
+
+ /* Create the assignments part of the UPDATE */
+ for(ii=0; ii<pIter->nCol; ii++){
+ if( p->abPK[ii]==0 && sessionChangesetNew(pIter, ii) ){
+ sessionAppendStr(&buf, zSep, &rc);
+ sessionAppendIdent(&buf, p->azCol[ii], &rc);
+ sessionAppendStr(&buf, " = ?", &rc);
+ sessionAppendInteger(&buf, ii*2+1, &rc);
+ zSep = ", ";
+ }
+ }
+
+ /* Create the WHERE clause part of the UPDATE */
+ zSep = "";
+ sessionAppendStr(&buf, " WHERE ", &rc);
+ for(ii=0; ii<pIter->nCol; ii++){
+ if( p->abPK[ii] || (bPatchset==0 && sessionChangesetOld(pIter, ii)) ){
+ sessionAppendStr(&buf, zSep, &rc);
+ if( bStat1 && ii==1 ){
+ assert( sqlite3_stricmp(p->azCol[ii], "idx")==0 );
+ sessionAppendStr(&buf,
+ "idx IS CASE "
+ "WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL "
+ "ELSE ?4 END ", &rc
+ );
+ }else{
+ sessionAppendIdent(&buf, p->azCol[ii], &rc);
+ sessionAppendStr(&buf, " IS ?", &rc);
+ sessionAppendInteger(&buf, ii*2+2, &rc);
+ }
+ zSep = " AND ";
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ char *zSql = (char*)buf.aBuf;
+ rc = sqlite3_prepare_v2(p->db, zSql, buf.nBuf, &pUp->pStmt, 0);
+ }
+
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pUp);
+ pUp = 0;
+ }else{
+ pUp->pNext = p->pUp;
+ p->pUp = pUp;
+ }
+ sqlite3_free(buf.aBuf);
+ }
+ }
+ }
+
+ assert( (rc==SQLITE_OK)==(pUp!=0) );
+ if( pUp ){
+ *ppStmt = pUp->pStmt;
+ }else{
+ *ppStmt = 0;
+ }
+ return rc;
+}
+
+/*
+** Free all cached UPDATE statements.
+*/
+static void sessionUpdateFree(SessionApplyCtx *p){
+ SessionUpdate *pUp;
+ SessionUpdate *pNext;
+ for(pUp=p->pUp; pUp; pUp=pNext){
+ pNext = pUp->pNext;
+ sqlite3_finalize(pUp->pStmt);
+ sqlite3_free(pUp);
+ }
+ p->pUp = 0;
+ sqlite3_free(p->aUpdateMask);
+ p->aUpdateMask = 0;
+}
+
/*
** Formulate a statement to DELETE a row from database db. Assuming a table
** structure like this:
@@ -206342,103 +208881,6 @@ static int sessionDeleteRow(
}
/*
-** Formulate and prepare a statement to UPDATE a row from database db.
-** Assuming a table structure like this:
-**
-** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
-**
-** The UPDATE statement looks like this:
-**
-** UPDATE x SET
-** a = CASE WHEN ?2 THEN ?3 ELSE a END,
-** b = CASE WHEN ?5 THEN ?6 ELSE b END,
-** c = CASE WHEN ?8 THEN ?9 ELSE c END,
-** d = CASE WHEN ?11 THEN ?12 ELSE d END
-** WHERE a = ?1 AND c = ?7 AND (?13 OR
-** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND
-** )
-**
-** For each column in the table, there are three variables to bind:
-**
-** ?(i*3+1) The old.* value of the column, if any.
-** ?(i*3+2) A boolean flag indicating that the value is being modified.
-** ?(i*3+3) The new.* value of the column, if any.
-**
-** Also, a boolean flag that, if set to true, causes the statement to update
-** a row even if the non-PK values do not match. This is required if the
-** conflict-handler is invoked with CHANGESET_DATA and returns
-** CHANGESET_REPLACE. This is variable "?(nCol*3+1)".
-**
-** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left
-** pointing to the prepared version of the SQL statement.
-*/
-static int sessionUpdateRow(
- sqlite3 *db, /* Database handle */
- const char *zTab, /* Table name */
- SessionApplyCtx *p /* Session changeset-apply context */
-){
- int rc = SQLITE_OK;
- int i;
- const char *zSep = "";
- SessionBuffer buf = {0, 0, 0};
-
- /* Append "UPDATE tbl SET " */
- sessionAppendStr(&buf, "UPDATE main.", &rc);
- sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, " SET ", &rc);
-
- /* Append the assignments */
- for(i=0; i<p->nCol; i++){
- sessionAppendStr(&buf, zSep, &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = CASE WHEN ?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, " THEN ?", &rc);
- sessionAppendInteger(&buf, i*3+3, &rc);
- sessionAppendStr(&buf, " ELSE ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " END", &rc);
- zSep = ", ";
- }
-
- /* Append the PK part of the WHERE clause */
- sessionAppendStr(&buf, " WHERE ", &rc);
- for(i=0; i<p->nCol; i++){
- if( p->abPK[i] ){
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, " AND ", &rc);
- }
- }
-
- /* Append the non-PK part of the WHERE clause */
- sessionAppendStr(&buf, " (?", &rc);
- sessionAppendInteger(&buf, p->nCol*3+1, &rc);
- sessionAppendStr(&buf, " OR 1", &rc);
- for(i=0; i<p->nCol; i++){
- if( !p->abPK[i] ){
- sessionAppendStr(&buf, " AND (?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, "=0 OR ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " IS ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, ")", &rc);
- }
- }
- sessionAppendStr(&buf, ")", &rc);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0);
- }
- sqlite3_free(buf.aBuf);
-
- return rc;
-}
-
-
-/*
** Formulate and prepare an SQL statement to query table zTab by primary
** key. Assuming the following table structure:
**
@@ -206519,17 +208961,6 @@ static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){
);
}
if( rc==SQLITE_OK ){
- rc = sessionPrepare(db, &p->pUpdate,
- "UPDATE main.sqlite_stat1 SET "
- "tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, "
- "idx = CASE WHEN ?5 THEN ?6 ELSE idx END, "
- "stat = CASE WHEN ?8 THEN ?9 ELSE stat END "
- "WHERE tbl=?1 AND idx IS "
- "CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END "
- "AND (?10 OR ?8=0 OR stat IS ?7)"
- );
- }
- if( rc==SQLITE_OK ){
rc = sessionPrepare(db, &p->pDelete,
"DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
"CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END "
@@ -206845,7 +209276,7 @@ static int sessionApplyOneOp(
int nCol;
int rc = SQLITE_OK;
- assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect );
+ assert( p->pDelete && p->pInsert && p->pSelect );
assert( p->azCol && p->abPK );
assert( !pbReplace || *pbReplace==0 );
@@ -206885,29 +209316,28 @@ static int sessionApplyOneOp(
}else if( op==SQLITE_UPDATE ){
int i;
+ sqlite3_stmt *pUp = 0;
+ int bPatchset = (pbRetry==0 || pIter->bPatchset);
+
+ rc = sessionUpdateFind(pIter, p, bPatchset, &pUp);
/* Bind values to the UPDATE statement. */
for(i=0; rc==SQLITE_OK && i<nCol; i++){
sqlite3_value *pOld = sessionChangesetOld(pIter, i);
sqlite3_value *pNew = sessionChangesetNew(pIter, i);
-
- sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew);
- if( pOld ){
- rc = sessionBindValue(p->pUpdate, i*3+1, pOld);
+ if( p->abPK[i] || (bPatchset==0 && pOld) ){
+ rc = sessionBindValue(pUp, i*2+2, pOld);
}
if( rc==SQLITE_OK && pNew ){
- rc = sessionBindValue(p->pUpdate, i*3+3, pNew);
+ rc = sessionBindValue(pUp, i*2+1, pNew);
}
}
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset);
- }
if( rc!=SQLITE_OK ) return rc;
/* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict,
** the result will be SQLITE_OK with 0 rows modified. */
- sqlite3_step(p->pUpdate);
- rc = sqlite3_reset(p->pUpdate);
+ sqlite3_step(pUp);
+ rc = sqlite3_reset(pUp);
if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){
/* A NOTFOUND or DATA error. Search the table to see if it contains
@@ -207039,7 +209469,7 @@ static int sessionRetryConstraints(
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
rc = sessionChangesetStart(
- &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints
+ &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
);
if( rc==SQLITE_OK ){
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
@@ -207130,14 +209560,13 @@ static int sessionChangesetApply(
);
if( rc!=SQLITE_OK ) break;
+ sessionUpdateFree(&sApply);
sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlite3_finalize(sApply.pDelete);
- sqlite3_finalize(sApply.pUpdate);
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pSelect);
sApply.db = db;
sApply.pDelete = 0;
- sApply.pUpdate = 0;
sApply.pInsert = 0;
sApply.pSelect = 0;
sApply.nCol = 0;
@@ -207165,7 +209594,7 @@ static int sessionChangesetApply(
int i;
sqlite3changeset_pk(pIter, &abPK, 0);
- rc = sessionTableInfo(
+ rc = sessionTableInfo(0,
db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
);
if( rc!=SQLITE_OK ) break;
@@ -207201,11 +209630,10 @@ static int sessionChangesetApply(
}
sApply.bStat1 = 1;
}else{
- if((rc = sessionSelectRow(db, zTab, &sApply))
- || (rc = sessionUpdateRow(db, zTab, &sApply))
- || (rc = sessionDeleteRow(db, zTab, &sApply))
- || (rc = sessionInsertRow(db, zTab, &sApply))
- ){
+ if( (rc = sessionSelectRow(db, zTab, &sApply))
+ || (rc = sessionDeleteRow(db, zTab, &sApply))
+ || (rc = sessionInsertRow(db, zTab, &sApply))
+ ){
break;
}
sApply.bStat1 = 0;
@@ -207264,9 +209692,9 @@ static int sessionChangesetApply(
*pnRebase = sApply.rebase.nBuf;
sApply.rebase.aBuf = 0;
}
+ sessionUpdateFree(&sApply);
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pDelete);
- sqlite3_finalize(sApply.pUpdate);
sqlite3_finalize(sApply.pSelect);
sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlite3_free((char*)sApply.constraints.aBuf);
@@ -207297,8 +209725,8 @@ SQLITE_API int sqlite3changeset_apply_v2(
int flags
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
- int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse);
+ int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+ int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -207356,7 +209784,7 @@ SQLITE_API int sqlite3changeset_apply_v2_strm(
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
- int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse);
+ int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse, 1);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -207644,7 +210072,7 @@ static int sessionChangesetToHash(
}
}
- if( sessionGrowHash(pIter->bPatchset, pTab) ){
+ if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
rc = SQLITE_NOMEM;
break;
}
@@ -207830,7 +210258,7 @@ SQLITE_API int sqlite3changegroup_output_strm(
*/
SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
if( pGrp ){
- sessionDeleteTable(pGrp->pList);
+ sessionDeleteTable(0, pGrp->pList);
sqlite3_free(pGrp);
}
}
@@ -207976,7 +210404,7 @@ static void sessionAppendPartialUpdate(
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( pIter->abPK[i] || a2[0]==0 ){
- if( !pIter->abPK[i] ) bData = 1;
+ if( !pIter->abPK[i] && a1[0] ) bData = 1;
memcpy(pOut, a1, n1);
pOut += n1;
}else if( a2[0]!=0xFF ){
@@ -208231,7 +210659,7 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
*/
SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){
if( p ){
- sessionDeleteTable(p->grp.pList);
+ sessionDeleteTable(0, p->grp.pList);
sqlite3_free(p);
}
}
@@ -210693,55 +213121,6 @@ static fts5YYACTIONTYPE fts5yy_reduce(
(void)fts5yyLookahead;
(void)fts5yyLookaheadToken;
fts5yymsp = fts5yypParser->fts5yytos;
- assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) );
-#ifndef NDEBUG
- if( fts5yyTraceFILE ){
- fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
- if( fts5yysize ){
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
- fts5yyTracePrompt,
- fts5yyruleno, fts5yyRuleName[fts5yyruleno],
- fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action",
- fts5yymsp[fts5yysize].stateno);
- }else{
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s.\n",
- fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno],
- fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action");
- }
- }
-#endif /* NDEBUG */
-
- /* Check that the stack is large enough to grow by a single entry
- ** if the RHS of the rule is empty. This ensures that there is room
- ** enough on the stack to push the LHS value */
- if( fts5yyRuleInfoNRhs[fts5yyruleno]==0 ){
-#ifdef fts5YYTRACKMAXSTACKDEPTH
- if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){
- fts5yypParser->fts5yyhwm++;
- assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack));
- }
-#endif
-#if fts5YYSTACKDEPTH>0
- if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){
- fts5yyStackOverflow(fts5yypParser);
- /* The call to fts5yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
-#else
- if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){
- if( fts5yyGrowStack(fts5yypParser) ){
- fts5yyStackOverflow(fts5yypParser);
- /* The call to fts5yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
- fts5yymsp = fts5yypParser->fts5yytos;
- }
-#endif
- }
switch( fts5yyruleno ){
/* Beginning here are the reduction cases. A typical example
@@ -211044,12 +213423,56 @@ static void sqlite3Fts5Parser(
}
#endif
- do{
+ while(1){ /* Exit by "break" */
+ assert( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystack );
assert( fts5yyact==fts5yypParser->fts5yytos->stateno );
fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact);
if( fts5yyact >= fts5YY_MIN_REDUCE ){
- fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE,fts5yymajor,
- fts5yyminor sqlite3Fts5ParserCTX_PARAM);
+ unsigned int fts5yyruleno = fts5yyact - fts5YY_MIN_REDUCE; /* Reduce by this rule */
+ assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) );
+#ifndef NDEBUG
+ if( fts5yyTraceFILE ){
+ int fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
+ if( fts5yysize ){
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
+ fts5yyTracePrompt,
+ fts5yyruleno, fts5yyRuleName[fts5yyruleno],
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action",
+ fts5yypParser->fts5yytos[fts5yysize].stateno);
+ }else{
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s.\n",
+ fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno],
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action");
+ }
+ }
+#endif /* NDEBUG */
+
+ /* Check that the stack is large enough to grow by a single entry
+ ** if the RHS of the rule is empty. This ensures that there is room
+ ** enough on the stack to push the LHS value */
+ if( fts5yyRuleInfoNRhs[fts5yyruleno]==0 ){
+#ifdef fts5YYTRACKMAXSTACKDEPTH
+ if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){
+ fts5yypParser->fts5yyhwm++;
+ assert( fts5yypParser->fts5yyhwm ==
+ (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack));
+ }
+#endif
+#if fts5YYSTACKDEPTH>0
+ if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){
+ fts5yyStackOverflow(fts5yypParser);
+ break;
+ }
+#else
+ if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){
+ if( fts5yyGrowStack(fts5yypParser) ){
+ fts5yyStackOverflow(fts5yypParser);
+ break;
+ }
+ }
+#endif
+ }
+ fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyruleno,fts5yymajor,fts5yyminor sqlite3Fts5ParserCTX_PARAM);
}else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){
fts5yy_shift(fts5yypParser,fts5yyact,(fts5YYCODETYPE)fts5yymajor,fts5yyminor);
#ifndef fts5YYNOERRORRECOVERY
@@ -211162,7 +213585,7 @@ static void sqlite3Fts5Parser(
break;
#endif
}
- }while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack );
+ }
#ifndef NDEBUG
if( fts5yyTraceFILE ){
fts5yyStackEntry *i;
@@ -214774,8 +217197,8 @@ static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bD
}
/* If the iterator is not at a real match, skip forward until it is. */
- while( pRoot->bNomatch ){
- assert( pRoot->bEof==0 && rc==SQLITE_OK );
+ while( pRoot->bNomatch && rc==SQLITE_OK ){
+ assert( pRoot->bEof==0 );
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
}
return rc;
@@ -218960,14 +221383,10 @@ static void fts5SegIterNext(
}else{
/* The following could be done by calling fts5SegIterLoadNPos(). But
** this block is particularly performance critical, so equivalent
- ** code is inlined.
- **
- ** Later: Switched back to fts5SegIterLoadNPos() because it supports
- ** detail=none mode. Not ideal.
- */
+ ** code is inlined. */
int nSz;
assert( p->rc==SQLITE_OK );
- assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
+ assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
@@ -219959,7 +222378,7 @@ static void fts5ChunkIterate(
int pgno = pSeg->iLeafPgno;
int pgnoSave = 0;
- /* This function does notmwork with detail=none databases. */
+ /* This function does not work with detail=none databases. */
assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
@@ -219972,6 +222391,9 @@ static void fts5ChunkIterate(
fts5DataRelease(pData);
if( nRem<=0 ){
break;
+ }else if( pSeg->pSeg==0 ){
+ p->rc = FTS5_CORRUPT;
+ return;
}else{
pgno++;
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
@@ -220023,66 +222445,72 @@ static void fts5SegiterPoslist(
}
/*
-** IN/OUT parameter (*pa) points to a position list n bytes in size. If
-** the position list contains entries for column iCol, then (*pa) is set
-** to point to the sub-position-list for that column and the number of
-** bytes in it returned. Or, if the argument position list does not
-** contain any entries for column iCol, return 0.
+** Parameter pPos points to a buffer containing a position list, size nPos.
+** This function filters it according to pColset (which must be non-NULL)
+** and sets pIter->base.pData/nData to point to the new position list.
+** If memory is required for the new position list, use buffer pIter->poslist.
+** Or, if the new position list is a contiguous subset of the input, set
+** pIter->base.pData/nData to point directly to it.
+**
+** This function is a no-op if *pRc is other than SQLITE_OK when it is
+** called. If an OOM error is encountered, *pRc is set to SQLITE_NOMEM
+** before returning.
*/
-static int fts5IndexExtractCol(
- const u8 **pa, /* IN/OUT: Pointer to poslist */
- int n, /* IN: Size of poslist in bytes */
- int iCol /* Column to extract from poslist */
-){
- int iCurrent = 0; /* Anything before the first 0x01 is col 0 */
- const u8 *p = *pa;
- const u8 *pEnd = &p[n]; /* One byte past end of position list */
-
- while( iCol>iCurrent ){
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint. Note that it is not possible for a negative
- ** or extremely large varint to occur within an uncorrupted position
- ** list. So the last byte of each varint may be assumed to have a clear
- ** 0x80 bit. */
- while( *p!=0x01 ){
- while( *p++ & 0x80 );
- if( p>=pEnd ) return 0;
- }
- *pa = p++;
- iCurrent = *p++;
- if( iCurrent & 0x80 ){
- p--;
- p += fts5GetVarint32(p, iCurrent);
- }
- }
- if( iCol!=iCurrent ) return 0;
-
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint */
- while( p<pEnd && *p!=0x01 ){
- while( *p++ & 0x80 );
- }
-
- return p - (*pa);
-}
-
static void fts5IndexExtractColset(
int *pRc,
Fts5Colset *pColset, /* Colset to filter on */
const u8 *pPos, int nPos, /* Position list */
- Fts5Buffer *pBuf /* Output buffer */
+ Fts5Iter *pIter
){
if( *pRc==SQLITE_OK ){
- int i;
- fts5BufferZero(pBuf);
- for(i=0; i<pColset->nCol; i++){
- const u8 *pSub = pPos;
- int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
- if( nSub ){
- fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
+ const u8 *p = pPos;
+ const u8 *aCopy = p;
+ const u8 *pEnd = &p[nPos]; /* One byte past end of position list */
+ int i = 0;
+ int iCurrent = 0;
+
+ if( pColset->nCol>1 && sqlite3Fts5BufferSize(pRc, &pIter->poslist, nPos) ){
+ return;
+ }
+
+ while( 1 ){
+ while( pColset->aiCol[i]<iCurrent ){
+ i++;
+ if( i==pColset->nCol ){
+ pIter->base.pData = pIter->poslist.p;
+ pIter->base.nData = pIter->poslist.n;
+ return;
+ }
+ }
+
+ /* Advance pointer p until it points to pEnd or an 0x01 byte that is
+ ** not part of a varint */
+ while( p<pEnd && *p!=0x01 ){
+ while( *p++ & 0x80 );
+ }
+
+ if( pColset->aiCol[i]==iCurrent ){
+ if( pColset->nCol==1 ){
+ pIter->base.pData = aCopy;
+ pIter->base.nData = p-aCopy;
+ return;
+ }
+ fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy);
+ }
+ if( p==pEnd ){
+ pIter->base.pData = pIter->poslist.p;
+ pIter->base.nData = pIter->poslist.n;
+ return;
+ }
+ aCopy = p++;
+ iCurrent = *p++;
+ if( iCurrent & 0x80 ){
+ p--;
+ p += fts5GetVarint32(p, iCurrent);
}
}
}
+
}
/*
@@ -220202,16 +222630,9 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
/* All data is stored on the current page. Populate the output
** variables to point into the body of the page object. */
const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
- if( pColset->nCol==1 ){
- pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
- pIter->base.pData = a;
- }else{
- int *pRc = &pIter->pIndex->rc;
- fts5BufferZero(&pIter->poslist);
- fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
- pIter->base.pData = pIter->poslist.p;
- pIter->base.nData = pIter->poslist.n;
- }
+ int *pRc = &pIter->pIndex->rc;
+ fts5BufferZero(&pIter->poslist);
+ fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, pIter);
}else{
/* The data is distributed over two or more pages. Copy it into the
** Fts5Iter.poslist buffer and then set the output pointer to point
@@ -221694,7 +224115,7 @@ static void fts5AppendPoslist(
static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
- assert( pIter->aPoslist );
+ assert( pIter->aPoslist || (p==0 && pIter->aPoslist==0) );
if( p>=pIter->aEof ){
pIter->aPoslist = 0;
}else{
@@ -221714,6 +224135,9 @@ static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
}
pIter->aPoslist = p;
+ if( &pIter->aPoslist[pIter->nPoslist]>pIter->aEof ){
+ pIter->aPoslist = 0;
+ }
}
}
@@ -221722,9 +224146,11 @@ static void fts5DoclistIterInit(
Fts5DoclistIter *pIter
){
memset(pIter, 0, sizeof(*pIter));
- pIter->aPoslist = pBuf->p;
- pIter->aEof = &pBuf->p[pBuf->n];
- fts5DoclistIterNext(pIter);
+ if( pBuf->n>0 ){
+ pIter->aPoslist = pBuf->p;
+ pIter->aEof = &pBuf->p[pBuf->n];
+ fts5DoclistIterNext(pIter);
+ }
}
#if 0
@@ -221778,16 +224204,20 @@ static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
static void fts5MergeRowidLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
+ int nBuf, /* Number of entries in apBuf[] */
+ Fts5Buffer *aBuf /* Array of other lists to merge into p1 */
){
int i1 = 0;
int i2 = 0;
i64 iRowid1 = 0;
i64 iRowid2 = 0;
i64 iOut = 0;
-
+ Fts5Buffer *p2 = &aBuf[0];
Fts5Buffer out;
+
+ (void)nBuf;
memset(&out, 0, sizeof(out));
+ assert( nBuf==1 );
sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
if( p->rc ) return;
@@ -221814,180 +224244,213 @@ static void fts5MergeRowidLists(
fts5BufferFree(&out);
}
+typedef struct PrefixMerger PrefixMerger;
+struct PrefixMerger {
+ Fts5DoclistIter iter; /* Doclist iterator */
+ i64 iPos; /* For iterating through a position list */
+ int iOff;
+ u8 *aPos;
+ PrefixMerger *pNext; /* Next in docid/poslist order */
+};
+
+static void fts5PrefixMergerInsertByRowid(
+ PrefixMerger **ppHead,
+ PrefixMerger *p
+){
+ if( p->iter.aPoslist ){
+ PrefixMerger **pp = ppHead;
+ while( *pp && p->iter.iRowid>(*pp)->iter.iRowid ){
+ pp = &(*pp)->pNext;
+ }
+ p->pNext = *pp;
+ *pp = p;
+ }
+}
+
+static void fts5PrefixMergerInsertByPosition(
+ PrefixMerger **ppHead,
+ PrefixMerger *p
+){
+ if( p->iPos>=0 ){
+ PrefixMerger **pp = ppHead;
+ while( *pp && p->iPos>(*pp)->iPos ){
+ pp = &(*pp)->pNext;
+ }
+ p->pNext = *pp;
+ *pp = p;
+ }
+}
+
+
/*
-** Buffers p1 and p2 contain doclists. This function merges the content
-** of the two doclists together and sets buffer p1 to the result before
-** returning.
-**
-** If an error occurs, an error code is left in p->rc. If an error has
-** already occurred, this function is a no-op.
+** Array aBuf[] contains nBuf doclists. These are all merged in with the
+** doclist in buffer p1.
*/
static void fts5MergePrefixLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
-){
- if( p2->n ){
- i64 iLastRowid = 0;
- Fts5DoclistIter i1;
- Fts5DoclistIter i2;
- Fts5Buffer out = {0, 0, 0};
- Fts5Buffer tmp = {0, 0, 0};
-
- /* The maximum size of the output is equal to the sum of the two
- ** input sizes + 1 varint (9 bytes). The extra varint is because if the
- ** first rowid in one input is a large negative number, and the first in
- ** the other a non-negative number, the delta for the non-negative
- ** number will be larger on disk than the literal integer value
- ** was.
- **
- ** Or, if the input position-lists are corrupt, then the output might
- ** include up to 2 extra 10-byte positions created by interpreting -1
- ** (the value PoslistNext64() uses for EOF) as a position and appending
- ** it to the output. This can happen at most once for each input
- ** position-list, hence two 10 byte paddings. */
- if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9+10+10) ) return;
- fts5DoclistIterInit(p1, &i1);
- fts5DoclistIterInit(p2, &i2);
+ int nBuf, /* Number of buffers in array aBuf[] */
+ Fts5Buffer *aBuf /* Other lists to merge in */
+){
+#define fts5PrefixMergerNextPosition(p) \
+ sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos);
+#define FTS5_MERGE_NLIST 16
+ PrefixMerger aMerger[FTS5_MERGE_NLIST];
+ PrefixMerger *pHead = 0;
+ int i;
+ int nOut = 0;
+ Fts5Buffer out = {0, 0, 0};
+ Fts5Buffer tmp = {0, 0, 0};
+ i64 iLastRowid = 0;
+
+ /* Initialize a doclist-iterator for each input buffer. Arrange them in
+ ** a linked-list starting at pHead in ascending order of rowid. Avoid
+ ** linking any iterators already at EOF into the linked list at all. */
+ assert( nBuf+1<=sizeof(aMerger)/sizeof(aMerger[0]) );
+ memset(aMerger, 0, sizeof(PrefixMerger)*(nBuf+1));
+ pHead = &aMerger[nBuf];
+ fts5DoclistIterInit(p1, &pHead->iter);
+ for(i=0; i<nBuf; i++){
+ fts5DoclistIterInit(&aBuf[i], &aMerger[i].iter);
+ fts5PrefixMergerInsertByRowid(&pHead, &aMerger[i]);
+ nOut += aBuf[i].n;
+ }
+ if( nOut==0 ) return;
+ nOut += p1->n + 9 + 10*nBuf;
+
+ /* The maximum size of the output is equal to the sum of the
+ ** input sizes + 1 varint (9 bytes). The extra varint is because if the
+ ** first rowid in one input is a large negative number, and the first in
+ ** the other a non-negative number, the delta for the non-negative
+ ** number will be larger on disk than the literal integer value
+ ** was.
+ **
+ ** Or, if the input position-lists are corrupt, then the output might
+ ** include up to (nBuf+1) extra 10-byte positions created by interpreting -1
+ ** (the value PoslistNext64() uses for EOF) as a position and appending
+ ** it to the output. This can happen at most once for each input
+ ** position-list, hence (nBuf+1) 10 byte paddings. */
+ if( sqlite3Fts5BufferSize(&p->rc, &out, nOut) ) return;
+
+ while( pHead ){
+ fts5MergeAppendDocid(&out, iLastRowid, pHead->iter.iRowid);
+
+ if( pHead->pNext && iLastRowid==pHead->pNext->iter.iRowid ){
+ /* Merge data from two or more poslists */
+ i64 iPrev = 0;
+ int nTmp = FTS5_DATA_ZERO_PADDING;
+ int nMerge = 0;
+ PrefixMerger *pSave = pHead;
+ PrefixMerger *pThis = 0;
+ int nTail = 0;
+
+ pHead = 0;
+ while( pSave && pSave->iter.iRowid==iLastRowid ){
+ PrefixMerger *pNext = pSave->pNext;
+ pSave->iOff = 0;
+ pSave->iPos = 0;
+ pSave->aPos = &pSave->iter.aPoslist[pSave->iter.nSize];
+ fts5PrefixMergerNextPosition(pSave);
+ nTmp += pSave->iter.nPoslist + 10;
+ nMerge++;
+ fts5PrefixMergerInsertByPosition(&pHead, pSave);
+ pSave = pNext;
+ }
+
+ if( pHead==0 || pHead->pNext==0 ){
+ p->rc = FTS5_CORRUPT;
+ break;
+ }
- while( 1 ){
- if( i1.iRowid<i2.iRowid ){
- /* Copy entry from i1 */
- fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
- fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
- fts5DoclistIterNext(&i1);
- if( i1.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
- }
- else if( i2.iRowid!=i1.iRowid ){
- /* Copy entry from i2 */
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
- fts5DoclistIterNext(&i2);
- if( i2.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
+ /* See the earlier comment in this function for an explanation of why
+ ** corrupt input position lists might cause the output to consume
+ ** at most nMerge*10 bytes of unexpected space. */
+ if( sqlite3Fts5BufferSize(&p->rc, &tmp, nTmp+nMerge*10) ){
+ break;
}
- else{
- /* Merge the two position lists. */
- i64 iPos1 = 0;
- i64 iPos2 = 0;
- int iOff1 = 0;
- int iOff2 = 0;
- u8 *a1 = &i1.aPoslist[i1.nSize];
- u8 *a2 = &i2.aPoslist[i2.nSize];
- int nCopy;
- u8 *aCopy;
-
- i64 iPrev = 0;
- Fts5PoslistWriter writer;
- memset(&writer, 0, sizeof(writer));
-
- /* See the earlier comment in this function for an explanation of why
- ** corrupt input position lists might cause the output to consume
- ** at most 20 bytes of unexpected space. */
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferZero(&tmp);
- sqlite3Fts5BufferSize(&p->rc, &tmp,
- i1.nPoslist + i2.nPoslist + 10 + 10 + FTS5_DATA_ZERO_PADDING
- );
- if( p->rc ) break;
+ fts5BufferZero(&tmp);
- sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- assert_nc( iPos1>=0 && iPos2>=0 );
+ pThis = pHead;
+ pHead = pThis->pNext;
+ sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
+ fts5PrefixMergerNextPosition(pThis);
+ fts5PrefixMergerInsertByPosition(&pHead, pThis);
- if( iPos1<iPos2 ){
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- }else{
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- }
- if( iPos1>=0 && iPos2>=0 ){
- while( 1 ){
- if( iPos1<iPos2 ){
- if( iPos1!=iPrev ){
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- }
- sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- if( iPos1<0 ) break;
- }else{
- assert_nc( iPos2!=iPrev );
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- if( iPos2<0 ) break;
- }
- }
+ while( pHead->pNext ){
+ pThis = pHead;
+ if( pThis->iPos!=iPrev ){
+ sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
}
+ fts5PrefixMergerNextPosition(pThis);
+ pHead = pThis->pNext;
+ fts5PrefixMergerInsertByPosition(&pHead, pThis);
+ }
- if( iPos1>=0 ){
- if( iPos1!=iPrev ){
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- }
- aCopy = &a1[iOff1];
- nCopy = i1.nPoslist - iOff1;
- }else{
- assert_nc( iPos2>=0 && iPos2!=iPrev );
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- aCopy = &a2[iOff2];
- nCopy = i2.nPoslist - iOff2;
- }
- if( nCopy>0 ){
- fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
- }
+ if( pHead->iPos!=iPrev ){
+ sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
+ }
+ nTail = pHead->iter.nPoslist - pHead->iOff;
- /* WRITEPOSLISTSIZE */
- assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist );
- assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 );
- if( tmp.n>i1.nPoslist+i2.nPoslist ){
- if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
- break;
+ /* WRITEPOSLISTSIZE */
+ assert( tmp.n+nTail<=nTmp );
+ if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
+ if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
+ break;
+ }
+ fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
+ fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
+ if( nTail>0 ){
+ fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail);
+ }
+
+ pHead = pSave;
+ for(i=0; i<nBuf+1; i++){
+ PrefixMerger *pX = &aMerger[i];
+ if( pX->iter.aPoslist && pX->iter.iRowid==iLastRowid ){
+ fts5DoclistIterNext(&pX->iter);
+ fts5PrefixMergerInsertByRowid(&pHead, pX);
}
- fts5BufferSafeAppendVarint(&out, tmp.n * 2);
- fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
- fts5DoclistIterNext(&i1);
- fts5DoclistIterNext(&i2);
- assert_nc( out.n<=(p1->n+p2->n+9) );
- if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
}
- }
- if( i1.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
- fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist);
- }
- else if( i2.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
+ }else{
+ /* Copy poslist from pHead to output */
+ PrefixMerger *pThis = pHead;
+ Fts5DoclistIter *pI = &pThis->iter;
+ fts5BufferSafeAppendBlob(&out, pI->aPoslist, pI->nPoslist+pI->nSize);
+ fts5DoclistIterNext(pI);
+ pHead = pThis->pNext;
+ fts5PrefixMergerInsertByRowid(&pHead, pThis);
}
- assert_nc( out.n<=(p1->n+p2->n+9) );
-
- fts5BufferFree(p1);
- fts5BufferFree(&tmp);
- memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
- *p1 = out;
}
+
+ fts5BufferFree(p1);
+ fts5BufferFree(&tmp);
+ memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
+ *p1 = out;
}
static void fts5SetupPrefixIter(
Fts5Index *p, /* Index to read from */
int bDesc, /* True for "ORDER BY rowid DESC" */
- const u8 *pToken, /* Buffer containing prefix to match */
+ int iIdx, /* Index to scan for data */
+ u8 *pToken, /* Buffer containing prefix to match */
int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset, /* Restrict matches to these columns */
Fts5Iter **ppIter /* OUT: New iterator */
){
Fts5Structure *pStruct;
Fts5Buffer *aBuf;
- const int nBuf = 32;
+ int nBuf = 32;
+ int nMerge = 1;
- void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
+ void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
xMerge = fts5MergeRowidLists;
xAppend = fts5AppendRowid;
}else{
+ nMerge = FTS5_MERGE_NLIST-1;
+ nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
xMerge = fts5MergePrefixLists;
xAppend = fts5AppendPoslist;
}
@@ -222007,6 +224470,27 @@ static void fts5SetupPrefixIter(
int bNewTerm = 1;
memset(&doclist, 0, sizeof(doclist));
+ if( iIdx!=0 ){
+ int dummy = 0;
+ const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
+ pToken[0] = FTS5_MAIN_PREFIX;
+ fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
+ fts5IterSetOutputCb(&p->rc, p1);
+ for(;
+ fts5MultiIterEof(p, p1)==0;
+ fts5MultiIterNext2(p, p1, &dummy)
+ ){
+ Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
+ p1->xSetOutputs(p1, pSeg);
+ if( p1->base.nData ){
+ xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
+ iLastRowid = p1->base.iRowid;
+ }
+ }
+ fts5MultiIterFree(p1);
+ }
+
+ pToken[0] = FTS5_MAIN_PREFIX + iIdx;
fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for( /* no-op */ ;
@@ -222027,13 +224511,21 @@ static void fts5SetupPrefixIter(
if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
- assert( i<nBuf );
- if( aBuf[i].n==0 ){
- fts5BufferSwap(&doclist, &aBuf[i]);
- fts5BufferZero(&doclist);
- }else{
- xMerge(p, &doclist, &aBuf[i]);
- fts5BufferZero(&aBuf[i]);
+ int i1 = i*nMerge;
+ int iStore;
+ assert( i1+nMerge<=nBuf );
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
+ if( aBuf[iStore].n==0 ){
+ fts5BufferSwap(&doclist, &aBuf[iStore]);
+ fts5BufferZero(&doclist);
+ break;
+ }
+ }
+ if( iStore==i1+nMerge ){
+ xMerge(p, &doclist, nMerge, &aBuf[i1]);
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
+ fts5BufferZero(&aBuf[iStore]);
+ }
}
}
iLastRowid = 0;
@@ -222043,11 +224535,15 @@ static void fts5SetupPrefixIter(
iLastRowid = p1->base.iRowid;
}
- for(i=0; i<nBuf; i++){
+ assert( (nBuf%nMerge)==0 );
+ for(i=0; i<nBuf; i+=nMerge){
+ int iFree;
if( p->rc==SQLITE_OK ){
- xMerge(p, &doclist, &aBuf[i]);
+ xMerge(p, &doclist, nMerge, &aBuf[i]);
+ }
+ for(iFree=i; iFree<i+nMerge; iFree++){
+ fts5BufferFree(&aBuf[iFree]);
}
- fts5BufferFree(&aBuf[i]);
}
fts5MultiIterFree(p1);
@@ -222302,6 +224798,7 @@ static int sqlite3Fts5IndexQuery(
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
+ int iPrefixIdx = 0; /* +1 prefix index */
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
/* Figure out which index to search and set iIdx accordingly. If this
@@ -222323,7 +224820,9 @@ static int sqlite3Fts5IndexQuery(
if( flags & FTS5INDEX_QUERY_PREFIX ){
int nChar = fts5IndexCharlen(pToken, nToken);
for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
- if( pConfig->aPrefix[iIdx-1]==nChar ) break;
+ int nIdxChar = pConfig->aPrefix[iIdx-1];
+ if( nIdxChar==nChar ) break;
+ if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
}
}
@@ -222340,8 +224839,7 @@ static int sqlite3Fts5IndexQuery(
}else{
/* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
- buf.p[0] = FTS5_MAIN_PREFIX;
- fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
+ fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
assert( p->rc!=SQLITE_OK || pRet->pColset==0 );
fts5IterSetOutputCb(&p->rc, pRet);
if( p->rc==SQLITE_OK ){
@@ -222414,8 +224912,9 @@ static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
int n;
const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
+ assert_nc( z || n<=1 );
*pn = n-1;
- return &z[1];
+ return (z ? &z[1] : 0);
}
/*
@@ -225701,7 +228200,8 @@ static int fts5ApiPhraseFirst(
int n;
int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
*piCol = 0;
*piOff = 0;
fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
@@ -225760,7 +228260,8 @@ static int fts5ApiPhraseFirstColumn(
rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
}
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
*piCol = 0;
fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
}
@@ -225768,7 +228269,8 @@ static int fts5ApiPhraseFirstColumn(
int n;
rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
if( n<=0 ){
*piCol = -1;
}else if( pIter->a[0]==0x01 ){
@@ -226246,7 +228748,7 @@ static int sqlite3Fts5GetTokenizer(
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
}else{
rc = pMod->x.xCreate(
- pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
+ pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
);
pConfig->pTokApi = &pMod->x;
if( rc!=SQLITE_OK ){
@@ -226309,7 +228811,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2020-12-01 16:14:00 0000000000000000000000000000000000000000000000000000000000000000", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2021-04-19 18:32:05 0000000000000000000000000000000000000000000000000000000000000000", -1, SQLITE_TRANSIENT);
}
/*
@@ -231235,9 +233737,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=231238
+#if __LINE__!=233740
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
+#define SQLITE_SOURCE_ID "2021-04-19 18:32:05 7dd0b0cff3f06b1f1a3bc94233e1d1574288f3ed9bbc277639d2cc5713d0alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/chromium/third_party/sqlite/amalgamation/sqlite3.h b/chromium/third_party/sqlite/amalgamation/sqlite3.h
index 44be7872663..31e4fc4d294 100644
--- a/chromium/third_party/sqlite/amalgamation/sqlite3.h
+++ b/chromium/third_party/sqlite/amalgamation/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.34.0"
-#define SQLITE_VERSION_NUMBER 3034000
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
+#define SQLITE_VERSION "3.35.5"
+#define SQLITE_VERSION_NUMBER 3035005
+#define SQLITE_SOURCE_ID "2021-04-19 18:32:05 7dd0b0cff3f06b1f1a3bc94233e1d1574288f3ed9bbc277639d2cc5713d0alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -2115,7 +2115,13 @@ struct sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the trigger setting is not reported back. </dd>
+** which case the trigger setting is not reported back.
+**
+** <p>Originally this option disabled all triggers. ^(However, since
+** SQLite version 3.35.0, TEMP triggers are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** triggers in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
@@ -2126,7 +2132,13 @@ struct sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the view setting is not reported back. </dd>
+** which case the view setting is not reported back.
+**
+** <p>Originally this option disabled all views. ^(However, since
+** SQLite version 3.35.0, TEMP views are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** views in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
@@ -3499,6 +3511,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** that uses dot-files in place of posix advisory locking.
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
+** Use "ro" instead: "file:data.db?mode=ro".
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
@@ -3697,7 +3710,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
** If the Y parameter to sqlite3_free_filename(Y) is anything other
** than a NULL pointer or a pointer previously acquired from
** sqlite3_create_filename(), then bad things such as heap
-** corruption or segfaults may occur. The value Y should be
+** corruption or segfaults may occur. The value Y should not be
** used again after sqlite3_free_filename(Y) has been called. This means
** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
** then the corresponding [sqlite3_module.xClose() method should also be
@@ -7765,7 +7778,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_SEEK_COUNT 30
-#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_TRACEFLAGS 31
+#define SQLITE_TESTCTRL_LAST 31 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -10439,6 +10453,14 @@ SQLITE_API int sqlite3session_patchset(
SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
/*
+** CAPI3REF: Query for the amount of heap memory used by a session object.
+**
+** This API returns the total amount of heap memory in bytes currently
+** used by the session object passed as the only argument.
+*/
+SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
+
+/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
** CONSTRUCTOR: sqlite3_changeset_iter
**
@@ -10540,18 +10562,23 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
-** If argument pzTab is not NULL, then *pzTab is set to point to a
-** nul-terminated utf-8 encoded string containing the name of the table
-** affected by the current change. The buffer remains valid until either
-** sqlite3changeset_next() is called on the iterator or until the
-** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
-** set to the number of columns in the table affected by the change. If
-** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
+** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
+** outputs are set through these pointers:
+**
+** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the type of change that the iterator currently points to;
+**
+** *pnCol is set to the number of columns in the table affected by the change; and
+**
+** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
+** the name of the table affected by the current change. The buffer remains
+** valid until either sqlite3changeset_next() is called on the iterator
+** or until the conflict-handler function returns.
+**
+** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
-** changes. Finally, if pOp is not NULL, then *pOp is set to one of
-** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
-** type of change that the iterator currently points to.
+** changes.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3.c b/chromium/third_party/sqlite/src/ext/fts3/fts3.c
index ef69a7b1868..0dfe304a437 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3.c
@@ -61,7 +61,7 @@
** A doclist (document list) holds a docid-sorted list of hits for a
** given term. Doclists hold docids and associated token positions.
** A docid is the unique integer identifier for a single document.
-** A position is the index of a word within the document. The first
+** A position is the index of a word within the document. The first
** word of the document has a position of 0.
**
** FTS3 used to optionally store character offsets using a compile-time
@@ -86,7 +86,7 @@
**
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory. A "position" is an index of a token in the token stream
-** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
+** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
** in the same logical place as the position element, and act as sentinals
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
** The positions numbers are not stored literally but rather as two more
@@ -110,7 +110,7 @@
** a document record consists of a docid followed by a position-list and
** a doclist consists of one or more document records.
**
-** A bare doclist omits the position information, becoming an
+** A bare doclist omits the position information, becoming an
** array of varint-encoded docids.
**
**** Segment leaf nodes ****
@@ -287,7 +287,6 @@
** query logic likewise merges doclists so that newer data knocks out
** older data.
*/
-#define CHROMIUM_FTS3_CHANGES 1
#include "fts3Int.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
@@ -304,7 +303,7 @@
#include <stdarg.h>
#include "fts3.h"
-#ifndef SQLITE_CORE
+#ifndef SQLITE_CORE
# include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#endif
@@ -322,6 +321,14 @@ int sqlite3Fts3Never(int b) { assert( !b ); return b; }
#endif
/*
+** This variable is set to false when running tests for which the on disk
+** structures should not be corrupt. Otherwise, true. If it is false, extra
+** assert() conditions in the fts3 code are activated - conditions that are
+** only true if it is guaranteed that the fts3 database is not corrupt.
+*/
+int sqlite3_fts3_may_be_corrupt = 1;
+
+/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
@@ -339,18 +346,13 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
}
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
- v = (v & mask1) | ( (*ptr++) << shift ); \
+ v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \
if( (v & mask2)==0 ){ var = v; return ret; }
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
v = (*ptr++); \
if( (v & mask2)==0 ){ var = v; return ret; }
-/*
-** Read a 64-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read, or 0 on error.
-** The value is stored in *v.
-*/
-int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
+int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
const unsigned char *p = (const unsigned char*)pBuf;
const unsigned char *pStart = p;
u32 a;
@@ -372,25 +374,61 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
return (int)(p - pStart);
}
+/*
+** Read a 64-bit variable-length integer from memory starting at p[0].
+** Return the number of bytes read, or 0 on error.
+** The value is stored in *v.
+*/
+int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
+ return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v);
+}
+
+/*
+** Read a 64-bit variable-length integer from memory starting at p[0] and
+** not extending past pEnd[-1].
+** Return the number of bytes read, or 0 on error.
+** The value is stored in *v.
+*/
+int sqlite3Fts3GetVarintBounded(
+ const char *pBuf,
+ const char *pEnd,
+ sqlite_int64 *v
+){
+ const unsigned char *p = (const unsigned char*)pBuf;
+ const unsigned char *pStart = p;
+ const unsigned char *pX = (const unsigned char*)pEnd;
+ u64 b = 0;
+ int shift;
+ for(shift=0; shift<=63; shift+=7){
+ u64 c = p<pX ? *p : 0;
+ p++;
+ b += (c&0x7F) << shift;
+ if( (c & 0x80)==0 ) break;
+ }
+ *v = b;
+ return (int)(p - pStart);
+}
+
/*
-** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
+** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
** a non-negative 32-bit integer before it is returned.
*/
int sqlite3Fts3GetVarint32(const char *p, int *pi){
+ const unsigned char *ptr = (const unsigned char*)p;
u32 a;
#ifndef fts3GetVarint32
- GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
+ GETVARINT_INIT(a, ptr, 0, 0x00, 0x80, *pi, 1);
#else
- a = (*p++);
+ a = (*ptr++);
assert( a & 0x80 );
#endif
- GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
- GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
- GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
+ GETVARINT_STEP(a, ptr, 7, 0x7F, 0x4000, *pi, 2);
+ GETVARINT_STEP(a, ptr, 14, 0x3FFF, 0x200000, *pi, 3);
+ GETVARINT_STEP(a, ptr, 21, 0x1FFFFF, 0x10000000, *pi, 4);
a = (a & 0x0FFFFFFF );
- *pi = (int)(a | ((u32)(*p & 0x07) << 28));
+ *pi = (int)(a | ((u32)(*ptr & 0x07) << 28));
assert( 0==(a & 0x80000000) );
assert( *pi>=0 );
return 5;
@@ -431,7 +469,7 @@ void sqlite3Fts3Dequote(char *z){
int iOut = 0; /* Index of next byte to write to output */
/* If the first byte was a '[', then the close-quote character is a ']' */
- if( quote=='[' ) quote = ']';
+ if( quote=='[' ) quote = ']';
while( z[iIn] ){
if( z[iIn]==quote ){
@@ -467,14 +505,14 @@ static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
** varint is part of.
*/
static void fts3GetReverseVarint(
- char **pp,
- char *pStart,
+ char **pp,
+ char *pStart,
sqlite3_int64 *pVal
){
sqlite3_int64 iVal;
char *p;
- /* Pointer p now points at the first byte past the varint we are
+ /* Pointer p now points at the first byte past the varint we are
** interested in. So, unless the doclist is corrupt, the 0x80 bit is
** clear on character p[-1]. */
for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
@@ -561,13 +599,18 @@ static int fts3DestroyMethod(sqlite3_vtab *pVtab){
sqlite3 *db = p->db; /* Database handle */
/* Drop the shadow tables */
- if( p->zContentTbl==0 ){
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
- }
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
+ fts3DbExec(&rc, db,
+ "DROP TABLE IF EXISTS %Q.'%q_segments';"
+ "DROP TABLE IF EXISTS %Q.'%q_segdir';"
+ "DROP TABLE IF EXISTS %Q.'%q_docsize';"
+ "DROP TABLE IF EXISTS %Q.'%q_stat';"
+ "%s DROP TABLE IF EXISTS %Q.'%q_content';",
+ zDb, p->zName,
+ zDb, p->zName,
+ zDb, p->zName,
+ zDb, p->zName,
+ (p->zContentTbl ? "--" : ""), zDb,p->zName
+ );
/* If everything has worked, invoke fts3DisconnectMethod() to free the
** memory associated with the Fts3Table structure and return SQLITE_OK.
@@ -582,7 +625,7 @@ static int fts3DestroyMethod(sqlite3_vtab *pVtab){
** passed as the first argument. This is done as part of the xConnect()
** and xCreate() methods.
**
-** If *pRc is non-zero when this function is called, it is a no-op.
+** If *pRc is non-zero when this function is called, it is a no-op.
** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
** before returning.
*/
@@ -605,7 +648,7 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){
/* Create the whole "CREATE TABLE" statement to pass to SQLite */
zSql = sqlite3_mprintf(
- "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
+ "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
zCols, p->zName, zLanguageid
);
if( !zCols || !zSql ){
@@ -624,7 +667,7 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){
** Create the %_stat table if it does not already exist.
*/
void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){
- fts3DbExec(pRc, p->db,
+ fts3DbExec(pRc, p->db,
"CREATE TABLE IF NOT EXISTS %Q.'%q_stat'"
"(id INTEGER PRIMARY KEY, value BLOB);",
p->zDb, p->zName
@@ -660,9 +703,9 @@ static int fts3CreateTables(Fts3Table *p){
zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid);
}
if( zContentCols==0 ) rc = SQLITE_NOMEM;
-
+
/* Create the content table */
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_content'(%s)",
p->zDb, p->zName, zContentCols
);
@@ -670,11 +713,11 @@ static int fts3CreateTables(Fts3Table *p){
}
/* Create other tables */
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",
p->zDb, p->zName
);
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_segdir'("
"level INTEGER,"
"idx INTEGER,"
@@ -687,7 +730,7 @@ static int fts3CreateTables(Fts3Table *p){
p->zDb, p->zName
);
if( p->bHasDocsize ){
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
p->zDb, p->zName
);
@@ -702,7 +745,7 @@ static int fts3CreateTables(Fts3Table *p){
/*
** Store the current database page-size in bytes in p->nPgsz.
**
-** If *pRc is non-zero when this function is called, it is a no-op.
+** If *pRc is non-zero when this function is called, it is a no-op.
** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
** before returning.
*/
@@ -711,7 +754,7 @@ static void fts3DatabasePageSize(int *pRc, Fts3Table *p){
int rc; /* Return code */
char *zSql; /* SQL text "PRAGMA %Q.page_size" */
sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */
-
+
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb);
if( !zSql ){
rc = SQLITE_NOMEM;
@@ -737,11 +780,11 @@ static void fts3DatabasePageSize(int *pRc, Fts3Table *p){
**
** <key> = <value>
**
-** There may not be whitespace surrounding the "=" character. The <value>
+** There may not be whitespace surrounding the "=" character. The <value>
** term may be quoted, but the <key> may not.
*/
static int fts3IsSpecialColumn(
- const char *z,
+ const char *z,
int *pnKey,
char **pzValue
){
@@ -799,10 +842,10 @@ static void fts3Appendf(
** memory.
*/
static char *fts3QuoteId(char const *zInput){
- int nRet;
+ sqlite3_int64 nRet;
char *zRet;
nRet = 2 + (int)strlen(zInput)*2 + 1;
- zRet = sqlite3_malloc(nRet);
+ zRet = sqlite3_malloc64(nRet);
if( zRet ){
int i;
char *z = zRet;
@@ -818,7 +861,7 @@ static char *fts3QuoteId(char const *zInput){
}
/*
-** Return a list of comma separated SQL expressions and a FROM clause that
+** Return a list of comma separated SQL expressions and a FROM clause that
** could be used in a SELECT statement such as the following:
**
** SELECT <list of expressions> FROM %_content AS x ...
@@ -869,7 +912,7 @@ static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){
fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid);
}
}
- fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
+ fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
p->zDb,
(p->zContentTbl ? p->zContentTbl : p->zName),
(p->zContentTbl ? "" : "_content")
@@ -884,7 +927,7 @@ static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){
**
** If argument zFunc is not NULL, then all but the first question mark
** is preceded by zFunc and an open bracket, and followed by a closed
-** bracket. For example, if zFunc is "zip" and the FTS3 table has three
+** bracket. For example, if zFunc is "zip" and the FTS3 table has three
** user-defined text columns, the following string is returned:
**
** "?, zip(?), zip(?), zip(?)"
@@ -920,12 +963,28 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
}
/*
+** Buffer z contains a positive integer value encoded as utf-8 text.
+** Decode this value and store it in *pnOut, returning the number of bytes
+** consumed. If an overflow error occurs return a negative value.
+*/
+int sqlite3Fts3ReadInt(const char *z, int *pnOut){
+ u64 iVal = 0;
+ int i;
+ for(i=0; z[i]>='0' && z[i]<='9'; i++){
+ iVal = iVal*10 + (z[i] - '0');
+ if( iVal>0x7FFFFFFF ) return -1;
+ }
+ *pnOut = (int)iVal;
+ return i;
+}
+
+/*
** This function interprets the string at (*pp) as a non-negative integer
-** value. It reads the integer and sets *pnOut to the value read, then
+** value. It reads the integer and sets *pnOut to the value read, then
** sets *pp to point to the byte immediately following the last byte of
** the integer value.
**
-** Only decimal digits ('0'..'9') may be part of an integer value.
+** Only decimal digits ('0'..'9') may be part of an integer value.
**
** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
** the output value undefined. Otherwise SQLITE_OK is returned.
@@ -934,19 +993,17 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
*/
static int fts3GobbleInt(const char **pp, int *pnOut){
const int MAX_NPREFIX = 10000000;
- const char *p; /* Iterator pointer */
int nInt = 0; /* Output value */
-
- for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
- nInt = nInt * 10 + (p[0] - '0');
- if( nInt>MAX_NPREFIX ){
- nInt = 0;
- break;
- }
+ int nByte;
+ nByte = sqlite3Fts3ReadInt(*pp, &nInt);
+ if( nInt>MAX_NPREFIX ){
+ nInt = 0;
+ }
+ if( nByte==0 ){
+ return SQLITE_ERROR;
}
- if( p==*pp ) return SQLITE_ERROR;
*pnOut = nInt;
- *pp = p;
+ *pp += nByte;
return SQLITE_OK;
}
@@ -983,7 +1040,7 @@ static int fts3PrefixParameter(
}
}
- aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
+ aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex);
*apIndex = aIndex;
if( !aIndex ){
return SQLITE_NOMEM;
@@ -1046,7 +1103,7 @@ static int fts3ContentColumns(
char **pzErr /* OUT: error message */
){
int rc = SQLITE_OK; /* Return code */
- char *zSql; /* "SELECT *" statement on zTbl */
+ char *zSql; /* "SELECT *" statement on zTbl */
sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */
zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl);
@@ -1062,7 +1119,7 @@ static int fts3ContentColumns(
if( rc==SQLITE_OK ){
const char **azCol; /* Output array */
- int nStr = 0; /* Size of all column names (incl. 0x00) */
+ sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */
int nCol; /* Number of table columns */
int i; /* Used to iterate through columns */
@@ -1072,11 +1129,11 @@ static int fts3ContentColumns(
nCol = sqlite3_column_count(pStmt);
for(i=0; i<nCol; i++){
const char *zCol = sqlite3_column_name(pStmt, i);
- nStr += (int)strlen(zCol) + 1;
+ nStr += strlen(zCol) + 1;
}
/* Allocate and populate the array to return. */
- azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
+ azCol = (const char **)sqlite3_malloc64(sizeof(char *) * nCol + nStr);
if( azCol==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1124,7 +1181,7 @@ static int fts3InitVtab(
Fts3Table *p = 0; /* Pointer to allocated vtab */
int rc = SQLITE_OK; /* Return code */
int i; /* Iterator variable */
- int nByte; /* Size of allocation used for *p */
+ sqlite3_int64 nByte; /* Size of allocation used for *p */
int iCol; /* Column index */
int nString = 0; /* Bytes required to hold all column names */
int nCol = 0; /* Number of columns in the FTS table */
@@ -1158,10 +1215,10 @@ static int fts3InitVtab(
nName = (int)strlen(argv[2]) + 1;
nByte = sizeof(const char *) * (argc-2);
- aCol = (const char **)sqlite3_malloc(nByte);
+ aCol = (const char **)sqlite3_malloc64(nByte);
if( aCol ){
memset((void*)aCol, 0, nByte);
- azNotindexed = (char **)sqlite3_malloc(nByte);
+ azNotindexed = (char **)sqlite3_malloc64(nByte);
}
if( azNotindexed ){
memset(azNotindexed, 0, nByte);
@@ -1188,9 +1245,9 @@ static int fts3InitVtab(
char *zVal;
/* Check if this is a tokenizer specification */
- if( !pTokenizer
+ if( !pTokenizer
&& strlen(z)>8
- && 0==sqlite3_strnicmp(z, "tokenize", 8)
+ && 0==sqlite3_strnicmp(z, "tokenize", 8)
&& 0==sqlite3Fts3IsIdChar(z[8])
){
rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
@@ -1250,8 +1307,8 @@ static int fts3InitVtab(
break;
case 4: /* ORDER */
- if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
- && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
+ if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
+ && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
@@ -1302,17 +1359,17 @@ static int fts3InitVtab(
** TABLE statement, use all columns from the content table.
*/
if( rc==SQLITE_OK && zContent ){
- sqlite3_free(zCompress);
- sqlite3_free(zUncompress);
+ sqlite3_free(zCompress);
+ sqlite3_free(zUncompress);
zCompress = 0;
zUncompress = 0;
if( nCol==0 ){
- sqlite3_free((void*)aCol);
+ sqlite3_free((void*)aCol);
aCol = 0;
rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr);
/* If a languageid= option was specified, remove the language id
- ** column from the aCol[] array. */
+ ** column from the aCol[] array. */
if( rc==SQLITE_OK && zLanguageid ){
int j;
for(j=0; j<nCol; j++){
@@ -1356,7 +1413,7 @@ static int fts3InitVtab(
nName + /* zName */
nDb + /* zDb */
nString; /* Space for azColumn strings */
- p = (Fts3Table*)sqlite3_malloc(nByte);
+ p = (Fts3Table*)sqlite3_malloc64(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
goto fts3_init_out;
@@ -1399,7 +1456,7 @@ static int fts3InitVtab(
/* Fill in the azColumn array */
for(iCol=0; iCol<nCol; iCol++){
- char *z;
+ char *z;
int n = 0;
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
if( n>0 ){
@@ -1418,7 +1475,7 @@ static int fts3InitVtab(
for(i=0; i<nNotindexed; i++){
char *zNot = azNotindexed[i];
if( zNot && n==(int)strlen(zNot)
- && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n)
+ && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n)
){
p->abNotindexed[iCol] = 1;
sqlite3_free(zNot);
@@ -1442,7 +1499,7 @@ static int fts3InitVtab(
p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
if( rc!=SQLITE_OK ) goto fts3_init_out;
- /* If this is an xCreate call, create the underlying tables in the
+ /* If this is an xCreate call, create the underlying tables in the
** database. TODO: For xConnect(), it could verify that said tables exist.
*/
if( isCreate ){
@@ -1461,6 +1518,10 @@ static int fts3InitVtab(
fts3DatabasePageSize(&rc, p);
p->nNodeSize = p->nPgsz-35;
+#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST)
+ p->nMergeCount = FTS3_MERGE_COUNT;
+#endif
+
/* Declare the table schema to SQLite. */
fts3DeclareVtab(&rc, p);
@@ -1538,11 +1599,11 @@ static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){
#endif
}
-/*
+/*
** Implementation of the xBestIndex method for FTS3 tables. There
** are three possible strategies, in order of preference:
**
-** 1. Direct lookup by rowid or docid.
+** 1. Direct lookup by rowid or docid.
** 2. Full-text search using a MATCH operator on a non-docid column.
** 3. Linear scan of %_content table.
*/
@@ -1556,8 +1617,12 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
int iDocidLe = -1; /* Index of docid<=x constraint, if present */
int iIdx;
+ if( p->bLock ){
+ return SQLITE_ERROR;
+ }
+
/* By default use a full table scan. This is an expensive option,
- ** so search through the constraints to see if a more efficient
+ ** so search through the constraints to see if a more efficient
** strategy is possible.
*/
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
@@ -1593,12 +1658,12 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
**
** If there is more than one MATCH constraint available, use the first
** one encountered. If there is both a MATCH constraint and a direct
- ** rowid/docid lookup, prefer the MATCH strategy. This is done even
+ ** rowid/docid lookup, prefer the MATCH strategy. This is done even
** though the rowid/docid lookup is faster than a MATCH query, selecting
- ** it would lead to an "unable to use function MATCH in the requested
+ ** it would lead to an "unable to use function MATCH in the requested
** context" error.
*/
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
&& pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
){
pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
@@ -1607,7 +1672,7 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
}
/* Equality constraint on the langid column */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
&& pCons->iColumn==p->nColumn + 2
){
iLangidCons = i;
@@ -1635,22 +1700,22 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
if( iCons>=0 ){
pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
pInfo->aConstraintUsage[iCons].omit = 1;
- }
+ }
if( iLangidCons>=0 ){
pInfo->idxNum |= FTS3_HAVE_LANGID;
pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
- }
+ }
if( iDocidGe>=0 ){
pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
- }
+ }
if( iDocidLe>=0 ){
pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
- }
+ }
/* Regardless of the strategy selected, FTS can deliver rows in rowid (or
- ** docid) order. Both ascending and descending are possible.
+ ** docid) order. Both ascending and descending are possible.
*/
if( pInfo->nOrderBy==1 ){
struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
@@ -1677,7 +1742,7 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
UNUSED_PARAMETER(pVTab);
/* Allocate a buffer large enough for an Fts3Cursor structure. If the
- ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
+ ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
** if the allocation fails, return SQLITE_NOMEM.
*/
*ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
@@ -1754,7 +1819,11 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
}else{
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
+ p->bLock++;
+ rc = sqlite3_prepare_v3(
+ p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
+ );
+ p->bLock--;
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
@@ -1765,18 +1834,22 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
/*
** Position the pCsr->pStmt statement so that it is on the row
** of the %_content table that contains the last match. Return
-** SQLITE_OK on success.
+** SQLITE_OK on success.
*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->isRequireSeek ){
rc = fts3CursorSeekStmt(pCsr);
if( rc==SQLITE_OK ){
+ Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
+ pTab->bLock++;
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
+ pTab->bLock--;
return SQLITE_OK;
}else{
+ pTab->bLock--;
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
/* If no row was found and no error has occurred, then the %_content
@@ -1797,7 +1870,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
/*
** This function is used to process a single interior node when searching
-** a b-tree for a term or term prefix. The node data is passed to this
+** a b-tree for a term or term prefix. The node data is passed to this
** function via the zNode/nNode parameters. The term to search for is
** passed in zTerm/nTerm.
**
@@ -1824,11 +1897,12 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
+ int nBuffer = 0; /* Total term size */
- /* Skip over the 'height' varint that occurs at the start of every
+ /* Skip over the 'height' varint that occurs at the start of every
** interior node. Then load the blockid of the left-child of the b-tree
- ** node into variable iChild.
+ ** node into variable iChild.
**
** Even if the data structure on disk is corrupted, this (reading two
** varints from the buffer) does not risk an overread. If zNode is a
@@ -1839,28 +1913,31 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
-
+
while( zCsr<zEnd && (piFirst || piLast) ){
int cmp; /* memcmp() result */
int nSuffix; /* Size of term suffix */
int nPrefix = 0; /* Size of term prefix */
- int nBuffer; /* Total term size */
-
+
/* Load the next term on the node into zBuffer. Use realloc() to expand
** the size of zBuffer if required. */
if( !isFirstTerm ){
zCsr += fts3GetVarint32(zCsr, &nPrefix);
+ if( nPrefix>nBuffer ){
+ rc = FTS_CORRUPT_VTAB;
+ goto finish_scan;
+ }
}
isFirstTerm = 0;
zCsr += fts3GetVarint32(zCsr, &nSuffix);
-
+
assert( nPrefix>=0 && nSuffix>=0 );
- if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
+ if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){
rc = FTS_CORRUPT_VTAB;
goto finish_scan;
}
@@ -1881,8 +1958,8 @@ static int fts3ScanInteriorNode(
/* Compare the term we are searching for with the term just loaded from
** the interior node. If the specified term is greater than or equal
- ** to the term from the interior node, then all terms on the sub-tree
- ** headed by node iChild are smaller than zTerm. No need to search
+ ** to the term from the interior node, then all terms on the sub-tree
+ ** headed by node iChild are smaller than zTerm. No need to search
** iChild.
**
** If the interior node term is larger than the specified term, then
@@ -1890,20 +1967,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
@@ -1918,20 +1995,20 @@ static int fts3ScanInteriorNode(
** node for the range of leaf nodes that may contain the specified term
** or terms for which the specified term is a prefix.
**
-** If piLeaf is not NULL, then *piLeaf is set to the blockid of the
+** If piLeaf is not NULL, then *piLeaf is set to the blockid of the
** left-most leaf node in the tree that may contain the specified term.
** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the
** right-most leaf node that may contain a term for which the specified
** term is a prefix.
**
-** It is possible that the range of returned leaf nodes does not contain
-** the specified term or any terms for which it is a prefix. However, if the
+** It is possible that the range of returned leaf nodes does not contain
+** the specified term or any terms for which it is a prefix. However, if the
** segment does contain any such terms, they are stored within the identified
** range. Because this function only inspects interior segment nodes (and
** never loads leaf nodes into memory), it is not possible to be sure.
**
** If an error occurs, an error code other than SQLITE_OK is returned.
-*/
+*/
static int fts3SelectLeaf(
Fts3Table *p, /* Virtual table handle */
const char *zTerm, /* Term to select leaves for */
@@ -1948,7 +2025,7 @@ static int fts3SelectLeaf(
fts3GetVarint32(zNode, &iHeight);
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
- assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
+ assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
if( rc==SQLITE_OK && iHeight>1 ){
char *zBlob = 0; /* Blob read from %_segments table */
@@ -1968,7 +2045,13 @@ static int fts3SelectLeaf(
rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
}
if( rc==SQLITE_OK ){
- rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
+ int iNewHeight = 0;
+ fts3GetVarint32(zBlob, &iNewHeight);
+ if( iNewHeight>=iHeight ){
+ rc = FTS_CORRUPT_VTAB;
+ }else{
+ rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
+ }
}
sqlite3_free(zBlob);
}
@@ -1977,7 +2060,7 @@ static int fts3SelectLeaf(
}
/*
-** This function is used to create delta-encoded serialized lists of FTS3
+** This function is used to create delta-encoded serialized lists of FTS3
** varints. Each call to this function appends a single varint to a list.
*/
static void fts3PutDeltaVarint(
@@ -1985,17 +2068,17 @@ static void fts3PutDeltaVarint(
sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
sqlite3_int64 iVal /* Write this value to the list */
){
- assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
+ assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
*piPrev = iVal;
}
/*
-** When this function is called, *ppPoslist is assumed to point to the
+** When this function is called, *ppPoslist is assumed to point to the
** start of a position-list. After it returns, *ppPoslist points to the
** first byte after the position-list.
**
-** A position list is list of positions (delta encoded) and columns for
+** A position list is list of positions (delta encoded) and columns for
** a single document record of a doclist. So, in other words, this
** routine advances *ppPoslist so that it points to the next docid in
** the doclist, or to the first byte past the end of the doclist.
@@ -2008,12 +2091,12 @@ static void fts3PoslistCopy(char **pp, char **ppPoslist){
char *pEnd = *ppPoslist;
char c = 0;
- /* The end of a position list is marked by a zero encoded as an FTS3
+ /* The end of a position list is marked by a zero encoded as an FTS3
** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by
** a byte with the 0x80 bit set, then it is not a varint 0, but the tail
** of some other, multi-byte, value.
**
- ** The following while-loop moves pEnd to point to the first byte that is not
+ ** The following while-loop moves pEnd to point to the first byte that is not
** immediately preceded by a byte with the 0x80 bit set. Then increments
** pEnd once more so that it points to the byte immediately following the
** last byte in the position-list.
@@ -2035,7 +2118,7 @@ static void fts3PoslistCopy(char **pp, char **ppPoslist){
}
/*
-** When this function is called, *ppPoslist is assumed to point to the
+** When this function is called, *ppPoslist is assumed to point to the
** start of a column-list. After it returns, *ppPoslist points to the
** to the terminator (POS_COLUMN or POS_END) byte of the column-list.
**
@@ -2073,10 +2156,11 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
}
/*
-** Value used to signify the end of an position-list. This is safe because
-** it is not possible to have a document with 2^31 terms.
+** Value used to signify the end of an position-list. This must be
+** as large or larger than any value that might appear on the
+** position-list, even a position list that has been corrupted.
*/
-#define POSITION_LIST_END 0x7fffffff
+#define POSITION_LIST_END LARGEST_INT64
/*
** This function is used to help parse position-lists. When this function is
@@ -2085,7 +2169,7 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
** (in which case **pp will be a terminator bytes POS_END (0) or
** (1)).
**
-** If *pp points past the end of the current position-list, set *pi to
+** If *pp points past the end of the current position-list, set *pi to
** POSITION_LIST_END and return. Otherwise, read the next varint from *pp,
** increment the current value of *pi by the value read, and set *pp to
** point to the next value before returning.
@@ -2101,7 +2185,9 @@ static void fts3ReadNextPos(
sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
){
if( (**pp)&0xFE ){
- fts3GetDeltaVarint(pp, pi);
+ int iVal;
+ *pp += fts3GetVarint32((*pp), &iVal);
+ *pi += iVal;
*pi -= 2;
}else{
*pi = POSITION_LIST_END;
@@ -2113,7 +2199,7 @@ static void fts3ReadNextPos(
** the value of iCol encoded as a varint to *pp. This will start a new
** column list.
**
-** Set *pp to point to the byte just after the last byte written before
+** Set *pp to point to the byte just after the last byte written before
** returning (do not modify it if iCol==0). Return the total number of bytes
** written (0 if iCol==0).
*/
@@ -2135,7 +2221,7 @@ static int fts3PutColNumber(char **pp, int iCol){
** updated appropriately. The caller is responsible for insuring
** that there is enough space in *pp to hold the complete output.
*/
-static void fts3PoslistMerge(
+static int fts3PoslistMerge(
char **pp, /* Output buffer */
char **pp1, /* Left input list */
char **pp2 /* Right input list */
@@ -2148,12 +2234,18 @@ static void fts3PoslistMerge(
int iCol1; /* The current column index in pp1 */
int iCol2; /* The current column index in pp2 */
- if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
- else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
+ if( *p1==POS_COLUMN ){
+ fts3GetVarint32(&p1[1], &iCol1);
+ if( iCol1==0 ) return FTS_CORRUPT_VTAB;
+ }
+ else if( *p1==POS_END ) iCol1 = 0x7fffffff;
else iCol1 = 0;
- if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
- else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
+ if( *p2==POS_COLUMN ){
+ fts3GetVarint32(&p2[1], &iCol2);
+ if( iCol2==0 ) return FTS_CORRUPT_VTAB;
+ }
+ else if( *p2==POS_END ) iCol2 = 0x7fffffff;
else iCol2 = 0;
if( iCol1==iCol2 ){
@@ -2166,7 +2258,7 @@ static void fts3PoslistMerge(
/* At this point, both p1 and p2 point to the start of column-lists
** for the same column (the column with index iCol1 and iCol2).
- ** A column-list is a list of non-negative delta-encoded varints, each
+ ** A column-list is a list of non-negative delta-encoded varints, each
** incremented by 2 before being stored. Each list is terminated by a
** POS_END (0) or POS_COLUMN (1). The following block merges the two lists
** and writes the results to buffer p. p is left pointing to the byte
@@ -2175,8 +2267,11 @@ static void fts3PoslistMerge(
*/
fts3GetDeltaVarint(&p1, &i1);
fts3GetDeltaVarint(&p2, &i2);
+ if( i1<2 || i2<2 ){
+ break;
+ }
do {
- fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
+ fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
iPrev -= 2;
if( i1==i2 ){
fts3ReadNextPos(&p1, &i1);
@@ -2200,6 +2295,7 @@ static void fts3PoslistMerge(
*pp = p;
*pp1 = p1 + 1;
*pp2 = p2 + 1;
+ return SQLITE_OK;
}
/*
@@ -2217,7 +2313,7 @@ static void fts3PoslistMerge(
** When this function returns, both *pp1 and *pp2 are left pointing to the
** byte following the 0x00 terminator of their respective position lists.
**
-** If isSaveLeft is 0, an entry is added to the output position list for
+** If isSaveLeft is 0, an entry is added to the output position list for
** each position in *pp2 for which there exists one or more positions in
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
** when the *pp1 token appears before the *pp2 token, but not more than nToken
@@ -2242,12 +2338,12 @@ static int fts3PoslistPhraseMerge(
/* Never set both isSaveLeft and isExact for the same invocation. */
assert( isSaveLeft==0 || isExact==0 );
- assert( p!=0 && *p1!=0 && *p2!=0 );
- if( *p1==POS_COLUMN ){
+ assert_fts3_nc( p!=0 && *p1!=0 && *p2!=0 );
+ if( *p1==POS_COLUMN ){
p1++;
p1 += fts3GetVarint32(p1, &iCol1);
}
- if( *p2==POS_COLUMN ){
+ if( *p2==POS_COLUMN ){
p2++;
p2 += fts3GetVarint32(p2, &iCol2);
}
@@ -2264,14 +2360,13 @@ static int fts3PoslistPhraseMerge(
p += sqlite3Fts3PutVarint(p, iCol1);
}
- assert( *p1!=POS_END && *p1!=POS_COLUMN );
- assert( *p2!=POS_END && *p2!=POS_COLUMN );
fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
+ if( iPos1<0 || iPos2<0 ) break;
while( 1 ){
- if( iPos2==iPos1+nToken
- || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
+ if( iPos2==iPos1+nToken
+ || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
){
sqlite3_int64 iSave;
iSave = isSaveLeft ? iPos1 : iPos2;
@@ -2306,8 +2401,8 @@ static int fts3PoslistPhraseMerge(
/* Advance pointer p1 or p2 (whichever corresponds to the smaller of
** iCol1 and iCol2) so that it points to either the 0x00 that marks the
- ** end of the position list, or the 0x01 that precedes the next
- ** column-number in the position list.
+ ** end of the position list, or the 0x01 that precedes the next
+ ** column-number in the position list.
*/
else if( iCol1<iCol2 ){
fts3ColumnlistCopy(0, &p1);
@@ -2336,14 +2431,14 @@ static int fts3PoslistPhraseMerge(
/*
** Merge two position-lists as required by the NEAR operator. The argument
-** position lists correspond to the left and right phrases of an expression
+** position lists correspond to the left and right phrases of an expression
** like:
**
** "phrase 1" NEAR "phrase number 2"
**
-** Position list *pp1 corresponds to the left-hand side of the NEAR
-** expression and *pp2 to the right. As usual, the indexes in the position
-** lists are the offsets of the last token in each phrase (tokens "1" and "2"
+** Position list *pp1 corresponds to the left-hand side of the NEAR
+** expression and *pp2 to the right. As usual, the indexes in the position
+** lists are the offsets of the last token in each phrase (tokens "1" and "2"
** in the example above).
**
** The output position list - written to *pp - is a copy of *pp2 with those
@@ -2383,7 +2478,7 @@ static int fts3PoslistNearMerge(
return res;
}
-/*
+/*
** An instance of this function is used to merge together the (potentially
** large number of) doclists for each term that matches a prefix query.
** See function fts3TermSelectMerge() for details.
@@ -2404,7 +2499,7 @@ struct TermSelect {
** from *pp. *pp is then set to point 1 byte past the end of the read varint.
**
** If bDescIdx is false, the value read is added to *pVal before returning.
-** If it is true, the value read is subtracted from *pVal before this
+** If it is true, the value read is subtracted from *pVal before this
** function returns.
*/
static void fts3GetDeltaVarint3(
@@ -2416,12 +2511,12 @@ static void fts3GetDeltaVarint3(
if( *pp>=pEnd ){
*pp = 0;
}else{
- sqlite3_int64 iVal;
- *pp += sqlite3Fts3GetVarint(*pp, &iVal);
+ u64 iVal;
+ *pp += sqlite3Fts3GetVarintU(*pp, &iVal);
if( bDescIdx ){
- *pVal -= iVal;
+ *pVal = (i64)((u64)*pVal - iVal);
}else{
- *pVal += iVal;
+ *pVal = (i64)((u64)*pVal + iVal);
}
}
}
@@ -2432,9 +2527,9 @@ static void fts3GetDeltaVarint3(
** end of the value written.
**
** If *pbFirst is zero when this function is called, the value written to
-** the buffer is that of parameter iVal.
+** the buffer is that of parameter iVal.
**
-** If *pbFirst is non-zero when this function is called, then the value
+** If *pbFirst is non-zero when this function is called, then the value
** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
** (if bDescIdx is non-zero).
**
@@ -2448,14 +2543,16 @@ static void fts3PutDeltaVarint3(
int *pbFirst, /* IN/OUT: True after first int written */
sqlite3_int64 iVal /* Write this value to the list */
){
- sqlite3_int64 iWrite;
+ sqlite3_uint64 iWrite;
if( bDescIdx==0 || *pbFirst==0 ){
- iWrite = iVal - *piPrev;
+ assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev );
+ iWrite = (u64)iVal - (u64)*piPrev;
}else{
- iWrite = *piPrev - iVal;
+ assert_fts3_nc( *piPrev>=iVal );
+ iWrite = (u64)*piPrev - (u64)iVal;
}
assert( *pbFirst || *piPrev==0 );
- assert( *pbFirst==0 || iWrite>0 );
+ assert_fts3_nc( *pbFirst==0 || iWrite>0 );
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
*piPrev = iVal;
*pbFirst = 1;
@@ -2465,17 +2562,18 @@ static void fts3PutDeltaVarint3(
/*
** This macro is used by various functions that merge doclists. The two
** arguments are 64-bit docid values. If the value of the stack variable
-** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
+** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
** Otherwise, (i2-i1).
**
** Using this makes it easier to write code that can merge doclists that are
** sorted in either ascending or descending order.
*/
-#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
+/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1)))
/*
** This function does an "OR" merge of two doclists (output contains all
-** positions contained in either argument doclist). If the docids in the
+** positions contained in either argument doclist). If the docids in the
** input doclists are sorted in ascending order, parameter bDescDoclist
** should be false. If they are sorted in ascending order, it should be
** passed a non-zero value.
@@ -2493,6 +2591,7 @@ static int fts3DoclistOrMerge(
char *a2, int n2, /* Second doclist */
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
){
+ int rc = SQLITE_OK;
sqlite3_int64 i1 = 0;
sqlite3_int64 i2 = 0;
sqlite3_int64 iPrev = 0;
@@ -2514,12 +2613,12 @@ static int fts3DoclistOrMerge(
** current and previous docid (a positive number - since the list is in
** ascending order).
**
- ** The first docid written to the output is therefore encoded using the
+ ** The first docid written to the output is therefore encoded using the
** same number of bytes as it is in whichever of the input lists it is
- ** read from. And each subsequent docid read from the same input list
+ ** read from. And each subsequent docid read from the same input list
** consumes either the same or less bytes as it did in the input (since
** the difference between it and the previous value in the output must
- ** be a positive value less than or equal to the delta value read from
+ ** be a positive value less than or equal to the delta value read from
** the input list). The same argument applies to all but the first docid
** read from the 'other' list. And to the contents of all position lists
** that will be copied and merged from the input to the output.
@@ -2531,12 +2630,12 @@ static int fts3DoclistOrMerge(
**
** The space required to store the output is therefore the sum of the
** sizes of the two inputs, plus enough space for exactly one of the input
- ** docids to grow.
+ ** docids to grow.
**
- ** A symetric argument may be made if the doclists are in descending
+ ** A symetric argument may be made if the doclists are in descending
** order.
*/
- aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
+ aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
if( !aOut ) return SQLITE_NOMEM;
p = aOut;
@@ -2547,7 +2646,8 @@ static int fts3DoclistOrMerge(
if( p2 && p1 && iDiff==0 ){
fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
- fts3PoslistMerge(&p, &p1, &p2);
+ rc = fts3PoslistMerge(&p, &p1, &p2);
+ if( rc ) break;
fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}else if( !p2 || (p1 && iDiff<0) ){
@@ -2559,12 +2659,20 @@ static int fts3DoclistOrMerge(
fts3PoslistCopy(&p, &p2);
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}
+
+ assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) );
}
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(aOut);
+ p = aOut = 0;
+ }else{
+ assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 );
+ memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING);
+ }
*paOut = aOut;
*pnOut = (int)(p-aOut);
- assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
- return SQLITE_OK;
+ return rc;
}
/*
@@ -2574,7 +2682,7 @@ static int fts3DoclistOrMerge(
** exactly nDist tokens before it.
**
** If the docids in the input doclists are sorted in ascending order,
-** parameter bDescDoclist should be false. If they are sorted in ascending
+** parameter bDescDoclist should be false. If they are sorted in ascending
** order, it should be passed a non-zero value.
**
** The right-hand input doclist is overwritten by this function.
@@ -2599,7 +2707,7 @@ static int fts3DoclistPhraseMerge(
assert( nDist>0 );
if( bDescDoclist ){
- aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
+ aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX);
if( aOut==0 ) return SQLITE_NOMEM;
}else{
aOut = aRight;
@@ -2720,7 +2828,7 @@ static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
int nNew;
char *aNew;
- int rc = fts3DoclistOrMerge(p->bDescIdx,
+ int rc = fts3DoclistOrMerge(p->bDescIdx,
pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew
);
if( rc!=SQLITE_OK ){
@@ -2764,15 +2872,15 @@ static int fts3TermSelectMerge(
){
if( pTS->aaOutput[0]==0 ){
/* If this is the first term selected, copy the doclist to the output
- ** buffer using memcpy().
+ ** buffer using memcpy().
**
- ** Add FTS3_VARINT_MAX bytes of unused space to the end of the
+ ** Add FTS3_VARINT_MAX bytes of unused space to the end of the
** allocation. This is so as to ensure that the buffer is big enough
** to hold the current doclist AND'd with any other doclist. If the
** doclists are stored in order=ASC order, this padding would not be
** required (since the size of [doclistA AND doclistB] is always less
** than or equal to the size of [doclistA] in that case). But this is
- ** not true for order=DESC. For example, a doclist containing (1, -1)
+ ** not true for order=DESC. For example, a doclist containing (1, -1)
** may be smaller than (-1), as in the first example the -1 may be stored
** as a single-byte delta, whereas in the second it must be stored as a
** FTS3_VARINT_MAX byte varint.
@@ -2783,6 +2891,7 @@ static int fts3TermSelectMerge(
pTS->anOutput[0] = nDoclist;
if( pTS->aaOutput[0] ){
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
+ memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX);
}else{
return SQLITE_NOMEM;
}
@@ -2801,7 +2910,7 @@ static int fts3TermSelectMerge(
char *aNew;
int nNew;
- int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
+ int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew
);
if( rc!=SQLITE_OK ){
@@ -2812,7 +2921,7 @@ static int fts3TermSelectMerge(
if( aMerge!=aDoclist ) sqlite3_free(aMerge);
sqlite3_free(pTS->aaOutput[iOut]);
pTS->aaOutput[iOut] = 0;
-
+
aMerge = aNew;
nMerge = nNew;
if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
@@ -2829,13 +2938,13 @@ static int fts3TermSelectMerge(
** Append SegReader object pNew to the end of the pCsr->apSegment[] array.
*/
static int fts3SegReaderCursorAppend(
- Fts3MultiSegReader *pCsr,
+ Fts3MultiSegReader *pCsr,
Fts3SegReader *pNew
){
if( (pCsr->nSegment%16)==0 ){
Fts3SegReader **apNew;
- int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
- apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
+ sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
+ apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte);
if( !apNew ){
sqlite3Fts3SegReaderFree(pNew);
return SQLITE_NOMEM;
@@ -2868,13 +2977,13 @@ static int fts3SegReaderCursor(
sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
int rc2; /* Result of sqlite3_reset() */
- /* If iLevel is less than 0 and this is not a scan, include a seg-reader
+ /* If iLevel is less than 0 and this is not a scan, include a seg-reader
** for the pending-terms. If this is a scan, then this call must be being
** made by an fts4aux module, not an FTS table. In this case calling
- ** Fts3SegReaderPending might segfault, as the data structures used by
+ ** Fts3SegReaderPending might segfault, as the data structures used by
** fts4aux are not completely populated. So it's easiest to filter these
** calls out here. */
- if( iLevel<0 && p->aIndex ){
+ if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
Fts3SegReader *pSeg = 0;
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
if( rc==SQLITE_OK && pSeg ){
@@ -2899,16 +3008,16 @@ static int fts3SegReaderCursor(
/* If zTerm is not NULL, and this segment is not stored entirely on its
** root node, the range of leaves scanned can be reduced. Do this. */
- if( iStartBlock && zTerm ){
+ if( iStartBlock && zTerm && zRoot ){
sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
if( rc!=SQLITE_OK ) goto finished;
if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
}
-
- rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
+
+ rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
(isPrefix==0 && isScan==0),
- iStartBlock, iLeavesEndBlock,
+ iStartBlock, iLeavesEndBlock,
iEndBlock, zRoot, nRoot, &pSeg
);
if( rc!=SQLITE_OK ) goto finished;
@@ -2924,7 +3033,7 @@ static int fts3SegReaderCursor(
}
/*
-** Set up a cursor object for iterating through a full-text index or a
+** Set up a cursor object for iterating through a full-text index or a
** single level therein.
*/
int sqlite3Fts3SegReaderCursor(
@@ -2940,7 +3049,7 @@ int sqlite3Fts3SegReaderCursor(
){
assert( iIndex>=0 && iIndex<p->nIndex );
assert( iLevel==FTS3_SEGCURSOR_ALL
- || iLevel==FTS3_SEGCURSOR_PENDING
+ || iLevel==FTS3_SEGCURSOR_PENDING
|| iLevel>=0
);
assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
@@ -2966,20 +3075,20 @@ static int fts3SegReaderCursorAddZero(
int nTerm, /* Number of bytes in zTerm */
Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
){
- return fts3SegReaderCursor(p,
+ return fts3SegReaderCursor(p,
iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr
);
}
/*
** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
-** if isPrefix is true, to scan the doclist for all terms for which
+** if isPrefix is true, to scan the doclist for all terms for which
** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
** an SQLite error code.
**
** It is the responsibility of the caller to free this object by eventually
-** passing it to fts3SegReaderCursorFree()
+** passing it to fts3SegReaderCursorFree()
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
** Output parameter *ppSegcsr is set to 0 if an error occurs.
@@ -3004,7 +3113,7 @@ static int fts3TermSegReaderCursor(
for(i=1; bFound==0 && i<p->nIndex; i++){
if( p->aIndex[i].nPrefix==nTerm ){
bFound = 1;
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr
);
pSegcsr->bLookup = 1;
@@ -3014,7 +3123,7 @@ static int fts3TermSegReaderCursor(
for(i=1; bFound==0 && i<p->nIndex; i++){
if( p->aIndex[i].nPrefix==nTerm+1 ){
bFound = 1;
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
);
if( rc==SQLITE_OK ){
@@ -3027,7 +3136,7 @@ static int fts3TermSegReaderCursor(
}
if( bFound==0 ){
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
);
pSegcsr->bLookup = !isPrefix;
@@ -3075,7 +3184,7 @@ static int fts3TermSelect(
rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
while( SQLITE_OK==rc
- && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
+ && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
){
rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
}
@@ -3104,7 +3213,7 @@ static int fts3TermSelect(
**
** If the isPoslist argument is true, then it is assumed that the doclist
** contains a position-list following each docid. Otherwise, it is assumed
-** that the doclist is simply a list of docids stored as delta encoded
+** that the doclist is simply a list of docids stored as delta encoded
** varints.
*/
static int fts3DoclistCountDocids(char *aList, int nList){
@@ -3137,6 +3246,8 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
int rc;
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
+ Fts3Table *pTab = (Fts3Table*)pCursor->pVtab;
+ pTab->bLock++;
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
pCsr->isEof = 1;
rc = sqlite3_reset(pCsr->pStmt);
@@ -3144,6 +3255,7 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
rc = SQLITE_OK;
}
+ pTab->bLock--;
}else{
rc = fts3EvalNext((Fts3Cursor *)pCursor);
}
@@ -3152,18 +3264,6 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
}
/*
-** The following are copied from sqliteInt.h.
-**
-** Constants for the largest and smallest possible 64-bit signed integers.
-** These macros are designed to work correctly on both 32-bit and 64-bit
-** compilers.
-*/
-#ifndef SQLITE_AMALGAMATION
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
-/*
** If the numeric type of argument pVal is "integer", then return it
** converted to a 64-bit signed integer. Otherwise, return a copy of
** the second parameter, iDefault.
@@ -3216,6 +3316,10 @@ static int fts3FilterMethod(
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(nVal);
+ if( p->bLock ){
+ return SQLITE_ERROR;
+ }
+
eSearch = (idxNum & 0x0000FFFF);
assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
assert( p->pSegments==0 );
@@ -3255,7 +3359,7 @@ static int fts3FilterMethod(
assert( p->base.zErrMsg==0 );
rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
- p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
+ p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
&p->base.zErrMsg
);
if( rc!=SQLITE_OK ){
@@ -3282,12 +3386,16 @@ static int fts3FilterMethod(
(pCsr->bDesc ? "DESC" : "ASC")
);
}else{
- zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s",
+ zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s",
p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
);
}
if( zSql ){
- rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
+ p->bLock++;
+ rc = sqlite3_prepare_v3(
+ p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
+ );
+ p->bLock--;
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
@@ -3303,8 +3411,8 @@ static int fts3FilterMethod(
return fts3NextMethod(pCursor);
}
-/*
-** This is the xEof method of the virtual table. SQLite calls this
+/*
+** This is the xEof method of the virtual table. SQLite calls this
** routine to find out if it has reached the end of a result set.
*/
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
@@ -3316,7 +3424,7 @@ static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
return pCsr->isEof;
}
-/*
+/*
** This is the xRowid method. The SQLite core calls this routine to
** retrieve the rowid for the current row of the result set. fts3
** exposes %_content.docid as the rowid for the virtual table. The
@@ -3328,7 +3436,7 @@ static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
return SQLITE_OK;
}
-/*
+/*
** This is the xColumn method, called by SQLite to request a value from
** the row that the supplied cursor currently points to.
**
@@ -3371,7 +3479,7 @@ static int fts3ColumnMethod(
break;
}else{
iCol = p->nColumn;
- /* fall-through */
+ /* no break */ deliberate_fall_through
}
default:
@@ -3388,8 +3496,8 @@ static int fts3ColumnMethod(
return rc;
}
-/*
-** This function is the implementation of the xUpdate callback used by
+/*
+** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
** inserted, updated or deleted.
*/
@@ -3424,7 +3532,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
**
** Of course, updating the input segments also involves deleting a bunch
** of blocks from the segments table. But this is not considered overhead
- ** as it would also be required by a crisis-merge that used the same input
+ ** as it would also be required by a crisis-merge that used the same input
** segments.
*/
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
@@ -3434,8 +3542,8 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
rc = sqlite3Fts3PendingTermsFlush(p);
- if( rc==SQLITE_OK
- && p->nLeafAdd>(nMinMerge/16)
+ if( rc==SQLITE_OK
+ && p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
){
int mxLevel = 0; /* Maximum relative level value in db */
@@ -3474,7 +3582,7 @@ static int fts3SetHasStat(Fts3Table *p){
}
/*
-** Implementation of xBegin() method.
+** Implementation of xBegin() method.
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
@@ -3530,17 +3638,17 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){
/* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */
while( p>pStart && (c=*p--)==0 );
- /* Search backwards for a varint with value zero (the end of the previous
+ /* Search backwards for a varint with value zero (the end of the previous
** poslist). This is an 0x00 byte preceded by some byte that does not
** have the 0x80 bit set. */
- while( p>pStart && (*p & 0x80) | c ){
- c = *p--;
+ while( p>pStart && (*p & 0x80) | c ){
+ c = *p--;
}
assert( p==pStart || c==0 );
/* At this point p points to that preceding byte without the 0x80 bit
** set. So to find the start of the poslist, skip forward 2 bytes then
- ** over a varint.
+ ** over a varint.
**
** Normally. The other case is that p==pStart and the poslist to return
** is the first in the doclist. In this case do not skip forward 2 bytes.
@@ -3561,7 +3669,7 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){
** offsets() and optimize() SQL functions.
**
** If the value passed as the third argument is a blob of size
-** sizeof(Fts3Cursor*), then the blob contents are copied to the
+** sizeof(Fts3Cursor*), then the blob contents are copied to the
** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error
** message is written to context pContext and SQLITE_ERROR returned. The
** string passed via zFunc is used as part of the error message.
@@ -3606,7 +3714,7 @@ static void fts3SnippetFunc(
assert( nVal>=1 );
if( nVal>6 ){
- sqlite3_result_error(pContext,
+ sqlite3_result_error(pContext,
"wrong number of arguments to function snippet()", -1);
return;
}
@@ -3614,9 +3722,13 @@ static void fts3SnippetFunc(
switch( nVal ){
case 6: nToken = sqlite3_value_int(apVal[5]);
+ /* no break */ deliberate_fall_through
case 5: iCol = sqlite3_value_int(apVal[4]);
+ /* no break */ deliberate_fall_through
case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
+ /* no break */ deliberate_fall_through
case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
+ /* no break */ deliberate_fall_through
case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
}
if( !zEllipsis || !zEnd || !zStart ){
@@ -3648,8 +3760,8 @@ static void fts3OffsetsFunc(
}
}
-/*
-** Implementation of the special optimize() function for FTS3. This
+/*
+** Implementation of the special optimize() function for FTS3. This
** function merges all segments in the database to a single segment.
** Example usage is:
**
@@ -3758,10 +3870,10 @@ static int fts3RenameMethod(
/* At this point it must be known if the %_stat table exists or not.
** So bHasStat may not be 2. */
rc = fts3SetHasStat(p);
-
+
/* As it happens, the pending terms table is always empty here. This is
- ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
- ** always opens a savepoint transaction. And the xSavepoint() method
+ ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
+ ** always opens a savepoint transaction. And the xSavepoint() method
** flushes the pending terms table. But leave the (no-op) call to
** PendingTermsFlush() in in case that changes.
*/
@@ -3841,7 +3953,6 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts3Table *p = (Fts3Table*)pVtab;
UNUSED_PARAMETER(iSavepoint);
assert( p->inTransaction );
- assert( p->mxSavepoint >= iSavepoint );
TESTONLY( p->mxSavepoint = iSavepoint );
sqlite3Fts3PendingTermsClear(p);
return SQLITE_OK;
@@ -3853,7 +3964,7 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
*/
static int fts3ShadowName(const char *zName){
static const char *azName[] = {
- "content", "docsize", "segdir", "segments", "stat",
+ "content", "docsize", "segdir", "segments", "stat",
};
unsigned int i;
for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
@@ -3901,7 +4012,7 @@ static void hashDestroy(void *p){
}
/*
-** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are
+** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are
** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c
** respectively. The following three forward declarations are for functions
** declared in these files used to retrieve the respective implementations.
@@ -3965,10 +4076,10 @@ int sqlite3Fts3Init(sqlite3 *db){
/* Load the built-in tokenizers into the hash table */
if( rc==SQLITE_OK ){
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
- || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
+ || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
#ifndef SQLITE_DISABLE_FTS3_UNICODE
- || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
+ || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
#endif
#ifdef SQLITE_ENABLE_ICU
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
@@ -3984,16 +4095,12 @@ int sqlite3Fts3Init(sqlite3 *db){
}
#endif
- /* Create the virtual table wrapper around the hash-table and overload
+ /* Create the virtual table wrapper around the hash-table and overload
** the four scalar functions. If this is successful, register the
** module with sqlite.
*/
- if( SQLITE_OK==rc
-#if CHROMIUM_FTS3_CHANGES && !SQLITE_TEST
- /* fts3_tokenizer() disabled for security reasons. */
-#else
+ if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
-#endif
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
@@ -4003,9 +4110,6 @@ int sqlite3Fts3Init(sqlite3 *db){
rc = sqlite3_create_module_v2(
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
);
-#if CHROMIUM_FTS3_CHANGES && !SQLITE_TEST
- /* Disable fts4 and tokenizer vtab pending review. */
-#else
if( rc==SQLITE_OK ){
rc = sqlite3_create_module_v2(
db, "fts4", &fts3Module, (void *)pHash, 0
@@ -4014,7 +4118,6 @@ int sqlite3Fts3Init(sqlite3 *db){
if( rc==SQLITE_OK ){
rc = sqlite3Fts3InitTok(db, (void *)pHash);
}
-#endif
return rc;
}
@@ -4030,7 +4133,7 @@ int sqlite3Fts3Init(sqlite3 *db){
/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
-** by pExpr.
+** by pExpr.
**
** An Fts3SegReader object is a cursor that can seek or scan a range of
** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
@@ -4040,7 +4143,7 @@ int sqlite3Fts3Init(sqlite3 *db){
** If the allocated Fts3MultiSegReader just seeks to a single entry in a
** segment b-tree (if the term is not a prefix or it is a prefix for which
** there exists prefix b-tree of the right length) then it may be traversed
-** and merged incrementally. Otherwise, it has to be merged into an in-memory
+** and merged incrementally. Otherwise, it has to be merged into an in-memory
** doclist and then traversed.
*/
static void fts3EvalAllocateReaders(
@@ -4057,7 +4160,7 @@ static void fts3EvalAllocateReaders(
*pnToken += nToken;
for(i=0; i<nToken; i++){
Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
- int rc = fts3TermSegReaderCursor(pCsr,
+ int rc = fts3TermSegReaderCursor(pCsr,
pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
);
if( rc!=SQLITE_OK ){
@@ -4263,7 +4366,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
sqlite3_free(aPoslist);
return SQLITE_NOMEM;
}
-
+
pPhrase->doclist.pList = aOut;
if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
pPhrase->doclist.bFreeList = 1;
@@ -4288,7 +4391,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
#define MAX_INCR_PHRASE_TOKENS 4
/*
-** This function is called for each Fts3Phrase in a full-text query
+** This function is called for each Fts3Phrase in a full-text query
** expression to initialize the mechanism for returning rows. Once this
** function has been called successfully on an Fts3Phrase, it may be
** used with fts3EvalPhraseNext() to iterate through the matching docids.
@@ -4306,14 +4409,14 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
/* Determine if doclists may be loaded from disk incrementally. This is
** possible if the bOptOk argument is true, the FTS doclists will be
- ** scanned in forward order, and the phrase consists of
+ ** scanned in forward order, and the phrase consists of
** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
** tokens or prefix tokens that cannot use a prefix-index. */
int bHaveIncr = 0;
- int bIncrOk = (bOptOk
- && pCsr->bDesc==pTab->bDescIdx
+ int bIncrOk = (bOptOk
+ && pCsr->bDesc==pTab->bDescIdx
&& p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
-#ifdef SQLITE_TEST
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
&& pTab->bNoIncrDoclist==0
#endif
);
@@ -4347,12 +4450,12 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
}
/*
-** This function is used to iterate backwards (from the end to start)
+** This function is used to iterate backwards (from the end to start)
** through doclists. It is used by this module to iterate through phrase
** doclists in reverse and by the fts3_write.c module to iterate through
** pending-terms lists when writing to databases with "order=desc".
**
-** The doclist may be sorted in ascending (parameter bDescIdx==0) or
+** The doclist may be sorted in ascending (parameter bDescIdx==0) or
** descending (parameter bDescIdx==1) order of docid. Regardless, this
** function iterates from the end of the doclist to the beginning.
*/
@@ -4424,7 +4527,7 @@ void sqlite3Fts3DoclistNext(
assert( nDoclist>0 );
assert( *pbEof==0 );
- assert( p || *piDocid==0 );
+ assert_fts3_nc( p || *piDocid==0 );
assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) );
if( p==0 ){
@@ -4432,7 +4535,7 @@ void sqlite3Fts3DoclistNext(
p += sqlite3Fts3GetVarint(p, piDocid);
}else{
fts3PoslistCopy(0, &p);
- while( p<&aDoclist[nDoclist] && *p==0 ) p++;
+ while( p<&aDoclist[nDoclist] && *p==0 ) p++;
if( p>=&aDoclist[nDoclist] ){
*pbEof = 1;
}else{
@@ -4455,15 +4558,16 @@ static void fts3EvalDlPhraseNext(
u8 *pbEof
){
char *pIter; /* Used to iterate through aAll */
- char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
-
+ char *pEnd; /* 1 byte past end of aAll */
+
if( pDL->pNextDocid ){
pIter = pDL->pNextDocid;
+ assert( pDL->aAll!=0 || pIter==0 );
}else{
pIter = pDL->aAll;
}
- if( pIter>=pEnd ){
+ if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){
/* We have already reached the end of this doclist. EOF. */
*pbEof = 1;
}else{
@@ -4504,12 +4608,12 @@ struct TokenDoclist {
};
/*
-** Token pToken is an incrementally loaded token that is part of a
+** Token pToken is an incrementally loaded token that is part of a
** multi-token phrase. Advance it to the next matching document in the
** database and populate output variable *p with the details of the new
** entry. Or, if the iterator has reached EOF, set *pbEof to true.
**
-** If an error occurs, return an SQLite error code. Otherwise, return
+** If an error occurs, return an SQLite error code. Otherwise, return
** SQLITE_OK.
*/
static int incrPhraseTokenNext(
@@ -4550,18 +4654,18 @@ static int incrPhraseTokenNext(
/*
** The phrase iterator passed as the second argument:
**
-** * features at least one token that uses an incremental doclist, and
+** * features at least one token that uses an incremental doclist, and
**
** * does not contain any deferred tokens.
**
** Advance it to the next matching documnent in the database and populate
-** the Fts3Doclist.pList and nList fields.
+** the Fts3Doclist.pList and nList fields.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
** 1 before returning. Otherwise, if no error occurs and the iterator is
** successfully advanced, *pbEof is set to 0.
**
-** If an error occurs, return an SQLite error code. Otherwise, return
+** If an error occurs, return an SQLite error code. Otherwise, return
** SQLITE_OK.
*/
static int fts3EvalIncrPhraseNext(
@@ -4579,7 +4683,7 @@ static int fts3EvalIncrPhraseNext(
assert( p->bIncr==1 );
if( p->nToken==1 ){
- rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
+ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
&pDL->iDocid, &pDL->pList, &pDL->nList
);
if( pDL->pList==0 ) bEof = 1;
@@ -4609,8 +4713,8 @@ static int fts3EvalIncrPhraseNext(
/* Keep advancing iterators until they all point to the same document */
for(i=0; i<p->nToken; i++){
- while( rc==SQLITE_OK && bEof==0
- && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
+ while( rc==SQLITE_OK && bEof==0
+ && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
){
rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
@@ -4624,9 +4728,10 @@ static int fts3EvalIncrPhraseNext(
if( bEof==0 ){
int nList = 0;
int nByte = a[p->nToken-1].nList;
- char *aDoclist = sqlite3_malloc(nByte+1);
+ char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
if( !aDoclist ) return SQLITE_NOMEM;
memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
+ memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
for(i=0; i<(p->nToken-1); i++){
if( a[i].bIgnore==0 ){
@@ -4656,8 +4761,8 @@ static int fts3EvalIncrPhraseNext(
}
/*
-** Attempt to move the phrase iterator to point to the next matching docid.
-** If an error occurs, return an SQLite error code. Otherwise, return
+** Attempt to move the phrase iterator to point to the next matching docid.
+** If an error occurs, return an SQLite error code. Otherwise, return
** SQLITE_OK.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
@@ -4676,7 +4781,7 @@ static int fts3EvalPhraseNext(
if( p->bIncr ){
rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
}else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
- sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
+ sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
&pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
);
pDL->pList = pDL->pNextDocid;
@@ -4736,7 +4841,7 @@ static void fts3EvalStartReaders(
** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
** to phrases that are connected only by AND and NEAR operators (not OR or
** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
-** separately. The root of a tokens AND/NEAR cluster is stored in
+** separately. The root of a tokens AND/NEAR cluster is stored in
** Fts3TokenAndCost.pRoot.
*/
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
@@ -4804,7 +4909,7 @@ static void fts3EvalTokenCosts(
** write this value to *pnPage and return SQLITE_OK. Otherwise, return
** an SQLite error code.
**
-** The average document size in pages is calculated by first calculating
+** The average document size in pages is calculated by first calculating
** determining the average size in bytes, B. If B is less than the amount
** of data that will fit on a single leaf page of an intkey table in
** this database, then the average docsize is 1. Otherwise, it is 1 plus
@@ -4814,10 +4919,10 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
int rc = SQLITE_OK;
if( pCsr->nRowAvg==0 ){
/* The average document size, which is required to calculate the cost
- ** of each doclist, has not yet been determined. Read the required
+ ** of each doclist, has not yet been determined. Read the required
** data from the %_stat table to calculate it.
**
- ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
+ ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
** varints, where nCol is the number of columns in the FTS3 table.
** The first varint is the number of documents currently stored in
** the table. The following nCol varints contain the total amount of
@@ -4834,12 +4939,13 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
if( rc!=SQLITE_OK ) return rc;
a = sqlite3_column_blob(pStmt, 0);
- assert( a );
-
- pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
- a += sqlite3Fts3GetVarint(a, &nDoc);
- while( a<pEnd ){
- a += sqlite3Fts3GetVarint(a, &nByte);
+ testcase( a==0 ); /* If %_stat.value set to X'' */
+ if( a ){
+ pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
+ while( a<pEnd ){
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nByte);
+ }
}
if( nDoc==0 || nByte==0 ){
sqlite3_reset(pStmt);
@@ -4848,7 +4954,7 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
pCsr->nDoc = nDoc;
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
- assert( pCsr->nRowAvg>0 );
+ assert( pCsr->nRowAvg>0 );
rc = sqlite3_reset(pStmt);
}
@@ -4857,11 +4963,11 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
}
/*
-** This function is called to select the tokens (if any) that will be
+** This function is called to select the tokens (if any) that will be
** deferred. The array aTC[] has already been populated when this is
** called.
**
-** This function is called once for each AND/NEAR cluster in the
+** This function is called once for each AND/NEAR cluster in the
** expression. Each invocation determines which tokens to defer within
** the cluster with root node pRoot. See comments above the definition
** of struct Fts3TokenAndCost for more details.
@@ -4911,8 +5017,8 @@ static int fts3EvalSelectDeferred(
assert( rc!=SQLITE_OK || nDocSize>0 );
- /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
- ** of the number of overflow pages that will be loaded by the pager layer
+ /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
+ ** of the number of overflow pages that will be loaded by the pager layer
** to retrieve the entire doclist for the token from the full-text index.
** Load the doclists for tokens that are either:
**
@@ -4923,7 +5029,7 @@ static int fts3EvalSelectDeferred(
**
** After each token doclist is loaded, merge it with the others from the
** same phrase and count the number of documents that the merged doclist
- ** contains. Set variable "nMinEst" to the smallest number of documents in
+ ** contains. Set variable "nMinEst" to the smallest number of documents in
** any phrase doclist for which 1 or more token doclists have been loaded.
** Let nOther be the number of other phrases for which it is certain that
** one or more tokens will not be deferred.
@@ -4939,8 +5045,8 @@ static int fts3EvalSelectDeferred(
/* Set pTC to point to the cheapest remaining token. */
for(iTC=0; iTC<nTC; iTC++){
- if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
- && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
+ if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
+ && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
){
pTC = &aTC[iTC];
}
@@ -4949,7 +5055,7 @@ static int fts3EvalSelectDeferred(
if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
/* The number of overflow pages to load for this (and therefore all
- ** subsequent) tokens is greater than the estimated number of pages
+ ** subsequent) tokens is greater than the estimated number of pages
** that will be loaded if all subsequent tokens are deferred.
*/
Fts3PhraseToken *pToken = pTC->pToken;
@@ -4958,7 +5064,7 @@ static int fts3EvalSelectDeferred(
pToken->pSegcsr = 0;
}else{
/* Set nLoad4 to the value of (4^nOther) for the next iteration of the
- ** for-loop. Except, limit the value to 2^24 to prevent it from
+ ** for-loop. Except, limit the value to 2^24 to prevent it from
** overflowing the 32-bit integer it is stored in. */
if( ii<12 ) nLoad4 = nLoad4*4;
@@ -5017,7 +5123,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
Fts3Expr **apOr;
- aTC = (Fts3TokenAndCost *)sqlite3_malloc(
+ aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
@@ -5071,7 +5177,7 @@ static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
**
** Parameter nNear is passed the NEAR distance of the expression (5 in
** the example above). When this function is called, *paPoslist points to
-** the position list, and *pnToken is the number of phrase tokens in, the
+** the position list, and *pnToken is the number of phrase tokens in the
** phrase on the other side of the NEAR operator to pPhrase. For example,
** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
** the position list associated with phrase "abc".
@@ -5080,7 +5186,7 @@ static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
** close to a position in the *paPoslist position list are removed. If this
** leaves 0 positions, zero is returned. Otherwise, non-zero.
**
-** Before returning, *paPoslist is set to point to the position lsit
+** Before returning, *paPoslist is set to point to the position lsit
** associated with pPhrase. And *pnToken is set to the number of tokens in
** pPhrase.
*/
@@ -5094,8 +5200,8 @@ static int fts3EvalNearTrim(
int nParam1 = nNear + pPhrase->nToken;
int nParam2 = nNear + *pnToken;
int nNew;
- char *p2;
- char *pOut;
+ char *p2;
+ char *pOut;
int res;
assert( pPhrase->doclist.pList );
@@ -5106,10 +5212,12 @@ static int fts3EvalNearTrim(
);
if( res ){
nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
- assert( pPhrase->doclist.pList[nNew]=='\0' );
- assert( nNew<=pPhrase->doclist.nList && nNew>0 );
- memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
- pPhrase->doclist.nList = nNew;
+ assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 );
+ if( nNew>=0 && nNew<=pPhrase->doclist.nList ){
+ assert( pPhrase->doclist.pList[nNew]=='\0' );
+ memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
+ pPhrase->doclist.nList = nNew;
+ }
*paPoslist = pPhrase->doclist.pList;
*pnToken = pPhrase->nToken;
}
@@ -5142,19 +5250,19 @@ static int fts3EvalNearTrim(
**
** 1. Deferred tokens are not taken into account. If a phrase consists
** entirely of deferred tokens, it is assumed to match every row in
-** the db. In this case the position-list is not populated at all.
+** the db. In this case the position-list is not populated at all.
**
** Or, if a phrase contains one or more deferred tokens and one or
-** more non-deferred tokens, then the expression is advanced to the
+** more non-deferred tokens, then the expression is advanced to the
** next possible match, considering only non-deferred tokens. In other
** words, if the phrase is "A B C", and "B" is deferred, the expression
-** is advanced to the next row that contains an instance of "A * C",
+** is advanced to the next row that contains an instance of "A * C",
** where "*" may match any single token. The position list in this case
** is populated as for "A * C" before returning.
**
-** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
+** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
** advanced to point to the next row that matches "x AND y".
-**
+**
** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is
** really a match, taking into account deferred tokens and NEAR operators.
*/
@@ -5218,11 +5326,12 @@ static void fts3EvalNextRow(
fts3EvalNextRow(pCsr, pLeft, pRc);
}
}
+ pRight->bEof = pLeft->bEof = 1;
}
}
break;
}
-
+
case FTSQUERY_OR: {
Fts3Expr *pLeft = pExpr->pLeft;
Fts3Expr *pRight = pExpr->pRight;
@@ -5262,9 +5371,9 @@ static void fts3EvalNextRow(
fts3EvalNextRow(pCsr, pLeft, pRc);
if( pLeft->bEof==0 ){
- while( !*pRc
- && !pRight->bEof
- && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
+ while( !*pRc
+ && !pRight->bEof
+ && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
){
fts3EvalNextRow(pCsr, pRight, pRc);
}
@@ -5289,14 +5398,14 @@ static void fts3EvalNextRow(
** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
** cluster, then this function returns 1 immediately.
**
-** Otherwise, it checks if the current row really does match the NEAR
-** expression, using the data currently stored in the position lists
-** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
+** Otherwise, it checks if the current row really does match the NEAR
+** expression, using the data currently stored in the position lists
+** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
**
** If the current row is a match, the position list associated with each
** phrase in the NEAR expression is edited in place to contain only those
** phrase instances sufficiently close to their peers to satisfy all NEAR
-** constraints. In this case it returns 1. If the NEAR expression does not
+** constraints. In this case it returns 1. If the NEAR expression does not
** match the current row, 0 is returned. The position lists may or may not
** be edited if 0 is returned.
*/
@@ -5319,16 +5428,16 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
** | |
** "w" "x"
**
- ** The right-hand child of a NEAR node is always a phrase. The
+ ** The right-hand child of a NEAR node is always a phrase. The
** left-hand child may be either a phrase or a NEAR node. There are
** no exceptions to this - it's the way the parser in fts3_expr.c works.
*/
- if( *pRc==SQLITE_OK
- && pExpr->eType==FTSQUERY_NEAR
+ if( *pRc==SQLITE_OK
+ && pExpr->eType==FTSQUERY_NEAR
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
- Fts3Expr *p;
- int nTmp = 0; /* Bytes of temp space */
+ Fts3Expr *p;
+ sqlite3_int64 nTmp = 0; /* Bytes of temp space */
char *aTmp; /* Temp space for PoslistNearMerge() */
/* Allocate temporary working space. */
@@ -5337,7 +5446,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
- aTmp = sqlite3_malloc(nTmp*2);
+ aTmp = sqlite3_malloc64(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
@@ -5374,12 +5483,12 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
/*
** This function is a helper function for sqlite3Fts3EvalTestDeferred().
** Assuming no error occurs or has occurred, It returns non-zero if the
-** expression passed as the second argument matches the row that pCsr
+** expression passed as the second argument matches the row that pCsr
** currently points to, or zero if it does not.
**
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-** If an error occurs during execution of this function, *pRc is set to
-** the appropriate SQLite error code. In this case the returned value is
+** If an error occurs during execution of this function, *pRc is set to
+** the appropriate SQLite error code. In this case the returned value is
** undefined.
*/
static int fts3EvalTestExpr(
@@ -5398,10 +5507,10 @@ static int fts3EvalTestExpr(
&& fts3EvalNearTest(pExpr, pRc)
);
- /* If the NEAR expression does not match any rows, zero the doclist for
+ /* If the NEAR expression does not match any rows, zero the doclist for
** all phrases involved in the NEAR. This is because the snippet(),
- ** offsets() and matchinfo() functions are not supposed to recognize
- ** any instances of phrases that are part of unmatched NEAR queries.
+ ** offsets() and matchinfo() functions are not supposed to recognize
+ ** any instances of phrases that are part of unmatched NEAR queries.
** For example if this expression:
**
** ... MATCH 'a OR (b NEAR c)'
@@ -5413,8 +5522,8 @@ static int fts3EvalTestExpr(
** then any snippet() should ony highlight the "a" term, not the "b"
** (as "b" is part of a non-matching NEAR clause).
*/
- if( bHit==0
- && pExpr->eType==FTSQUERY_NEAR
+ if( bHit==0
+ && pExpr->eType==FTSQUERY_NEAR
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
@@ -5446,7 +5555,7 @@ static int fts3EvalTestExpr(
default: {
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
- if( pCsr->pDeferred
+ if( pCsr->pDeferred
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
){
Fts3Phrase *pPhrase = pExpr->pPhrase;
@@ -5460,7 +5569,10 @@ static int fts3EvalTestExpr(
}else
#endif
{
- bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
+ bHit = (
+ pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId
+ && pExpr->pPhrase->doclist.nList>0
+ );
}
break;
}
@@ -5502,7 +5614,7 @@ int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){
** memory and scan it to determine the position list for each deferred
** token. Then, see if this row is really a match, considering deferred
** tokens and NEAR operators (neither of which were taken into account
- ** earlier, by fts3EvalNextRow()).
+ ** earlier, by fts3EvalNextRow()).
*/
if( pCsr->pDeferred ){
rc = fts3CursorSeek(0, pCsr);
@@ -5557,7 +5669,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
/*
** Restart interation for expression pExpr so that the next call to
-** fts3EvalNext() visits the first row. Do not allow incremental
+** fts3EvalNext() visits the first row. Do not allow incremental
** loading or merging of phrase doclists for this iteration.
**
** If *pRc is other than SQLITE_OK when this function is called, it is
@@ -5600,22 +5712,21 @@ static void fts3EvalRestart(
}
/*
-** After allocating the Fts3Expr.aMI[] array for each phrase in the
+** After allocating the Fts3Expr.aMI[] array for each phrase in the
** expression rooted at pExpr, the cursor iterates through all rows matched
** by pExpr, calling this function for each row. This function increments
** the values in Fts3Expr.aMI[] according to the position-list currently
-** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
+** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
** expression nodes.
*/
-static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
+static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
if( pExpr ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase && pPhrase->doclist.pList ){
int iCol = 0;
char *p = pPhrase->doclist.pList;
- assert( *p );
- while( 1 ){
+ do{
u8 c = 0;
int iCnt = 0;
while( 0xFE & (*p | c) ){
@@ -5631,11 +5742,11 @@ static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
if( *p==0x00 ) break;
p++;
p += fts3GetVarint32(p, &iCol);
- }
+ }while( iCol<nCol );
}
- fts3EvalUpdateCounts(pExpr->pLeft);
- fts3EvalUpdateCounts(pExpr->pRight);
+ fts3EvalUpdateCounts(pExpr->pLeft, nCol);
+ fts3EvalUpdateCounts(pExpr->pRight, nCol);
}
}
@@ -5679,7 +5790,7 @@ static int fts3EvalGatherStats(
for(p=pRoot; p; p=p->pLeft){
Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
assert( pE->aMI==0 );
- pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
+ pE->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32));
if( !pE->aMI ) return SQLITE_NOMEM;
memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
}
@@ -5699,13 +5810,13 @@ static int fts3EvalGatherStats(
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
pCsr->iPrevId = pRoot->iDocid;
- }while( pCsr->isEof==0
- && pRoot->eType==FTSQUERY_NEAR
- && sqlite3Fts3EvalTestDeferred(pCsr, &rc)
+ }while( pCsr->isEof==0
+ && pRoot->eType==FTSQUERY_NEAR
+ && sqlite3Fts3EvalTestDeferred(pCsr, &rc)
);
if( rc==SQLITE_OK && pCsr->isEof==0 ){
- fts3EvalUpdateCounts(pRoot);
+ fts3EvalUpdateCounts(pRoot, pTab->nColumn);
}
}
@@ -5716,7 +5827,7 @@ static int fts3EvalGatherStats(
pRoot->bEof = bEof;
}else{
/* Caution: pRoot may iterate through docids in ascending or descending
- ** order. For this reason, even though it seems more defensive, the
+ ** order. For this reason, even though it seems more defensive, the
** do loop can not be written:
**
** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
@@ -5724,7 +5835,8 @@ static int fts3EvalGatherStats(
fts3EvalRestart(pCsr, pRoot, &rc);
do {
fts3EvalNextRow(pCsr, pRoot, &rc);
- assert( pRoot->bEof==0 );
+ assert_fts3_nc( pRoot->bEof==0 );
+ if( pRoot->bEof ) rc = FTS_CORRUPT_VTAB;
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
}
}
@@ -5732,10 +5844,10 @@ static int fts3EvalGatherStats(
}
/*
-** This function is used by the matchinfo() module to query a phrase
+** This function is used by the matchinfo() module to query a phrase
** expression node for the following information:
**
-** 1. The total number of occurrences of the phrase in each column of
+** 1. The total number of occurrences of the phrase in each column of
** the FTS table (considering all rows), and
**
** 2. For each column, the number of rows in the table for which the
@@ -5749,12 +5861,12 @@ static int fts3EvalGatherStats(
**
** Caveats:
**
-** * If a phrase consists entirely of deferred tokens, then all output
+** * If a phrase consists entirely of deferred tokens, then all output
** values are set to the number of documents in the table. In other
-** words we assume that very common tokens occur exactly once in each
+** words we assume that very common tokens occur exactly once in each
** column of each row of the table.
**
-** * If a phrase contains some deferred tokens (and some non-deferred
+** * If a phrase contains some deferred tokens (and some non-deferred
** tokens), count the potential occurrence identified by considering
** the non-deferred tokens instead of actual phrase occurrences.
**
@@ -5792,14 +5904,14 @@ int sqlite3Fts3EvalPhraseStats(
/*
** The expression pExpr passed as the second argument to this function
-** must be of type FTSQUERY_PHRASE.
+** must be of type FTSQUERY_PHRASE.
**
** The returned value is either NULL or a pointer to a buffer containing
** a position-list indicating the occurrences of the phrase in column iCol
-** of the current row.
+** of the current row.
**
-** More specifically, the returned buffer contains 1 varint for each
-** occurrence of the phrase in the column, stored using the normal (delta+2)
+** More specifically, the returned buffer contains 1 varint for each
+** occurrence of the phrase in the column, stored using the normal (delta+2)
** compression and is terminated by either an 0x01 or 0x00 byte. For example,
** if the requested column contains "a b X c d X X" and the position-list
** for 'X' is requested, the buffer returned may contain:
@@ -5821,7 +5933,7 @@ int sqlite3Fts3EvalPhrasePoslist(
int iThis;
sqlite3_int64 iDocid;
- /* If this phrase is applies specifically to some column other than
+ /* If this phrase is applies specifically to some column other than
** column iCol, return a NULL pointer. */
*ppOut = 0;
assert( iCol>=0 && iCol<pTab->nColumn );
@@ -5840,8 +5952,8 @@ int sqlite3Fts3EvalPhrasePoslist(
Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
int bMatch;
- /* Check if this phrase descends from an OR expression node. If not,
- ** return NULL. Otherwise, the entry that corresponds to docid
+ /* Check if this phrase descends from an OR expression node. If not,
+ ** return NULL. Otherwise, the entry that corresponds to docid
** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
** tree that the node is part of has been marked as EOF, but the node
** itself is not EOF, then it may point to an earlier entry. */
@@ -5889,7 +6001,7 @@ int sqlite3Fts3EvalPhrasePoslist(
(pIter >= (pPh->doclist.aAll + pPh->doclist.nAll));
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
sqlite3Fts3DoclistNext(
- bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll,
+ bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll,
&pIter, &iDocid, &bEof
);
}
@@ -5898,7 +6010,7 @@ int sqlite3Fts3EvalPhrasePoslist(
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
int dummy;
sqlite3Fts3DoclistPrev(
- bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll,
+ bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll,
&pIter, &iDocid, &dummy, &bEof
);
}
@@ -5974,7 +6086,7 @@ int sqlite3Fts3Corrupt(){
__declspec(dllexport)
#endif
int sqlite3_fts3_init(
- sqlite3 *db,
+ sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c
index fc599a0c3e0..bd2f19db5d9 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c
@@ -13,7 +13,7 @@
** This file is part of the SQLite FTS3 extension module. Specifically,
** this file contains code to insert, update and delete rows from FTS3
** tables. It also contains code to merge FTS3 b-tree segments. Some
-** of the sub-routines used to merge segments are also used by the query
+** of the sub-routines used to merge segments are also used by the query
** code in fts3.c.
*/
@@ -23,13 +23,13 @@
#include <string.h>
#include <assert.h>
#include <stdlib.h>
-
+#include <stdio.h>
#define FTS_MAX_APPENDABLE_HEIGHT 16
/*
** When full-text index nodes are loaded from disk, the buffer that they
-** are loaded into has the following number of bytes of padding at the end
+** are loaded into has the following number of bytes of padding at the end
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
** of 920 bytes is allocated for it.
**
@@ -46,10 +46,10 @@
** method before retrieving all query results (as may happen, for example,
** if a query has a LIMIT clause).
**
-** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
+** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
-** The code is written so that the hard lower-limit for each of these values
-** is 1. Clearly such small values would be inefficient, but can be useful
+** The code is written so that the hard lower-limit for each of these values
+** is 1. Clearly such small values would be inefficient, but can be useful
** for testing purposes.
**
** If this module is built with SQLITE_TEST defined, these constants may
@@ -62,12 +62,12 @@ int test_fts3_node_chunk_threshold = (4*1024)*4;
# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
#else
-# define FTS3_NODE_CHUNKSIZE (4*1024)
+# define FTS3_NODE_CHUNKSIZE (4*1024)
# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
#endif
/*
-** The two values that may be meaningfully bound to the :1 parameter in
+** The values that may be meaningfully bound to the :1 parameter in
** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
*/
#define FTS_STAT_DOCTOTAL 0
@@ -76,7 +76,7 @@ int test_fts3_node_chunk_threshold = (4*1024)*4;
/*
** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic
-** and incremental merge operation that takes place. This is used for
+** and incremental merge operation that takes place. This is used for
** debugging FTS only, it should not usually be turned on in production
** systems.
*/
@@ -162,7 +162,7 @@ struct Fts3SegReader {
char *aDoclist; /* Pointer to doclist of current entry */
int nDoclist; /* Size of doclist in current entry */
- /* The following variables are used by fts3SegReaderNextDocid() to iterate
+ /* The following variables are used by fts3SegReaderNextDocid() to iterate
** through the current doclist (aDoclist/nDoclist).
*/
char *pOffsetList;
@@ -207,11 +207,11 @@ struct SegmentWriter {
** fts3NodeFree()
**
** When a b+tree is written to the database (either as a result of a merge
-** or the pending-terms table being flushed), leaves are written into the
+** or the pending-terms table being flushed), leaves are written into the
** database file as soon as they are completely populated. The interior of
** the tree is assembled in memory and written out only once all leaves have
** been populated and stored. This is Ok, as the b+-tree fanout is usually
-** very large, meaning that the interior of the tree consumes relatively
+** very large, meaning that the interior of the tree consumes relatively
** little memory.
*/
struct SegmentNode {
@@ -232,7 +232,7 @@ struct SegmentNode {
*/
#define SQL_DELETE_CONTENT 0
#define SQL_IS_EMPTY 1
-#define SQL_DELETE_ALL_CONTENT 2
+#define SQL_DELETE_ALL_CONTENT 2
#define SQL_DELETE_ALL_SEGMENTS 3
#define SQL_DELETE_ALL_SEGDIR 4
#define SQL_DELETE_ALL_DOCSIZE 5
@@ -280,7 +280,7 @@ struct SegmentNode {
** Otherwise, an SQLite error code is returned and *pp is set to 0.
**
** If argument apVal is not NULL, then it must point to an array with
-** at least as many entries as the requested statement has bound
+** at least as many entries as the requested statement has bound
** parameters. The values are bound to the statements parameters before
** returning.
*/
@@ -304,7 +304,7 @@ static int fts3SqlStmt(
/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
- /* Return segments in order from oldest to newest.*/
+ /* Return segments in order from oldest to newest.*/
/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
@@ -335,13 +335,15 @@ static int fts3SqlStmt(
** returns zero rows. */
/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
" GROUP BY level HAVING cnt>=?"
- " ORDER BY (level %% 1024) ASC LIMIT 1",
+ " ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1",
/* Estimate the upper limit on the number of leaf nodes in a new segment
-** created by merging the oldest :2 segments from absolute level :1. See
+** created by merging the oldest :2 segments from absolute level :1. See
** function sqlite3Fts3Incrmerge() for details. */
/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
- " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
+ " FROM (SELECT * FROM %Q.'%q_segdir' "
+ " WHERE level = ? ORDER BY idx ASC LIMIT ?"
+ " )",
/* SQL_DELETE_SEGDIR_ENTRY
** Delete the %_segdir entry on absolute level :1 with index :2. */
@@ -353,7 +355,7 @@ static int fts3SqlStmt(
/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?",
/* SQL_SELECT_SEGDIR
-** Read a single entry from the %_segdir table. The entry from absolute
+** Read a single entry from the %_segdir table. The entry from absolute
** level :1 with index value :2. */
/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
@@ -377,7 +379,7 @@ static int fts3SqlStmt(
** Return the largest relative level in the FTS index or indexes. */
/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'",
- /* Return segments in order from oldest to newest.*/
+ /* Return segments in order from oldest to newest.*/
/* 37 */ "SELECT level, idx, end_block "
"FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? "
"ORDER BY level DESC, idx ASC",
@@ -393,13 +395,15 @@ static int fts3SqlStmt(
assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
-
+
pStmt = p->aStmt[eStmt];
if( !pStmt ){
+ 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 ){
+ f &= ~SQLITE_PREPARE_NO_VTAB;
zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
}else{
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
@@ -407,8 +411,7 @@ static int fts3SqlStmt(
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
- rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
- &pStmt, NULL);
+ rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pStmt==0 );
p->aStmt[eStmt] = pStmt;
@@ -497,7 +500,7 @@ static void fts3SqlExec(
sqlite3_stmt *pStmt;
int rc;
if( *pRC ) return;
- rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
+ rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
@@ -507,22 +510,22 @@ static void fts3SqlExec(
/*
-** This function ensures that the caller has obtained an exclusive
-** shared-cache table-lock on the %_segdir table. This is required before
+** This function ensures that the caller has obtained an exclusive
+** shared-cache table-lock on the %_segdir table. This is required before
** writing data to the fts3 table. If this lock is not acquired first, then
** the caller may end up attempting to take this lock as part of committing
-** a transaction, causing SQLite to return SQLITE_LOCKED or
+** a transaction, causing SQLite to return SQLITE_LOCKED or
** LOCKED_SHAREDCACHEto a COMMIT command.
**
-** It is best to avoid this because if FTS3 returns any error when
-** committing a transaction, the whole transaction will be rolled back.
-** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE.
-** It can still happen if the user locks the underlying tables directly
+** It is best to avoid this because if FTS3 returns any error when
+** committing a transaction, the whole transaction will be rolled back.
+** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE.
+** It can still happen if the user locks the underlying tables directly
** instead of accessing them via FTS.
*/
static int fts3Writelock(Fts3Table *p){
int rc = SQLITE_OK;
-
+
if( p->nPendingData==0 ){
sqlite3_stmt *pStmt;
rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0);
@@ -539,7 +542,7 @@ static int fts3Writelock(Fts3Table *p){
/*
** FTS maintains a separate indexes for each language-id (a 32-bit integer).
** Within each language id, a separate index is maintained to store the
-** document terms, and each configured prefix size (configured the FTS
+** document terms, and each configured prefix size (configured the FTS
** "prefix=" option). And each index consists of multiple levels ("relative
** levels").
**
@@ -549,14 +552,14 @@ static int fts3Writelock(Fts3Table *p){
** separate component values into the single 64-bit integer value that
** can be used to query the %_segdir table.
**
-** Specifically, each language-id/index combination is allocated 1024
+** Specifically, each language-id/index combination is allocated 1024
** 64-bit integer level values ("absolute levels"). The main terms index
** for language-id 0 is allocate values 0-1023. The first prefix index
** (if any) for language-id 0 is allocated values 1024-2047. And so on.
** Language 1 indexes are allocated immediately following language 0.
**
** So, for a system with nPrefix prefix indexes configured, the block of
-** absolute levels that corresponds to language-id iLangid and index
+** absolute levels that corresponds to language-id iLangid and index
** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024).
*/
static sqlite3_int64 getAbsoluteLevel(
@@ -566,7 +569,7 @@ static sqlite3_int64 getAbsoluteLevel(
int iLevel /* Level of segments */
){
sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
- assert( iLangid>=0 );
+ assert_fts3_nc( iLangid>=0 );
assert( p->nIndex>0 );
assert( iIndex>=0 && iIndex<p->nIndex );
@@ -577,7 +580,7 @@ static sqlite3_int64 getAbsoluteLevel(
/*
** Set *ppStmt to a statement handle that may be used to iterate through
** all rows in the %_segdir table, from oldest to newest. If successful,
-** return SQLITE_OK. If an error occurs while preparing the statement,
+** return SQLITE_OK. If an error occurs while preparing the statement,
** return an SQLite error code.
**
** There is only ever one instance of this SQL statement compiled for
@@ -608,16 +611,16 @@ int sqlite3Fts3AllSegdirs(
if( iLevel<0 ){
/* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK ){
sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pStmt, 2,
+ sqlite3_bind_int64(pStmt, 2,
getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
);
}
}else{
/* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK ){
sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel));
}
}
@@ -695,7 +698,7 @@ static int fts3PendingListAppend(
assert( !p || p->iLastDocid<=iDocid );
if( !p || p->iLastDocid!=iDocid ){
- sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
+ u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0);
if( p ){
assert( p->nData<p->nSpace );
assert( p->aData[p->nData]==0 );
@@ -761,7 +764,7 @@ static int fts3PendingTermsAddOne(
}
if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
- /* Malloc failed while inserting the new entry. This can only
+ /* Malloc failed while inserting the new entry. This can only
** happen if there was no previous entry for this token.
*/
assert( 0==fts3HashFind(pHash, zToken, nToken) );
@@ -807,7 +810,7 @@ static int fts3PendingTermsAdd(
assert( pTokenizer && pModule );
/* If the user has inserted a NULL value, this function may be called with
- ** zText==0. In this case, add zero token entries to the hash table and
+ ** zText==0. In this case, add zero token entries to the hash table and
** return early. */
if( zText==0 ){
*pnWord = 0;
@@ -838,8 +841,8 @@ static int fts3PendingTermsAdd(
rc = fts3PendingTermsAddOne(
p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
);
-
- /* Add the term to each of the prefix indexes that it is not too
+
+ /* Add the term to each of the prefix indexes that it is not too
** short for. */
for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
struct Fts3Index *pIndex = &p->aIndex[i];
@@ -855,8 +858,8 @@ static int fts3PendingTermsAdd(
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
-/*
-** Calling this function indicates that subsequent calls to
+/*
+** Calling this function indicates that subsequent calls to
** fts3PendingTermsAdd() are to add term/position-list pairs for the
** contents of the document with docid iDocid.
*/
@@ -875,10 +878,10 @@ static int fts3PendingTermsDocid(
** buffer was half empty, that would let the less frequent terms
** generate longer doclists.
*/
- if( iDocid<p->iPrevDocid
+ if( iDocid<p->iPrevDocid
|| (iDocid==p->iPrevDocid && p->bPrevDelete==0)
|| p->iPrevLangid!=iLangid
- || p->nPendingData>p->nMaxPendingData
+ || p->nPendingData>p->nMaxPendingData
){
int rc = sqlite3Fts3PendingTermsFlush(p);
if( rc!=SQLITE_OK ) return rc;
@@ -890,7 +893,7 @@ static int fts3PendingTermsDocid(
}
/*
-** Discard the contents of the pending-terms hash tables.
+** Discard the contents of the pending-terms hash tables.
*/
void sqlite3Fts3PendingTermsClear(Fts3Table *p){
int i;
@@ -915,9 +918,9 @@ void sqlite3Fts3PendingTermsClear(Fts3Table *p){
** fts3InsertData(). Parameter iDocid is the docid of the new row.
*/
static int fts3InsertTerms(
- Fts3Table *p,
- int iLangid,
- sqlite3_value **apVal,
+ Fts3Table *p,
+ int iLangid,
+ sqlite3_value **apVal,
u32 *aSz
){
int i; /* Iterator variable */
@@ -980,7 +983,7 @@ static int fts3InsertData(
rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
if( rc==SQLITE_OK && p->zLanguageid ){
rc = sqlite3_bind_int(
- pContentInsert, p->nColumn+2,
+ pContentInsert, p->nColumn+2,
sqlite3_value_int(apVal[p->nColumn+4])
);
}
@@ -1007,8 +1010,8 @@ static int fts3InsertData(
if( rc!=SQLITE_OK ) return rc;
}
- /* Execute the statement to insert the record. Set *piDocid to the
- ** new docid value.
+ /* Execute the statement to insert the record. Set *piDocid to the
+ ** new docid value.
*/
sqlite3_step(pContentInsert);
rc = sqlite3_reset(pContentInsert);
@@ -1058,7 +1061,7 @@ static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){
** (an integer) of a row about to be deleted. Remove all terms from the
** full-text index.
*/
-static void fts3DeleteTerms(
+static void fts3DeleteTerms(
int *pRC, /* Result code */
Fts3Table *p, /* The FTS table to delete from */
sqlite3_value *pRowid, /* The docid to be deleted */
@@ -1105,7 +1108,7 @@ static void fts3DeleteTerms(
*/
static int fts3SegmentMerge(Fts3Table *, int, int, int);
-/*
+/*
** This function allocates a new level iLevel index in the segdir table.
** Usually, indexes are allocated within a level sequentially starting
** with 0, so the allocated index is one greater than the value returned
@@ -1114,17 +1117,17 @@ static int fts3SegmentMerge(Fts3Table *, int, int, int);
** SELECT max(idx) FROM %_segdir WHERE level = :iLevel
**
** However, if there are already FTS3_MERGE_COUNT indexes at the requested
-** level, they are merged into a single level (iLevel+1) segment and the
+** level, they are merged into a single level (iLevel+1) segment and the
** allocated index is 0.
**
** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
** returned. Otherwise, an SQLite error code is returned.
*/
static int fts3AllocateSegdirIdx(
- Fts3Table *p,
+ Fts3Table *p,
int iLangid, /* Language id */
int iIndex, /* Index for p->aIndex */
- int iLevel,
+ int iLevel,
int *piIdx
){
int rc; /* Return Code */
@@ -1152,7 +1155,7 @@ static int fts3AllocateSegdirIdx(
** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
*/
- if( iNext>=FTS3_MERGE_COUNT ){
+ if( iNext>=MergeCount(p) ){
fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
*piIdx = 0;
@@ -1172,7 +1175,7 @@ static int fts3AllocateSegdirIdx(
** This function reads data from a single row of the %_segments table. The
** specific row is identified by the iBlockid parameter. If paBlob is not
** NULL, then a buffer is allocated using sqlite3_malloc() and populated
-** with the contents of the blob stored in the "block" column of the
+** with the contents of the blob stored in the "block" column of the
** identified table row is. Whether or not paBlob is NULL, *pnBlob is set
** to the size of the blob in bytes before returning.
**
@@ -1236,6 +1239,8 @@ int sqlite3Fts3ReadBlock(
}
*paBlob = aByte;
}
+ }else if( rc==SQLITE_ERROR ){
+ rc = FTS_CORRUPT_VTAB;
}
return rc;
@@ -1249,14 +1254,14 @@ void sqlite3Fts3SegmentsClose(Fts3Table *p){
sqlite3_blob_close(p->pSegments);
p->pSegments = 0;
}
-
+
static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
int nRead; /* Number of bytes to read */
int rc; /* Return code */
nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
rc = sqlite3_blob_read(
- pReader->pBlob,
+ pReader->pBlob,
&pReader->aNode[pReader->nPopulate],
nRead,
pReader->nPopulate
@@ -1276,10 +1281,10 @@ static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
int rc = SQLITE_OK;
- assert( !pReader->pBlob
+ assert( !pReader->pBlob
|| (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
);
- while( pReader->pBlob && rc==SQLITE_OK
+ while( pReader->pBlob && rc==SQLITE_OK
&& (pFrom - pReader->aNode + nByte)>pReader->nPopulate
){
rc = fts3SegReaderIncrRead(pReader);
@@ -1305,7 +1310,7 @@ static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
** SQLITE_DONE. Otherwise, an SQLite error code.
*/
static int fts3SegReaderNext(
- Fts3Table *p,
+ Fts3Table *p,
Fts3SegReader *pReader,
int bIncr
){
@@ -1345,15 +1350,17 @@ static int fts3SegReaderNext(
fts3SegReaderSetEof(pReader);
- /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
+ /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
** blocks have already been traversed. */
- assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
+#ifdef CORRUPT_DB
+ assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB );
+#endif
if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
return SQLITE_OK;
}
rc = sqlite3Fts3ReadBlock(
- p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
+ p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
(bIncr ? &pReader->nPopulate : 0)
);
if( rc!=SQLITE_OK ) return rc;
@@ -1369,14 +1376,14 @@ static int fts3SegReaderNext(
rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
if( rc!=SQLITE_OK ) return rc;
-
- /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
+
+ /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
** safe (no risk of overread) even if the node data is corrupted. */
pNext += fts3GetVarint32(pNext, &nPrefix);
pNext += fts3GetVarint32(pNext, &nSuffix);
- if( nSuffix<=0
+ if( nSuffix<=0
|| (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
- || nPrefix>pReader->nTermAlloc
+ || nPrefix>pReader->nTerm
){
return FTS_CORRUPT_VTAB;
}
@@ -1405,11 +1412,12 @@ static int fts3SegReaderNext(
pReader->pOffsetList = 0;
/* Check that the doclist does not appear to extend past the end of the
- ** b-tree node. And that the final byte of the doclist is 0x00. If either
+ ** b-tree node. And that the final byte of the doclist is 0x00. If either
** of these statements is untrue, then the data structure is corrupt.
*/
- if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
+ if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
+ || pReader->nDoclist==0
){
return FTS_CORRUPT_VTAB;
}
@@ -1429,7 +1437,7 @@ static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
pReader->iDocid = 0;
pReader->nOffsetList = 0;
sqlite3Fts3DoclistPrev(0,
- pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
+ pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
&pReader->iDocid, &pReader->nOffsetList, &bEof
);
}else{
@@ -1445,8 +1453,8 @@ static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
/*
** Advance the SegReader to point to the next docid in the doclist
** associated with the current term.
-**
-** If arguments ppOffsetList and pnOffsetList are not NULL, then
+**
+** If arguments ppOffsetList and pnOffsetList are not NULL, then
** *ppOffsetList is set to point to the first column-offset list
** in the doclist entry (i.e. immediately past the docid varint).
** *pnOffsetList is set to the length of the set of column-offset
@@ -1489,22 +1497,22 @@ static int fts3SegReaderNextDocid(
** following block advances it to point one byte past the end of
** the same offset list. */
while( 1 ){
-
+
/* The following line of code (and the "p++" below the while() loop) is
- ** normally all that is required to move pointer p to the desired
+ ** normally all that is required to move pointer p to the desired
** position. The exception is if this node is being loaded from disk
** incrementally and pointer "p" now points to the first byte past
** the populated part of pReader->aNode[].
*/
while( *p | c ) c = *p++ & 0x80;
assert( *p==0 );
-
+
if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
rc = fts3SegReaderIncrRead(pReader);
if( rc!=SQLITE_OK ) return rc;
}
p++;
-
+
/* If required, populate the output variables with a pointer to and the
** size of the previous offset-list.
*/
@@ -1515,7 +1523,7 @@ static int fts3SegReaderNextDocid(
/* List may have been edited in place by fts3EvalNearTrim() */
while( p<pEnd && *p==0 ) p++;
-
+
/* If there are no more entries in the doclist, set pOffsetList to
** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
** Fts3SegReader.pOffsetList to point to the next offset list before
@@ -1526,23 +1534,23 @@ static int fts3SegReaderNextDocid(
}else{
rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
if( rc==SQLITE_OK ){
- sqlite3_int64 iDelta;
- pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
+ u64 iDelta;
+ pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta);
if( pTab->bDescIdx ){
- pReader->iDocid -= iDelta;
+ pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta);
}else{
- pReader->iDocid += iDelta;
+ pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta);
}
}
}
}
- return SQLITE_OK;
+ return rc;
}
int sqlite3Fts3MsrOvfl(
- Fts3Cursor *pCsr,
+ Fts3Cursor *pCsr,
Fts3MultiSegReader *pMsr,
int *pnOvfl
){
@@ -1557,8 +1565,8 @@ int sqlite3Fts3MsrOvfl(
for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
Fts3SegReader *pReader = pMsr->apSegment[ii];
- if( !fts3SegReaderIsPending(pReader)
- && !fts3SegReaderIsRootOnly(pReader)
+ if( !fts3SegReaderIsPending(pReader)
+ && !fts3SegReaderIsRootOnly(pReader)
){
sqlite3_int64 jj;
for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
@@ -1576,7 +1584,7 @@ int sqlite3Fts3MsrOvfl(
}
/*
-** Free all allocations associated with the iterator passed as the
+** Free all allocations associated with the iterator passed as the
** second argument.
*/
void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
@@ -1608,8 +1616,13 @@ int sqlite3Fts3SegReaderNew(
Fts3SegReader *pReader; /* Newly allocated SegReader object */
int nExtra = 0; /* Bytes to allocate segment root node */
- assert( iStartLeaf<=iEndLeaf );
+ assert( zRoot!=0 || nRoot==0 );
+#ifdef CORRUPT_DB
+ assert( zRoot!=0 || CORRUPT_DB );
+#endif
+
if( iStartLeaf==0 ){
+ if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB;
nExtra = nRoot + FTS3_NODE_PADDING;
}
@@ -1629,7 +1642,7 @@ int sqlite3Fts3SegReaderNew(
pReader->aNode = (char *)&pReader[1];
pReader->rootOnly = 1;
pReader->nNode = nRoot;
- memcpy(pReader->aNode, zRoot, nRoot);
+ if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot);
memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
}else{
pReader->iCurrentBlock = iStartLeaf-1;
@@ -1730,7 +1743,7 @@ int sqlite3Fts3SegReaderPending(
}else{
/* The query is a simple term lookup that matches at most one term in
- ** the index. All that is required is a straight hash-lookup.
+ ** the index. All that is required is a straight hash-lookup.
**
** Because the stack address of pE may be accessed via the aElem pointer
** below, the "Fts3HashElem *pE" must be declared so that it is valid
@@ -1744,8 +1757,9 @@ int sqlite3Fts3SegReaderPending(
}
if( nElem>0 ){
- int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
- pReader = (Fts3SegReader *)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte;
+ nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
+ pReader = (Fts3SegReader *)sqlite3_malloc64(nByte);
if( !pReader ){
rc = SQLITE_NOMEM;
}else{
@@ -1764,7 +1778,7 @@ int sqlite3Fts3SegReaderPending(
}
/*
-** Compare the entries pointed to by two Fts3SegReader structures.
+** Compare the entries pointed to by two Fts3SegReader structures.
** Comparison is as follows:
**
** 1) EOF is greater than not EOF.
@@ -1835,7 +1849,7 @@ static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
/*
** Compare the term that the Fts3SegReader object passed as the first argument
-** points to with the term specified by arguments zTerm and nTerm.
+** points to with the term specified by arguments zTerm and nTerm.
**
** If the pSeg iterator is already at EOF, return 0. Otherwise, return
** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are
@@ -1896,7 +1910,7 @@ static void fts3SegReaderSort(
#endif
}
-/*
+/*
** Insert a record into the %_segments table.
*/
static int fts3WriteSegment(
@@ -1938,7 +1952,7 @@ int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){
return rc;
}
-/*
+/*
** Insert a record into the %_segdir table.
*/
static int fts3WriteSegdir(
@@ -1976,7 +1990,7 @@ static int fts3WriteSegdir(
/*
** Return the size of the common prefix (if any) shared by zPrev and
-** zNext, in bytes. For example,
+** zNext, in bytes. For example,
**
** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3
** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2
@@ -1989,8 +2003,8 @@ static int fts3PrefixCompress(
int nNext /* Size of buffer zNext in bytes */
){
int n;
- UNUSED_PARAMETER(nNext);
- for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
+ for(n=0; n<nPrev && n<nNext && zPrev[n]==zNext[n]; n++);
+ assert_fts3_nc( n<nNext );
return n;
}
@@ -2000,7 +2014,7 @@ static int fts3PrefixCompress(
*/
static int fts3NodeAddTerm(
Fts3Table *p, /* Virtual table handle */
- SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
+ SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
int isCopyTerm, /* True if zTerm/nTerm is transient */
const char *zTerm, /* Pointer to buffer containing term */
int nTerm /* Size of term in bytes */
@@ -2009,7 +2023,7 @@ static int fts3NodeAddTerm(
int rc;
SegmentNode *pNew;
- /* First try to append the term to the current node. Return early if
+ /* First try to append the term to the current node. Return early if
** this is possible.
*/
if( pTree ){
@@ -2021,6 +2035,11 @@ static int fts3NodeAddTerm(
nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
+ /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
+ ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
+ ** compared with BINARY collation. This indicates corruption. */
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
+
nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
if( nReq<=p->nNodeSize || !pTree->zTerm ){
@@ -2029,8 +2048,8 @@ static int fts3NodeAddTerm(
** and the static node buffer (p->nNodeSize bytes) is not large
** enough. Use a separately malloced buffer instead This wastes
** p->nNodeSize bytes, but since this scenario only comes about when
- ** the database contain two terms that share a prefix of almost 2KB,
- ** this is not expected to be a serious problem.
+ ** the database contain two terms that share a prefix of almost 2KB,
+ ** this is not expected to be a serious problem.
*/
assert( pTree->aData==(char *)&pTree[1] );
pTree->aData = (char *)sqlite3_malloc(nReq);
@@ -2074,7 +2093,7 @@ static int fts3NodeAddTerm(
** If this is the first node in the tree, the term is added to it.
**
** Otherwise, the term is not added to the new node, it is left empty for
- ** now. Instead, the term is inserted into the parent of pTree. If pTree
+ ** now. Instead, the term is inserted into the parent of pTree. If pTree
** has no parent, one is created here.
*/
pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
@@ -2099,7 +2118,7 @@ static int fts3NodeAddTerm(
pTree->zMalloc = 0;
}else{
pNew->pLeftmost = pNew;
- rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
+ rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
}
*ppTree = pNew;
@@ -2110,8 +2129,8 @@ static int fts3NodeAddTerm(
** Helper function for fts3NodeWrite().
*/
static int fts3TreeFinishNode(
- SegmentNode *pTree,
- int iHeight,
+ SegmentNode *pTree,
+ int iHeight,
sqlite3_int64 iLeftChild
){
int nStart;
@@ -2124,15 +2143,15 @@ static int fts3TreeFinishNode(
/*
** Write the buffer for the segment node pTree and all of its peers to the
-** database. Then call this function recursively to write the parent of
-** pTree and its peers to the database.
+** database. Then call this function recursively to write the parent of
+** pTree and its peers to the database.
**
** Except, if pTree is a root node, do not write it to the database. Instead,
** set output variables *paRoot and *pnRoot to contain the root node.
**
** If successful, SQLITE_OK is returned and output variable *piLast is
** set to the largest blockid written to the database (or zero if no
-** blocks were written to the db). Otherwise, an SQLite error code is
+** blocks were written to the db). Otherwise, an SQLite error code is
** returned.
*/
static int fts3NodeWrite(
@@ -2160,7 +2179,7 @@ static int fts3NodeWrite(
for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){
int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf);
int nWrite = pIter->nData - nStart;
-
+
rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite);
iNextFree++;
iNextLeaf += (pIter->nEntry+1);
@@ -2206,7 +2225,7 @@ static void fts3NodeFree(SegmentNode *pTree){
*/
static int fts3SegWriterAdd(
Fts3Table *p, /* Virtual table handle */
- SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
+ SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
int isCopyTerm, /* True if buffer zTerm must be copied */
const char *zTerm, /* Pointer to buffer containing term */
int nTerm, /* Size of term in bytes */
@@ -2249,6 +2268,11 @@ static int fts3SegWriterAdd(
nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
+ /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
+ ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
+ ** compared with BINARY collation. This indicates corruption. */
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
+
/* Figure out how many bytes are required by this new entry */
nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
@@ -2260,6 +2284,7 @@ static int fts3SegWriterAdd(
int rc;
/* The current leaf node is full. Write it out to the database. */
+ if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB;
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
if( rc!=SQLITE_OK ) return rc;
p->nLeafAdd++;
@@ -2309,9 +2334,11 @@ static int fts3SegWriterAdd(
/* Append the prefix-compressed term and doclist to the buffer. */
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
+ assert( nSuffix>0 );
memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
nData += nSuffix;
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
+ assert( nDoclist>0 );
memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
pWriter->nData = nData + nDoclist;
@@ -2331,6 +2358,7 @@ static int fts3SegWriterAdd(
pWriter->zTerm = zNew;
}
assert( pWriter->zTerm==pWriter->zMalloc );
+ assert( nTerm>0 );
memcpy(pWriter->zTerm, zTerm, nTerm);
}else{
pWriter->zTerm = (char *)zTerm;
@@ -2366,12 +2394,12 @@ static int fts3SegWriterFlush(
pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
}
if( rc==SQLITE_OK ){
- rc = fts3WriteSegdir(p, iLevel, iIdx,
+ rc = fts3WriteSegdir(p, iLevel, iIdx,
pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot);
}
}else{
/* The entire tree fits on the root node. Write it to the segdir table. */
- rc = fts3WriteSegdir(p, iLevel, iIdx,
+ rc = fts3WriteSegdir(p, iLevel, iIdx,
0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData);
}
p->nLeafAdd++;
@@ -2379,7 +2407,7 @@ static int fts3SegWriterFlush(
}
/*
-** Release all memory held by the SegmentWriter object passed as the
+** Release all memory held by the SegmentWriter object passed as the
** first argument.
*/
static void fts3SegWriterFree(SegmentWriter *pWriter){
@@ -2429,9 +2457,9 @@ static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
** Return SQLITE_OK if successful, or an SQLite error code if not.
*/
static int fts3SegmentMaxLevel(
- Fts3Table *p,
+ Fts3Table *p,
int iLangid,
- int iIndex,
+ int iIndex,
sqlite3_int64 *pnMax
){
sqlite3_stmt *pStmt;
@@ -2447,7 +2475,7 @@ static int fts3SegmentMaxLevel(
rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pStmt, 2,
+ sqlite3_bind_int64(pStmt, 2,
getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
@@ -2476,8 +2504,8 @@ static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
- sqlite3_bind_int64(pStmt, 2,
- ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
+ sqlite3_bind_int64(pStmt, 2,
+ (((u64)iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
);
*pbMax = 0;
@@ -2514,9 +2542,9 @@ static int fts3DeleteSegment(
** This function is used after merging multiple segments into a single large
** segment to delete the old, now redundant, segment b-trees. Specifically,
** it:
-**
-** 1) Deletes all %_segments entries for the segments associated with
-** each of the SegReader objects in the array passed as the third
+**
+** 1) Deletes all %_segments entries for the segments associated with
+** each of the SegReader objects in the array passed as the third
** argument, and
**
** 2) deletes all %_segdir entries with level iLevel, or all %_segdir
@@ -2548,7 +2576,7 @@ static int fts3DeleteSegdir(
rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pDelete, 2,
+ sqlite3_bind_int64(pDelete, 2,
getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
);
}
@@ -2570,7 +2598,7 @@ static int fts3DeleteSegdir(
}
/*
-** When this function is called, buffer *ppList (size *pnList bytes) contains
+** When this function is called, buffer *ppList (size *pnList bytes) contains
** a position list that may (or may not) feature multiple columns. This
** function adjusts the pointer *ppList and the length *pnList so that they
** identify the subset of the position list that corresponds to column iCol.
@@ -2597,7 +2625,7 @@ static void fts3ColumnFilter(
while( 1 ){
char c = 0;
while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80;
-
+
if( iCol==iCurrent ){
nList = (int)(p - pList);
break;
@@ -2605,14 +2633,14 @@ static void fts3ColumnFilter(
nList -= (int)(p - pList);
pList = p;
- if( nList==0 ){
+ if( nList<=0 ){
break;
}
p = &pList[1];
p += fts3GetVarint32(p, &iCurrent);
}
- if( bZero && &pList[nList]!=pEnd ){
+ if( bZero && (pEnd - &pList[nList])>0){
memset(&pList[nList], 0, pEnd - &pList[nList]);
}
*ppList = pList;
@@ -2639,6 +2667,7 @@ static int fts3MsrBufferData(
pMsr->aBuffer = pNew;
}
+ assert( nList>0 );
memcpy(pMsr->aBuffer, pList, nList);
return SQLITE_OK;
}
@@ -2677,7 +2706,7 @@ int sqlite3Fts3MsrIncrNext(
rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
j = 1;
- while( rc==SQLITE_OK
+ while( rc==SQLITE_OK
&& j<nMerge
&& apSegment[j]->pOffsetList
&& apSegment[j]->iDocid==iDocid
@@ -2720,7 +2749,7 @@ static int fts3SegReaderStart(
int i;
int nSeg = pCsr->nSegment;
- /* If the Fts3SegFilter defines a specific term (or term prefix) to search
+ /* If the Fts3SegFilter defines a specific term (or term prefix) to search
** for, then advance each segment iterator until it points to a term of
** equal or greater value than the specified term. This prevents many
** unnecessary merge/sort operations for the case where single segment
@@ -2804,7 +2833,7 @@ int sqlite3Fts3MsrIncrStart(
** sqlite3Fts3SegReaderStart()
** sqlite3Fts3SegReaderStep()
**
-** then the entire doclist for the term is available in
+** then the entire doclist for the term is available in
** MultiSegReader.aDoclist/nDoclist.
*/
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
@@ -2826,6 +2855,19 @@ int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
return SQLITE_OK;
}
+static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){
+ if( nReq>pCsr->nBuffer ){
+ char *aNew;
+ pCsr->nBuffer = nReq*2;
+ aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
+ if( !aNew ){
+ return SQLITE_NOMEM;
+ }
+ pCsr->aBuffer = aNew;
+ }
+ return SQLITE_OK;
+}
+
int sqlite3Fts3SegReaderStep(
Fts3Table *p, /* Virtual table handle */
@@ -2852,9 +2894,9 @@ int sqlite3Fts3SegReaderStep(
do {
int nMerge;
int i;
-
+
/* Advance the first pCsr->nAdvance entries in the apSegment[] array
- ** forward. Then sort the list in order of current term again.
+ ** forward. Then sort the list in order of current term again.
*/
for(i=0; i<pCsr->nAdvance; i++){
Fts3SegReader *pSeg = apSegment[i];
@@ -2876,34 +2918,34 @@ int sqlite3Fts3SegReaderStep(
pCsr->zTerm = apSegment[0]->zTerm;
/* If this is a prefix-search, and if the term that apSegment[0] points
- ** to does not share a suffix with pFilter->zTerm/nTerm, then all
+ ** to does not share a suffix with pFilter->zTerm/nTerm, then all
** required callbacks have been made. In this case exit early.
**
** Similarly, if this is a search for an exact match, and the first term
** of segment apSegment[0] is not a match, exit early.
*/
if( pFilter->zTerm && !isScan ){
- if( pCsr->nTerm<pFilter->nTerm
+ if( pCsr->nTerm<pFilter->nTerm
|| (!isPrefix && pCsr->nTerm>pFilter->nTerm)
- || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm)
+ || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm)
){
break;
}
}
nMerge = 1;
- while( nMerge<nSegment
+ while( nMerge<nSegment
&& apSegment[nMerge]->aNode
- && apSegment[nMerge]->nTerm==pCsr->nTerm
+ && apSegment[nMerge]->nTerm==pCsr->nTerm
&& 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm)
){
nMerge++;
}
assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
- if( nMerge==1
- && !isIgnoreEmpty
- && !isFirst
+ if( nMerge==1
+ && !isIgnoreEmpty
+ && !isFirst
&& (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
){
pCsr->nDoclist = apSegment[0]->nDoclist;
@@ -2948,32 +2990,26 @@ int sqlite3Fts3SegReaderStep(
if( !isIgnoreEmpty || nList>0 ){
- /* Calculate the 'docid' delta value to write into the merged
+ /* Calculate the 'docid' delta value to write into the merged
** doclist. */
sqlite3_int64 iDelta;
if( p->bDescIdx && nDoclist>0 ){
- iDelta = iPrev - iDocid;
+ if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB;
+ iDelta = (i64)((u64)iPrev - (u64)iDocid);
}else{
- iDelta = iDocid - iPrev;
+ if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB;
+ iDelta = (i64)((u64)iDocid - (u64)iPrev);
}
- assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
- assert( nDoclist>0 || iDelta==iDocid );
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
- if( nDoclist+nByte>pCsr->nBuffer ){
- char *aNew;
- pCsr->nBuffer = (nDoclist+nByte)*2;
- aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
- if( !aNew ){
- return SQLITE_NOMEM;
- }
- pCsr->aBuffer = aNew;
- }
+
+ rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist);
+ if( rc ) return rc;
if( isFirst ){
char *a = &pCsr->aBuffer[nDoclist];
int nWrite;
-
+
nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a);
if( nWrite ){
iPrev = iDocid;
@@ -2993,6 +3029,9 @@ int sqlite3Fts3SegReaderStep(
fts3SegReaderSort(apSegment, nMerge, j, xCmp);
}
if( nDoclist>0 ){
+ rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING);
+ if( rc ) return rc;
+ memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING);
pCsr->aDoclist = pCsr->aBuffer;
pCsr->nDoclist = nDoclist;
rc = SQLITE_ROW;
@@ -3023,18 +3062,18 @@ void sqlite3Fts3SegReaderFinish(
}
/*
-** Decode the "end_block" field, selected by column iCol of the SELECT
-** statement passed as the first argument.
+** Decode the "end_block" field, selected by column iCol of the SELECT
+** statement passed as the first argument.
**
** The "end_block" field may contain either an integer, or a text field
-** containing the text representation of two non-negative integers separated
-** by one or more space (0x20) characters. In the first case, set *piEndBlock
-** to the integer value and *pnByte to zero before returning. In the second,
+** containing the text representation of two non-negative integers separated
+** by one or more space (0x20) characters. In the first case, set *piEndBlock
+** to the integer value and *pnByte to zero before returning. In the second,
** set *piEndBlock to the first value and *pnByte to the second.
*/
static void fts3ReadEndBlockField(
- sqlite3_stmt *pStmt,
- int iCol,
+ sqlite3_stmt *pStmt,
+ int iCol,
i64 *piEndBlock,
i64 *pnByte
){
@@ -3042,11 +3081,11 @@ static void fts3ReadEndBlockField(
if( zText ){
int i;
int iMul = 1;
- i64 iVal = 0;
+ u64 iVal = 0;
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
- *piEndBlock = iVal;
+ *piEndBlock = (i64)iVal;
while( zText[i]==' ' ) i++;
iVal = 0;
if( zText[i]=='-' ){
@@ -3056,7 +3095,7 @@ static void fts3ReadEndBlockField(
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
- *pnByte = (iVal * (i64)iMul);
+ *pnByte = ((i64)iVal * (i64)iMul);
}
}
@@ -3080,10 +3119,10 @@ static int fts3PromoteSegments(
i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1;
i64 nLimit = (nByte*3)/2;
- /* Loop through all entries in the %_segdir table corresponding to
+ /* Loop through all entries in the %_segdir table corresponding to
** segments in this index on levels greater than iAbsLevel. If there is
- ** at least one such segment, and it is possible to determine that all
- ** such segments are smaller than nLimit bytes in size, they will be
+ ** at least one such segment, and it is possible to determine that all
+ ** such segments are smaller than nLimit bytes in size, they will be
** promoted to level iAbsLevel. */
sqlite3_bind_int64(pRange, 1, iAbsLevel+1);
sqlite3_bind_int64(pRange, 2, iLast);
@@ -3091,7 +3130,7 @@ static int fts3PromoteSegments(
i64 nSize = 0, dummy;
fts3ReadEndBlockField(pRange, 2, &dummy, &nSize);
if( nSize<=0 || nSize>nLimit ){
- /* If nSize==0, then the %_segdir.end_block field does not not
+ /* If nSize==0, then the %_segdir.end_block field does not not
** contain a size value. This happens if it was written by an
** old version of FTS. In this case it is not possible to determine
** the size of the segment, and so segment promotion does not
@@ -3157,18 +3196,18 @@ static int fts3PromoteSegments(
}
/*
-** Merge all level iLevel segments in the database into a single
+** Merge all level iLevel segments in the database into a single
** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
-** single segment with a level equal to the numerically largest level
+** single segment with a level equal to the numerically largest level
** currently present in the database.
**
** If this function is called with iLevel<0, but there is only one
-** segment in the database, SQLITE_DONE is returned immediately.
-** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
+** segment in the database, SQLITE_DONE is returned immediately.
+** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
** an SQLite error code is returned.
*/
static int fts3SegmentMerge(
- Fts3Table *p,
+ Fts3Table *p,
int iLangid, /* Language id to merge */
int iIndex, /* Index in p->aIndex[] to merge */
int iLevel /* Level to merge */
@@ -3212,7 +3251,7 @@ static int fts3SegmentMerge(
}else{
/* This call is to merge all segments at level iLevel. find the next
** available segment index at level iLevel+1. The call to
- ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
+ ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
** a single iLevel+2 segment if necessary. */
assert( FTS3_SEGCURSOR_PENDING==-1 );
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
@@ -3222,8 +3261,10 @@ static int fts3SegmentMerge(
if( rc!=SQLITE_OK ) goto finished;
assert( csr.nSegment>0 );
- assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
- assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
+ assert_fts3_nc( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
+ assert_fts3_nc(
+ iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL)
+ );
memset(&filter, 0, sizeof(Fts3SegFilter));
filter.flags = FTS3_SEGMENT_REQUIRE_POS;
@@ -3233,11 +3274,11 @@ static int fts3SegmentMerge(
while( SQLITE_OK==rc ){
rc = sqlite3Fts3SegReaderStep(p, &csr);
if( rc!=SQLITE_ROW ) break;
- rc = fts3SegWriterAdd(p, &pWriter, 1,
+ rc = fts3SegWriterAdd(p, &pWriter, 1,
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
}
if( rc!=SQLITE_OK ) goto finished;
- assert( pWriter || bIgnoreEmpty );
+ assert_fts3_nc( pWriter || bIgnoreEmpty );
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3DeleteSegdir(
@@ -3261,13 +3302,13 @@ static int fts3SegmentMerge(
}
-/*
-** Flush the contents of pendingTerms to level 0 segments.
+/*
+** Flush the contents of pendingTerms to level 0 segments.
*/
int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
int rc = SQLITE_OK;
int i;
-
+
for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
@@ -3322,14 +3363,16 @@ static void fts3DecodeIntArray(
const char *zBuf, /* The BLOB containing the varints */
int nBuf /* size of the BLOB */
){
- int i, j;
- UNUSED_PARAMETER(nBuf);
- for(i=j=0; i<N; i++){
- sqlite3_int64 x;
- j += sqlite3Fts3GetVarint(&zBuf[j], &x);
- assert(j<=nBuf);
- a[i] = (u32)(x & 0xffffffff);
+ int i = 0;
+ if( nBuf && (zBuf[nBuf-1]&0x80)==0 ){
+ int j;
+ for(i=j=0; i<N && j<nBuf; i++){
+ sqlite3_int64 x;
+ j += sqlite3Fts3GetVarint(&zBuf[j], &x);
+ a[i] = (u32)(x & 0xffffffff);
+ }
}
+ while( i<N ) a[i++] = 0;
}
/*
@@ -3348,7 +3391,7 @@ static void fts3InsertDocsize(
int rc; /* Result code from subfunctions */
if( *pRC ) return;
- pBlob = sqlite3_malloc( 10*p->nColumn );
+ pBlob = sqlite3_malloc64( 10*(sqlite3_int64)p->nColumn );
if( pBlob==0 ){
*pRC = SQLITE_NOMEM;
return;
@@ -3369,7 +3412,7 @@ static void fts3InsertDocsize(
/*
** Record 0 of the %_stat table contains a blob consisting of N varints,
** where N is the number of user defined columns in the fts3 table plus
-** two. If nCol is the number of user defined columns, then values of the
+** two. If nCol is the number of user defined columns, then values of the
** varints are set as follows:
**
** Varint 0: Total number of rows in the table.
@@ -3398,7 +3441,7 @@ static void fts3UpdateDocTotals(
const int nStat = p->nColumn+2;
if( *pRC ) return;
- a = sqlite3_malloc( (sizeof(u32)+10)*nStat );
+ a = sqlite3_malloc64( (sizeof(u32)+10)*(sqlite3_int64)nStat );
if( a==0 ){
*pRC = SQLITE_NOMEM;
return;
@@ -3454,7 +3497,7 @@ static void fts3UpdateDocTotals(
}
/*
-** Merge the entire database so that there is one segment for each
+** Merge the entire database so that there is one segment for each
** iIndex/iLangid combination.
*/
static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
@@ -3462,7 +3505,10 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
int rc;
sqlite3_stmt *pAllLangid = 0;
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
+ rc = sqlite3Fts3PendingTermsFlush(p);
+ if( rc==SQLITE_OK ){
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
+ }
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
@@ -3483,7 +3529,6 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
}
sqlite3Fts3SegmentsClose(p);
- sqlite3Fts3PendingTermsClear(p);
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
}
@@ -3493,7 +3538,7 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
**
** INSERT INTO <tbl>(<tbl>) VALUES('rebuild');
**
-** The entire FTS index is discarded and rebuilt. If the table is one
+** The entire FTS index is discarded and rebuilt. If the table is one
** created using the content=xxx option, then the new index is based on
** the current contents of the xxx table. Otherwise, it is rebuilt based
** on the contents of the %_content table.
@@ -3519,8 +3564,8 @@ static int fts3DoRebuild(Fts3Table *p){
}
if( rc==SQLITE_OK ){
- int nByte = sizeof(u32) * (p->nColumn+1)*3;
- aSz = (u32 *)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3;
+ aSz = (u32 *)sqlite3_malloc64(nByte);
if( aSz==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -3573,9 +3618,9 @@ static int fts3DoRebuild(Fts3Table *p){
/*
-** This function opens a cursor used to read the input data for an
+** This function opens a cursor used to read the input data for an
** incremental merge operation. Specifically, it opens a cursor to scan
-** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
+** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
** level iAbsLevel.
*/
static int fts3IncrmergeCsr(
@@ -3585,13 +3630,13 @@ static int fts3IncrmergeCsr(
Fts3MultiSegReader *pCsr /* Cursor object to populate */
){
int rc; /* Return Code */
- sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
- int nByte; /* Bytes allocated at pCsr->apSegment[] */
+ sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
+ sqlite3_int64 nByte; /* Bytes allocated at pCsr->apSegment[] */
/* Allocate space for the Fts3MultiSegReader.aCsr[] array */
memset(pCsr, 0, sizeof(*pCsr));
nByte = sizeof(Fts3SegReader *) * nSeg;
- pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
+ pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte);
if( pCsr->apSegment==0 ){
rc = SQLITE_NOMEM;
@@ -3640,7 +3685,7 @@ struct Blob {
};
/*
-** This structure is used to build up buffers containing segment b-tree
+** This structure is used to build up buffers containing segment b-tree
** nodes (blocks).
*/
struct NodeWriter {
@@ -3709,12 +3754,12 @@ static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
/*
** Attempt to advance the node-reader object passed as the first argument to
-** the next entry on the node.
+** the next entry on the node.
**
-** Return an error code if an error occurs (SQLITE_NOMEM is possible).
+** Return an error code if an error occurs (SQLITE_NOMEM is possible).
** Otherwise return SQLITE_OK. If there is no next entry on the node
** (e.g. because the current entry is the last) set NodeReader->aNode to
-** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
+** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
** variables for the new entry.
*/
static int nodeReaderNext(NodeReader *p){
@@ -3734,8 +3779,8 @@ static int nodeReaderNext(NodeReader *p){
}
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
- if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
- return SQLITE_CORRUPT_VTAB;
+ if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){
+ return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK ){
@@ -3745,7 +3790,7 @@ static int nodeReaderNext(NodeReader *p){
if( p->iChild==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
if( (p->nNode-p->iOff)<p->nDoclist ){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
p->aDoclist = &p->aNode[p->iOff];
p->iOff += p->nDoclist;
@@ -3753,7 +3798,7 @@ static int nodeReaderNext(NodeReader *p){
}
}
- assert( p->iOff<=p->nNode );
+ assert_fts3_nc( p->iOff<=p->nNode );
return rc;
}
@@ -3767,7 +3812,7 @@ static void nodeReaderRelease(NodeReader *p){
/*
** Initialize a node-reader object to read the node in buffer aNode/nNode.
**
-** If successful, SQLITE_OK is returned and the NodeReader object set to
+** If successful, SQLITE_OK is returned and the NodeReader object set to
** point to the first entry on the node (if any). Otherwise, an SQLite
** error code is returned.
*/
@@ -3777,14 +3822,14 @@ static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
p->nNode = nNode;
/* Figure out if this is a leaf or an internal node. */
- if( p->aNode[0] ){
+ if( aNode && aNode[0] ){
/* An internal node. */
p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
}else{
p->iOff = 1;
}
- return nodeReaderNext(p);
+ return aNode ? nodeReaderNext(p) : SQLITE_OK;
}
/*
@@ -3816,17 +3861,18 @@ static int fts3IncrmergePush(
int nSpace;
/* Figure out how much space the key will consume if it is written to
- ** the current node of layer iLayer. Due to the prefix compression,
+ ** the current node of layer iLayer. Due to the prefix compression,
** the space required changes depending on which node the key is to
** be added to. */
nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
+ if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
nSpace = sqlite3Fts3VarintLen(nPrefix);
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
- if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
+ if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
/* If the current node of layer iLayer contains zero keys, or if adding
- ** the key to it will not cause it to grow to larger than nNodeSize
+ ** the key to it will not cause it to grow to larger than nNodeSize
** bytes in size, write the key here. */
Blob *pBlk = &pNode->block;
@@ -3882,12 +3928,12 @@ static int fts3IncrmergePush(
** A node header is a single 0x00 byte for a leaf node, or a height varint
** followed by the left-hand-child varint for an internal node.
**
-** The term to be appended is passed via arguments zTerm/nTerm. For a
+** The term to be appended is passed via arguments zTerm/nTerm. For a
** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal
** node, both aDoclist and nDoclist must be passed 0.
**
** If the size of the value in blob pPrev is zero, then this is the first
-** term written to the node. Otherwise, pPrev contains a copy of the
+** term written to the node. Otherwise, pPrev contains a copy of the
** previous term. Before this function returns, it is updated to contain a
** copy of zTerm/nTerm.
**
@@ -3904,7 +3950,7 @@ static int fts3AppendToNode(
const char *zTerm, /* New term to write */
int nTerm, /* Size of zTerm in bytes */
const char *aDoclist, /* Doclist (or NULL) to write */
- int nDoclist /* Size of aDoclist in bytes */
+ int nDoclist /* Size of aDoclist in bytes */
){
int rc = SQLITE_OK; /* Return code */
int bFirst = (pPrev->n==0); /* True if this is the first term written */
@@ -3914,13 +3960,14 @@ static int fts3AppendToNode(
/* Node must have already been started. There must be a doclist for a
** leaf node, and there must not be a doclist for an internal node. */
assert( pNode->n>0 );
- assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
+ assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) );
blobGrowBuffer(pPrev, nTerm, &rc);
if( rc!=SQLITE_OK ) return rc;
nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
memcpy(pPrev->a, zTerm, nTerm);
pPrev->n = nTerm;
@@ -3978,7 +4025,7 @@ static int fts3IncrmergeAppend(
rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
pWriter->nWork++;
- /* Add the current term to the parent node. The term added to the
+ /* Add the current term to the parent node. The term added to the
** parent must:
**
** a) be greater than the largest term on the leaf node just written
@@ -4043,7 +4090,7 @@ static void fts3IncrmergeRelease(
NodeWriter *pRoot; /* NodeWriter for root node */
int rc = *pRc; /* Error code */
- /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
+ /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
** root node. If the segment fits entirely on a single leaf node, iRoot
** will be set to 0. If the root node is the parent of the leaves, iRoot
** will be 1. And so on. */
@@ -4061,17 +4108,17 @@ static void fts3IncrmergeRelease(
/* The entire output segment fits on a single node. Normally, this means
** the node would be stored as a blob in the "root" column of the %_segdir
- ** table. However, this is not permitted in this case. The problem is that
- ** space has already been reserved in the %_segments table, and so the
- ** start_block and end_block fields of the %_segdir table must be populated.
- ** And, by design or by accident, released versions of FTS cannot handle
+ ** table. However, this is not permitted in this case. The problem is that
+ ** space has already been reserved in the %_segments table, and so the
+ ** start_block and end_block fields of the %_segdir table must be populated.
+ ** And, by design or by accident, released versions of FTS cannot handle
** segments that fit entirely on the root node with start_block!=0.
**
- ** Instead, create a synthetic root node that contains nothing but a
+ ** Instead, create a synthetic root node that contains nothing but a
** pointer to the single content node. So that the segment consists of a
** single leaf and a single interior (root) node.
**
- ** Todo: Better might be to defer allocating space in the %_segments
+ ** Todo: Better might be to defer allocating space in the %_segments
** table until we are sure it is needed.
*/
if( iRoot==0 ){
@@ -4099,7 +4146,7 @@ static void fts3IncrmergeRelease(
/* Write the %_segdir record. */
if( rc==SQLITE_OK ){
- rc = fts3WriteSegdir(p,
+ rc = fts3WriteSegdir(p,
pWriter->iAbsLevel+1, /* level */
pWriter->iIdx, /* idx */
pWriter->iStart, /* start_block */
@@ -4130,7 +4177,7 @@ static int fts3TermCmp(
int nCmp = MIN(nLhs, nRhs);
int res;
- res = memcmp(zLhs, zRhs, nCmp);
+ res = (nCmp ? memcmp(zLhs, zRhs, nCmp) : 0);
if( res==0 ) res = nLhs - nRhs;
return res;
@@ -4138,11 +4185,11 @@ static int fts3TermCmp(
/*
-** Query to see if the entry in the %_segments table with blockid iEnd is
+** Query to see if the entry in the %_segments table with blockid iEnd is
** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before
-** returning. Otherwise, set *pbRes to 0.
+** returning. Otherwise, set *pbRes to 0.
**
-** Or, if an error occurs while querying the database, return an SQLite
+** Or, if an error occurs while querying the database, return an SQLite
** error code. The final value of *pbRes is undefined in this case.
**
** This is used to test if a segment is an "appendable" segment. If it
@@ -4160,14 +4207,14 @@ static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){
if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1;
rc = sqlite3_reset(pCheck);
}
-
+
*pbRes = bRes;
return rc;
}
/*
** This function is called when initializing an incremental-merge operation.
-** It checks if the existing segment with index value iIdx at absolute level
+** It checks if the existing segment with index value iIdx at absolute level
** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the
** merge-writer object *pWriter is initialized to write to it.
**
@@ -4176,7 +4223,7 @@ static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){
** * It was initially created as an appendable segment (with all required
** space pre-allocated), and
**
-** * The first key read from the input (arguments zKey and nKey) is
+** * The first key read from the input (arguments zKey and nKey) is
** greater than the largest key currently stored in the potential
** output segment.
*/
@@ -4214,6 +4261,10 @@ static int fts3IncrmergeLoad(
pWriter->bNoLeafData = (pWriter->nLeafData==0);
nRoot = sqlite3_column_bytes(pSelect, 4);
aRoot = sqlite3_column_blob(pSelect, 4);
+ if( aRoot==0 ){
+ sqlite3_reset(pSelect);
+ return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB;
+ }
}else{
return sqlite3_reset(pSelect);
}
@@ -4249,6 +4300,10 @@ static int fts3IncrmergeLoad(
int i;
int nHeight = (int)aRoot[0];
NodeWriter *pNode;
+ if( nHeight<1 || nHeight>=FTS_MAX_APPENDABLE_HEIGHT ){
+ sqlite3_reset(pSelect);
+ return FTS_CORRUPT_VTAB;
+ }
pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
pWriter->iStart = iStart;
@@ -4262,34 +4317,45 @@ static int fts3IncrmergeLoad(
pNode = &pWriter->aNodeWriter[nHeight];
pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
- blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
+ blobGrowBuffer(&pNode->block,
+ MAX(nRoot, p->nNodeSize)+FTS3_NODE_PADDING, &rc
+ );
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aRoot, nRoot);
pNode->block.n = nRoot;
+ memset(&pNode->block.a[nRoot], 0, FTS3_NODE_PADDING);
}
for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
NodeReader reader;
pNode = &pWriter->aNodeWriter[i];
- rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
- while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
- blobGrowBuffer(&pNode->key, reader.term.n, &rc);
- if( rc==SQLITE_OK ){
- memcpy(pNode->key.a, reader.term.a, reader.term.n);
- pNode->key.n = reader.term.n;
- if( i>0 ){
- char *aBlock = 0;
- int nBlock = 0;
- pNode = &pWriter->aNodeWriter[i-1];
- pNode->iBlock = reader.iChild;
- rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
- blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
- if( rc==SQLITE_OK ){
- memcpy(pNode->block.a, aBlock, nBlock);
- pNode->block.n = nBlock;
+ if( pNode->block.a){
+ rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
+ while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
+ blobGrowBuffer(&pNode->key, reader.term.n, &rc);
+ if( rc==SQLITE_OK ){
+ assert_fts3_nc( reader.term.n>0 || reader.aNode==0 );
+ if( reader.term.n>0 ){
+ memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ }
+ pNode->key.n = reader.term.n;
+ if( i>0 ){
+ char *aBlock = 0;
+ int nBlock = 0;
+ pNode = &pWriter->aNodeWriter[i-1];
+ pNode->iBlock = reader.iChild;
+ rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0);
+ blobGrowBuffer(&pNode->block,
+ MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
+ );
+ if( rc==SQLITE_OK ){
+ memcpy(pNode->block.a, aBlock, nBlock);
+ pNode->block.n = nBlock;
+ memset(&pNode->block.a[nBlock], 0, FTS3_NODE_PADDING);
+ }
+ sqlite3_free(aBlock);
}
- sqlite3_free(aBlock);
}
}
nodeReaderRelease(&reader);
@@ -4306,13 +4372,13 @@ static int fts3IncrmergeLoad(
/*
** Determine the largest segment index value that exists within absolute
** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus
-** one before returning SQLITE_OK. Or, if there are no segments at all
+** one before returning SQLITE_OK. Or, if there are no segments at all
** within level iAbsLevel, set *piIdx to zero.
**
** If an error occurs, return an SQLite error code. The final value of
** *piIdx is undefined in this case.
*/
-static int fts3IncrmergeOutputIdx(
+static int fts3IncrmergeOutputIdx(
Fts3Table *p, /* FTS Table handle */
sqlite3_int64 iAbsLevel, /* Absolute index of input segments */
int *piIdx /* OUT: Next free index at iAbsLevel+1 */
@@ -4331,7 +4397,7 @@ static int fts3IncrmergeOutputIdx(
return rc;
}
-/*
+/*
** Allocate an appendable output segment on absolute level iAbsLevel+1
** with idx value iIdx.
**
@@ -4345,7 +4411,7 @@ static int fts3IncrmergeOutputIdx(
** When an appendable segment is allocated, it is estimated that the
** maximum number of leaf blocks that may be required is the sum of the
** number of leaf blocks consumed by the input segments, plus the number
-** of input segments, multiplied by two. This value is stored in stack
+** of input segments, multiplied by two. This value is stored in stack
** variable nLeafEst.
**
** A total of 16*nLeafEst blocks are allocated when an appendable segment
@@ -4354,10 +4420,10 @@ static int fts3IncrmergeOutputIdx(
** of interior nodes that are parents of the leaf nodes start at block
** (start_block + (1 + end_block - start_block) / 16). And so on.
**
-** In the actual code below, the value "16" is replaced with the
+** In the actual code below, the value "16" is replaced with the
** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT.
*/
-static int fts3IncrmergeWriter(
+static int fts3IncrmergeWriter(
Fts3Table *p, /* Fts3 table handle */
sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
int iIdx, /* Index of new output segment */
@@ -4395,7 +4461,7 @@ static int fts3IncrmergeWriter(
if( rc!=SQLITE_OK ) return rc;
/* Insert the marker in the %_segments table to make sure nobody tries
- ** to steal the space just allocated. This is also used to identify
+ ** to steal the space just allocated. This is also used to identify
** appendable segments. */
rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0);
if( rc!=SQLITE_OK ) return rc;
@@ -4412,13 +4478,13 @@ static int fts3IncrmergeWriter(
}
/*
-** Remove an entry from the %_segdir table. This involves running the
+** Remove an entry from the %_segdir table. This involves running the
** following two statements:
**
** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx
** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx
**
-** The DELETE statement removes the specific %_segdir level. The UPDATE
+** The DELETE statement removes the specific %_segdir level. The UPDATE
** statement ensures that the remaining segments have contiguously allocated
** idx values.
*/
@@ -4532,7 +4598,10 @@ static int fts3TruncateNode(
NodeReader reader; /* Reader object */
Blob prev = {0, 0, 0}; /* Previous term written to new node */
int rc = SQLITE_OK; /* Return code */
- int bLeaf = aNode[0]=='\0'; /* True for a leaf node */
+ int bLeaf; /* True for a leaf node */
+
+ if( nNode<1 ) return FTS_CORRUPT_VTAB;
+ bLeaf = aNode[0]=='\0';
/* Allocate required output space */
blobGrowBuffer(pNew, nNode, &rc);
@@ -4540,8 +4609,8 @@ static int fts3TruncateNode(
pNew->n = 0;
/* Populate new node buffer */
- for(rc = nodeReaderInit(&reader, aNode, nNode);
- rc==SQLITE_OK && reader.aNode;
+ for(rc = nodeReaderInit(&reader, aNode, nNode);
+ rc==SQLITE_OK && reader.aNode;
rc = nodeReaderNext(&reader)
){
if( pNew->n==0 ){
@@ -4568,7 +4637,7 @@ static int fts3TruncateNode(
}
/*
-** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
+** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
** level iAbsLevel. This may involve deleting entries from the %_segments
** table, and modifying existing entries in both the %_segments and %_segdir
** tables.
@@ -4692,9 +4761,9 @@ static int fts3IncrmergeChomp(
}
*pnRem = 0;
}else{
- /* The incremental merge did not copy all the data from this
+ /* The incremental merge did not copy all the data from this
** segment to the upper level. The segment is modified in place
- ** so that it contains no keys smaller than zTerm/nTerm. */
+ ** so that it contains no keys smaller than zTerm/nTerm. */
const char *zTerm = pSeg->zTerm;
int nTerm = pSeg->nTerm;
rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm);
@@ -4730,7 +4799,7 @@ static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
}
/*
-** Load an incr-merge hint from the database. The incr-merge hint, if one
+** Load an incr-merge hint from the database. The incr-merge hint, if one
** exists, is stored in the rowid==1 row of the %_stat table.
**
** If successful, populate blob *pHint with the value read from the %_stat
@@ -4767,7 +4836,7 @@ static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
/*
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
** Otherwise, append an entry to the hint stored in blob *pHint. Each entry
-** consists of two varints, the absolute level number of the input segments
+** consists of two varints, the absolute level number of the input segments
** and the number of input segments.
**
** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs,
@@ -4788,7 +4857,7 @@ static void fts3IncrmergeHintPush(
/*
** Read the last entry (most recently pushed) from the hint blob *pHint
-** and then remove the entry. Write the two values read to *piAbsLevel and
+** and then remove the entry. Write the two values read to *piAbsLevel and
** *pnInput before returning.
**
** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
@@ -4798,13 +4867,17 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
const int nHint = pHint->n;
int i;
- i = pHint->n-2;
+ i = pHint->n-1;
+ if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
+ if( i==0 ) return FTS_CORRUPT_VTAB;
+ i--;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
pHint->n = i;
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
i += fts3GetVarint32(&pHint->a[i], pnInput);
+ assert( i<=nHint );
if( i!=nHint ) return FTS_CORRUPT_VTAB;
return SQLITE_OK;
@@ -4814,10 +4887,10 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
/*
** Attempt an incremental merge that writes nMerge leaf blocks.
**
-** Incremental merges happen nMin segments at a time. The segments
-** to be merged are the nMin oldest segments (the ones with the smallest
-** values for the _segdir.idx field) in the highest level that contains
-** at least nMin segments. Multiple merges might occur in an attempt to
+** Incremental merges happen nMin segments at a time. The segments
+** to be merged are the nMin oldest segments (the ones with the smallest
+** values for the _segdir.idx field) in the highest level that contains
+** at least nMin segments. Multiple merges might occur in an attempt to
** write the quota of nMerge leaf blocks.
*/
int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
@@ -4848,7 +4921,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
/* Search the %_segdir table for the absolute level with the smallest
** relative level number that contains at least nMin segments, if any.
** If one is found, set iAbsLevel to the absolute level number and
- ** nSeg to nMin. If no level with at least nMin segments can be found,
+ ** nSeg to nMin. If no level with at least nMin segments can be found,
** set nSeg to -1.
*/
rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
@@ -4864,7 +4937,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
/* If the hint read from the %_stat table is not empty, check if the
** last entry in it specifies a relative level smaller than or equal
- ** to the level identified by the block above (if any). If so, this
+ ** to the level identified by the block above (if any). If so, this
** iteration of the loop will work on merging at the hinted level.
*/
if( rc==SQLITE_OK && hint.n ){
@@ -4874,8 +4947,14 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
+ /* Based on the scan in the block above, it is known that there
+ ** are no levels with a relative level smaller than that of
+ ** iAbsLevel with more than nSeg segments, or if nSeg is -1,
+ ** no levels with more than nMin segments. Use this to limit the
+ ** value of nHintSeg to avoid a large memory allocation in case the
+ ** merge-hint is corrupt*/
iAbsLevel = iHintAbsLevel;
- nSeg = nHintSeg;
+ nSeg = MIN(MAX(nMin,nSeg), nHintSeg);
bUseHint = 1;
bDirtyHint = 1;
}else{
@@ -4888,13 +4967,19 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
/* If nSeg is less that zero, then there is no level with at least
** nMin segments and no hint in the %_stat table. No work to do.
** Exit early in this case. */
- if( nSeg<0 ) break;
+ if( nSeg<=0 ) break;
- /* Open a cursor to iterate through the contents of the oldest nSeg
- ** indexes of absolute level iAbsLevel. If this cursor is opened using
+ assert( nMod<=0x7FFFFFFF );
+ if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){
+ rc = FTS_CORRUPT_VTAB;
+ break;
+ }
+
+ /* Open a cursor to iterate through the contents of the oldest nSeg
+ ** indexes of absolute level iAbsLevel. If this cursor is opened using
** the 'hint' parameters, it is possible that there are less than nSeg
** segments available in level iAbsLevel. In this case, no work is
- ** done on iAbsLevel - fall through to the next iteration of the loop
+ ** done on iAbsLevel - fall through to the next iteration of the loop
** to start work on some other level. */
memset(pWriter, 0, nAlloc);
pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
@@ -4916,8 +5001,15 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
}
if( SQLITE_OK==rc && pCsr->nSegment==nSeg
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
- && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
){
+ int bEmpty = 0;
+ rc = sqlite3Fts3SegReaderStep(p, pCsr);
+ if( rc==SQLITE_OK ){
+ bEmpty = 1;
+ }else if( rc!=SQLITE_ROW ){
+ sqlite3Fts3SegReaderFinish(pCsr);
+ break;
+ }
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
@@ -4928,11 +5020,13 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
if( rc==SQLITE_OK && pWriter->nLeafEst ){
fts3LogMerge(nSeg, iAbsLevel);
- do {
- rc = fts3IncrmergeAppend(p, pWriter, pCsr);
- if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
- if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
- }while( rc==SQLITE_ROW );
+ if( bEmpty==0 ){
+ do {
+ rc = fts3IncrmergeAppend(p, pWriter, pCsr);
+ if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
+ if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
+ }while( rc==SQLITE_ROW );
+ }
/* Update or delete the input segments */
if( rc==SQLITE_OK ){
@@ -4973,7 +5067,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
** the integer.
**
** This function used for parameters to merge= and incrmerge=
-** commands.
+** commands.
*/
static int fts3Getint(const char **pz){
const char *z = *pz;
@@ -4997,7 +5091,7 @@ static int fts3DoIncrmerge(
const char *zParam /* Nul-terminated string containing "A,B" */
){
int rc;
- int nMin = (FTS3_MERGE_COUNT / 2);
+ int nMin = (MergeCount(p) / 2);
int nMerge = 0;
const char *z = zParam;
@@ -5042,7 +5136,7 @@ static int fts3DoAutoincrmerge(
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
p->nAutoincrmerge = fts3Getint(&zParam);
- if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
+ if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){
p->nAutoincrmerge = 8;
}
if( !p->bHasStat ){
@@ -5125,12 +5219,12 @@ static u64 fts3ChecksumIndex(
i64 iDocid = 0;
i64 iCol = 0;
- i64 iPos = 0;
+ u64 iPos = 0;
pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
while( pCsr<pEnd ){
- i64 iVal = 0;
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
+ u64 iVal = 0;
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
if( pCsr<pEnd ){
if( iVal==0 || iVal==1 ){
iCol = 0;
@@ -5138,8 +5232,12 @@ static u64 fts3ChecksumIndex(
if( iVal ){
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
}else{
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
- iDocid += iVal;
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
+ if( p->bDescIdx ){
+ iDocid = (i64)((u64)iDocid - iVal);
+ }else{
+ iDocid = (i64)((u64)iDocid + iVal);
+ }
}
}else{
iPos += (iVal - 2);
@@ -5164,7 +5262,7 @@ static u64 fts3ChecksumIndex(
** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk
** to false before returning.
**
-** If an error occurs (e.g. an OOM or IO error), return an SQLite error
+** If an error occurs (e.g. an OOM or IO error), return an SQLite error
** code. The final value of *pbOk is undefined in this case.
*/
static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
@@ -5195,7 +5293,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
sqlite3_stmt *pStmt = 0;
char *zSql;
-
+
zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
if( !zSql ){
rc = SQLITE_NOMEM;
@@ -5212,10 +5310,9 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
if( p->abNotindexed[iCol]==0 ){
const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
- int nText = sqlite3_column_bytes(pStmt, iCol+1);
sqlite3_tokenizer_cursor *pT = 0;
- rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
+ rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken = 0; /* Number of bytes in token */
@@ -5255,7 +5352,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
** the FTS index are correct, return SQLITE_OK. Or, if the contents of the
** FTS index are incorrect, return SQLITE_CORRUPT_VTAB.
**
-** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
+** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
** error code.
**
** The integrity-check works as follows. For each token and indexed token
@@ -5264,7 +5361,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
**
** + The index number (0 for the main index, 1 for the first prefix
** index etc.),
-** + The token (or token prefix) text itself,
+** + The token (or token prefix) text itself,
** + The language-id of the row it appears in,
** + The docid of the row it appears in,
** + The column it appears in, and
@@ -5275,7 +5372,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
**
** The integrity-check code calculates the same checksum in two ways:
**
-** 1. By scanning the contents of the FTS index, and
+** 1. By scanning the contents of the FTS index, and
** 2. By scanning and tokenizing the content table.
**
** If the two checksums are identical, the integrity-check is deemed to have
@@ -5296,11 +5393,11 @@ static int fts3DoIntegrityCheck(
**
** "INSERT INTO tbl(tbl) VALUES(<expr>)"
**
-** Argument pVal contains the result of <expr>. Currently the only
+** Argument pVal contains the result of <expr>. Currently the only
** meaningful value to insert is the text 'optimize'.
*/
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
- int rc; /* Return Code */
+ int rc = SQLITE_ERROR; /* Return Code */
const char *zVal = (const char *)sqlite3_value_text(pVal);
int nVal = sqlite3_value_bytes(pVal);
@@ -5316,21 +5413,27 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
rc = fts3DoIncrmerge(p, &zVal[6]);
}else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
rc = fts3DoAutoincrmerge(p, &zVal[10]);
-#ifdef SQLITE_TEST
- }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
- p->nNodeSize = atoi(&zVal[9]);
- rc = SQLITE_OK;
- }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
- p->nMaxPendingData = atoi(&zVal[11]);
- rc = SQLITE_OK;
- }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
- p->bNoIncrDoclist = atoi(&zVal[21]);
- rc = SQLITE_OK;
-#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
}else{
- rc = SQLITE_ERROR;
+ int v;
+ if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
+ 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=", 9) ){
+ v = atoi(&zVal[11]);
+ if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v;
+ rc = SQLITE_OK;
+ }else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){
+ p->bNoIncrDoclist = atoi(&zVal[21]);
+ rc = SQLITE_OK;
+ }else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){
+ v = atoi(&zVal[11]);
+ if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v;
+ rc = SQLITE_OK;
+ }
+#endif
}
-
return rc;
}
@@ -5348,7 +5451,7 @@ void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
}
/*
-** Free all entries in the pCsr->pDeffered list. Entries are added to
+** Free all entries in the pCsr->pDeffered list. Entries are added to
** this list using sqlite3Fts3DeferToken().
*/
void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
@@ -5376,14 +5479,14 @@ int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
int i; /* Used to iterate through table columns */
sqlite3_int64 iDocid; /* Docid of the row pCsr points to */
Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */
-
+
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
sqlite3_tokenizer *pT = p->pTokenizer;
sqlite3_tokenizer_module const *pModule = pT->pModule;
-
+
assert( pCsr->isRequireSeek==0 );
iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
-
+
for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
if( p->abNotindexed[i]==0 ){
const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
@@ -5424,8 +5527,8 @@ int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
}
int sqlite3Fts3DeferredTokenList(
- Fts3DeferredToken *p,
- char **ppData,
+ Fts3DeferredToken *p,
+ char **ppData,
int *pnData
){
char *pRet;
@@ -5445,7 +5548,7 @@ int sqlite3Fts3DeferredTokenList(
nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
*pnData = p->pList->nData - nSkip;
*ppData = pRet;
-
+
memcpy(pRet, &p->pList->aData[nSkip], *pnData);
return SQLITE_OK;
}
@@ -5465,7 +5568,7 @@ int sqlite3Fts3DeferToken(
}
memset(pDeferred, 0, sizeof(*pDeferred));
pDeferred->pToken = pToken;
- pDeferred->pNext = pCsr->pDeferred;
+ pDeferred->pNext = pCsr->pDeferred;
pDeferred->iCol = iCol;
pCsr->pDeferred = pDeferred;
@@ -5482,8 +5585,8 @@ int sqlite3Fts3DeferToken(
** of subsiduary data structures accordingly.
*/
static int fts3DeleteByRowid(
- Fts3Table *p,
- sqlite3_value *pRowid,
+ Fts3Table *p,
+ sqlite3_value *pRowid,
int *pnChng, /* IN/OUT: Decrement if row is deleted */
u32 *aSzDel
){
@@ -5521,14 +5624,14 @@ static int fts3DeleteByRowid(
** This function does the work for the xUpdate method of FTS3 virtual
** tables. The schema of the virtual table being:
**
-** CREATE TABLE <table name>(
+** CREATE TABLE <table name>(
** <user columns>,
-** <table name> HIDDEN,
-** docid HIDDEN,
+** <table name> HIDDEN,
+** docid HIDDEN,
** <langid> HIDDEN
** );
**
-**
+**
*/
int sqlite3Fts3UpdateMethod(
sqlite3_vtab *pVtab, /* FTS3 vtab object */
@@ -5548,7 +5651,7 @@ int sqlite3Fts3UpdateMethod(
assert( p->bHasStat==0 || p->bHasStat==1 );
assert( p->pSegments==0 );
- assert(
+ assert(
nArg==1 /* DELETE operations */
|| nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */
);
@@ -5557,9 +5660,9 @@ int sqlite3Fts3UpdateMethod(
**
** INSERT INTO xyz(xyz) VALUES('command');
*/
- if( nArg>1
- && sqlite3_value_type(apVal[0])==SQLITE_NULL
- && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
+ if( nArg>1
+ && sqlite3_value_type(apVal[0])==SQLITE_NULL
+ && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
){
rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
goto update_out;
@@ -5571,7 +5674,7 @@ int sqlite3Fts3UpdateMethod(
}
/* Allocate space to hold the change in document sizes */
- aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
+ aSzDel = sqlite3_malloc64(sizeof(aSzDel[0])*((sqlite3_int64)p->nColumn+1)*2);
if( aSzDel==0 ){
rc = SQLITE_NOMEM;
goto update_out;
@@ -5598,24 +5701,24 @@ int sqlite3Fts3UpdateMethod(
pNewRowid = apVal[1];
}
- if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
+ if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
sqlite3_value_type(apVal[0])==SQLITE_NULL
|| sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
)){
/* The new rowid is not NULL (in this case the rowid will be
- ** automatically assigned and there is no chance of a conflict), and
+ ** automatically assigned and there is no chance of a conflict), and
** the statement is either an INSERT or an UPDATE that modifies the
** rowid column. So if the conflict mode is REPLACE, then delete any
- ** existing row with rowid=pNewRowid.
+ ** existing row with rowid=pNewRowid.
**
- ** Or, if the conflict mode is not REPLACE, insert the new record into
+ ** Or, if the conflict mode is not REPLACE, insert the new record into
** the %_content table. If we hit the duplicate rowid constraint (or any
** other error) while doing so, return immediately.
**
** This branch may also run if pNewRowid contains a value that cannot
- ** be losslessly converted to an integer. In this case, the eventual
+ ** be losslessly converted to an integer. In this case, the eventual
** call to fts3InsertData() (either just below or further on in this
- ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
+ ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
** invoked, it will delete zero rows (since no row will have
** docid=$pNewRowid if $pNewRowid is not an integer value).
*/
@@ -5636,7 +5739,7 @@ int sqlite3Fts3UpdateMethod(
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
}
-
+
/* If this is an INSERT or UPDATE operation, insert the new record. */
if( nArg>1 && rc==SQLITE_OK ){
int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]);
@@ -5669,10 +5772,10 @@ int sqlite3Fts3UpdateMethod(
return rc;
}
-/*
+/*
** Flush any data in the pending-terms hash table to disk. If successful,
-** merge all segments in the database (including the new segment, if
-** there was any data to flush) into a single segment.
+** merge all segments in the database (including the new segment, if
+** there was any data to flush) into a single segment.
*/
int sqlite3Fts3Optimize(Fts3Table *p){
int rc;
diff --git a/chromium/third_party/sqlite/src/manifest b/chromium/third_party/sqlite/src/manifest
index bb8f3728c11..27be9944ca8 100644
--- a/chromium/third_party/sqlite/src/manifest
+++ b/chromium/third_party/sqlite/src/manifest
@@ -1,54 +1,58 @@
-C Version\s3.26.0
-D 2018-12-01T12:34:55.966
+C Version\s3.35.5
+D 2021-04-19T18:32:05.830
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
-F Makefile.in a050c8670ea0d7b37b2192306cbb50d392acd9902b84e9b56f3444d006f97a6c
-F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
-F Makefile.msc 0d6831ff7951b302e888d86d4c469e2ec3c22f59eba4118b8c38d5a51d9e2d4f
-F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
-F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb
+F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
+F Makefile.in fe6cc1db11e02b308f3ab0ec2504344697b9eaaa410fa73f48d16a143462e5d3
+F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
+F Makefile.msc 6b5428cef2af1288e02faeb602dabe68fbf2de7bc8a8e29c7299778ee08cd35c
+F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
+F VERSION 0c32b05000702ccfdfb5fc72e16b0f965ed664d6cb4fec361196fd0d91eb52c9
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
-F autoconf/Makefile.am e14b629addaa1ce372b72043f28f40de2e32b7e211b6e0fc18dbb87989197e40
+F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc 9e73d9abaadb7a4951ddd0e947c5c791770f23bb1e04bfa50b43c01bee0575f2
+F autoconf/Makefile.msc ebe7e66edbb2f453593cbde186d1a0fa0dcd8cae9977febcae27aef1dab5678d
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
-F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
+F autoconf/configure.ac a8ba2a9e61216f5093d44f3b7d2cb8fe1890d6b7dc330a02f802d8efaa1fdc79
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
-F autoconf/tea/configure.ac 8aa16e3f0a5ca7959d4af198f46934ec187d395f
+F autoconf/tea/configure.ac ea61e07340d97e4a79a081f0b8977198a6073edd060738dbb3ae5cb8d5e96f1c
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5
-F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928
+F autoconf/tea/win/makefile.vc a5ff708245260c2794c6aaa0151efe5403d5896566eaf096747be0d9075284e4
F autoconf/tea/win/nmakehlp.c 247538ad8e8c508f33c03ec1fbd67d3a07ef6291
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
-F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
+F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
-F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
-F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x
-F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
+F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
+F configure 64b2ab5ac52a8657cfdf97a2a1589441d0deaa859e0d2bbad5ff401829f71676 x
+F configure.ac 4e4b58b32f88c8da9914a2f2c3158f80e69907eccc019fcc7e3ba14ffd91c640
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
-F doc/lemon.html 24956ab2995e55fe171e55bdd04f22b553957dc8bb43501dbb9311e30187e0d3
+F doc/lemon.html 1bb72ece6271df0d901d233551dd985f2c6ba30d09382cf2d321ed951ab57491
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
+F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
+F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
+F doc/wal-lock.md 781726aaba20bafeceb7ba9f91d5c98c6731691b30c954e37cf0b49a053d461d
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
-F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
-F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
+F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
+F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test 333d037021c901322f9afc4a5687648ea23d56f1a0a079358a390664babf01be
-F ext/expert/sqlite3expert.c 3da865f2286433588260f41e796422c611bceaca3a0bbf9139a619cf7d062c19
-F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
+F ext/expert/expert1.test 63d778d964e55ef2d1a723043d91c59e7dc6ef1649d91c78c0bef00f9c6f1427
+F ext/expert/sqlite3expert.c de51b187c629a4c4264d5de0b77862641e11426f7a963a92abf2d4077085fc8c
+F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
@@ -76,59 +80,59 @@ F ext/fts2/fts2_tokenizer.c b529493d55e55497213c37e1f31680a77746be26
F ext/fts2/fts2_tokenizer.h 27a1a99ca2d615cf7e142839b8d79e8751b4529e
F ext/fts2/fts2_tokenizer1.c 07e223eecb483d448313b5f1553a4f299a7fb7a1
F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
-F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
+F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
-F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
+F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 65b8489e35da23b127992c6dd6cfd382a486f8c87bf26dfa72876efe46e551bb
+F ext/fts3/fts3.c 7b449348226a91cc851fe969f5c1932d4f00c359a32fd17f2afea92bf875147b
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5
-F ext/fts3/fts3_aux.c e9b465f8469acc2cd700a90c0242912a3202e4e4e15df72d7db7f1e3a2222c85
-F ext/fts3/fts3_expr.c 3b1dbceddd8622599f3cc2626897667fe40487aaa1676707d6c37ec5a8422fc1
-F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
+F ext/fts3/fts3Int.h 045179f538c478ced266ca14327269cde8ad8d573c5be902230a5ebaa5636c59
+F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34
+F ext/fts3/fts3_expr.c 5853cd7a35a79d193614add9b4c461b2d56f465d90899ca4309f05d9d1536558
+F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
-F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
+F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
-F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
-F ext/fts3/fts3_term.c 9b8065cc70ad514fcc25a7b099ddab8b5333f724dedd57184b7e79238e2b2a39
-F ext/fts3/fts3_test.c 79f2a7fbb3f672fa032e5a432ca274ea3ee93c34
-F ext/fts3/fts3_tokenize_vtab.c a47c2a33de6db00816704315ac0a9afdfa1c71fa5b99f79171c0f7b30861f784
-F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
+F ext/fts3/fts3_snippet.c 86e7e947a176f0f005720b3ca17631aca2fd2f9daa6729d4adbf2d16ab1b9613
+F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1
+F ext/fts3/fts3_test.c 73b16e229e517c1b1f0fb8e1046182a4e5dbc8dbe6eea8a5d4353fcce7dbbf39
+F ext/fts3/fts3_tokenize_vtab.c 8d15b148e7d88a4280389a200b26e8d52abda4c4ec2e9a35e9d7a1fa50e5aa03
+F ext/fts3/fts3_tokenizer.c 6d8fc150c48238955d5182bf661498db0dd473c8a2a80e00c16994a646fa96e7
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
-F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
-F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
-F ext/fts3/fts3_write.c a85bc4885fde7f1b44c9de013b62f7cd3332dc59e208053d878729b1d04745bc
+F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
+F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
+F ext/fts3/fts3_write.c 75b151c9b074c0f74f29ab4b843d1c272fd96a9e82556bca947ad2d0fc8ea41d
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
-F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
+F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
-F ext/fts3/unicode/mkunicode.tcl 0069320b64db6ee269c5e95f1f150d070fbf0a863fc7b3549d7e52bd068fb118
-F ext/fts3/unicode/parseunicode.tcl 024ae0bdd96309d7b8fc479148191e9b3001dc74017a3f65f9a27de3b3ff968b
+F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7
+F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
-F ext/fts5/fts5.h 5edc74ca603d71284d475886e6e91b5c5cf2e8e93e9ba3a36ba2f2440ee97948
-F ext/fts5/fts5Int.h 39f12034b598df4e0f59bbe6cf03af03a905a534b04f182d155641a04e1eb797
-F ext/fts5/fts5_aux.c ca666a3bbe07c5a3bbe9fffaea19c935a1efaf337333e28bad7bdd1971ffd093
-F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff
-F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
-F ext/fts5/fts5_expr.c 5aef080ba3c8947e22f38ce1ff9fe548e4a740e72b77241f35ed941ae128d2c7
-F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
-F ext/fts5/fts5_index.c baf3ad4451d32d35c2bd692ee4a81235ca7f26bd6f7613f7f73505474c33bbf2
-F ext/fts5/fts5_main.c 287a1a56580df304d7fa2fc1890f85b9cb6ac6b9e7c8af7dfa2151528db4b059
-F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d733d278634
+F ext/fts5/fts5.h c132a9323f22a972c4c93a8d5a3d901113a6e612faf30ca8e695788438c5ca2a
+F ext/fts5/fts5Int.h 26c74dd5776f798436fbf604a0bf0e8de263b35b5060b05c15f9085845d9fda2
+F ext/fts5/fts5_aux.c f558e1fb9f0f86a4f7489e258c162e1f947de5ff2709087fbb465fddb7092f98
+F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
+F ext/fts5/fts5_config.c be54f44fca491e96c6923a4b9a736f2da2b13811600eb6e38d1bcc91c4ea2e61
+F ext/fts5/fts5_expr.c 016bd06030679bd31b0f07ef87d62c42031e5da25cb3174a84e5b0f6ef4b47b0
+F ext/fts5/fts5_hash.c 1aa93c9b5f461afba66701ee226297dc78402b3bdde81e90a10de5fe3df14959
+F ext/fts5/fts5_index.c df5e18b705ac601e826576298a5ce23ef1e5d417fbfdb3feb5f702f89e5f6f41
+F ext/fts5/fts5_main.c d77648a52b8d73d13887306149912e420f7e0b2d7b3d7da2f54152bfa140ac02
+F ext/fts5/fts5_storage.c 58ba71e6cd3d43a5735815e7956ee167babb4d2cbfe206905174792af4d09d75
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
-F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
-F ext/fts5/fts5_test_tok.c 80de1a4b1a3caa216c3be8862440f0117a8357dd9b7cfc5a2a2ce11fe6eb64ae
-F ext/fts5/fts5_tokenize.c ebd13d034f3dc7c841e1c32c364a4fca5cc2e05a0b91682a93fa1e6defcd4292
-F ext/fts5/fts5_unicode2.c 543cf0987c27ad59e5a7a6222480b917b5431009b7b139027c9581a63e39e37e
-F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
-F ext/fts5/fts5_vocab.c fbe38044889b2d2d99babeeef239c620fb0332bb928a84506ac748d81500b354
+F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
+F ext/fts5/fts5_test_tok.c a2bed8edb25f6432e8cdb62aad5916935c19dba8dac2b8324950cfff397e25ff
+F ext/fts5/fts5_tokenize.c 5e251efb0f1af99a25ed50010ba6b1ad1250aca5921af1988fdcabe5ebc3cb43
+F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
+F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
+F ext/fts5/fts5_vocab.c 7a071833064dc8bca236c3c323e56aac36f583aa2c46ce916d52e31ce87462c9
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
-F ext/fts5/test/fts5aa.test 840081efaee97f5ec570146bbdd79cfdfaea0ab303de3d5037b6d6c78b42ccdd
+F ext/fts5/test/fts5aa.test 5bd43427b7d08ce2e19c488a26534be450538b9232d4d5305049e8de236e9aa9
F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18ca9385880bb7
F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
@@ -136,33 +140,35 @@ F ext/fts5/test/fts5ae.test 1142d16d9cc193894dc13cc8f9c7a8a21411ac61b5567a878514
F ext/fts5/test/fts5af.test 724247405b13f8f06cc6ce464dc4f152dc5dd4e86b12c2099685d8f19747bf7b
F ext/fts5/test/fts5ag.test 7816f25a0707578f08145ab539fc0ca025f8951e788b28a6a18a06b2099469dd
F ext/fts5/test/fts5ah.test 27b5a33bfd0363ca8a4dc659e6e2a5df3dea1c3c5b04bc51ca6aeb1277bd9b21
-F ext/fts5/test/fts5ai.test d837c42249c0d8ad1a2912270e22cf2f303790a611f85c0be3a58e42a3696e3d
+F ext/fts5/test/fts5ai.test bc97e4758cc93e06bf851d61c98fdf4e8b8f8315ee28a84fb15f916360856414
F ext/fts5/test/fts5aj.test 745020852d85f5dd49d11cb7ad11d3cc6dafc4fe6d6d24bc0875ac8f43ee4149
-F ext/fts5/test/fts5ak.test 0d41cbf04e70249c84670e1782aa8972e4f67d91c9bc6205d0ba7c34e159481b
+F ext/fts5/test/fts5ak.test fc3595f8e6873bb86d70c9bd4b67d0413ce577bd4793c39a2b60a7b8825b60a6
F ext/fts5/test/fts5al.test 00c4c1c6a1366b73aa48ce2068c634520867c3cf7f5d1676ebbb775ee1f35734
F ext/fts5/test/fts5alter.test 5565f7e4605512b69171ac18ca84398603f9f6456dbe377beeca97e83cc242cd
F ext/fts5/test/fts5auto.test 78989e6527ce69c9eddbef7392fea5c10b0010cd2b2ae68eec7bc869c471e691
-F ext/fts5/test/fts5aux.test 8e7f9c96f8570f48402f2fd7b74e1ccfadd319fa56ef677321880000f9739846
+F ext/fts5/test/fts5aux.test ebf6f2ff7cb556e83f66991b7f12bff016d3c83d4eab36704b649dd6b1437318
F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f24137eb1fc079e7611
F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
F ext/fts5/test/fts5cat.test daba0b80659460b0cb60bd1f40b402478a761fe7ea414c3c94c2be25568cc33a
-F ext/fts5/test/fts5colset.test a30473451321bbf0b6218af62e96b4ae5fa99931cfdb210b5ecc804623b30f75
+F ext/fts5/test/fts5circref.test f880dfd0d99f6fb73b88ccacb0927d18e833672fd906cc47d6b4e529419eaa62
+F ext/fts5/test/fts5colset.test 7031ce84fb4d312df5a99fc4e7b324e660ccb513c97eccdef469bfd52d3d0f8f
F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482
F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d
F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4
-F ext/fts5/test/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116
+F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
-F ext/fts5/test/fts5corrupt3.test ff9aee403611461e2619d2217c0d7d101a9c0179277c13c8a89516d7cf0dda43
-F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775
+F ext/fts5/test/fts5corrupt3.test 1cad09897fc69084a904c921dee7f777e1c866964ee2ec2cc7a8a69cc3f1ab68
+F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
+F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
F ext/fts5/test/fts5doclist.test e39a6001495f1dc68e20323586ac965787986c2bf6f515b9b0285627b089d9e6
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
-F ext/fts5/test/fts5eb.test e5fe57b4141db456f06094afca45541fb0c13b30032eccae05100b4dbec11955
+F ext/fts5/test/fts5eb.test 239bb2f02571f8cccfc7018d08f502df1cd8cc6a69b65ed1dde5f6a070e3f669
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344
F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
@@ -173,81 +179,89 @@ F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd1640
F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2
F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
-F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e
-F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
+F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05cf54f5b045b729ab5
+F ext/fts5/test/fts5faultD.test e7ed7895abfe6bc98a5e853826f6b74956e7ba7f594f1860bbf9e504b9647996
+F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e4710c77eb8ce7075
F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
-F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2
+F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
-F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
-F ext/fts5/test/fts5integrity.test 4317561cd25eca7df16aa1f7d1a700ee958059fa639785f94aba0a84df9ab17b
+F ext/fts5/test/fts5hash.test dc7bc7e0cdeb42cfce31294ad2f8fcf43192bfd0145bb7f3ecc5465d8c72696f
+F ext/fts5/test/fts5integrity.test e387b2bd1c83e50f4a12f58a5fd399111bbab36be2f1c9fd5bb974be08a32de6
+F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
-F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35
+F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
+F ext/fts5/test/fts5misc.test 088ac5f0f5de1ad45b0f83197ab5263bcae8130156cdc901bff2375ff2b8af86
+F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
-F ext/fts5/test/fts5plan.test 00dc4c974938b509db7cb3680407f068ee6e9cc824f492f68cb741a7b679fe41
+F ext/fts5/test/fts5plan.test 79d35b5e83bbdcba48d946a7f008df161f6b0ede1a966892d0aa6c8dd0b6e773
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
+F ext/fts5/test/fts5prefix2.test 3847ce46f70b82d61c6095103a9d7c53f2952c40a4704157bc079c04d9c8b18b
F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728
-F ext/fts5/test/fts5rank.test ca5000241924ecc2882db33c60f4f3a62b1ee6b16b5a9c8c6ddd9b6b2138489c
+F ext/fts5/test/fts5rank.test c9fd4a1e36b4fa92d572ec13d846469b97da249d1c2f7fd3ee7e017ce46f2416
F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415
F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6
-F ext/fts5/test/fts5simple.test 313ad28ef38ebe25f0a1673dd18f2fac446e25feb15bbb0c223a65ea00594f72
+F ext/fts5/test/fts5savepoint.test fc02929f238d02a22df4172625704e029f7c1e0e92e332d654375690f8e6e43f
+F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb
F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947ec60b6fadbc4b3fb17a
-F ext/fts5/test/fts5tok1.test ce6551e41ff56f30b69963577324624733bed0d1753589f06120d664d9cd45c9
+F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
-F ext/fts5/test/fts5tokenizer.test 6aeb5e8061ffc0ff9a5299f27beaee3b2b4b8b336d4f107262bca338bea8f8e9
+F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
+F ext/fts5/test/fts5trigram.test e2ce256fd0ccd6707e740aa3596206aedb0d5834b100c0cb49e344dcd1d8463c
+F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
-F ext/fts5/test/fts5unicode3.test c3caecbe8264629ffe653b43ca5790b9793eba4422f92203e5247558e5a534e7
+F ext/fts5/test/fts5unicode3.test 590c72e18195bda2446133f9d82d04a4e89d094bba58c75ae10f4afc6faa0744
F ext/fts5/test/fts5unicode4.test 6463301d669f963c83988017aa354108be0b947d325aef58d3abddf27147b687
F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
-F ext/fts5/test/fts5update.test 0737876e20e97a6a6abf45de19fc99315727bcee6a83fadcada1cc080b9aa8f0
+F ext/fts5/test/fts5update.test b8affd796e45c94a4d19ad5c26606ea06065a0f162a9562d9f005b5a80ccf0bc
F ext/fts5/test/fts5version.test c8f2cc105f0abf0224965f93e584633dee3e06c91478bc67e468f7cfdf97fd6a
-F ext/fts5/test/fts5vocab.test 2de834ee6405130d3373817ced8fefbfee392b63d932e471740e09829f1e4510
-F ext/fts5/test/fts5vocab2.test d6039b20118e886113fc63614d9ad39a466fc2af34184f3e915b9f92b7ebfa10
+F ext/fts5/test/fts5vocab.test 7ed80d9af1ddaaa1637da05e406327b5aac250848bc604c1c1cc667908b87760
+F ext/fts5/test/fts5vocab2.test e0fdc3a3095f6eda68ac9bf9a443ff929a124d46f00af19933604085712e9d47
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
-F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
+F ext/fts5/tool/fts5txt2db.tcl c0d43c8590656f8240e622b00957b3a0facc49482411a9fdc2870b45c0c82f9f
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
-F ext/icu/README.txt a295e91db742b153e8dce8f7efd31d28ad1eea4df31ef4daa3eedc85be2f5138
-F ext/icu/icu.c c2c7592574c08cd1270d909b8fb8797f6ea1f49e931e71dbcc25506b9b224580
-F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
-F ext/lsm1/Makefile 98b0a24b45e248283d6bea4b6cb3e58d7b394edd8e96a0ac28c5fa5104813bad
+F ext/icu/README.txt 1c48ffaf7f255bd73d00a35f68f6de357c2a6594f16cb00506a151be23694706
+F ext/icu/icu.c 91c021c7e3e8bbba286960810fa303295c622e323567b2e6def4ce58e4466e60
+F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
+F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9
F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86
F ext/lsm1/lsm-test/lsmtest.h cf58528ffe0cfe535e91b44584e2ec5fb1caacdabecef0d8dcf83bf83168bf28
-F ext/lsm1/lsm-test/lsmtest1.c ae6ba48a0851b39be69a7d0eb220bfb9521a526e926223d5014bd385df10abb3
+F ext/lsm1/lsm-test/lsmtest1.c 54374fe88cee888c52c31160013c26184288f47a45b23d4d85390aa539733aab
F ext/lsm1/lsm-test/lsmtest2.c 188b09aec776516aeedcfd13b9c6faf85ba16b3671a0897a2c740ee00a5dc4f8
F ext/lsm1/lsm-test/lsmtest3.c 9ab87528a36dbf4a61d7c8ad954f5ee368c0878c127b84b942b2e2abe522de26
F ext/lsm1/lsm-test/lsmtest4.c d258d6a245db5d8eaede096e2368d23f859c5e92c80ab9122463f708514fe10c
F ext/lsm1/lsm-test/lsmtest5.c 8d5242a0f870d65eeada191c8945781fed9cb8ece3886573790ebd373b62dac5
F ext/lsm1/lsm-test/lsmtest6.c 869cb4a172cd07d1a75b3aeaecd61d0a477787b3b8668bad0d3ff0f43b642b7c
F ext/lsm1/lsm-test/lsmtest7.c 7a917455a0f956a8ed3f44f5c9387ec0ea6627714874464cc3fa5c5a9cabb2f2
-F ext/lsm1/lsm-test/lsmtest8.c 589b68c44531a0f04d5e879bb1e211be5f7100f48eed7e8631e07ed5cbd68f94
-F ext/lsm1/lsm-test/lsmtest9.c dd1a0ebf41134933a744d1e00e60429a2a21fc50d587ae7dd6bdb6e96d805bdc
-F ext/lsm1/lsm-test/lsmtest_bt.c d70d9a9be5eef9360af1251dd083948d74fd30137a08f61bef995f7ac04e037f
+F ext/lsm1/lsm-test/lsmtest8.c 773f226163d0f0d62701e3764d0c35fd4365faca74098bd63648bc57d6f14402
+F ext/lsm1/lsm-test/lsmtest9.c 0a168757b757b106191acf43143dbbb5b2d76e57a3c8fd3018cecbaee1080aba
+F ext/lsm1/lsm-test/lsmtest_bt.c 79b24bfd37e05fd626c35ec23bc5bb62d8a403afd66c710335384884dc1366d7
F ext/lsm1/lsm-test/lsmtest_datasource.c 5d770be191d0ca51315926723009b2c25c0b4b8136840494ef710ac324aa916c
F ext/lsm1/lsm-test/lsmtest_func.c 159aa401bc8032bfa3d8cf2977bd687abebab880255895a5eb45770d626fa38d
F ext/lsm1/lsm-test/lsmtest_io.c cf11b27b129c6bd5818fa1d440176502dc27229f0db892b4479118d61993ea20
F ext/lsm1/lsm-test/lsmtest_main.c a9bc647738c0dcaebf205d6d194b3ce4a6ef3925801cd2d919f0a4ea33a15aeb
F ext/lsm1/lsm-test/lsmtest_mem.c 4e63c764345ab1df59d4f13a77980c6f3643798210b10d6cdbd785b4b888fda5
-F ext/lsm1/lsm-test/lsmtest_tdb.c 618a8619183fda4f5540fcde15f9068293c5e3180e1a246e34409b0c148758b3
+F ext/lsm1/lsm-test/lsmtest_tdb.c 754b1ca8e1cfa7b29cbe2e4ab500f7eee0059033741b8d83267afe6f495a536d
F ext/lsm1/lsm-test/lsmtest_tdb.h 8733eee249b12956a9df8322994b43d19bd8c02ad2e8b0bb5164db4d6ccc1735
-F ext/lsm1/lsm-test/lsmtest_tdb2.cc 99ea7f2dd9c7536c8fb9bdd329e4cfeb76899f3ddf6f48bdd3926e016922b715
+F ext/lsm1/lsm-test/lsmtest_tdb2.cc aebe50f2cb7a759214241938046fe5f00da66e4217637f946f436ca209776af9
F ext/lsm1/lsm-test/lsmtest_tdb3.c 7a7ccae189f5bb25bcd1ec3bbd740529706eded7f6729a5a0a9eeaeb57785320
-F ext/lsm1/lsm-test/lsmtest_tdb4.c 47e8bb5eba266472d690fb8264f1855ebdba0ae5a0e541e35fcda61ebf1d277f
+F ext/lsm1/lsm-test/lsmtest_tdb4.c cbe230727b9413d244062943371af1421ace472ccb023b75af6540e0fa52b1bb
F ext/lsm1/lsm-test/lsmtest_util.c 241622db5a332a09c8e6e7606b617d288a37b557f7d3bce0bb97809f67cc2806
F ext/lsm1/lsm-test/lsmtest_win32.c 0e0a224674c4d3170631c41b026b56c7e1672b151f5261e1b4cc19068641da2d
F ext/lsm1/lsm.h 0f6f64ff071471cb87bf98beb8386566f30ea001
@@ -262,58 +276,70 @@ F ext/lsm1/lsm_shared.c 76adfc1ed9ffebaf92746dde4b370ccc48143ca8b05b563816eadd2a
F ext/lsm1/lsm_sorted.c 6f7d8cf7a7d3d3f1ab5d9ba6347e8f39f3d73c00ec48afcd0c4bcbefd806f9b8
F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82
F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
-F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b
+F ext/lsm1/lsm_unix.c 11e0a5c19d754a4e1d93dfad06de8cc201f10f886b8e61a4c599ed34e334fc24
F ext/lsm1/lsm_varint.c 43f954af668a66c7928b81597c14d6ad4be9fedbc276bbd80f52fa28a02fdb62
-F ext/lsm1/lsm_vtab.c 529255dc704289001b225d97e57e0cfa14b29c3f281c7349cfa8fdb655de79ae
+F ext/lsm1/lsm_vtab.c 169bfe7ef8e6c9de9c77e17c4c50c9ae55fb0167d80be3d1be82c991184b6f35
F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c
F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82
-F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422
+F ext/lsm1/test/lsm1_simple.test a04d08e8661ae6fc53786c67f0bd102c6692f003e859dde03ed9ac3f12e066e5
F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0
F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
-F ext/misc/amatch.c c0a6a807a553eaa220bf69fca0353cd1587a3bfb3d2224fa425e3e6efcacc98a
+F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
-F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7
-F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2
-F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
-F ext/misc/closure.c 9f8fa11aa6c6e2f6d7296ffa88f103df4b46abd9602bcab3ea2f8fc24f334f63
-F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f
-F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
-F ext/misc/csv.c 88333dc9f7dcf6a8148406f10ae04261e24e3b4c721550ae33e9e71f1265c1f1
-F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a
-F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
-F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f
-F ext/misc/fileio.c e3153b04433897a18a3d17185845f286892e96fdf87f4301290d09c36ae1759f
-F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
-F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
-F ext/misc/json1.c 3f017d2659e531d021d015ec5d69ea0b1c71f2e15bf9768b1e149fcdf6c3e0b1
-F ext/misc/memstat.c 941928c6104d8ed569a6c47caa756dc78b8091f7a15f87d3004f3b1e576b10da
+F ext/misc/appendvfs.c bdc9de0a0e61c21327e975da178b4fd6f57de9c46123044aa6ee3a20798c5db2
+F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
+F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
+F ext/misc/carray.c b75a0f207391038bf1540d3372f482a95c3613511c7c474db51ede1196321c7c
+F ext/misc/carray.h de74ac70b2338f416723f7d538026e8ec0b7f1d388319f8f140c9a4d7677f02e
+F ext/misc/cksumvfs.c 8dc4e1b718e374bed3a9b5c0a08da2922438002e33267311697768e06217b983
+F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
+F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
+F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
+F ext/misc/csv.c 53b3338d4fa812eda51a2637df30233a4dae16b964ee5666e2051b9672ed8bb4
+F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf93940
+F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
+F ext/misc/decimal.c 3ddbf8162015be4d5ec2395dee4538f1e638bb517174bb148274b132df6e1d08
+F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
+F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
+F ext/misc/fileio.c 9b69e25da3b51d4a1d905a464ccb96709792ad627a742ba09215bc0d1447e7bd
+F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
+F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
+F ext/misc/ieee754.c cd6ab89f85fda8a020559b3f4d03001a8a62dd856beda5af3f558621d12be913
+F ext/misc/json1.c f31e89171f932d1821c91f10d2cb4979fc0447030030a8bce70420cd43d074c0
+F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
+F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
-F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
-F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
-F ext/misc/normalize.c b4290464f542bae7a97b43f15bd197949b833ffd668b7c313631bd5d4610212c
-F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
-F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
+F ext/misc/mmapwarm.c 347caa99915fb254e8949ec131667b7fae99e2a9ce91bd468efb6dc372d9b7a9
+F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58f34edd
+F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1ab
+F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
+F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
+F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196
+F ext/misc/regexp.c 246244c714267f303df76acf73dcf110cf2eaf076896aaaba8db6d6d21a129db
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
-F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
-F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
-F ext/misc/series.c 0c97f63378fddc9f425e82ba139b9aaf902211f24ced115c2b6ae12b425f7334
-F ext/misc/sha1.c df0a667211baa2c0612d8486acbf6331b9f8633fd4d605c17c7cccd26d59c6bd
-F ext/misc/shathree.c 22ba7ca84a433d6466a7d05dcc876910b435a715da8cc462517db9351412b8c8
+F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
+F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
+F ext/misc/series.c c6bd5d249e5199a1b55aeee4d0e6576ff3a68702fc475dbd64503a32903516c7
+F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac
+F ext/misc/shathree.c e984f31731de4cf302a0386be5fe664580f63d8204c47b9b41cc4b997745f9ec
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
-F ext/misc/spellfix.c f88ecb2c0294453ce8b7704b211f5350c41b085b38c8e056852e3a08b0f5e484
-F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
-F ext/misc/stmt.c 8a8dc4675042e4551e4afe99b8d0cc7a4a2fc1a8dacc0a9ce1b1bbff145da93d
+F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
+F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
+F ext/misc/stmt.c 35063044a388ead95557e4b84b89c1b93accc2f1c6ddea3f9710e8486a7af94a
F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
-F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
-F ext/misc/unionvtab.c acf947858054850db2d4a611bfeae072cdc6d9f517b46a993fe1f2f1ea20031e
-F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
-F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
+F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
+F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
+F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
+F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
+F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
+F ext/misc/vfslog.c 3b25c2f56ba60788db247287be6ab024b53c4afffd412b4876db563389be0d35
+F ext/misc/vfsstat.c 389ea13983d3af926504c314f06a83cc858d5adc24b40af74aaed1fece00c118
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
-F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
-F ext/misc/zipfile.c 1d731db326c40e11fc608f38132acff31619946c000e85ab8efe75bbedc2a441
+F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6b010b4546
+F ext/misc/zipfile.c e35e035bc2765b1ccdcb15f9815c2112843fcbc8f36aa071f0e5935df7072228
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
-F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
+F ext/rbu/rbu.c b880ca5cb857d6d6f52e72eb7397813058ef48c78c5402cd04ff2b6b5437f622
F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
F ext/rbu/rbu10.test 0a201c32202143f23c81c0144503da339786fc20acb7a2fda11601b65659f314
F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144
@@ -329,31 +355,36 @@ F ext/rbu/rbu9.test 0e4d985e25620d61920597e8ea69c871c9e8c1f5a0be2ae9fa70bb641d74
F ext/rbu/rbuA.test b34a90cb495682c25b5fc03a9d5e7a4fc99541c29256f25e2e2a4f6542b4f5b3
F ext/rbu/rbuB.test 52b07158824c6927b7e25554ace92a695cdebfc296ae3d308ac386984aded9bc
F ext/rbu/rbuC.test 80f1cc2fb74f44b1128fd0ed8eedab3a76fefeb72a947860e2869ef76fc8dc6b
-F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5
+F ext/rbu/rbu_common.tcl 60d904133ff843fe72cc0514e9dd2486707181e6e0fbab20979da28c48d21de9
F ext/rbu/rbucollate.test cac528a9a46318cba42e61258bb42660bbbf4fdb9a8c863de5a54ad0c658d197
F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68ffa613b4
F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41
-F ext/rbu/rbudiff.test 156957851136b63c143478518dc1bda6c832103cdbe8ac1d7cdd47edb3cbe0a3
+F ext/rbu/rbudiff.test abe895a8d479e4d33acb40e244e3d8e2cd25f55a18dfa8b9f83e13d00073f600
F ext/rbu/rbudor.test e3e8623926012f43eebe51fedf06a102df2640750d971596b052495f2536db20
+F ext/rbu/rbuexpr.test 10d0420537c3bc7666e576d72adeffe7e86cfbb00dcc30aa9ce096c042415190
F ext/rbu/rbufault.test 2d7f567b79d558f6e093c58808cab4354f8a174e3802f69e7790a9689b3c09f8
-F ext/rbu/rbufault2.test 06e735c002c17802d93debca41f59b027e7429db7de17f2a81318ecfd3c651d4
-F ext/rbu/rbufault3.test e0052ccba428ffdd2bb989d3ae84716f058ec5ab5f7196c64ba407b9d23c7255
+F ext/rbu/rbufault2.test c81327a3ac2c385b9b954db3644d4e0df93eeebfc3de9f1f29975a1e73fd3d0c
+F ext/rbu/rbufault3.test b2fcc9db5c982b869f67d1d4688d8cb515d5b92f58011fff95665f2e62cec179
F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204db2a5930a
F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d
+F ext/rbu/rbumisc.test 329986cf5dd51890c4eb906c2f960ebb773a79a64bed90f506b7c417825b37eb
F ext/rbu/rbumulti.test 5fb139058f37ddc5a113c5b93238de915b769b7792de41b44c983bc7c18cf5b9
-F ext/rbu/rbuprogress.test 04614ff8820bab9c1ec1b7dbec1edc4b45474421d4fe7abbd2a879a9c02884f9
+F ext/rbu/rbupartial.test f25df014b8dbe3c5345851fba6e66f79ab237f57dc201b2d5f0dbae658ae5a4c
+F ext/rbu/rbuprogress.test 857cf1f8166c83ef977edb9ef4fc42d80f71fbd798652b46ae2f3a7031870f8d
F ext/rbu/rburesume.test dbdc4ca504e9c76375a69e5f0d91205db967dcc509a5166ca80231f8fda49eb1
F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d1cdd926
F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8
-F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce00af9147a341
+F ext/rbu/rbutemplimit.test 05ceefa90a2e26a99f40dd48282ed63a00df5e59c1f2bfd479c143e201a1b0ba
F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534
-F ext/rbu/rbuvacuum2.test 0a7669bbabdaeed915f02f59f33fe20e13d4932ba2086fe00a82064d9424c80b
-F ext/rbu/sqlite3rbu.c 71f8c09948d09ec9c5a8dbe7127e8ef61ef0853e698b2650be2485ac7b9c75c8
-F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
-F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
+F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
+F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
+F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
+F ext/rbu/sqlite3rbu.c e6531884442b72f9e0ba47036fb5c4641ea817ff659a642b3984c10b8535b0fd
+F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
+F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/repair/checkfreelist.c 0dbae18c1b552f58d64f8969e4fb1e7f11930c60a8c2a9a8d50b7f15bdfd54bd
-F ext/repair/checkindex.c 7d28c01a2e012ac64257d230fc452b2cafb78311a91a343633d01d95220f66f3
+F ext/repair/checkindex.c 4383e4469c21e5b9ae321d0d63cec53e981af9d7a6564be6374f0eeb93dfc890
F ext/repair/sqlite3_checker.c.in 4a5a3af3f450fe503e5a2985e98516dc2a6b9ad247449e284c1cf140fc91720f
F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
@@ -361,40 +392,43 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/geopoly.c d56ff997f2646b03be742eb85e8206f779d777f3a282fe0da576780ca0e11f20
-F ext/rtree/rtree.c 7125183bf6c37b8b8ee1a04d2b0fe258531fd31650fdd050ed041817f1943d17
+F ext/rtree/geopoly.c 1b1ddecb79877b12331d35de9f393b80bbb731e0bf6db6c572f23191987ea803
+F ext/rtree/rtree.c 60f6f1675134201974be4189dbd219494c13e1ed30e80bd92ae0dcc86df1b035
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
-F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
-F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
+F ext/rtree/rtree1.test 00792b030a4e188ff1b22e8530e8aa0452bb5dd81c2b18cb004afc7dc63e040e
+F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
-F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4
+F ext/rtree/rtree6.test 1252a0439da01d2f1f5cbbdeeb80455a2d68b9bae2a9787937b167a5e3957828
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
F ext/rtree/rtreeA.test ed2f1be9c06dde0b1ab93a95dd9e87eeaa02db2d30bcb4b9179b69ee3dc3319b
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
-F ext/rtree/rtreeC.test 128928549d22b65c381ab1366760d08703cd75e34f6a7a506ece38f9330b7282
+F ext/rtree/rtreeC.test 6aa87eba4d9a3003b941a1ba77db259c5cabc3fd92fc5a6360f5369520eb9a4d
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e0184939c
-F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4cdf8d87a
+F ext/rtree/rtreeH.test 0885151ee8429242625600ae47142cca935332c70a06737f35af53a7bd7aaf90
+F ext/rtree/rtreeI.test 608e77f7fde9be5a12eae316baef640fffaafcfa90a3d67443e78123e19c4ca4
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
+F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
+F ext/rtree/rtreefuzz001.test eef1ed593bb15886cd5d5367a2f2492f81e315848896cdf7afb6e21454978827
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66
-F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
-F ext/session/changesetfuzz.c 255826ee367781ec4c29a36c7c63e9ee6387dc03a8346cf240feb8d597958b0e
+F ext/session/changeset.c 7a1e6a14c7e92d36ca177e92e88b5281acd709f3b726298dc34ec0fb58869cb5
+F ext/session/changesetfuzz.c 227076ab0ae4447d742c01ee88a564da6478bbf26b65108bf8fac9cd8b0b24aa
F ext/session/changesetfuzz1.test 2e1b90d888fbf0eea5e1bd2f1e527a48cc85f8e0ff75df1ec4e320b21f580b3a
F ext/session/session1.test 0b2f88995832ea040ae8e83a1ad4afa99c00b85c779d213da73a95ea4113233e
-F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
+F ext/session/session2.test 7f53d755d921e0baf815c4258348e0ed460dfd8a772351bca5ad3ccbb1dc786e
F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
@@ -402,33 +436,35 @@ F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26
F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b
F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
-F ext/session/sessionB.test 886252dcb7e692e62ef7e357456200912e367823
+F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
F ext/session/sessionC.test f8a5508bc059ae646e5ec9bdbca66ad24bc92fe99fda5790ac57e1f59fce2fdf
F ext/session/sessionD.test 4f91d0ca8afc4c3969c72c9f0b5ea9527e21de29039937d0d973f821e8470724
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
F ext/session/sessionG.test 3828b944cd1285f4379340fd36f8b64c464fc84df6ff3ccbc95578fd87140b9c
-F ext/session/sessionH.test a417559f29a7e775950fc5fc82b3d01256a7cbe793ddf1180df234df823d56e2
-F ext/session/session_common.tcl 29ec9910aca1e996ca1c8531b8cecabf96eb576aa53de65a8ff03d848b9a2a8b
-F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
+F ext/session/sessionH.test b17afdbd3b8f17e9bab91e235acf167cf35485db2ab2df0ea8893fbb914741a4
+F ext/session/session_common.tcl f613174665456b2d916ae8df3e5735092a1c1712f36f46840172e9a01e8cc53e
+F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3
F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181332da26f29cddd7bb
-F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b2953cf48683fb2724169
+F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25
+F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
+F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
-F ext/session/sessionwor.test 07f0b304dc4df5454906069140bf6ec67edcaa3c548f3683354003cf2c22b64a
-F ext/session/sqlite3session.c dbd6f7a89c1236d8e7b58f4e217391670ce91b9e6f85c16ba02832674ef0cf3c
-F ext/session/sqlite3session.h 05351d2f50a1203fdffbeb590fdbbc796c9a6bfcd0c9b26cf6db3854e3eb4294
-F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec
+F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
+F ext/session/sqlite3session.c a7c5ac1acfe21d94b37921b29b0458d64d022a66b282338eee4aafa9c018cb1c
+F ext/session/sqlite3session.h f48662626e7a3176a188787a0bd360933dd46cccd98df01c208b02051c540fb7
+F ext/session/test_session.c 90ccf1c30c857bd2fb3f6c990163e8f389ddbdbdc7fa5baa2f6f5f287df41c08
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
-F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648
+F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk eeaa279fa6acdcfa6555058548075569a06f891fd67f5901b1e7700d18052fda
+F main.mk c6afb1c8bcacc4c3e320ab10259879bc927f0747401e184b64e8f4b78f057ab2
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -440,90 +476,90 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c f886160da189e4e99093cd5a2aca625652cc9b027d5100b87f81c175d1056387
-F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
-F src/attach.c 92b51739a885da8bd84bc9a05485f1e48148bce5c15432f059b45af98fff75cd
-F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
-F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
+F src/alter.c 68467416a491b1111d319f653efa4c32ea7dac02a75eb8d59679626fc880a62d
+F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
+F src/attach.c 9cbe761e464025694df8e6f6ee4d9f41432c3a255ca9443ccbb4130eeb87cf72
+F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
+F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c ba7c7eef4461790f37c309936bfc5d0d6ba9b194b02d3c8ff1fd53b420ea6d3b
-F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
-F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c 127d33ad57b455a9339e9fabff41284c8b030cc6247ca7a2a6c0ad7abfc1ce85
-F src/callback.c 789bd33d188146f66c0dd8306472a72d1c05f71924b24a91caf6bd45cf9aba73
+F src/btree.c cfd2a37794532d765e235a2550ad2732924a6d06b07a3bc9f6a71750e3b3cca1
+F src/btree.h 096cc53baa58be22b02c896d1cf933c38cfc6d65f9253c1367ece8cc88a24de5
+F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
+F src/build.c 69cb3c8a65de7fdfaca1b586247a27c24cfbeabfb04fa74ae327d56a81d1f80a
+F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
-F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
-F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
-F src/dbstat.c 3c8bd4e77f0244fd2bd7cc90acf116ad2f8e82d70e536637f35ac2bc99b726f9
-F src/delete.c f7938125847e8ef485448db5fbad29acb2991381a02887dd854c1617315ab9fb
-F src/expr.c 9aacc0b72348ba90010b672dcbbbe2fa56e1182043bc917a3a147b2bc57a5497
+F src/ctime.c 2a322b9a3d75771fb4d99e0702851f4f68dda982507a0f798eefb0712969a410
+F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
+F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
+F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
+F src/delete.c 73f57a9a183532c344a3135cf8f2a5589376e39183e0b5f562d6b61b2af0f4d8
+F src/expr.c cfab1113f9eba24f1d6d11b710577c9fcc9cc8e29ed60bd7ac7906be7481dda4
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
-F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
-F src/global.c 8291eee0782b83124de14ec0389ec9fd6ae1873358a6b0d9469fe17a46ad803b
-F src/hash.c 931ec82d7e070654a8facb42549bbb3a25720171d73ba94c3d3160580d01ef1f
-F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
-F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
+F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
+F src/func.c 479f6929be027eb0210cbdde9d3529c012facf082d64a6b854a9415940761e5e
+F src/global.c ed55af196a9b66e198aaeda3f5454c3aa7d7d050c6c938181fd044b70d180a81
+F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
+F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
+F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 6b81aae27b196925d8ff78824f4bbd435d6a40cd38dc324685e21735bb402109
-F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
-F src/loadext.c 9050dd153b5583804184be9c9dee9ebb554178d6db1f8ac280899e8aad9060e6
-F src/main.c 4cfb3913cc9e65d3ac649b1785ac753fc225d29425d5437e012f7eac0cefe0eb
-F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
+F src/insert.c e36be69e3810902eaf7e171260c885bc9547b1d41616c868f1cc46e6a0a3b7fd
+F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
+F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
+F src/main.c 2a7ece3a67c646e5fe9984ffe0277d6a76f80ce9715bf2faa591d8cb66b9d913
+F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
-F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
-F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
+F src/mem2.c b93b8762ab999a29ae7751532dadf0a1ac78040308a5fb1d17fcc365171d67eb
+F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memdb.c cb4013d56fa71c79c498717cbc47b27dd1c7653fd866584b2071ae04114eec46
-F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
-F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
-F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604
-F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
+F src/memdb.c ab0632d42407e866d2b616bd19d4211ac0ad1b430f04c4e187d60005b8700b98
+F src/memjournal.c 431c70a111223a8a6e2e7e9f014afc6c88d818d357d866afc563195f2277d50e
+F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
+F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
+F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
-F src/mutex_unix.c aaf9ebc3f89df28483c52208497a99a02cc3650011422fc9d4c57e4392f7fe58
-F src/mutex_w32.c 7670d770c94bbfe8289bec9d7f1394c5a00a57c37f892aab6b6612d085255235
-F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
-F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de
+F src/mutex_unix.c dd2b3f1cc1863079bc1349ac0fec395a500090c4fe4e11ab775310a49f2f956d
+F src/mutex_w32.c caa50e1c0258ac4443f52e00fe8aaea73b6d0728bd8856bedfff822cae418541
+F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
+F src/os.c 2d6e646370b1aa78942c68d7edf124e518963adf4a90bce87f365a5a5495529a
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c f6e91b8fd82af7afbfd073c4974ad6cdb8e62d9f65ceddb45167835a0567fdc0
-F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
+F src/os_unix.c 7a9eab7b11f552ab91ead980086b312c7e3b871efdee8c0c072b682bbec6592e
+F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 75e0f3cfa3962c714f519f8a3d1e67ecca1c91de0e010a036b988e40ce9e4c73
-F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
-F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
-F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
+F src/pager.c 970691daea03f9f15e34de671bd8675c1e136232b529e21bfd36d4dba6d41753
+F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
+F src/parse.y 2107aff88e361bbf8388fdede3fed20fda875f23ba7585ec83b20e3e16a95670
+F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
-F src/pcache1.c bf9fcea656dce1cd2cca6b77a1d1d3552050d55a31c98bf0d9f405930a83bc95
-F src/pragma.c 4e056f042683b99c4ea0db395f68d051b1a95833ab40951c40d3ef7e1fee1354
-F src/pragma.h fdd03d78a7497f74a3f652909f945328480089189526841ae829ce7313d98d13
-F src/prepare.c f81f8d707e583192c28fea0b2e19385415b7d188123b23f49b038076408d7a69
-F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
+F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f
+F src/pragma.c eb42cb9bec189cf18cef5d8fcae56e13bb73ef2b019b198fb48740ced81bce95
+F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
+F src/prepare.c e21b54489b5c73b06ada15e6fc79b5c6f64b06701924a6ca98944ae59e06256f
+F src/printf.c 2b03a80d7c11bb422115dca175a18bf430e9c9dbaa0eee63b758f0c022f8f34f
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 4cfc44def0f0690ceaab8f6481f5d76284d7f9509aab6e218a679b4836a54614
-F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f
-F src/shell.c.in 482e23a370cbe5b0d4c73a0f0f5fce34f7caa08a14a8d75e12f0225c4e14915c
-F src/sqlite.h.in cce9feede1c1c03923c091b4bbbd081dd77aaf92024cc2cdbf65f712c2f668c3
+F src/resolve.c fec151c9c33a6fa2e93d10b4e8cd4084a7c773df36fb3ec6788eb89ae493a1a4
+F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
+F src/select.c 71bdd55e32850a6c7e080d5a59b7d81c0441e23d232262ee2604e798d4e97514
+F src/shell.c.in aa28256887d049badaf93aa30ab5c76a2ec88143a674d685c0e739056702e5c3
+F src/sqlite.h.in 3426a080ea1f222a73e3bd91e7eacbd30570a0117c03d42c6dde606f33e5e318
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
-F src/sqliteInt.h 1161f7579cdd6217737a66517ef27f4016426603eff492e9b31f45a7d7d4c61f
-F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
-F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
-F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
-F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6
-F src/test1.c 5390e5afb31fed61f72d0be0cb1b322d198a6e03fc13ff245ae76d17b4dcf2e9
+F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
+F src/sqliteInt.h e56aa05ef78513cd596c30a56fda68cd9bba91d444ac40e135e919fed40cd875
+F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
+F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
+F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
+F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
+F src/test1.c cff43d8e21be543b77651b4d2caf49bd6488fee220f8540ecd9f71d13169dbd1
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
-F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
+F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
-F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
+F src/test6.c ae73a3a42bbc982fb9e301b84d30bda65a307be48c6dff20aba1461e17a9b0ce
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
-F src/test8.c 3f7d0cc4e12e06832ba3db4455cb16867ccadafa602eb6ff5fcf097bffce56ed
+F src/test8.c 7fb971777c2c79c734bb52757191d68d4af659b8de9b4a071be3f527a9d19a02
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
@@ -531,153 +567,161 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
-F src/test_config.c 5ebafbcd5c75ac1c16bb0c8fe926dc325cc03e780943a88ca50e0d9a4fc4d2f5
+F src/test_config.c 98698f5242be88af75eaac54adde573471d5ed2f6484e0dac034cb1e763a551a
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
-F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
-F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
-F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
-F src/test_func.c d12d805953bcb3bb19f71d29cdc93383b7b7a3369504d2b7e398a1bd77376294
-F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
+F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
+F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
+F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480
+F src/test_func.c 181f992e5495644434c4f0e3cc72362a78c295eb2cf3ff4d02498b8bde7aa276
+F src/test_hexio.c 9478e56a0f08e07841a014a93b20e4ba2709ab56d039d1ca8020e26846aa19bd
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71
F src/test_intarray.h d57ae92f420cda25e22790dac474d60961bd0c500cbaa3338a05152d4a669ef7
-F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
+F src/test_journal.c a0b9709b2f12b1ec819eea8a1176f283bca6d688a6d4a502bd6fd79786f4e287
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
-F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
+F src/test_malloc.c 21121ea85b49ec0bdb69995847cef9036ef9beca3ce63bbb776e4ea2ecc44b97
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
-F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
+F src/test_multiplex.c 2ccf35551c094e353af20b0cdfac053a37bf3e96e10e7cf9f4abd1d279890a78
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
-F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a
+F src/test_mutex.c abf486e91bd65e2448027d4bb505e7cce6ba110e1afb9bd348d1996961cadf0d
F src/test_onefile.c f31e52e891c5fef6709b9fcef54ce660648a34172423a9cbdf4cbce3ba0049f4
-F src/test_osinst.c 98ef31ff03d55497829ca0f6c74a9f4e1aa48690
+F src/test_osinst.c d341f9d7613e007c8c3f7eba6cd307230047506aa8f97858c1fd21f5069616bd
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 6cb9297115b551f433a9ad1741817a9831abed99
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b
-F src/test_schema.c f575932cb6274d12147a77e13ea4b49d52408513
+F src/test_schema.c f5d6067dfc2f2845c4dd56df63e66ee826fb23877855c785f75cc2ca83fd0c1b
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
-F src/test_sqllog.c 11e6ce7575f489155c604ac4b439f2ac1d3d5aef
+F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
-F src/test_tclsh.c 06317648b0d85a85fd823f7973b55535c59a3156c1ef59394fe511f932cfa78d
+F src/test_tclsh.c eeafce33ad2136d57e5dec10f1e9a4347447eb72ffd504a1c7b9c6bfe2e71578
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
-F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
-F src/test_vfs.c 112f1f9271c33c211812e0e681830a84262dac065da58579ff49f9cefec97d4f
+F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c
+F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43
+F src/test_vfs.c 2cc38a79892017702d13da79ad5152c196eec19bbd67fbde4d88065aac894a84
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
-F src/tokenize.c 9e781e1ca80eefe7b5d6a9e2cd5c678c847da55fd6f093781fad7950934d4c83
-F src/treeview.c 7b12ac059de54c939b6eb0dbffc9410c29c80d2470cee5cbe07d5ff9ea2d9253
-F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
-F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
-F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
-F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
-F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
-F src/vacuum.c 836cadc922de866c849e23a75f93d344cdc143d388339305d09a3fed27e8798d
-F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
-F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
-F src/vdbeInt.h 437e6c6af679fdf157867eb83a8adc6cf5145d6774453c2214cfd0bd01d92980
-F src/vdbeapi.c ecccfce6f614c33a95952efeec969d163e8349eac314ee2b7b163eda921b5eb0
-F src/vdbeaux.c f547901b1aa9e2d81c63f06893f633648e434180666a827aacb547d7d6c8a601
-F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
-F src/vdbemem.c 7b3305bc4a5139f4536ac9b5f61da0f915e49d2e3fdfa87dfdfa9d7aba8bc1e9
-F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
-F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
-F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
+F src/tokenize.c 0b9c82fa628b5adce93e2bcaf935a24d43eb83344fb51551f7835526d0693fc4
+F src/treeview.c c6260e1fa5f41c361b2409edc9b0050bcaef5bc4d6abc467fbc45f0d7ccf3d84
+F src/trigger.c bce0908f714a5b89360c01e444521a648997425e2a91ff9b92b899cf8d53c20b
+F src/update.c 837d782fa99a69021f97516a626b76206fe68677ce050643f64a54f70c1d4391
+F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
+F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
+F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
+F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
+F src/vdbe.c 5001a0d3003d3664615dd7ac3cedab1d51e2391b5bdd0878f40a41fdcd942e13
+F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
+F src/vdbeInt.h 000d9ab1ea4cb55a80de15e28f3f595645b4fddef34bca4347fb3db8031d9041
+F src/vdbeapi.c 4a43e303ec3354c785f453e881521969378e85628278ab74ba4a9df790c0d93b
+F src/vdbeaux.c 1b3eaa3a70d9d1877266e8ade0d0c3b2b4c6cf77d393d94dbcbd522b9bfefc15
+F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
+F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
+F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
+F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724
+F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
+F src/vtab.c 032a0165c147fda16927e6a3230e90c068d4af93f887ce94e26f678fe48e5e4c
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
-F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
-F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
-F src/where.c 3818e8a736a05d2cb194e64399af707e367fbcc5c251d785804d02eaf121288e
-F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
-F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5
-F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c
-F src/window.c 6550e2850ebced51100ef83d49b00a1cf03f81a482dafedafb0320df647ed8fc
+F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
+F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
+F src/walker.c d42d6c80ea363ef689a462e65eefcfe87deab924c50de5baa37ecb6af7d7ddaa
+F src/where.c 10d06b16670a1d2a992d52a9f08e49426d38a08fb0a7ae5f7f62fd023d560e1e
+F src/whereInt.h 446e5e8018f83358ef917cf32d8e6a86dc8430113d0b17e720f1839d3faa44c4
+F src/wherecode.c e57a8690311a75d06e723e8d379f9831de04aba300e07174d236e32a7f9c7a13
+F src/whereexpr.c d8cafcf6781cf871082f04d7540862cf0fe30cb381dd1b2145a380376364fe8e
+F src/window.c 32b03808aff2e7263889cce0cbcb2a68efefc2a9d5187514ddb6a2a1046dc7f5
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
-F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
-F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
+F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
+F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
-F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1
+F test/aggnested.test 2f65ec8132e0ca896de550b9908094d49ad65a99116a9d79deeb6017604ad4f6
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
-F test/alter.test 93dee7c0ff9106fbd53a8bbf519107904b884050a99c4565412c58c37d68c802
+F test/alter.test f53d8a4ecd35f051c07e54a36beec5d0a30d30a9d98bc723f6cde6afbfb3c5ca
F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687
-F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
-F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433
+F test/alter3.test e487958dec7932453e0b83baf21d6b1e71d5e7d9a55bc20eadfa62a51ddffc29
+F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f08cf
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
-F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499
-F test/altercol.test 313ed080ed61691c52cd87053129889f71582d6d0efebdd5f3edad2a98c66874
-F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
+F test/alterauth2.test 794ac5cef251819fe364b4fe20f12f86e9c5d68070513c7fd26c17cb244c89af
+F test/altercol.test 3456f7cc4196ef8f7d82d245d6e91940eb12bc95c36c91ac4b512f6b5c9a4fa9
+F test/altercorrupt.test 584d707a80e106952d6382790c8919bcf9f0db678ed3a1c09fd98b7f9d1d3a10
+F test/alterdropcol.test 7c5199c930d3db8621672265db0cc05bfa87867bae1ee5362f3cf4eaf36c06ba
+F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
+F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
-F test/altertab.test 17e46baa6b2234048c91891a303141afceca4da95a36ee1a0a9fec6ccef1f4da
-F test/altertab2.test 0d64de5632ca5de13b023839cfe5b8952d029e4622befcea1433adaa93883220
+F test/altermalloc3.test 2c7bbd8cf3e9c4a91e28675bb62bcc2ef70f227967fa74349f03d9f4642f0615
+F test/altertab.test 7691872aadfe00a94b459af9086504bcf399dd936336e486da1b182930744b77
+F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
+F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
-F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c
-F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
+F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
+F test/analyze3.test fca2a9de0017becfdcc201647f03b1cfd5ba0e7b5b5c852936e4ec62780cde49
F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e
-F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
-F test/analyze6.test 7b2667b879976ac4b90d8df80d5456328684f1f6f6fdef9469d6e53401f2f469
-F test/analyze7.test a37f4d9cb699a8af068ae02df1bb08bf844df8e98a92a8126cbff89e226879d8
-F test/analyze8.test e32a970564271114786703750e6939cf81dea4b8580874e38e9213ee092f6936
+F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
+F test/analyze6.test 6c3f7df2996cb6872f355a6ac1eb6d5de00a5a9288214bad7ef25c97d9cc72dc
+F test/analyze7.test 6ef0b12369f61ddeadc7d8a705c40e6b52cb29f63de3a4c56581b510b46b5783
+F test/analyze8.test 36ce54947710bd44e4f9484e1ad07e725ef01a9d7078b417c1bc884356febe4d
F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54
-F test/analyzeA.test 22a892d67bd2223126335b99774cce56ba91122cfe82446d2927afc43ad667dc
-F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70
-F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
+F test/analyzeC.test 489fe2ea3be3f17548e8dd895f1b41c9669b52de1b0861f5bffe6eec46eac710
F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb
+F test/analyzeG.test a48c0f324dd14de9a40d52abe5ca2637f682b9a791d2523dd619f6efa14e345b
F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
-F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
+F test/atof1.test 10049623e77006691c4c2978c1dc8a3f75276377a53417811aa85bda7493f963
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
-F test/atrc.c ec92d56d8fbed9eb3e11aaf1ab98cf7dd59e69dae31f128013f1d97e54e7dfed
-F test/attach.test 21bce8681f780a8d631a5ec7ecd0d849bfe84611257b038ae4ffeccc609d8a4e
+F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
+F test/attach.test 54f8e49e88d0de48f6428267a678465863d2b8f72320612f35bd5c02e240bc2f
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
-F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
+F test/attach4.test aa05b1d8218b24eba5a7cccf4f224f514ba57ba705c9267f09d2bb63fed0eea1
F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438
-F test/auth.test 3310d9c08e928beca42d3eadaaf53cef619d9d275f598565a3758a21ce63138e
+F test/auth.test 2154625c05bc79f0e0ea72cb2358395a8041243caa0fd7ce7617d50da4331794
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
-F test/autoinc.test 381f494fefa90acd999933829e2934efb6b40906db9d6a39e822e3f7b4c8bf61
-F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0
+F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39
+F test/autoindex1.test 96185415f5faacd5b8d7a7f505efddd5abb1f111d58338e9c0b1dc40b87cd3cc
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
-F test/autoindex5.test 4a0eb6c7c7ae456d97a2061d4c8d6380946272c5c91d91507c1feb1af3dc7cce
+F test/autoindex5.test a5d72fe8c217cc0ea356dc6fa06a282a8a3fc53aa807709d79dba07a8f248102
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
+F test/avfs.test 0c3a38e03cccb0fc3127838462dc05dc3f4c1480d770c084b388304c25de3652
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
-F test/backup2.test 1fd1ad8c5b3d2d5b9c0cce4143a4fc610d51ddc6ae16a7a122973d43e6b50bbd
+F test/backup2.test 8facb54df1388419d34b362ab1f7e233310ff3a3af64e8ad5ec47ba3c2bbe5cf
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
-F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
+F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
-F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a
+F test/bestindex1.test 705b57d7f51d53ee5fd043dd9666236e1fc18f4d59abf51da0ea5ea1b4804947
F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
-F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
+F test/bestindex3.test 7622e792ff2da16d262d3cea6ad914591ac4806d57ed128e6c940b7920b47b84
F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601
F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
-F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
+F test/bestindex7.test f36ada201973d3022cf7afffffe08de9e58341996020e7a2df9a1d2f2be20132
+F test/between.test 68137a6e941c221417c15b6fe2d55f27bb1b6ab48bdf9e2aa51efdd85bc53802
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
-F test/bigmmap.test 31dad31573638bd32de866cdefd11843f75685be4ba6aec1a47918f098f1899b
+F test/bigmmap.test e906cf9729d7c362270ffe9fa6471f4c39c28ba83f0f77fb795e1b4d38a22ba0
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
@@ -693,9 +737,10 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
-F test/btree02.test a0f33669ba76632247c14718af32db939fa6de5cd13890798ad3f2a362cf7fe4
+F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1d6cc
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
+F test/busy2.test 0a1633fef7987fc8ea25ed5838f7eef2f08fc6d2a3dcc77d23e6402e53946a7a
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
@@ -703,15 +748,18 @@ F test/capi2.test 34a1a9a96d543a2ec2c209696b11b164444f57253b1f2cba1c2e53fadede6c
F test/capi3.test 3910a73c38ac76d69778dd9eb481ab7cd6ed59117fc047b4f6056a5c72529de1
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e44b
-F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
+F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bccc4
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
-F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857
+F test/carray01.test 3f2658bbddd75a013735a296ae2178ff441aca3f00ba623cfbae00b732ede792
+F test/cast.test 336fa21989b5170ebcaf90c24266be22dd97b3e23d1fad5ecf6ad4efb04c4423
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
-F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a
-F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8
+F test/check.test 4a2a91ed67eee84a6be16057c48d5198b6fb24849cd6da6cd855981de3fbb416
+F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
+F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
+F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
-F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846
+F test/collate1.test 532b4992f78e91dd80c2e3c7bd944fada8cbe3d6c0ded0b20f7182b4dfca0006
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5
F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd
@@ -723,14 +771,15 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
-F test/colname.test fb28b3687e03625425bc216edf8b186ce974aa71008e2aa1f426a7dcb75a601d
-F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db
-F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
-F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9
+F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e
+F test/columncount.test eff33d402a7b0fde0a52a1920d238af200ca573327021e0ce3b7e5688de41449
+F test/conflict.test ac0667090f66130ac77d5fb764655558ca6600dd6d88f670ca9123b61c448337
+F test/conflict2.test 5557909ce683b1073982f5d1b61dfb1d41e369533bfdaf003180c5bc87282dd1
+F test/conflict3.test 81865d9599609aca394fb3b9cd5f561d4729ea5b176bece3644f6ecb540f88ac
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
-F test/corrupt2.test a7f95356d19a4e8bf9423622ad865cabf48ae49dad40eb7a17a0b39f1cdd6948
-F test/corrupt3.test f95d7bf78109e0b84eb285a787ce91a3fd6a2dd7d0cb55882abff3bdc081a57e
+F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35
+F test/corrupt3.test 2520432b1fbf99994841e69804a3c59fb828183f4d09b85a1631bc7adca17e31
F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a
F test/corrupt5.test 387be3250795e2a86e6234745558b80efb248a357d0cd8e53bce75c7463f545d
F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
@@ -739,111 +788,124 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
F test/corruptA.test 112f4b2ae0b95ebf3ea63718642fb969a93acea557ace3a307234d19c245989b
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
-F test/corruptC.test 138ecb02188ed1a719b533d4a139568204039f72f00e07a8d30d920bd83122db
-F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
-F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62
+F test/corruptC.test 74d4498fd25759618b393f1e9cde111de828b88c1848ab320f6c179fd52b5a60
+F test/corruptD.test 33a37ce3ed56a20093ceee778cd2d7109c7085a59f3213d2baede11d952e8e50
+F test/corruptE.test 4143791f2dfb443aec5b7fabfa5821e6063eccc3b49b06f212c2f014715fd476
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
-F test/corruptK.test 5ef338c560ca4dfb7360828da16f1829be4deba3b378cafdc7a1cdaf027eb5c4
-F test/cost.test b37db8a10d467a69e71a9f3d40bbb266c2f587742b37c6912f6e3f7185a0e216
-F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
-F test/countofview.test e3d4cd6900e4e4f074968ab24b8b87d3671cd624961bef40fd3a6b8f574343cf
+F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
+F test/corruptL.test 22589f503602cc5984e80f27f46c4de2134f24f1515ba2440513c377cb692258
+F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
+F test/corruptN.test 781c5f26a2d8918f03d45ac4968a738031eeb113a4b153c7588756d9b09c7b04
+F test/cost.test 1d156ce9858780a966c062694687afe0343a0ed12d081d071fb57027e726bafc
+F test/count.test e0699a15712bc2a4679d60e408921c2cce7f6365a30340e790c98e0f334a9c77
+F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
-F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae
+F test/crash5.test 4aa55e7ac3c4bc511873e457aa65d2827d52da9b51e061511899dadcfe22b1e8
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
-F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
-F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
-F test/csv01.test 4a92840619ef435b905e6d3f35cd0644df23225d7b7967d7940b40f06d6a90a6
+F test/createtab.test 85cdfdae5c3de331cd888d6c66e1aba575b47c2e3c3cc4a1d6f54140699f5165
+F test/cse.test 00b3aea44b16828833c94fbe92475fd6977583fcb064ae0bc590986812b38d0c
+F test/csv01.test c9c3af0d58c34e9ac970c5875a77939edb958762c8aafb95409e19a3f088b6cd
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
-F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
+F test/cursorhint.test 0175e4404181ace3ceca8b114eb0a98eae600d565aa4e2705abbe6614c7fe201
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
-F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
+F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
+F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
+F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
-F test/dbfuzz2.c 652f85bac1770e927da139db513234a3eba308f72ac2f8b32f0093d7d19def70
+F test/dbfuzz2.c db2a1710c0d30d38e1352ee1b52b717fcb224c8caacc6f10909ef540f73cc9e8
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
-F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e
+F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
-F test/default.test 3e46c421eebefd2787c2f96673efabf792d360f3a1d5073918cbe450ce672a62
+F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
+F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
-F test/delete4.test 21d2113217eeaacac2d99defe14fe6611615ae86
+F test/delete4.test 6aa279f459f4aa792cc251435c3809415c1ecaf9f27dce91675e26f05b503db3
F test/delete_db.test 096d828493c7907f9ea11a7098ea6a0f73edba89406487d5d6cc2228dc4ab8b0
-F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
-F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
-F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
+F test/descidx1.test edc8adee58d491b06c7157c50364eaf1c3605c9c19f8093cb1ea2b6184f3ac13
+F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad78298
+F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
-F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c
-F test/distinct2.test df0bb52b754661ea84ec9ff488d48913c97bd31d83ca17ce0bf1334645e660cf
+F test/distinct.test e7d0cf371944dd0cbedff86420744e2f1ea2b528156451c97eb6ff41a99b9236
+F test/distinct2.test cd1d15a4a2abf579298f7161e821ed50c0119136fe0424db85c52cf0adc230d1
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145
F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
-F test/e_createtable.test 1c602347e73ab80b11b9fa083f47155861aaafcff8054aac9e0b76d0df33b0a7
+F test/e_createtable.test 7107f5deda2324ea12dbf105044dc9265195401e9dbb3eead6a2c1a3da4bb5b7
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
-F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
-F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
-F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
-F test/e_fkey.test 2febb2084aef9b0186782421c07bc9d377abf067c9cb4efd49d9647ae31f5afe
+F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
+F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
+F test/e_expr.test 6ba7a51ece7b3e7fc145f14f924eed25ebb5a24e7b8596c78f3838d372cf0385
+F test/e_fkey.test a2907f749cccd0b2c30d8576b673002eebdcc1fc9964bae61e5117b1d54733e2
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
-F test/e_select.test c5a669b4d63217aa10094ba737ba3ddd07bd439d4bc7a5b798f6ea32511cbe7c
+F test/e_select.test f9474205669a7736ef725b29cc7ae9e8601919a3d0ffc0ab30745a028f2a4b61
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
F test/e_uri.test 47eeb2960e74613f0f8722b2f13aef08fde69daa16e5380ac93df84dac8b1f72
-F test/e_vacuum.test 1b8b4772d05374aa1b8958669138bbb4213ee26a
+F test/e_vacuum.test 0d8832a2ce92350db0d0cff47b419465fd9772562e1f77ff7d9478c07a4980d2
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
F test/e_walhook.test 01b494287ba9e60b70f6ebf3c6c62e0ffe01788e344a4846b08e5de0b344cb66
F test/emptytable.test a38110becbdfa6325cd65cb588dca658cd885f62
-F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
-F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
+F test/enc.test 9a7be5479da985381d740b15f432800f65e2c87029ee57a318f42cb2eb43763a
+F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test fc00ad1a7f5b90bf1bbccbf877ae9abef8bf5c7896174830d438c8f91a6ead88
+F test/eqp.test 84879b63e3110552bf8ce648a3507dc3ceb72109ecec83c2aef0db37a27f6382
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
-F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3
+F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
-F test/expr.test 7cb55e80aeb41d65fec968c08212505123063fea60bdc355d764d747670e9eea
+F test/exists2.test 47970f2ce98826519cc38ce502b718641755b30a93d9b89915019ba1e770f361
+F test/existsfault.test 74f7edc713f5a335e7ff47adf503067bf05c6f8630f88b2a19c24f0fa5486ab8
+F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf
+F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
-F test/fallocate.test 07416bd593a116d5893cb244f45a94d5c6fe030561df3bd972e6135f8106e509
+F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
+F test/filter1.test 6c483ecf7886c8843a8612c021aa23f33c581f584151f251842b3a3592c95ac8
+F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8
+F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a
+F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b
F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768
-F test/fkey2.test d35d1c81e7569bdd2b872e91750f7098117d2e8291369f70b7e3d50a0e523dc2
+F test/fkey2.test 1063d65e5923c054cfb8f0555a92a3ae0fa8c067275a33ee1715bd856cdb304c
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
-F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a
+F test/fkey5.test 6727452e163a427147e84e739da18713da553d79f9783559b04fdcd36d5c7421
F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0
-F test/fkey7.test 24076d43d3449f12f25503909ca4bfb5fc5fefd5af1f930723a496343eb28454
-F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c
+F test/fkey7.test 64fb28da03da5dfe3cdef5967aa7e832c2507bf7fb8f0780cacbca1f2338d031
+F test/fkey8.test 48ef829d63f5f7b37aabd4df9363ac05f65539d1da8c4a44251631769d920579
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
-F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff
-F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
+F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958fdde5c
+F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5
@@ -880,8 +942,8 @@ F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682
F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
-F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
-F test/fts3aa.test f267fcd6aca30fc70b81e5d82b68b34b38f581896020b57ed49e9777c7ebd85f
+F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a
+F test/fts3aa.test 814d60a1ba30b4a71d8f9306a6564bc7b636dd6efacd2ad80306f9b23ef3ebee
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
@@ -896,19 +958,21 @@ F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
F test/fts3ao.test 266989148fec6d9f1bb6c5382f7aa3dcea0e9cd444576e28dd2b9287ac7dd220
-F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1
-F test/fts3auto.test 19097050a3ca7ab7a43b2be967cb3dfd8ddf841dfdc4eac88deb172ad2f209f2
+F test/fts3atoken.test dc2078ce464914efe3a8dfc545dd034a0fc14f2ab425c240471d5a5f1c721400
+F test/fts3auto.test 649aa4c198d7acc5cd6355e19ee073d051c40d9e88a43fc3d88af46bdf3e99d5
F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6
-F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
+F test/fts3aux2.test 2459e7fa3e22734aed237d1e2ae192f5541c4d8b218956ad2d90754977bf907f
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
-F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae
-F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3
+F test/fts3corrupt.test 79a32ffdcd5254e2f7fa121d9656e61949ad049c3c6554229911b7ceac37c9c6
+F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c7880bb0c67d0
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
-F test/fts3corrupt4.test a27259f4f25d60b4eca481d050b3cfee97eddb0d937d38f231408c5239066e11
-F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338
+F test/fts3corrupt4.test b71512ec391d39da96d60d01959e4e9f20d4237a964a94abcf5f5a2ad28378c1
+F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
+F test/fts3corrupt6.test 938e5f118974c9169bb6ef9501b9d212e1124f2de1b5bf7e6499db870062dd9e
+F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
F test/fts3defer2.test 3da52ca2114e300e9971eee2f0cc1a2e5f27e6a9ee67957d49e63e41fdfcc0e7
@@ -918,15 +982,17 @@ F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
-F test/fts3expr4.test cac5dd815fe6b5921741abdccdde3b7f50b86394de91e13308ee7986859c4a9f
-F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
-F test/fts3fault.test 9fb7d6266a38806de841f7244bac1b0fe3a1477184bbb10b172d19d2ca6ad692
+F test/fts3expr4.test f5b2832549f01b1f7f73389fa21d4b875499bc95bf7c8b36271844888c6a0938
+F test/fts3expr5.test a5b9a053becbdb8e973fbf4d6d3abaabeb42d511d1848bd57931f3e0a1cf983e
+F test/fts3fault.test 798e45af84be7978ca33d5bdc94246eb44724db24174b5d8e9b1ac46c57fb08d
F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
+F test/fts3fuzz001.test e3c7b0ce9b04cc02281dcc96812a277f02df03cd7dc082055d87e11eb18aaf56
F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
-F test/fts3misc.test 0b20083efab36a42804bf8017a003f72f963c46163403dae7256493367d2f9d3
+F test/fts3matchinfo2.test 00144e841704b8debfcdf6097969cd9f2a1cf759e2203cda42583648f2e6bf58
+F test/fts3misc.test 9ec15e7c0b5831a6353bd4c46bf3acdf1360eda5d9f396f667db4d05bcf92ecf
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
@@ -935,68 +1001,79 @@ F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba16
F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
-F test/fts3snippet.test 8cf586fe4b6878192602a81a665448aacbbad80ade0867bb5299d40e73584311
+F test/fts3snippet.test 0887196d67cffbe365edde535b95ecc642a532ce8551ccd9a73aab5999c3ffae
+F test/fts3snippet2.test 2dabb5889eda4c9980aad325e688b470781f97ce7c0fca0db125616fae0a2cdd
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
-F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
-F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
+F test/fts3varint.test 0b84a3fd4eba8a39f3687523804d18f3b322e6d4539a55bf342079c3614f2ada
+F test/fts4aa.test 0e6bfd6a81695a39b23e448dda25d864e63dda75bde6949c45ddc95426c6c3f5
F test/fts4check.test 6259f856604445d7b684c9b306b2efb6346834c3f50e8fc4a59a2ca6d5319ad0
-F test/fts4content.test 1518195a9f92b711d94419f76409a31cc78755854fb0abb1da2b74b9e0cf843e
+F test/fts4content.test 73bbb123420d2c46ef2fb3b24761e9acdb78b0877179d3a5d7d57aada08066f6
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test 289833c34ad45a5e6e6133b53b6a71647231fb89d36ddcb8d9c87211b6721d7f
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
-F test/fts4langid.test 2168ba330af34f8a1c8832de0aab4c4b6fa195a16419c9c0c8aad59ceb6ff714
+F test/fts4langid.test 89e623218935507bca69d076ca254a7a8969dfc681c282b6374feaea8c7de784
F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
-F test/fts4merge.test 1096e30b58ad616bd502141bfe5bfe4c3a518df89e958d41a5ed1ce322369b9c
+F test/fts4merge.test e2b2ec21e287d54ec09824ccfb41e66896eeca568fc818ba0e0eb2efd94c35d2
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
+F test/fts4merge5.test 69932d85cda8a1c4dcfb742865900ed8fbda51724b8cf9a45bbe226dfd06c596
+F test/fts4min.test 1c11e4bde16674a0c795953509cbc3731a7d9cbd1ddc7f35467bf39d632d749f
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
-F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
+F test/fts4record.test a48508f69a84c9287c8019d3a1ae712f5730d8335ffaf8e2101e691d078950bb
+F test/fts4rename.test 2e0565ffd92b2c51f1a757df0b8f2ca30537197106fec09e943919801d173692
+F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429
+F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
+F test/fts4upfrom.test 8df5acb6e10ad73f393d1add082b042ab1db72567888847d098152121e507b34
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
-F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7
+F test/func.test f673822636fb8ed618dd2b80230d16e495d19c8f2e2e7d6c22e93e2b3de097ad
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
-F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c
-F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
-F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
+F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6
+F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
+F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
+F test/func7.test b9e2a1a30a8562b00841b4a21a5d2d81754fa3ab99275fd71fd5279287b44b1c
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
-F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
+F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
+F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c fda41c0e4e667fae96b002410bb19cece7a33314264ed6bbc6d012909ee9fd58
-F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
+F test/fuzzcheck.c 772110a59c6f839f95e49a9fd3e5f855bd9cbb90e9d366a6ccd15cb3616fc631
+F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
-F test/fuzzdata7.db a1bf54eb455e9772942abae1b2d1cf1e3d3659f0e5dd14f00792fd01411ae8ef
+F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
+F test/fuzzdata8.db c8325de6fbdd24d030cd3a01384a2ff325dda5d5e3ff5d531a26ada3d9d7e010
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
-F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
+F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
+F test/gencol1.test b05e6c5edb9b10d48efb634ed07342441bddc89d225043e17095c36e567521a0
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
-F test/having.test e4098a4b8962f9596035c3b87a8928a10648acc509f1bb8d6f96413bbf79a1b3
+F test/having.test a89236dd8d55aa50c4805f82ac9daf64d477a44d712d8209c118978d0ca21ec9
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
-F test/hook.test 1604b3b2f5931430087540404555c1b6be3618600b81558657c66b533ed70b13
+F test/hook.test fa54fa8afc842ae375f10c1f9fc0014fa59789052fc30c9eae19811fa3afa009
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
-F test/icu.test 41aa8847745a879b897a7febea0f8f9efc8e67fe8bf680589b6e07c7b0a1569a
-F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
+F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
+F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
-F test/in.test 2fa2dfba1afe30eb830f327e7131dfadaa7a701d677de0eb65f9303d99e18fe0
+F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
-F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
-F test/in5.test 7ae37fcd4a5e198291c6ab5f31a5bb3d15397efe8b75a6736d7a95a7b8dd9e08
-F test/in6.test 62d943a02f722948f4410ee0b53c3cb39acd7c41afb083df8d7004238fe90a20
+F test/in4.test 64ac9c767ac5af562f066a40163d4202f8fa3be05d264ec65d6258e74606b30c
+F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
+F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
@@ -1008,31 +1085,33 @@ F test/incrvacuum.test 2aaee202b1f230e55779f70d155f6ba67bbdff8481d650214d256ab0f
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
-F test/index.test df4cddf4435314a948237fdfa9acee67de21f7bebc789beab4b89b575b4f6a70
+F test/index.test a2e948ed949e575487b5c1d521767d4584ac42d352f2dcd8e48004638e7bc7dc
F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
-F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d
-F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98
+F test/index6.test f172653b35b20233e59200e8b92a76db61bf7285437bf777b93b306ba26a47e7
+F test/index7.test b8a0ba2110fd517bb48c4e76d26d60f1ab2ed9e257b18d71f820d7e71e9f8570
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
-F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
-F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
-F test/indexexpr2.test fc994dcd4b3da932d4add8e65ed7ca08166d541e00a46874cfacd98dfb93a31b
-F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
+F test/indexedby.test a3ca11f0819a9279619099f36b624bcaa315f7a1ed65c3ed2219c2a944683d2c
+F test/indexexpr1.test 284e119999d132cc8bf37735a928c9859b28e8e295d02b7a6a4f93977c7f9ba5
+F test/indexexpr2.test dba11dbb0a58fcba4cd694f46b4004976123b81b0501f525d43c9be59f0207b1
+F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
-F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a
+F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
-F test/insert4.test 46bead5f39e181850ee56adcf49d3a3157c460c52249211714612ac89fe34835
+F test/insert4.test 59cb99521be01a5aefc9be8e8b5a51ee7f3944781d4d7f6201b9f774fcd51662
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
-F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba
-F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a
-F test/intarray.test 8319986182af37c8eb4879c6bfe9cf0074e9d43b193a4c728a0efa3417c53fb7
+F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74
+F test/instr.test 107df2b9b74a4b59315916b575590a08f2a714de0754abe541f10a0971d0a2a4
+F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd0e0f44c
+F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
+F test/intreal.test 2a87e85a5949bd55e41ef04c58f5800587c5380bdbc559ff1c79b614b0e6a533
F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
F test/ioerr.test 470fcc78e9cd352d162baf782fe301ea807d764241f58a48fc58109c2dfcdb6b
F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
@@ -1040,32 +1119,33 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
-F test/istrue.test 62372ad3ddcc5d0eb8ff9097dcb0aad8961bf1b9cb45ba634f6e284695126f9a
-F test/join.test 2ad9d7fe10e0cc06bc7803c22e5533be11cdadbc592f5f95d789a873b57a5a66
-F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417
+F test/istrue.test 9619a2d77580f676048aaff7a16a0bcfea2b96c6c660dfaded2e53c873418899
+F test/join.test 25da4f53523a4aa17c893134b47fba6aa4799bb33350517b157785878290e238
+F test/join2.test 21fc30e54ab35ed66bf51b89cec18729205497f5cc43c83bc042f96a73721593
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
-F test/join5.test 5a2da0c3ea852a7063d3e72fc7d5a04a6de5ef6e6d85092582f69033f7459adc
-F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
+F test/join5.test 3a96dc62f0b45402d7207e22d1993fe0c2fce1c57644a11439891dd62b990eb7
+F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
-F test/journal3.test c9c29883f5bf535ae82ae21c472df6263806a22e467b6db7cd0d6d545305b4f6
-F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539
+F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
+F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9e1946
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
-F test/json101.test b40a9f5395d8e669b0bc3eb550ad2ae9e5ada01fbce23c446c2a30a305a6d575
+F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b
-F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
+F test/json104.test 317f4ec4b2d87afbba4d2460cf5be297aea76f2285eb618d276dbcd40a50950f
+F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
-F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba
+F test/kvtest.c feb4358fb022da8ebd098c45811f2f6507688bb6c43aa72b3e840df19026317b
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
-F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
+F test/like.test 0b7b4765ca59d95a1f92dfab9e4d810c9fb8280b5edd6332a01340a20db9e0ed
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
-F test/like3.test 430691e6057e11a59e934be74c06b85605b80061d45af5714d52886a811efeb7
-F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
+F test/like3.test 03d1bdf848483b78d2cfd1db283d75c4ec2e37c8b8eccc006813f3978d78fbbd
+F test/limit.test 350f5d03c29e7dff9a2cde016f84f8d368d40bcd02fa2b2a52fa10c4bf3cbfaf
F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e
F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
@@ -1076,7 +1156,7 @@ F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37
F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
-F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
+F test/lock_common.tcl 2f3f7f2e9637f93ccf609df48ef5b27a50278b6b1cd752b445d52262e5841413
F test/lookaside.test 5a828e7256f1ee4da8e1bdaa03373a3ccdb0f1ff98dfa82e9b76cb41a45b1083
F test/main.test 6bbb3999fd461eb8fb335cbab97409a3d7f91bbb8da60635e8be3e4a04a77772
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
@@ -1088,7 +1168,7 @@ F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e
-F test/mallocA.test 672cd7dedb63771bade3a6f557f851a4ad161d4a
+F test/mallocA.test aea76f2dd8bcc2d19748f6b911e876cefda74a563753bf26af046e9d34bb97e6
F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be
F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6
F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4
@@ -1107,22 +1187,22 @@ F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0f
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
-F test/memdb1.test 61aa1dbdeea6320791d2ff42a9a6149d5716be674bf06ee0ffa0aad1bf3eb5f8
+F test/memdb1.test 58d92c2bf622cc5f0f41461e1b35cf64f3f787199544c2c1dada37d88753f9d4
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
-F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063
+F test/minmax2.test 1edf66901ddfab26ae1e04165e8da834c8d3284e2b20aefb26b80ef217962eab
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
-F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
-F test/misc1.test c8cfd1c3f842b3341fda9d81a96236d5c76ca89973aeff3fe50bac6fefcfc421
+F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87
+F test/misc1.test 7ce84b25df9872e7d7878613a96815d2ba5bc974ac4e15a50118dde8f3917599
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
-F test/misc7.test 10d639a5e0fdf1bd51ad42be705393a38780ad71b6957110035a4e6c1e5e7f40
-F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
+F test/misc7.test 7b4c88c1d5ea8c8b9d537d212c08a0343d345fdd5c789598692c1c0e60fbda69
+F test/misc8.test 8782708f4c8a459591c3e8fe1215bd2048bffb4024b3df249e9b9ed407dc61ed
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test fb04e0c10492455007624ade884ca0c8852ff3e4e11d95408f9709ca2ef7f626
@@ -1135,38 +1215,42 @@ F test/multiplex.test dc0d67b66f84b484a83cb8bbdf3f0a7f49562ccd
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
-F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
+F test/mutex1.test 177db2e4edb530f2ff21edc52ac79a412dbe63e4c47c3ae9504d3fb4f1ce81fa
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
-F test/normalize.test 6a80564d2000702b5919ed2c1069fef0f95762142bc96a71b4c124a845165713
+F test/normalize.test f23b6c5926c59548635fcf39678ac613e726121e073dd902a3062fbb83903b72
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
-F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
+F test/notnull2.test d5e27e7eb9ff80c587998088a3c40dcc9e4faa71c7ec27a41b4435b0f3b8fdc9
+F test/notnullfault.test 6126e31300632070ca6021698393c7fcf61ab4791bc2aa1d6d704242c0fcd4f8
+F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
+F test/nulls1.test 82c5bc33148405f21205865abf13c786084438d573a4ac4e87e11b6091cde526
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
-F test/optfuzz-db01.c a0c256905c8ac79f9a5de2f374a3d9f757bef0dca2a238dc7c10cc8a38031834
+F test/optfuzz-db01.c 9f2fa80b8f84ebbf1f2e8b13421a4e0477fe300f6686fbd76cac1d2db66e0fdc
F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1
-F test/orderby1.test e4501f54721f804ca56922e253403ac6775f88e9f07569994ce99212b3ca5b10
+F test/orderby1.test 6bf0ce45cbfb1cf4779dd418ac5e8cf66abfa04de2c1d2edf1e0e85f1520d8f3
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
-F test/orderby5.test 5f4d6cb93cc2f6d3f4228354310a2ce1fbd95d5bbffcba8c6482eeb62a466407
+F test/orderby5.test bd7d9e3380e87e5dcf6ea817ebaab6d15da213c7804b38767e1b3e695e85650b
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
-F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
-F test/ossfuzz.c 273eaea2d65b70d77ea4f01404114b9e0244488943f768dc39458c72bd722e0e
+F test/orderbyA.test df608e59efc2ef50c1eddf1a773b272de3252e9401bfec86d04b52fd973866d5
+F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6abbc5
+F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d71096715
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
-F test/pager1.test 1e9ee778bdeaf4f7f09997d029cdaca6a42dfc2092edafe4f5e590acbf1eab13
+F test/pager1.test 293c7ad1f19a07e548179b97534c6588249d4e40058b378ea26e75cc84d936f5
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
@@ -1179,15 +1263,16 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test cf0b4e498db1d0143c19641d4420df7cc27fab2c95ed0abd2c7c5753beab25b8
-F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30
-F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867
+F test/permutations.test 0a7cf0b6b1283cdd4f0d6e31cb7afbde81d20b1caef60b73914e85b6bf660b8a
+F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
+F test/pragma.test 50b91bedea9324d3ab48e793f908ee7d2c7dcf84bfa2281e792838be59641ec8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
-F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9
-F test/pragma4.test 52d8186f9e8d09b87189432cdd401dfa66d0b32445e837fa19046c8ae7621b0e
-F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
+F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
+F test/pragma4.test ca5e4dfc46adfe490f75d73734f70349d95a199e6510973899e502eef2c8b1f8
+F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
-F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd
+F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
+F test/printf.test 390d0d7fcffc3c4ea3c1bb4cbb267444e32b33b048ae21895f23a291844fe1da
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
@@ -1197,33 +1282,38 @@ F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
-F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
+F test/quote.test b8ddaba6b81dcf63bb31243219e28a2f96e04396adc50108cc7e5593019c3eb5
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
+F test/recover.test ccb8c2623902a92ebb76770edd075cb4f75a4760bb7afde38026572c6e79070d
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
-F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
-F test/releasetest.tcl b290d538ffcb2ff711f09eadc7396c1a42580f3fb078605471dc8875ca0b4d1e x
-F test/resetdb.test 373a9eb8fcbd58bf87affec6a88c6353038f98a5d25be5ab75a0b9636c462a36
+F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
+F test/releasetest.tcl fb76d8fcc95ac29d6356cd9e52b726ab9e43a24082897618dfbcb7c2b0049153 x
+F test/releasetest_data.tcl 3d41ddb3f04f474ac9d925485da24ce6576ff0ebc4c7201c8a340bc09846c261
+F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
+F test/returning1.test ce2192b40045cc94d53ac5ec5789a72a3ade233a6ea6e29666e296d151b59479
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
+F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab21e
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
-F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
-F test/rowvalue.test b8680f07d19c8c5223b808bba998faffcec6d505f5689ff6070280119173bb51
+F test/rowid.test bfbd7b97d9267660be3c8f28507c4ed7f205196b8877c0db42df347c2e8845e3
+F test/rowvalue.test 6795850abf6243e96f09ef041919d1ea61713332237b60d01371c0fee73f6379
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
-F test/rowvalue4.test 2b20468da3775aba971caf3158e9696a4d99c69a7623fb495f332a596daebbee
+F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356
F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
-F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8
+F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b
F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504
+F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
F test/savepoint.test 1f8a6b1aea9a0d05837adc463d4bf47bd9d0f1c842f1c2a9caccd639baf34bf9
@@ -1233,8 +1323,8 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
-F test/scanstatus.test d14842d0a2757ee059bcffa365746453d60952ba1077980c9a348a9fefbd232a
-F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
+F test/scanstatus.test 874e35011779b07725a47dbf1dd6282b0ca04af7e028fb0b534ee544b571be42
+F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
F test/schema4.test 3b26c9fa916abb6dadf894137adcf41b7796f7b9
@@ -1243,18 +1333,18 @@ F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce
F test/schemafault.test 1936bceca55ac82c5efbcc9fc91a1933e45c8d1e1d106b9a7e56c972a5a2a51e
F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2ff09384
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
-F test/select1.test 2e760bab8f3658b3b97debcf52860d0d2e20aa6cbe8b40e678ddb99871a15491
+F test/select1.test 3d23f66bf9ba77570acfe2ca5f1540ece17037cc64ab1a00efec9758ac29c268
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
-F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
-F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
+F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c
+F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b
F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546
-F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
+F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801
F test/select7.test f659f231489349e8c5734e610803d7654207318f
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
-F test/selectA.test b8a590f6493cad5b0bb4dfe1709bf7dcda0b6c40bb4caf32d1e36a89eebc8fc5
+F test/selectA.test 68de52409e45a3313d00b8461b48bef4fb729faf36ade9067a994eae55cc86f4
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
-F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
+F test/selectC.test fec14c9015ed4ec941508bbc144f30b42e40ac34a4bb33001450369865dd0b75
F test/selectD.test fc20452847a01775710090383cfb4423275d2f745fed61f34fbf37573ac0d214
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
@@ -1262,10 +1352,10 @@ F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae
F test/server1.test c2b00864514a68a0e6fd518659dc95d0050307a357a08969872bef027d785dc4
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
-F test/sessionfuzz.c b0fcdcf757451957e17396a3af5171f1fdf9b2babc81da9fa35675df46c4729a
-F test/shared.test 1826673eb5eb745fb91a3bdac99a7737057742ae38dcb0fe076a384d6727578b
+F test/sessionfuzz.c f74c4e806bab5a093fb9c11b6123d17a6e0cf73fb7a0f49b12f5a75bf0b7b1a8
+F test/shared.test f022874d9d299fe913529dc10f52ad5a386e4e7ff709270b9b1111b3a0f3420a
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
-F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38
+F test/shared3.test f8cd07c1a2b7cdb315c01671a0b2f8e3830b11ef31da6baa9a9cd8da88965403
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
@@ -1275,28 +1365,29 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd
+F test/shell1.test 56a7358a2a05e850e9e4aa24629db9c8975e8038dbe8debd2d95be22a5f03612
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
-F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
-F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
+F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be
+F test/shell5.test 84a30b55722a95a5b72989e691c469a999ca7591e7aa00b7fabc783ea5c9a6fe
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 96be02ea0c21f05b24c1883d7b711a1fa8525a68ab7b636aacf6057876941013
+F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
-F test/skipscan1.test 3ea1cccca8f1b0e1cf3e73a63b43dd796f34d4aaee815e641f0d2ebb3fa448d4
-F test/skipscan2.test ef143c6e4a5ba4f19c1d1e3f517811f7942bdf2142736cc568feb34e0b5fb763
+F test/skipscan1.test ed524bc86f27646b3a297f45d6557b55db338977b6838f8064b196b35848b31b
+F test/skipscan2.test 3eb703ce794f139e7b83567911046298bcde29606116727f9b700ce34f559d2d
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
-F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
+F test/skipscan5.test 980875ad45d8aacfe7bdec7c288343520cd1d14e84befdcfe50c785f9e6c8709
F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
-F test/snapshot_fault.test 508ae6f211d4991e9ff3b5080aeb0a179bf6755138aabeac4bca8083044d895a
+F test/snapshot_fault.test f6c5ef7cb93bf92fbb4e864ecc5c87df7d3a250064838822db5b4d3a5563ede4
F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
@@ -1315,47 +1406,49 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
-F test/speedtest1.c cc7e6b4a7c9f3e3d1a497ae3f75236a832a2ce0f6a9b017f95d996c821605bfb
+F test/speedtest1.c 5e5b805f24cc939656058f6a498f5a2160f9142e4815c54faf758ec798d4cdad
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
-F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
+F test/sqllimits1.test 264f4b0f941800ba139d25e33ee919c5d95fea06dfbe8ac291d6811a30984ca5
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
-F test/stat.test f8f1279ffffabe6df825723af18cc6e0ae70a893
+F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
+F test/stat.test 15a3106eddedfc882f64bc09f237b4169be4b92dd57c93031b8ff8b13af3e7c5
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
-F test/subquery2.test 8250dfd6a773b04c7a5c37ac63276f62b329157ce171244d0cbe1acc365e3303
+F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
-F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
+F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
F test/swarmvtab3.test 247aa38b6ebd2b99db2075847ae47e789ac34f1c2ab5c720dfcffd990004c544
F test/swarmvtabfault.test 8a67a9f27c61073a47990829e92bc0c64420a807cb642b15a25f6c788210ed95
-F test/symlink.test 0d816670325536b8973ec08d32b45136baddb80bd45fd178e0ce7a9e8153f3e7
+F test/symlink.test 72b22238d4405ba34df8e60b335d290a3b1129fd5c260835c944c1e4e77288a9
+F test/symlink2.test 9531f475a53d8781c4f81373f87faf2e2aff4f5fb2102ec6386e0c827916a670
F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d4333092
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test 54300134f76db817685194d2f0e63e3fbf7380b45e0d426e00a9aee752497cfb
+F test/tabfunc01.test 5ca6d004157a3e886a55a9387b960cc0db41acd88753eb597ff409ec6cfb1be0
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
-F test/tclsqlite.test dca8aa30d84175e7d8c8fc43d3ffa11fa56e23fbdac2679d03833a0f326edf34
+F test/tclsqlite.test 79a473f5797e317c08f2c4f8192edb3eea6a67329b1087453328b66a7cb31070
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
-F test/tempdb2.test 2479226e4cb96f4c663eccd2d12c077cf6bda29ca5cc69a8a58a06127105dd62
+F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl fa5656391e3b477508abe12b3b81f019b2e71397399ab38a2f32d8d7f3bf8e56
+F test/tester.tcl 19d2a19a6dd55a2b4e2b943963959a05a2c088495dd5f5274b04e0494ce86d66
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1366,10 +1459,11 @@ F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
-F test/threadtest3.c 38a612ea62854349ed66372f330a40d73c5cf956
+F test/threadtest3.c e63013af10cf236c7610eb06d33bde08c861806dc64be811940ff4d9ddd34a4f
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
+F test/tkt-18458b1a.test 6a62cb1ee50fa3c620da59e3a6f531eb38fceaf7e2166203816b724524e6f1d6
F test/tkt-26ff0c2d1e.test c15bec890c4d226c0da2f35ff30f9e84c169cfef90e73a8cb5cec11d723dfa96
F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2
F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
@@ -1379,7 +1473,7 @@ F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf949607618b1
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
-F test/tkt-3a77c9714e.test b08bca26de1140bdf004a37716582a43d7bd8be8
+F test/tkt-3a77c9714e.test 90e3e8455ee945a4076d4c44062b8845708af24a880355328fe7008f2047c9f0
F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70
F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0
F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
@@ -1391,7 +1485,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
-F test/tkt-78e04e52ea.test 1b5be1bac961833a9fd70fe50738cb4064822c61f82c54f7d488435ec806ea62
+F test/tkt-78e04e52ea.test cb44d0f5e7940223be740a39913a1b9b9b30d7e4a17ed3349141f893bae1b8f2
F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f
F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
@@ -1405,17 +1499,18 @@ F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667
F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6
F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8
F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
-F test/tkt-a8a0d2996a.test 76662ff0622c90e7ce7bbcb4d9e1129acddf877d17c3489f2da7f17ddfaad1f4
+F test/tkt-a7debbe0.test e295fa83cd4416a8ca37b354eb5fadefc5e81fb55253db538d35261fe9c95067
+F test/tkt-a8a0d2996a.test 002e1cde8fc30c39611b52cf981c88200b858765748556822da72e0d32fac73e
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
-F test/tkt-b75a9ca6b0.test 1bc0381538fd21f96a10dbabc10ffc51b5b2e5f412d34bae571273ca784003d7
+F test/tkt-b75a9ca6b0.test ade89229d853a67a21bbd5e6e1e787a8f9d21f19908d1b7fca6bf3d4d5aa0767
F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
F test/tkt-c694113d5.test 82c461924ada5c14866c47e85535b0b0923ba16a2e907e370061a5ca77f65d77
-F test/tkt-cbd054fa6b.test 06ccd57af3c0c7895d0f7dc844f13c51f8258885
+F test/tkt-cbd054fa6b.test 708475ef4d730a6853512c8ce363bcbd3becf0e26826e1f4cd46e2f52ff38edf
F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d
F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
@@ -1460,7 +1555,7 @@ F test/tkt2817.test f31839e01f4243cff7399ef654d3af3558cb8d8d
F test/tkt2820.test 39940276b3436d125deb7d8ebeee053e4cf13213
F test/tkt2822.test f391776423a7c0d0949edfce375708bfb0f3141e
F test/tkt2832.test a9b0b74a02dca166a04d9e37739c414b10929caa
-F test/tkt2854.test e432965db29e27e16f539b2ba7f502eb2ccc49af
+F test/tkt2854.test 47a2ae03bf36812f675ec06806a7b958e0de75312261dd8280c187f4a4a8281a
F test/tkt2920.test a8737380e4ae6424e00c0273dc12775704efbebf
F test/tkt2927.test 4752868b9eeeb07a217f7f19f4cbaac98d6d086d
F test/tkt2942.test c5c87d179799ca6d1fbe83c815510b87cd5ec7ce
@@ -1468,7 +1563,7 @@ F test/tkt3080.test 1bca7579260920a66b4dd7e196e807c0f25ff804
F test/tkt3093.test fbdbc5b4969244ad11f540759003e361fcaf391f
F test/tkt3121.test 536df66a02838c26a12fe98639354ca1290ca68b
F test/tkt3201.test f1500ccecc0d578dc4cde7d3242008297c4d59b3
-F test/tkt3292.test 962465a0984a3b8c757efe59c2c59144871ee1dd
+F test/tkt3292.test 7bad4423cf5eb075dbb58511d66d46fe816744754c9f0050ae60157f71a4fca7
F test/tkt3298.test 20fd8773b825cb602e033aa04f8602e1ebdcd93c
F test/tkt3334.test 9756631e3c4aa3c416362c279e3c0953a83b7ca8274cb81a13264bb56296d8b0
F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a
@@ -1494,8 +1589,8 @@ F test/tkt3761.test b95ea9c98f21cf91325f18a984887e62caceab33
F test/tkt3762.test 4d439ff7abdc8d9323150269d182c37c2d514576
F test/tkt3773.test 7bca904d2a647a6a4a291bd86d7fd7c73855b789
F test/tkt3791.test a6624b9a80b216a26cf473607f42f3e51898c267
-F test/tkt3793.test d90ffd75c52413908d15e1c44fc2ea9c80fcc449
-F test/tkt3810.test 09608d81c63a6ff3aaf7bc70717909c51f5f4048
+F test/tkt3793.test 9ee9c6f300adce634e8990a131ad5e20e22241643a1240c6b372b351205ef7cb
+F test/tkt3810.test 3a3be9965d1861bd84019875851ad5ea90fd8d76b638361514a36a48ea53191b
F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
F test/tkt3838.test 292e72489101cd1320d7278dc111c173ebf334d4
@@ -1514,13 +1609,13 @@ F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32a2a
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
-F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144
-F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
+F test/trace3.test ae2004df24b585fed9046cc0bae4601762bc6fc4aa321d475f1350bba5047f31
+F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
-F test/trigger1.test 17e4b43e656c4b354df2357634a6ba887990f510c43629f4feca30e3338d2a61
-F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
+F test/trigger1.test d30cd09ae8ac365a088f09daba583cc5c0b8fc7d4e1d70809d0b4be3bf6ae2ab
+F test/trigger2.test d15da46f7012832faf3e0c536b47024409d5fb1722d2bb77e29c06d96d704bb1
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
@@ -1530,46 +1625,60 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
-F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
+F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
-F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d
-F test/triggerF.test 6a8c22bd058cf467f0c7d112afe87f7a8c579c0c4681b914b8f19020f48528a4
-F test/triggerG.test d5caeef6144ede2426dd13211fd72248241ff2ebc68e12a4c0bf30f5faa21499
+F test/triggerE.test 612969cb57a4ef792059ad6d01af0117e1ae862c283753ffcc9a6428642b22ee
+F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
+F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9
+F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4
+F test/trustschema1.test 4e970aef0bfe0cee139703cc7209d0e0f07725d999b180ba50770f49edef1494
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
-F test/tt3_stress.c c57d804716165811d979d4a719e05baccd79277f
+F test/tt3_shared.c b37d22defc944a2ac4c91c927fd06c1d48cd51e2ce9d004fe868625bd2399f93
+F test/tt3_stress.c f9a769ca8b026ecc76ee93ca8c9700a5619f8e51c581107c4053ba6ac97f616f
F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
-F test/unionvtab.test 5ae0f0b4f302a4c6bb310b64386f9ac6a4c1c271c08f31cc7c5d92722e2b2729
+F test/unionall.test fee6e6adebe5446938475432ae8b042835a286c7e2efdc1b186d2182dfb93ffb
+F test/unionall2.test c9a62db63350bcbce3a7bec50dd8c5410f08be33f8af435473756286d4657215
+F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73
+F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981
-F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60
-F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e
-F test/upsert1.test 994bde41800bb77dbe32fcd2e1f6c4b49cc9f2c6cd345731c774dff02b51c110
+F test/update.test e906ca7cb1dc6f52af1ea243e08f727edfa79f924c2691f2f9e72481f847310d
+F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
+F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
+F test/upfrom1.test d18f69f7c691bc791e7f31bf0e354eeff04cf2f44edc32d6b1928bad71697073
+F test/upfrom2.test 6ebd3be8c3fac984e89a177d823686f04605b512fc167392bce6d8ba2ba63325
+F test/upfrom3.test 7dab379d128e8dd7beb2055b295fb113c7ba93e8c2038f5ddb7a4a10f0ebb348
+F test/upfromfault.test 70ecf8eb85559727a487283f69374e3ae39879e994d8a2437c49d7c05ecb70c9
+F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266fb18
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
+F test/upsert5.test fff0dcfce73c649204543088d8e5bde01172676063ec9b8f8fc7f195abc386fe
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
+F test/vacuum-into.test 48f4cec354fb6f27c98ef58d2fe49a11b71ff131af0cd9140efacc9858b9f670
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
-F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
+F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
+F test/vacuum6.test d3173a54edc81d13d99e4cf4972232b3cbb52f1d56ed48c3a939ef4e751c1ee8
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
-F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f
-F test/vtab1.test 60b4f70aafa6078d6fdfc11417af3bd216d7ef5eafce16707a6ca3dae5166d20
+F test/view.test ea88361d5e9bc8eabf9f573185a16aea73a885be9b6c6a95ae84908913416a80
+F test/vtab1.test c5d9e90ed02bcacd776dcbb7360199d290f7f53c26b484ddece543060c54319f
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
@@ -1584,14 +1693,15 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
F test/vtabE.test 2a143fe75a11275781d1fd1988d86b66a3f69cb98f4add62e3da8fd0f637b45f
F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
-F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be450
+F test/vtabH.test 2efb5a24b0bb50796b21eca23032cfb77abfa4b0c03938e38ce5897abac404ca
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
-F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f
+F test/vtabJ.test a6aef49d558af90fae10565b29501f82a95781cb4f797f2d13e2d19f9b6bc77b
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
-F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
-F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
+F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12
+F test/wal.test b7cc6984709f54afbf8441747ced1f646af120bf0c1b1d847bfa39306fbea089
+F test/wal2.test 31f6e2c404b9f2cdf9ca19b105a1742fdc19653c2c936da39e3658c617524046
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
@@ -1610,148 +1720,169 @@ F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
F test/walcrash4.test e7b6e7639a950a0cca8e210e248c8dad4d63bf20
F test/walfault.test 09b8ad7e52d2f54bce50e31aa7ea51412bb9f70ac13c74e669ddcd8b48b0d98d
+F test/walfault2.test e039ac66c78d5561683cacde04097213cdad3b58e2b3f3fe1112862217bfd915
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
F test/walmode.test cd6e7cff618eaaa5910ce57c3657aa50110397f86213886a2400afb9bfec7b7b
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
-F test/walprotocol.test a112aba0b79e3adeaa485fed09484b32c654e97df58e454aa8489ac2cd57bf84
+F test/walprotocol.test 1b3f922125e341703f6e946d77fdc564d38fb3e07a9385cfdc6c99cac1ecf878
F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db868eebc131
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
+F test/walsetlk.test 11f7fe792fdce54cf09874dab824e0627f2eedecfb9f7983e325606ec5184e0c
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
-F test/where.test 8215d220633f08da331781cf9ede7fb7aed50eb113473c10acd39a643fd258ba
+F test/walvfs.test bccb3e0d235ef85e276f491d34db32c9ada1ea67be8d9f10aabe7b30319ec656
+F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
+F test/wapptest.tcl 899594e25684861d5b0c0880fb012364def50ef8097041b8ddf74be5ba7fa270 x
+F test/where.test e713c0c64e3e6b062235e39a2f7e5508c517df16b63d69fd786e26bc7330b1c6
F test/where2.test 478d2170637b9211f593120648858593bf2445a1
F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
-F test/where7.test e579da972eb3372edc9de850efc221848c763f9e4feafc8426d84a4453b92b23
+F test/where7.test 75722434c486ac9e74718caa6cce234f45ba34c0b6c0f9555b29eb8bb5f6ade1
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
-F test/where9.test ad2ddb339d10d324763c3da60502b8631f15a2397b869192fbd4e82f40e167d3
-F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
+F test/where9.test 8e3e0ff42cc17156f52361a1c012281550d0d632912fec92d1d6df74db7a8e6d
+F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
-F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
+F test/whereD.test c1c335e914e28b122e000e9310f02d2be83e1c9dbca2e29f46bd732703944d1b
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
-F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52
+F test/whereG.test 77127a4d214bb21da3b5c695cf4106cd9e418c60d9c24471ba55d3772067cd35
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
-F test/whereI.test b7769ee8dbefd987fb266715fee887f05f9ff180016b06fca7fa402df739193b
+F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
-F test/whereL.test 0a19fc44cd1122040f56c934f1b14d0ca85bde28f270268a428dd9796ea0634c
+F test/whereL.test 1afe47227f093dc0547236491fb37529b7be9724b8575925a321001b80e6a23a
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
-F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
-F test/wherelimit2.test 9bf0aa56cca40ea0e4c5e2915341355a2bbc0859ec4ce1589197fe2a9d94635f
-F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
+F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
+F test/wherelimit2.test 657a3f24aadee62d058c5091ea682dc4af4b95ffe32f137155be49799a58e721
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
-F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
+F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test 02e481ac48c445b43bab7b3cf1e4115165b5127a1aa29e14f5372922c836f1a4
-F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
-F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
-F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
-F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98
-F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb
-F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62
+F test/window1.test e52b81fff0c3cb122a1240f336688eb81bea2967a99c4ddb78969adec7aadc2a
+F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
+F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
+F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
+F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856ef3cb
+F test/window4.tcl 6f85307eb67242b654d051f7da32a996a66aee039a09c5ae358541aa61720742
+F test/window4.test fbead87f681400ac07ef3555e0488b544a47d35491f8bf09a7474b6f76ce9b4e
F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
-F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3
-F test/windowfault.test 12ceb6bbb355d13e8fcd88c5731a57256dfdf77b9a7ae20842a76fcd4623df5b
-F test/with1.test 2465d98ffce80d00553ac7135697c18b0369275b6ecc750daa2af320b8c812ca
-F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
-F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
+F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32
+F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
+F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd
+F test/window8.tcl f2711aa3571e4e6b0dad98db8d95fd6cb8d9db0c92bbdf535f153b07606a1ce2
+F test/window8.test c4331b27a6f66d69fa8f8bab10cc731db1a81d293ae108a68f7c3487fa94e65b
+F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
+F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
+F test/windowB.test 6e601f8178ba8ba28b2f19e74fe613815084bb4a8d2ad942defc7d42e191e521
+F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
+F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
+F test/windowfault.test d543d46571b32d19f198cb04b6505747fabf3cc369970daae47074ee793612be
+F test/windowpushd.test 5b9c114e8173c3addacf58a0fcd941437b14649f2033700184479a13f188ad00
+F test/with1.test 780be387f01e290e768bdfd1827280f9e37ba37223eb4736aba386864fac5a94
+F test/with2.test 000fb95f1f29dae868cea0f41505eb5126077d49eb967ff88f9ee46212ad8863
+F test/with3.test 2f1e05aef7aeef9a741cbf36deeb4be73003dc541921c3abc78becbbf5b7852d
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
+F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
+F test/with6.test 3001b59179cbdc26a8c67ff8f46944e3141fdece9ab064c49bbf08459b67b207
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
-F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f
+F test/without_rowid1.test e4034c0849ccc2e8bb749c69f15bd69bb9fcf8fe77e8d17ce02369604242fe83
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
-F test/without_rowid3.test ea4b59dd1b0d7f5f5e4b7cca978cdb905752a9d7c57dc4344a591dba765a3691
+F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
-F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
+F test/without_rowid6.test 8463b20098e9f75a501a9f17dfb42fffc79068eac0b2775fe56ef2281d2df45e
+F test/without_rowid7.test d7c59a93d726b55812d620f8f284e01904a5b85f9ee9eea8f2f68571a5e8c40e
F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912adec66
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
-F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
+F test/zeroblob.test 07a5b11ab591d1f26c626945fb7f228f68b993533b2ada77273edf6ee29db174
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
-F test/zipfile.test b3b558639f7a103e095713ad0f57fec1fce1b7d60c8054df5789b98f7547a395
+F test/zipfile.test 429cb81c518487fa1b644b6b04b6e9af704a4fa767bd1a110204c5f03b2e8616
F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
-F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
-F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
+F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
+F tool/GetTclKit.bat e95747c0f7a9fe279a9979178b71f6431a21f945b390fc3120244897ff3f5135
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
-F tool/addopcodes.tcl 0288d5b26b9b35f4cb5affb76eec63f1dfce117bbc2020066708069ef60b86ff
F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
-F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
+F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
-F tool/dbhash.c a06228aa21ebc4e6ea8daa486601d938499238a5
+F tool/dbhash.c 5da0c61032d23d74f2ab84ffc5740f0e8abec94f2c45c0b4306be7eb3ae96df0
+F tool/dbtotxt.c b2221864a20fb391c46bd31bc1fbdc4a96f5c8a89bef58f421eb9b9c36b1702c
+F tool/dbtotxt.md c9a57af8739957ef36d2cfad5c4b1443ff3688ed33e4901ee200c8b651f43f3c
+F tool/enlargedb.c 3e8b2612b985cfa7e3e8800031ee191b43ae80de96abb5abbd5eada62651ee21
+F tool/extract-sqlite3h.tcl 069ceab0cee26cba99952bfa08c0b23e35941c837acabe143f0c355d96c9e2eb x
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
-F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
+F tool/fast_vacuum.c c129ae2924a48310c7b766810391da9e8fda532b9f6bd3f9a9e3a799a1b42af9
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/fuzzershell.c e1d90a03ca790d7c331c2aae08ca46ff435f1ae1faa6cb9cc48f4687c18fdc6e
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
+F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 60d1e1eb0f7ebae709f68f1472d77fbf291c5345cd98ff417219da7e74fd09e9
-F tool/lempar.c 452f12d40229847634a160e5666b6c4ec4392fd81941c3443861b48d497054cc
+F tool/lemon.c d44ba4f03427c9bd34b601f315fe77c2b6d4bd215801a0259aeedbcc4c94a95c
+F tool/lempar.c 1d3d075da18681c67ecc66c1f171e7094e18cd2cfba6a8a1bd4f3f639d6656e1
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
-F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
+F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
-F tool/mkkeywordhash.c 1f7f2ac1d9f262c08b67faaca47e6a68262ff39113fa4b27d1db2843b4c33e73
-F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
+F tool/mkkeywordhash.c 08b6e4d7a482a7f37a9a0032e7ba968e26624a027b6b2e9ba589be6f5e3d8c2c
+F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
-F tool/mkpragmatab.tcl a1334e70a08fdf5de32cd0093613212bb11ac8f880487540987175c536ac335f
-F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
-F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
+F tool/mkpragmatab.tcl ae5585ae76ca26e4d6ccd5ea9cdebaf5efefb318bf989497a0e846cd711d9ab1
+F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
+F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
-F tool/mksqlite3c.tcl 5fed3d75069d8f66f202d3b5200b0cea4aa7108481acd06732a06fdd42eb83a2
-F tool/mksqlite3h.tcl 080873e3856eceb9d289a08a00c4b30f875ea3feadcbece796bd509b1532792c
+F tool/mksqlite3c.tcl 00c4c0382eb000153182da2bee2547ca05554eeeed10177efe5894c54e4e6d4d
+F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
-F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
-F tool/omittest.tcl dfc8b18a23e9e5289104145b712cdb887c2d840c2d70dc09ce5dbeba8ed8d47c
+F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
+F tool/omittest.tcl 6616fbf384f0f630113eab27d41d4530435dd94e2883307759988b45f0604a3b
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/replace.tcl 60f91e8dd06ab81f74d213ecbd9c9945f32ac048
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
-F tool/showdb.c e6bc9dba233bf1b57ca0a525a2bba762db4e223de84990739db3f09c46151b1e
+F tool/showdb.c 49e810f5c414c792b5bf38cd5557ca9639713ebfef32aaff32faf7cb7ccce513
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
-F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
+F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c2a1
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
-F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec
-F tool/speed-check.sh 27c7fe178d5b2f7c90a04a127907acda0bfe637fa85b13c43e03e5ed39b008b6
+F tool/spaceanal.tcl a95036b36622e25cffd65a55b22d6af53dfbbff0de02d45dd0059bb3c9978609
+F tool/speed-check.sh 8ba7c7c0dba37e664679974f5954f2282275271a5b92f890756e282df0bfc458
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
-F tool/sqldiff.c 7b9b7238284f02131dbb8f21a4e862409bff728045c5473139d28c67ac87580e
+F tool/sqldiff.c 21226ef092ec1e543b237c5d3d2d32d344a60f2437eadfea04f65b348fbd00e4
F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
-F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
+F tool/symbols.sh 1612bd947750e21e7b47befad5f6b3825b06cce0705441f903bf35ced65ae9b9
F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
@@ -1759,7 +1890,7 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh 09311479bdc290e20ec8e35a3d1b14b096bbd96222277cfd6274c3a99b3d012f
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
-F vsixtest/App.xaml.cpp c465147f50871165c60ca16955219f6c5812d6d8
+F vsixtest/App.xaml.cpp 41158ee43269820136fa3bba00c0bd91b26cc38b650ee392aec2a8d823e54318
F vsixtest/App.xaml.h 4a9768e2983d05600ad1e1c2f1b00a132967da9f
F vsixtest/Assets/LockScreenLogo.scale-200.png e820c9a3deb909197081b0bf3216c06e13905f0a
F vsixtest/Assets/SplashScreen.scale-200.png cab70988ca71bebec7bfeb3b6dbafe17b9ab0b4a
@@ -1779,11 +1910,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 23684cb841ac2cb0d69e5470253bd96feb733762a7553b952a08470834fe85fa
-R dcc394af10af6094607f56a6086fb748
-T +bgcolor * #d0c0ff
+P d917b70a35cce7d82a848b1ff5e8bea182217a2c6a4a3a3d6cc914cc26144ea6
+R eda62fe381e7f0ef5c89c883a9c1cd96
T +sym-release *
-T +sym-version-3.26.0 *
+T +sym-version-3.35.5 *
U drh
-Z 560a5decbb241d53eb97e72267b6e6e8
-# Remove this line to create a well-formed manifest.
+Z d4483274bc32f4bc8681ec9b9f324b4a
diff --git a/chromium/third_party/sqlite/src/src/btree.c b/chromium/third_party/sqlite/src/src/btree.c
index 28d759a8e5f..bc29742da81 100644
--- a/chromium/third_party/sqlite/src/src/btree.c
+++ b/chromium/third_party/sqlite/src/src/btree.c
@@ -51,7 +51,7 @@ int sqlite3BtreeTrace=1; /* True to enable tracing */
#define BTALLOC_LE 2 /* Allocate any page <= the parameter */
/*
-** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
+** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
** defined, or 0 if it is. For example:
**
** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum);
@@ -66,10 +66,10 @@ int sqlite3BtreeTrace=1; /* True to enable tracing */
/*
** A list of BtShared objects that are eligible for participation
** in shared cache. This variable has file scope during normal builds,
-** but the test harness needs to access it so we make it global for
+** but the test harness needs to access it so we make it global for
** test builds.
**
-** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER.
+** Access to this variable is protected by SQLITE_MUTEX_STATIC_MAIN.
*/
#ifdef SQLITE_TEST
BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
@@ -101,7 +101,7 @@ int sqlite3_enable_shared_cache(int enable){
** manipulate entries in the BtShared.pLock linked list used to store
** shared-cache table level locks. If the library is compiled with the
** shared-cache feature disabled, then there is only ever one user
- ** of each BtShared structure and so this locking is not necessary.
+ ** of each BtShared structure and so this locking is not necessary.
** So define the lock related functions as no-ops.
*/
#define querySharedCacheTableLock(a,b,c) SQLITE_OK
@@ -112,6 +112,17 @@ int sqlite3_enable_shared_cache(int enable){
#define hasReadConflicts(a, b) 0
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Return and reset the seek counter for a Btree object.
+*/
+sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){
+ u64 n = pBt->nSeek;
+ pBt->nSeek = 0;
+ return n;
+}
+#endif
+
/*
** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
** (MemPage*) as an argument. The (MemPage*) must not be NULL.
@@ -146,15 +157,15 @@ int corruptPageError(int lineno, MemPage *p){
/*
**** This function is only used as part of an assert() statement. ***
**
-** Check to see if pBtree holds the required locks to read or write to the
+** Check to see if pBtree holds the required locks to read or write to the
** table with root page iRoot. Return 1 if it does and 0 if not.
**
-** For example, when writing to a table with root-page iRoot via
+** For example, when writing to a table with root-page iRoot via
** Btree connection pBtree:
**
** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) );
**
-** When writing to an index that resides in a sharable database, the
+** When writing to an index that resides in a sharable database, the
** caller should have first obtained a lock specifying the root page of
** the corresponding table. This makes things a bit more complicated,
** as this module treats each table as a separate structure. To determine
@@ -176,7 +187,7 @@ static int hasSharedCacheTableLock(
BtLock *pLock;
/* If this database is not shareable, or if the client is reading
- ** and has the read-uncommitted flag set, then no lock is required.
+ ** and has the read-uncommitted flag set, then no lock is required.
** Return true immediately.
*/
if( (pBtree->sharable==0)
@@ -200,29 +211,31 @@ static int hasSharedCacheTableLock(
** table. */
if( isIndex ){
HashElem *p;
+ int bSeen = 0;
for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
Index *pIdx = (Index *)sqliteHashData(p);
if( pIdx->tnum==(int)iRoot ){
- if( iTab ){
+ if( bSeen ){
/* Two or more indexes share the same root page. There must
** be imposter tables. So just return true. The assert is not
** useful in that case. */
return 1;
}
iTab = pIdx->pTable->tnum;
+ bSeen = 1;
}
}
}else{
iTab = iRoot;
}
- /* Search for the required lock. Either a write-lock on root-page iTab, a
+ /* Search for the required lock. Either a write-lock on root-page iTab, a
** write-lock on the schema table, or (if the client is reading) a
** read-lock on iTab will suffice. Return 1 if any of these are found. */
for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){
- if( pLock->pBtree==pBtree
+ if( pLock->pBtree==pBtree
&& (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1))
- && pLock->eLock>=eLockType
+ && pLock->eLock>=eLockType
){
return 1;
}
@@ -255,7 +268,7 @@ static int hasSharedCacheTableLock(
static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
BtCursor *p;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- if( p->pgnoRoot==iRoot
+ if( p->pgnoRoot==iRoot
&& p->pBtree!=pBtree
&& 0==(p->pBtree->db->flags & SQLITE_ReadUncommit)
){
@@ -267,7 +280,7 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
#endif /* #ifdef SQLITE_DEBUG */
/*
-** Query to see if Btree handle p may obtain a lock of type eLock
+** Query to see if Btree handle p may obtain a lock of type eLock
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
** SQLITE_OK if the lock may be obtained (by calling
** setSharedCacheTableLock()), or SQLITE_LOCKED if not.
@@ -280,14 +293,14 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 );
-
+
/* If requesting a write-lock, then the Btree must have an open write
- ** transaction on this file. And, obviously, for this to be so there
+ ** transaction on this file. And, obviously, for this to be so there
** must be an open write transaction on the file itself.
*/
assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
-
+
/* This routine is a no-op if the shared-cache is not enabled */
if( !p->sharable ){
return SQLITE_OK;
@@ -302,7 +315,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
}
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- /* The condition (pIter->eLock!=eLock) in the following if(...)
+ /* The condition (pIter->eLock!=eLock) in the following if(...)
** statement is a simplification of:
**
** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
@@ -329,7 +342,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** Add a lock on the table with root-page iTable to the shared-btree used
-** by Btree handle p. Parameter eLock must be either READ_LOCK or
+** by Btree handle p. Parameter eLock must be either READ_LOCK or
** WRITE_LOCK.
**
** This function assumes the following:
@@ -341,7 +354,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
** with the requested lock (i.e. querySharedCacheTableLock() has
** already been called and returned SQLITE_OK).
**
-** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
+** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
** is returned if a malloc attempt fails.
*/
static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
@@ -355,11 +368,11 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
/* A connection with the read-uncommitted flag set will never try to
** obtain a read-lock using this function. The only read-lock obtained
- ** by a connection in read-uncommitted mode is on the sqlite_master
+ ** by a connection in read-uncommitted mode is on the sqlite_schema
** table, and that lock is obtained in BtreeBeginTrans(). */
assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK );
- /* This function should only be called on a sharable b-tree after it
+ /* This function should only be called on a sharable b-tree after it
** has been determined that no other b-tree holds a conflicting lock. */
assert( p->sharable );
assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) );
@@ -404,7 +417,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
** Release all the table locks (locks obtained via calls to
** the setSharedCacheTableLock() procedure) held by Btree object p.
**
-** This function assumes that Btree p has an open read or write
+** This function assumes that Btree p has an open read or write
** transaction. If it does not, then the BTS_PENDING flag
** may be incorrectly cleared.
*/
@@ -436,7 +449,7 @@ static void clearAllSharedCacheTableLocks(Btree *p){
pBt->pWriter = 0;
pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
}else if( pBt->nTransaction==2 ){
- /* This function is called when Btree p is concluding its
+ /* This function is called when Btree p is concluding its
** transaction. If there currently exists a writer, and p is not
** that writer, then the number of locks held by connections other
** than the writer must be about to drop to zero. In this case
@@ -482,7 +495,7 @@ static int cursorHoldsMutex(BtCursor *p){
}
/* Verify that the cursor and the BtShared agree about what is the current
-** database connetion. This is important in shared-cache mode. If the database
+** database connetion. This is important in shared-cache mode. If the database
** connection pointers get out-of-sync, it is possible for routines like
** btreeInitPage() to reference an stale connection pointer that references a
** a connection that has already closed. This routine is used inside assert()
@@ -553,8 +566,8 @@ static void invalidateIncrblobCursors(
#endif /* SQLITE_OMIT_INCRBLOB */
/*
-** Set bit pgno of the BtShared.pHasContent bitvec. This is called
-** when a page that previously contained data becomes a free-list leaf
+** Set bit pgno of the BtShared.pHasContent bitvec. This is called
+** when a page that previously contained data becomes a free-list leaf
** page.
**
** The BtShared.pHasContent bitvec exists to work around an obscure
@@ -580,7 +593,7 @@ static void invalidateIncrblobCursors(
** may be lost. In the event of a rollback, it may not be possible
** to restore the database to its original configuration.
**
-** The solution is the BtShared.pHasContent bitvec. Whenever a page is
+** The solution is the BtShared.pHasContent bitvec. Whenever a page is
** moved to become a free-list leaf page, the corresponding bit is
** set in the bitvec. Whenever a leaf page is extracted from the free-list,
** optimization 2 above is omitted if the corresponding bit is already
@@ -611,7 +624,7 @@ static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
*/
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
Bitvec *p = pBt->pHasContent;
- return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
+ return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno));
}
/*
@@ -641,13 +654,13 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){
** The cursor passed as the only argument must point to a valid entry
** when this function is called (i.e. have eState==CURSOR_VALID). This
** function saves the current cursor key in variables pCur->nKey and
-** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error
+** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error
** code otherwise.
**
** If the cursor is open on an intkey table, then the integer key
** (the rowid) is stored in pCur->nKey and pCur->pKey is left set to
-** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is
-** set to point to a malloced buffer pCur->nKey bytes in size containing
+** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is
+** set to point to a malloced buffer pCur->nKey bytes in size containing
** the key.
*/
static int saveCursorKey(BtCursor *pCur){
@@ -660,13 +673,19 @@ static int saveCursorKey(BtCursor *pCur){
/* Only the rowid is required for a table btree */
pCur->nKey = sqlite3BtreeIntegerKey(pCur);
}else{
- /* For an index btree, save the complete key content */
+ /* For an index btree, save the complete key content. It is possible
+ ** that the current key is corrupt. In that case, it is possible that
+ ** the sqlite3VdbeRecordUnpack() function may overread the buffer by
+ ** up to the size of 1 varint plus 1 8-byte value when the cursor
+ ** position is restored. Hence the 17 bytes of padding allocated
+ ** below. */
void *pKey;
pCur->nKey = sqlite3BtreePayloadSize(pCur);
- pKey = sqlite3Malloc( pCur->nKey );
+ pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
if( pKey ){
rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
+ memset(((u8*)pKey)+pCur->nKey, 0, 9+8);
pCur->pKey = pKey;
}else{
sqlite3_free(pKey);
@@ -680,11 +699,11 @@ static int saveCursorKey(BtCursor *pCur){
}
/*
-** Save the current cursor position in the variables BtCursor.nKey
+** Save the current cursor position in the variables BtCursor.nKey
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
**
** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
-** prior to calling this routine.
+** prior to calling this routine.
*/
static int saveCursorPosition(BtCursor *pCur){
int rc;
@@ -693,6 +712,9 @@ static int saveCursorPosition(BtCursor *pCur){
assert( 0==pCur->pKey );
assert( cursorHoldsMutex(pCur) );
+ if( pCur->curFlags & BTCF_Pinned ){
+ return SQLITE_CONSTRAINT_PINNED;
+ }
if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
}else{
@@ -720,7 +742,7 @@ static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*);
** routine is called just before cursor pExcept is used to modify the
** table, for example in BtreeDelete() or BtreeInsert().
**
-** If there are two or more cursors on the same btree, then all such
+** If there are two or more cursors on the same btree, then all such
** cursors should have their BTCF_Multiple flag set. The btreeCursor()
** routine enforces that rule. This routine only needs to be called in
** the uncommon case when pExpect has the BTCF_Multiple flag set.
@@ -798,11 +820,12 @@ static int btreeMoveto(
UnpackedRecord *pIdxKey; /* Unpacked index key */
if( pKey ){
+ KeyInfo *pKeyInfo = pCur->pKeyInfo;
assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
- if( pIdxKey->nField==0 ){
+ sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+ if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_done;
}
@@ -819,26 +842,30 @@ moveto_done:
/*
** Restore the cursor to the position it was in (or as close to as possible)
-** when saveCursorPosition() was called. Note that this call deletes the
+** when saveCursorPosition() was called. Note that this call deletes the
** saved position info stored by saveCursorPosition(), so there can be
-** at most one effective restoreCursorPosition() call after each
+** at most one effective restoreCursorPosition() call after each
** saveCursorPosition().
*/
static int btreeRestoreCursorPosition(BtCursor *pCur){
int rc;
- int skipNext;
+ int skipNext = 0;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState>=CURSOR_REQUIRESEEK );
if( pCur->eState==CURSOR_FAULT ){
return pCur->skipNext;
}
pCur->eState = CURSOR_INVALID;
- rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
+ if( sqlite3FaultSim(410) ){
+ rc = SQLITE_IOERR;
+ }else{
+ rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
+ }
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
- pCur->skipNext |= skipNext;
+ if( skipNext ) pCur->skipNext = skipNext;
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
pCur->eState = CURSOR_SKIPNEXT;
}
@@ -885,7 +912,7 @@ BtCursor *sqlite3BtreeFakeValidCursor(void){
/*
** This routine restores a cursor back to its original position after it
** has been moved by some outside activity (such as a btree rebalance or
-** a row having been deleted out from under the cursor).
+** a row having been deleted out from under the cursor).
**
** On success, the *pDifferentRow parameter is false if the cursor is left
** pointing at exactly the same row. *pDifferntRow is the row the cursor
@@ -908,7 +935,6 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
if( pCur->eState!=CURSOR_VALID ){
*pDifferentRow = 1;
}else{
- assert( pCur->skipNext==0 );
*pDifferentRow = 0;
}
return SQLITE_OK;
@@ -951,7 +977,7 @@ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
if( pgno<2 ) return 0;
nPagesPerMapPage = (pBt->usableSize/5)+1;
iPtrMap = (pgno-2)/nPagesPerMapPage;
- ret = (iPtrMap*nPagesPerMapPage) + 2;
+ ret = (iPtrMap*nPagesPerMapPage) + 2;
if( ret==PENDING_BYTE_PAGE(pBt) ){
ret++;
}
@@ -978,7 +1004,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
if( *pRC ) return;
assert( sqlite3_mutex_held(pBt->mutex) );
- /* The master-journal page number must never be used as a pointer map page */
+ /* The super-journal page number must never be used as a pointer map page */
assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
assert( pBt->autoVacuum );
@@ -1061,7 +1087,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
#else /* if defined SQLITE_OMIT_AUTOVACUUM */
#define ptrmapPut(w,x,y,z,rc)
#define ptrmapGet(w,x,y,z) SQLITE_OK
- #define ptrmapPutOvflPtr(x, y, rc)
+ #define ptrmapPutOvflPtr(x, y, z, rc)
#endif
/*
@@ -1118,6 +1144,24 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
}
/*
+** Given a record with nPayload bytes of payload stored within btree
+** page pPage, return the number of bytes of payload stored locally.
+*/
+static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
+ int maxLocal; /* Maximum amount of payload held locally */
+ maxLocal = pPage->maxLocal;
+ if( nPayload<=maxLocal ){
+ return nPayload;
+ }else{
+ int minLocal; /* Minimum amount of payload held locally */
+ int surplus; /* Overflow payload available for local storage */
+ minLocal = pPage->minLocal;
+ surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
+ return ( surplus <= maxLocal ) ? surplus : minLocal;
+ }
+}
+
+/*
** The following routines are implementations of the MemPage.xParseCell()
** method.
**
@@ -1297,7 +1341,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
}
pIter++;
if( pPage->intKey ){
- /* pIter now points at the 64-bit integer key value, a variable length
+ /* pIter now points at the 64-bit integer key value, a variable length
** integer. The following block moves pIter to point at the first byte
** past the end of the key value. */
pEnd = &pIter[9];
@@ -1354,18 +1398,20 @@ static u16 cellSize(MemPage *pPage, int iCell){
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
-** If the cell pCell, part of page pPage contains a pointer
-** to an overflow page, insert an entry into the pointer-map
-** for the overflow page.
+** The cell pCell is currently part of page pSrc but will ultimately be part
+** of pPage. (pSrc and pPager are often the same.) If pCell contains a
+** pointer to an overflow page, insert an entry into the pointer-map for
+** the overflow page that will be valid after pCell has been moved to pPage.
*/
-static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
+static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
CellInfo info;
if( *pRC ) return;
assert( pCell!=0 );
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
Pgno ovfl;
- if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
+ if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
+ testcase( pSrc!=pPage );
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
@@ -1413,30 +1459,21 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
hdr = pPage->hdrOffset;
cellOffset = pPage->cellOffset;
nCell = pPage->nCell;
- assert( nCell==get2byte(&data[hdr+3]) );
+ assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB );
iCellFirst = cellOffset + 2*nCell;
usableSize = pPage->pBt->usableSize;
/* This block handles pages with two or fewer free blocks and nMaxFrag
** or fewer fragmented bytes. In this case it is faster to move the
** two (or one) blocks of cells using memmove() and add the required
- ** offsets to each pointer in the cell-pointer array than it is to
+ ** offsets to each pointer in the cell-pointer array than it is to
** reconstruct the entire page. */
if( (int)data[hdr+7]<=nMaxFrag ){
int iFree = get2byte(&data[hdr+1]);
+ if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
if( iFree ){
int iFree2 = get2byte(&data[iFree]);
-
- /* pageFindSlot() has already verified that free blocks are sorted
- ** in order of offset within the page, and that no block extends
- ** past the end of the page. Provided the two free slots do not
- ** overlap, this guarantees that the memmove() calls below will not
- ** overwrite the usableSize byte buffer, even if the database page
- ** is corrupt. */
- assert( iFree2==0 || iFree2>iFree );
- assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
- assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
-
+ if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
u8 *pEnd = &data[cellOffset + nCell*2];
u8 *pAddr;
@@ -1447,12 +1484,15 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
return SQLITE_CORRUPT_PAGE(pPage);
}
if( iFree2 ){
- assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
+ if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
sz2 = get2byte(&data[iFree2+2]);
- assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
+ if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
+ }else if( NEVER(iFree+sz>usableSize) ){
+ return SQLITE_CORRUPT_PAGE(pPage);
}
+
cbrk = top+sz;
assert( cbrk+(iFree-top) <= usableSize );
memmove(&data[cbrk], &data[top], iFree-top);
@@ -1503,6 +1543,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
data[hdr+7] = 0;
defragment_out:
+ assert( pPage->nFree>=0 );
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -1530,16 +1571,16 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
** causes the fragmentation count to exceed 60.
*/
static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
- const int hdr = pPg->hdrOffset;
- u8 * const aData = pPg->aData;
- int iAddr = hdr + 1;
- int pc = get2byte(&aData[iAddr]);
- int x;
- int usableSize = pPg->pBt->usableSize;
- int size; /* Size of the free slot */
+ const int hdr = pPg->hdrOffset; /* Offset to page header */
+ u8 * const aData = pPg->aData; /* Page data */
+ int iAddr = hdr + 1; /* Address of ptr to pc */
+ int pc = get2byte(&aData[iAddr]); /* Address of a free slot */
+ int x; /* Excess size of the slot */
+ int maxPC = pPg->pBt->usableSize - nByte; /* Max address for a usable slot */
+ int size; /* Size of the free slot */
assert( pc>0 );
- while( pc<=usableSize-4 ){
+ while( pc<=maxPC ){
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
** freeblock form a big-endian integer which is the size of the freeblock
** in bytes, including the 4-byte header. */
@@ -1547,10 +1588,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
if( (x = size - nByte)>=0 ){
testcase( x==4 );
testcase( x==3 );
- if( size+pc > usableSize ){
- *pRc = SQLITE_CORRUPT_PAGE(pPg);
- return 0;
- }else if( x<4 ){
+ if( x<4 ){
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
** number of bytes in fragments may not exceed 60. */
if( aData[hdr+7]>57 ) return 0;
@@ -1559,21 +1597,31 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
+ }else if( x+pc > maxPC ){
+ /* This slot extends off the end of the usable part of the page */
+ *pRc = SQLITE_CORRUPT_PAGE(pPg);
+ return 0;
}else{
/* The slot remains on the free-list. Reduce its size to account
- ** for the portion used by the new allocation. */
+ ** for the portion used by the new allocation. */
put2byte(&aData[pc+2], x);
}
return &aData[pc + x];
}
iAddr = pc;
pc = get2byte(&aData[pc]);
- if( pc<iAddr+size ) break;
+ if( pc<=iAddr+size ){
+ if( pc ){
+ /* The next slot in the chain is not past the end of the current slot */
+ *pRc = SQLITE_CORRUPT_PAGE(pPg);
+ }
+ return 0;
+ }
}
- if( pc ){
+ if( pc>maxPC+nByte-4 ){
+ /* The free slot chain extends off the end of the page */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
}
-
return 0;
}
@@ -1596,7 +1644,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
int top; /* First byte of cell content area */
int rc = SQLITE_OK; /* Integer return code */
int gap; /* First byte of gap between cell pointers and cell content */
-
+
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
@@ -1614,7 +1662,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** However, that integer is too large to be stored in a 2-byte unsigned
** integer, so a value of 0 is used in its place. */
top = get2byte(&data[hdr+5]);
- assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */
+ assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */
if( gap>top ){
if( top==0 && pPage->pBt->usableSize==65536 ){
top = 65536;
@@ -1623,9 +1671,9 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
}
}
- /* If there is enough space between gap and top for one more cell pointer
- ** array entry offset, and if the freelist is not empty, then search the
- ** freelist looking for a free slot big enough to satisfy the request.
+ /* If there is enough space between gap and top for one more cell pointer,
+ ** and if the freelist is not empty, then search the
+ ** freelist looking for a slot big enough to satisfy the request.
*/
testcase( gap+2==top );
testcase( gap+1==top );
@@ -1633,9 +1681,14 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
if( pSpace ){
- assert( pSpace>=data && (pSpace - data)<65536 );
- *pIdx = (int)(pSpace - data);
- return SQLITE_OK;
+ int g2;
+ assert( pSpace+nByte<=data+pPage->pBt->usableSize );
+ *pIdx = g2 = (int)(pSpace-data);
+ if( NEVER(g2<=gap) ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }else{
+ return SQLITE_OK;
+ }
}else if( rc ){
return rc;
}
@@ -1647,6 +1700,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){
assert( pPage->nCell>0 || CORRUPT_DB );
+ assert( pPage->nFree>=0 );
rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]);
@@ -1655,7 +1709,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
/* Allocate memory from the gap in between the cell pointer array
- ** and the cell content area. The btreeInitPage() call has already
+ ** and the cell content area. The btreeComputeFreeSpace() call has already
** validated the freelist. Given that the freelist is valid, there
** is no way that the allocation can extend off the end of the page.
** The assert() below verifies the previous sentence.
@@ -1674,7 +1728,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
**
** Adjacent freeblocks are coalesced.
**
-** Note that even though the freeblock list was checked by btreeInitPage(),
+** Even though the freeblock list was checked by btreeComputeFreeSpace(),
** that routine will not detect overlap between cells or freeblocks. Nor
** does it detect cells or freeblocks that encrouch into the reserved bytes
** at the end of the page. So do additional corruption checks inside this
@@ -1698,7 +1752,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
assert( iSize>=4 ); /* Minimum cell size is 4 */
assert( iStart<=pPage->pBt->usableSize-4 );
- /* The list of freeblocks must be in ascending order. Find the
+ /* The list of freeblocks must be in ascending order. Find the
** spot on the list where iStart should be inserted.
*/
hdr = pPage->hdrOffset;
@@ -1708,16 +1762,16 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}else{
while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
if( iFreeBlk<iPtr+4 ){
- if( iFreeBlk==0 ) break;
+ if( iFreeBlk==0 ) break; /* TH3: corrupt082.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
iPtr = iFreeBlk;
}
- if( iFreeBlk>pPage->pBt->usableSize-4 ){
+ if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( iFreeBlk>iPtr || iFreeBlk==0 );
-
+
/* At this point:
** iFreeBlk: First freeblock after iStart, or zero if none
** iPtr: The address of a pointer to iFreeBlk
@@ -1734,7 +1788,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
-
+
/* If iPtr is another freeblock (that is, if iPtr is not the freelist
** pointer in the page header) then check to see if iStart should be
** coalesced onto the end of iPtr.
@@ -1756,7 +1810,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
** freelist entry */
- if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
+ if( iStart<x ) return SQLITE_CORRUPT_PAGE(pPage);
+ if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
put2byte(&data[hdr+1], iFreeBlk);
put2byte(&data[hdr+5], iEnd);
}else{
@@ -1836,21 +1891,14 @@ static int decodeFlags(MemPage *pPage, int flagByte){
}
/*
-** Initialize the auxiliary information for a disk block.
-**
-** Return SQLITE_OK on success. If we see that the page does
-** not contain a well-formed database page, then return
-** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
-** guarantee that the page is well-formed. It only shows that
-** we failed to detect any corruption.
+** Compute the amount of freespace on the page. In other words, fill
+** in the pPage->nFree field.
*/
-static int btreeInitPage(MemPage *pPage){
+static int btreeComputeFreeSpace(MemPage *pPage){
int pc; /* Address of a freeblock within pPage->aData[] */
u8 hdr; /* Offset to beginning of page header */
u8 *data; /* Equal to pPage->aData */
- BtShared *pBt; /* The main btree structure */
int usableSize; /* Amount of usable space on each page */
- u16 cellOffset; /* Offset from start of page to first cell pointer */
int nFree; /* Number of unused bytes on the page */
int top; /* First byte of the cell content area */
int iCellFirst; /* First allowable cell or freeblock offset */
@@ -1862,71 +1910,18 @@ static int btreeInitPage(MemPage *pPage){
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
- assert( pPage->isInit==0 );
+ assert( pPage->isInit==1 );
+ assert( pPage->nFree<0 );
- pBt = pPage->pBt;
+ usableSize = pPage->pBt->usableSize;
hdr = pPage->hdrOffset;
data = pPage->aData;
- /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
- ** the b-tree page type. */
- if( decodeFlags(pPage, data[hdr]) ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
- pPage->maskPage = (u16)(pBt->pageSize - 1);
- pPage->nOverflow = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
- pPage->aDataEnd = &data[usableSize];
- pPage->aCellIdx = &data[cellOffset];
- pPage->aDataOfst = &data[pPage->childPtrSize];
/* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
** the start of the cell content area. A zero value for this integer is
** interpreted as 65536. */
top = get2byteNotZero(&data[hdr+5]);
- /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
- ** number of cells on the page. */
- pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL(pBt) ){
- /* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- testcase( pPage->nCell==MX_CELL(pBt) );
- /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
- ** possible for a root page of a table that contains no rows) then the
- ** offset to the cell content area will equal the page size minus the
- ** bytes of reserved space. */
- assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
-
- /* A malformed database page might cause us to read past the end
- ** of page when parsing a cell.
- **
- ** The following block of code checks early to see if a cell extends
- ** past the end of a page boundary and causes SQLITE_CORRUPT to be
- ** returned if it does.
- */
- iCellFirst = cellOffset + 2*pPage->nCell;
+ iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell;
iCellLast = usableSize - 4;
- if( pBt->db->flags & SQLITE_CellSizeCk ){
- int i; /* Index into the cell pointer array */
- int sz; /* Size of a cell */
-
- if( !pPage->leaf ) iCellLast--;
- for(i=0; i<pPage->nCell; i++){
- pc = get2byteAligned(&data[cellOffset+i*2]);
- testcase( pc==iCellFirst );
- testcase( pc==iCellLast );
- if( pc<iCellFirst || pc>iCellLast ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- sz = pPage->xCellSize(pPage, &data[pc]);
- testcase( pc+sz==usableSize );
- if( pc+sz>usableSize ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- }
- if( !pPage->leaf ) iCellLast++;
- }
/* Compute the total free space on the page
** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
@@ -1936,11 +1931,11 @@ static int btreeInitPage(MemPage *pPage){
nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
if( pc>0 ){
u32 next, size;
- if( pc<iCellFirst ){
+ if( pc<top ){
/* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
** always be at least one cell before the first freeblock.
*/
- return SQLITE_CORRUPT_PAGE(pPage);
+ return SQLITE_CORRUPT_PAGE(pPage);
}
while( 1 ){
if( pc>iCellLast ){
@@ -1970,11 +1965,104 @@ static int btreeInitPage(MemPage *pPage){
** serves to verify that the offset to the start of the cell-content
** area, according to the page header, lies within the page.
*/
- if( nFree>usableSize ){
+ if( nFree>usableSize || nFree<iCellFirst ){
return SQLITE_CORRUPT_PAGE(pPage);
}
pPage->nFree = (u16)(nFree - iCellFirst);
+ return SQLITE_OK;
+}
+
+/*
+** Do additional sanity check after btreeInitPage() if
+** PRAGMA cell_size_check=ON
+*/
+static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){
+ int iCellFirst; /* First allowable cell or freeblock offset */
+ int iCellLast; /* Last possible cell or freeblock offset */
+ int i; /* Index into the cell pointer array */
+ int sz; /* Size of a cell */
+ int pc; /* Address of a freeblock within pPage->aData[] */
+ u8 *data; /* Equal to pPage->aData */
+ int usableSize; /* Maximum usable space on the page */
+ int cellOffset; /* Start of cell content area */
+
+ iCellFirst = pPage->cellOffset + 2*pPage->nCell;
+ usableSize = pPage->pBt->usableSize;
+ iCellLast = usableSize - 4;
+ data = pPage->aData;
+ cellOffset = pPage->cellOffset;
+ if( !pPage->leaf ) iCellLast--;
+ for(i=0; i<pPage->nCell; i++){
+ pc = get2byteAligned(&data[cellOffset+i*2]);
+ testcase( pc==iCellFirst );
+ testcase( pc==iCellLast );
+ if( pc<iCellFirst || pc>iCellLast ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ sz = pPage->xCellSize(pPage, &data[pc]);
+ testcase( pc+sz==usableSize );
+ if( pc+sz>usableSize ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Initialize the auxiliary information for a disk block.
+**
+** Return SQLITE_OK on success. If we see that the page does
+** not contain a well-formed database page, then return
+** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
+** guarantee that the page is well-formed. It only shows that
+** we failed to detect any corruption.
+*/
+static int btreeInitPage(MemPage *pPage){
+ u8 *data; /* Equal to pPage->aData */
+ BtShared *pBt; /* The main btree structure */
+
+ assert( pPage->pBt!=0 );
+ assert( pPage->pBt->db!=0 );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
+ assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
+ assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+ assert( pPage->isInit==0 );
+
+ pBt = pPage->pBt;
+ data = pPage->aData + pPage->hdrOffset;
+ /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
+ ** the b-tree page type. */
+ if( decodeFlags(pPage, data[0]) ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+ pPage->maskPage = (u16)(pBt->pageSize - 1);
+ pPage->nOverflow = 0;
+ pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
+ pPage->aCellIdx = data + pPage->childPtrSize + 8;
+ pPage->aDataEnd = pPage->aData + pBt->usableSize;
+ pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
+ /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
+ ** number of cells on the page. */
+ pPage->nCell = get2byte(&data[3]);
+ if( pPage->nCell>MX_CELL(pBt) ){
+ /* To many cells for a single page. The page must be corrupt */
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ testcase( pPage->nCell==MX_CELL(pBt) );
+ /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
+ ** possible for a root page of a table that contains no rows) then the
+ ** offset to the cell content area will equal the page size minus the
+ ** bytes of reserved space. */
+ assert( pPage->nCell>0
+ || get2byteNotZero(&data[5])==(int)pBt->usableSize
+ || CORRUPT_DB );
+ pPage->nFree = -1; /* Indicate that this value is yet uncomputed */
pPage->isInit = 1;
+ if( pBt->db->flags & SQLITE_CellSizeCk ){
+ return btreeCellSizeCheck(pPage);
+ }
return SQLITE_OK;
}
@@ -2029,7 +2117,7 @@ static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
pPage->hdrOffset = pgno==1 ? 100 : 0;
}
assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
- return pPage;
+ return pPage;
}
/*
@@ -2082,9 +2170,8 @@ static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
static Pgno btreePagecount(BtShared *pBt){
return pBt->nPage;
}
-u32 sqlite3BtreeLastPage(Btree *p){
+Pgno sqlite3BtreeLastPage(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
- assert( ((p->pBt->nPage)&0x80000000)==0 );
return btreePagecount(p->pBt);
}
@@ -2117,19 +2204,18 @@ static int getAndInitPage(
if( pgno>btreePagecount(pBt) ){
rc = SQLITE_CORRUPT_BKPT;
- goto getAndInitPage_error;
+ goto getAndInitPage_error1;
}
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
if( rc ){
- goto getAndInitPage_error;
+ goto getAndInitPage_error1;
}
*ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
if( (*ppPage)->isInit==0 ){
btreePageFromDbPage(pDbPage, pgno, pBt);
rc = btreeInitPage(*ppPage);
if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
- goto getAndInitPage_error;
+ goto getAndInitPage_error2;
}
}
assert( (*ppPage)->pgno==pgno );
@@ -2139,12 +2225,13 @@ static int getAndInitPage(
** compatible with the root page. */
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
rc = SQLITE_CORRUPT_PGNO(pgno);
- releasePage(*ppPage);
- goto getAndInitPage_error;
+ goto getAndInitPage_error2;
}
return SQLITE_OK;
-getAndInitPage_error:
+getAndInitPage_error2:
+ releasePage(*ppPage);
+getAndInitPage_error1:
if( pCur ){
pCur->iPage--;
pCur->pPage = pCur->apPage[pCur->iPage];
@@ -2247,17 +2334,16 @@ static int btreeInvokeBusyHandler(void *pArg){
BtShared *pBt = (BtShared*)pArg;
assert( pBt->db );
assert( sqlite3_mutex_held(pBt->db->mutex) );
- return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
- sqlite3PagerFile(pBt->pPager));
+ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
}
/*
** Open a database file.
-**
+**
** zFilename is the name of the database file. If zFilename is NULL
** then an ephemeral database is created. The ephemeral database might
** be exclusively in memory, or it might use a disk-based memory cache.
-** Either way, the ephemeral database will be automatically deleted
+** Either way, the ephemeral database will be automatically deleted
** when sqlite3BtreeClose() is called.
**
** If zFilename is ":memory:" then an in-memory database is created
@@ -2290,7 +2376,7 @@ int sqlite3BtreeOpen(
/* True if opening an ephemeral, temporary database */
const int isTempDb = zFilename==0 || zFilename[0]==0;
- /* Set the variable isMemdb to true for an in-memory database, or
+ /* Set the variable isMemdb to true for an in-memory database, or
** false for a file-based database.
*/
#ifdef SQLITE_OMIT_MEMORYDB
@@ -2352,15 +2438,19 @@ int sqlite3BtreeOpen(
rc = sqlite3OsFullPathname(pVfs, zFilename,
nFullPathname, zFullPathname);
if( rc ){
- sqlite3_free(zFullPathname);
- sqlite3_free(p);
- return rc;
+ if( rc==SQLITE_OK_SYMLINK ){
+ rc = SQLITE_OK;
+ }else{
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return rc;
+ }
}
}
#if SQLITE_THREADSAFE
mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
sqlite3_mutex_enter(mutexOpen);
- mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
sqlite3_mutex_enter(mutexShared);
#endif
for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
@@ -2409,7 +2499,7 @@ int sqlite3BtreeOpen(
assert( sizeof(u32)==4 );
assert( sizeof(u16)==2 );
assert( sizeof(Pgno)==4 );
-
+
pBt = sqlite3MallocZero( sizeof(*pBt) );
if( pBt==0 ){
rc = SQLITE_NOMEM_BKPT;
@@ -2428,7 +2518,7 @@ int sqlite3BtreeOpen(
pBt->db = db;
sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
-
+
pBt->pCursor = 0;
pBt->pPage1 = 0;
if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
@@ -2472,14 +2562,14 @@ int sqlite3BtreeOpen(
if( rc ) goto btree_open_out;
pBt->usableSize = pBt->pageSize - nReserve;
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
-
+
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
/* Add the new BtShared object to the linked list sharable BtShareds.
*/
pBt->nRef = 1;
if( p->sharable ){
MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
- MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
+ MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);)
if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
@@ -2544,7 +2634,7 @@ btree_open_out:
** do not change the pager-cache size.
*/
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
- sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
+ sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE);
}
pFile = sqlite3PagerFile(pBt->pPager);
@@ -2568,13 +2658,13 @@ btree_open_out:
*/
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
- MUTEX_LOGIC( sqlite3_mutex *pMaster; )
+ MUTEX_LOGIC( sqlite3_mutex *pMainMtx; )
BtShared *pList;
int removed = 0;
assert( sqlite3_mutex_notheld(pBt->mutex) );
- MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
- sqlite3_mutex_enter(pMaster);
+ MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
+ sqlite3_mutex_enter(pMainMtx);
pBt->nRef--;
if( pBt->nRef<=0 ){
if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
@@ -2593,7 +2683,7 @@ static int removeFromSharingList(BtShared *pBt){
}
removed = 1;
}
- sqlite3_mutex_leave(pMaster);
+ sqlite3_mutex_leave(pMainMtx);
return removed;
#else
return 1;
@@ -2601,7 +2691,7 @@ static int removeFromSharingList(BtShared *pBt){
}
/*
-** Make sure pBt->pTmpSpace points to an allocation of
+** Make sure pBt->pTmpSpace points to an allocation of
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
** pointer.
*/
@@ -2616,7 +2706,7 @@ static void allocateTempSpace(BtShared *pBt){
** can mean that fillInCell() only initializes the first 2 or 3
** bytes of pTmpSpace, but that the first 4 bytes are copied from
** it into a database page. This is not actually a problem, but it
- ** does cause a valgrind error when the 1 or 2 bytes of unitialized
+ ** does cause a valgrind error when the 1 or 2 bytes of unitialized
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
@@ -2647,19 +2737,23 @@ static void freeTempSpace(BtShared *pBt){
*/
int sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
- BtCursor *pCur;
/* Close all cursors opened via this handle. */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
- pCur = pBt->pCursor;
- while( pCur ){
- BtCursor *pTmp = pCur;
- pCur = pCur->pNext;
- if( pTmp->pBtree==p ){
- sqlite3BtreeCloseCursor(pTmp);
+
+ /* Verify that no other cursors have this Btree open */
+#ifdef SQLITE_DEBUG
+ {
+ BtCursor *pCur = pBt->pCursor;
+ while( pCur ){
+ BtCursor *pTmp = pCur;
+ pCur = pCur->pNext;
+ assert( pTmp->pBtree!=p );
+
}
}
+#endif
/* Rollback any active transaction and free the handle structure.
** The call to sqlite3BtreeRollback() drops any table-locks held by
@@ -2669,7 +2763,7 @@ int sqlite3BtreeClose(Btree *p){
sqlite3BtreeLeave(p);
/* If there are still other outstanding references to the shared-btree
- ** structure, return now. The remainder of this procedure cleans
+ ** structure, return now. The remainder of this procedure cleans
** up the shared-btree.
*/
assert( p->wantToLock==0 && p->locked==0 );
@@ -2775,7 +2869,7 @@ int sqlite3BtreeSetPagerFlags(
/*
** Change the default pages size and the number of reserved bytes per page.
-** Or, if the page size has already been fixed, return SQLITE_READONLY
+** Or, if the page size has already been fixed, return SQLITE_READONLY
** without changing anything.
**
** The page size must be a power of 2 between 512 and 65536. If the page
@@ -2795,24 +2889,23 @@ int sqlite3BtreeSetPagerFlags(
*/
int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
int rc = SQLITE_OK;
+ int x;
BtShared *pBt = p->pBt;
- assert( nReserve>=-1 && nReserve<=255 );
+ assert( nReserve>=0 && nReserve<=255 );
sqlite3BtreeEnter(p);
-#if SQLITE_HAS_CODEC
- if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve;
-#endif
+ pBt->nReserveWanted = nReserve;
+ x = pBt->pageSize - pBt->usableSize;
+ if( nReserve<x ) nReserve = x;
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
sqlite3BtreeLeave(p);
return SQLITE_READONLY;
}
- if( nReserve<0 ){
- nReserve = pBt->pageSize - pBt->usableSize;
- }
assert( nReserve>=0 && nReserve<=255 );
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pCursor );
+ if( nReserve>32 && pageSize==512 ) pageSize = 1024;
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@@ -2836,7 +2929,7 @@ int sqlite3BtreeGetPageSize(Btree *p){
** held.
**
** This is useful in one special case in the backup API code where it is
-** known that the shared b-tree mutex is held, but the mutex on the
+** known that the shared b-tree mutex is held, but the mutex on the
** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
** were to be called, it might collide with some other operation on the
** database handle that owns *p, causing undefined behavior.
@@ -2853,19 +2946,17 @@ int sqlite3BtreeGetReserveNoMutex(Btree *p){
** are intentually left unused. This is the "reserved" space that is
** sometimes used by extensions.
**
-** If SQLITE_HAS_MUTEX is defined then the number returned is the
-** greater of the current reserved space and the maximum requested
-** reserve space.
+** The value returned is the larger of the current reserve size and
+** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES.
+** The amount of reserve can only grow - never shrink.
*/
-int sqlite3BtreeGetOptimalReserve(Btree *p){
- int n;
+int sqlite3BtreeGetRequestedReserve(Btree *p){
+ int n1, n2;
sqlite3BtreeEnter(p);
- n = sqlite3BtreeGetReserveNoMutex(p);
-#ifdef SQLITE_HAS_CODEC
- if( n<p->pBt->optimalReserve ) n = p->pBt->optimalReserve;
-#endif
+ n1 = (int)p->pBt->nReserveWanted;
+ n2 = sqlite3BtreeGetReserveNoMutex(p);
sqlite3BtreeLeave(p);
- return n;
+ return n1>n2 ? n1 : n2;
}
@@ -2874,8 +2965,8 @@ int sqlite3BtreeGetOptimalReserve(Btree *p){
** No changes are made if mxPage is 0 or negative.
** Regardless of the value of mxPage, return the maximum page count.
*/
-int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
- int n;
+Pgno sqlite3BtreeMaxPageCount(Btree *p, Pgno mxPage){
+ Pgno n;
sqlite3BtreeEnter(p);
n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
sqlite3BtreeLeave(p);
@@ -2918,7 +3009,7 @@ int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
/*
** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
-** is disabled. The default value for the auto-vacuum property is
+** is disabled. The default value for the auto-vacuum property is
** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
*/
int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
@@ -2942,7 +3033,7 @@ int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
}
/*
-** Return the value of the 'auto-vacuum' property. If auto-vacuum is
+** Return the value of the 'auto-vacuum' property. If auto-vacuum is
** enabled 1 is returned. Otherwise 0.
*/
int sqlite3BtreeGetAutoVacuum(Btree *p){
@@ -2974,9 +3065,9 @@ static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
Db *pDb;
if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
- if( pDb->bSyncSet==0
- && pDb->safety_level!=safety_level
- && pDb!=&db->aDb[1]
+ if( pDb->bSyncSet==0
+ && pDb->safety_level!=safety_level
+ && pDb!=&db->aDb[1]
){
pDb->safety_level = safety_level;
sqlite3PagerSetFlags(pBt->pPager,
@@ -2993,60 +3084,20 @@ static int newDatabase(BtShared*);
/*
-** Change the 'auto-vacuum-slack-pages' property of the database. If auto vacuum
-** is enabled, this is the number of chunks of slack to allow before
-** automatically running an incremental vacuum.
-*/
-int sqlite3BtreeSetAutoVacuumSlackPages(Btree *p, int autoVacuumSlack){
-#ifdef SQLITE_OMIT_AUTOVACUUM
- return SQLITE_READONLY;
-#else
- BtShared *pBt = p->pBt;
- int rc = SQLITE_OK;
- u8 avs = (u8)autoVacuumSlack;
- if( autoVacuumSlack>avs ){
- avs = 0xFF;
- }
-
- sqlite3BtreeEnter(p);
- pBt->autoVacuumSlack = avs;
- sqlite3BtreeLeave(p);
- return rc;
-#endif
-}
-
-/*
-** Return the value of the 'auto-vacuum-slack-pages' property.
-*/
-int sqlite3BtreeGetAutoVacuumSlackPages(Btree *p){
-#ifdef SQLITE_OMIT_AUTOVACUUM
- return 0;
-#else
- int rc = 0;
- sqlite3BtreeEnter(p);
- if( p->pBt->autoVacuum!=0 ){
- rc = p->pBt->autoVacuumSlack;
- }
- sqlite3BtreeLeave(p);
- return rc;
-#endif
-}
-
-/*
** Get a reference to pPage1 of the database file. This will
** also acquire a readlock on that file.
**
** SQLITE_OK is returned on success. If the file is not a
** well-formed database file, then SQLITE_CORRUPT is returned.
** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
-** is returned if we run out of memory.
+** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
int rc; /* Result code from subfunctions */
MemPage *pPage1; /* Page 1 of the database file */
- int nPage; /* Number of pages in the database */
- int nPageFile = 0; /* Number of pages in the database file */
- int nPageHeader; /* Number of pages in the database according to hdr */
+ u32 nPage; /* Number of pages in the database */
+ u32 nPageFile = 0; /* Number of pages in the database file */
+ u32 nPageHeader; /* Number of pages in the database according to hdr */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pBt->pPage1==0 );
@@ -3056,10 +3107,10 @@ static int lockBtree(BtShared *pBt){
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
- ** a valid database file.
+ ** a valid database file.
*/
nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
- sqlite3PagerPagecount(pBt->pPager, &nPageFile);
+ sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
nPage = nPageFile;
}
@@ -3094,7 +3145,7 @@ static int lockBtree(BtShared *pBt){
}
/* If the write version is set to 2, this database should be accessed
- ** in WAL mode. If the log is not already open, open it now. Then
+ ** in WAL mode. If the log is not already open, open it now. Then
** return SQLITE_OK and return without populating BtShared.pPage1.
** The caller detects this and calls this function again. This is
** required as the version of page 1 currently in the page1 buffer
@@ -3135,15 +3186,16 @@ static int lockBtree(BtShared *pBt){
/* EVIDENCE-OF: R-25008-21688 The size of a page is a power of two
** between 512 and 65536 inclusive. */
if( ((pageSize-1)&pageSize)!=0
- || pageSize>SQLITE_MAX_PAGE_SIZE
- || pageSize<=256
+ || pageSize>SQLITE_MAX_PAGE_SIZE
+ || pageSize<=256
){
goto page1_init_failed;
}
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
assert( (pageSize & 7)==0 );
/* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte
** integer at offset 20 is the number of bytes of space at the end of
- ** each page to reserve for extensions.
+ ** each page to reserve for extensions.
**
** EVIDENCE-OF: R-37497-42412 The size of the reserved region is
** determined by the one-byte unsigned integer found at an offset of 20
@@ -3233,7 +3285,7 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
- && pCur->eState!=CURSOR_FAULT ) r++;
+ && pCur->eState!=CURSOR_FAULT ) r++;
}
return r;
}
@@ -3242,7 +3294,7 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
-** this routine unrefs the first page of the database file which
+** this routine unrefs the first page of the database file which
** has the effect of releasing the read lock.
**
** If there is a transaction in progress, this routine is a no-op.
@@ -3326,8 +3378,8 @@ int sqlite3BtreeNewDb(Btree *p){
** upgraded to exclusive by calling this routine a second time - the
** exclusivity flag only works for a new transaction.
**
-** A write-transaction must be started before attempting any
-** changes to the database. None of the following routines
+** A write-transaction must be started before attempting any
+** changes to the database. None of the following routines
** will work unless a transaction is started first:
**
** sqlite3BtreeCreateTable()
@@ -3341,7 +3393,7 @@ int sqlite3BtreeNewDb(Btree *p){
** If an initial attempt to acquire the lock fails because of lock contention
** and the database was previously unlocked, then invoke the busy handler
** if there is one. But if there was previously a read-lock, do not
-** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
+** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
** returned when there is already a read-lock in order to avoid a deadlock.
**
** Suppose there are two processes A and B. A has a read lock and B has
@@ -3354,6 +3406,7 @@ int sqlite3BtreeNewDb(Btree *p){
*/
int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
BtShared *pBt = p->pBt;
+ Pager *pPager = pBt->pPager;
int rc = SQLITE_OK;
sqlite3BtreeEnter(p);
@@ -3368,8 +3421,8 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
}
assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
- if( (p->db->flags & SQLITE_ResetDatabase)
- && sqlite3PagerIsreadonly(pBt->pPager)==0
+ if( (p->db->flags & SQLITE_ResetDatabase)
+ && sqlite3PagerIsreadonly(pPager)==0
){
pBt->btsFlags &= ~BTS_READ_ONLY;
}
@@ -3383,7 +3436,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
#ifndef SQLITE_OMIT_SHARED_CACHE
{
sqlite3 *pBlock = 0;
- /* If another database handle has already opened a write transaction
+ /* If another database handle has already opened a write transaction
** on this shared-btree structure and a second write transaction is
** requested, return SQLITE_LOCKED.
*/
@@ -3408,19 +3461,31 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
}
#endif
- /* Any read-only or read-write transaction implies a read-lock on
- ** page 1. So if some other shared-cache client already has a write-lock
+ /* Any read-only or read-write transaction implies a read-lock on
+ ** page 1. So if some other shared-cache client already has a write-lock
** on page 1, the transaction cannot be opened. */
- rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
+ rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
do {
+ sqlite3PagerWalDb(pPager, p->db);
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* If transitioning from no transaction directly to a write transaction,
+ ** block for the WRITER lock first if possible. */
+ if( pBt->pPage1==0 && wrflag ){
+ assert( pBt->inTransaction==TRANS_NONE );
+ rc = sqlite3PagerWalWriteLock(pPager, 1);
+ if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break;
+ }
+#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
- ** reading page 1 it discovers that the page-size of the database
+ ** reading page 1 it discovers that the page-size of the database
** file is not pBt->pageSize. In this case lockBtree() will update
** pBt->pageSize to the page-size of the file on disk.
*/
@@ -3430,7 +3495,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
rc = SQLITE_READONLY;
}else{
- rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
+ rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db));
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
@@ -3441,13 +3506,17 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
}
}
}
-
+
if( rc!=SQLITE_OK ){
+ (void)sqlite3PagerWalWriteLock(pPager, 0);
unlockBtreeIfUnused(pBt);
}
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
- sqlite3PagerResetLockTimeout(pBt->pPager);
+ sqlite3PagerWalDb(pPager, 0);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
+#endif
if( rc==SQLITE_OK ){
if( p->inTrans==TRANS_NONE ){
@@ -3476,7 +3545,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
/* If the db-size header field is incorrect (as it may be if an old
** client has been writing the database file), update it now. Doing
- ** this sooner rather than later means the database size can safely
+ ** this sooner rather than later means the database size can safely
** re-read the database size from page 1 if a savepoint or transaction
** rollback occurs within the transaction.
*/
@@ -3499,7 +3568,7 @@ trans_begun:
** open savepoints. If the second parameter is greater than 0 and
** the sub-journal is not already open, then it will be opened here.
*/
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
+ rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint);
}
}
@@ -3530,7 +3599,7 @@ static int setChildPtrmaps(MemPage *pPage){
for(i=0; i<nCell; i++){
u8 *pCell = findCell(pPage, i);
- ptrmapPutOvflPtr(pPage, pCell, &rc);
+ ptrmapPutOvflPtr(pPage, pPage, pCell, &rc);
if( !pPage->leaf ){
Pgno childPgno = get4byte(pCell);
@@ -3551,7 +3620,7 @@ static int setChildPtrmaps(MemPage *pPage){
** that it points to iTo. Parameter eType describes the type of pointer to
** be modified, as follows:
**
-** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
+** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
** page of pPage.
**
** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
@@ -3599,9 +3668,9 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
}
}
}
-
+
if( i==nCell ){
- if( eType!=PTRMAP_BTREE ||
+ if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -3613,11 +3682,11 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
/*
-** Move the open database page pDbPage to location iFreePage in the
+** Move the open database page pDbPage to location iFreePage in the
** database. The pDbPage reference remains valid.
**
** The isCommit flag indicates that there is no need to remember that
-** the journal needs to be sync()ed before database page pDbPage->pgno
+** the journal needs to be sync()ed before database page pDbPage->pgno
** can be written to. The caller has already promised not to write to that
** page.
*/
@@ -3634,14 +3703,14 @@ static int relocatePage(
Pager *pPager = pBt->pPager;
int rc;
- assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
+ assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pDbPage->pBt==pBt );
if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT;
/* Move page iDbPage from its current location to page number iFreePage */
- TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
+ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
iDbPage, iFreePage, iPtrPage, eType));
rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
if( rc!=SQLITE_OK ){
@@ -3700,19 +3769,19 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
/*
** Perform a single step of an incremental-vacuum. If successful, return
-** SQLITE_OK. If there is no work to do (and therefore no point in
-** calling this function again), return SQLITE_DONE. Or, if an error
+** SQLITE_OK. If there is no work to do (and therefore no point in
+** calling this function again), return SQLITE_DONE. Or, if an error
** occurs, return some other error code.
**
-** More specifically, this function attempts to re-organize the database so
+** More specifically, this function attempts to re-organize the database so
** that the last page of the file currently in use is no longer in use.
**
** Parameter nFin is the number of pages that this database would contain
** were this function called until it returns SQLITE_DONE.
**
-** If the bCommit parameter is non-zero, this function assumes that the
-** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
-** or an error. bCommit is passed true for an auto-vacuum-on-commit
+** If the bCommit parameter is non-zero, this function assumes that the
+** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
+** or an error. bCommit is passed true for an auto-vacuum-on-commit
** operation, or false for an incremental vacuum.
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
@@ -3743,7 +3812,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
if( bCommit==0 ){
/* Remove the page from the files free-list. This is not required
** if bCommit is non-zero. In that case, the free-list will be
- ** truncated to zero after this function returns, so it doesn't
+ ** truncated to zero after this function returns, so it doesn't
** matter if it still contains some garbage entries.
*/
Pgno iFreePg;
@@ -3787,7 +3856,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
releasePage(pFreePg);
}while( bCommit && iFreePg>nFin );
assert( iFreePg<iLastPg );
-
+
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
releasePage(pLastPg);
if( rc!=SQLITE_OK ){
@@ -3808,7 +3877,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
/*
** The database opened by the first argument is an auto-vacuum database
-** nOrig pages in size containing nFree free pages. Return the expected
+** nOrig pages in size containing nFree free pages. Return the expected
** size of the database in pages following an auto-vacuum operation.
*/
static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
@@ -3835,7 +3904,7 @@ static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
**
** If the incremental vacuum is finished after this function has run,
** SQLITE_DONE is returned. If it is not finished, but no error occurred,
-** SQLITE_OK is returned. Otherwise an SQLite error code.
+** SQLITE_OK is returned. Otherwise an SQLite error code.
*/
int sqlite3BtreeIncrVacuum(Btree *p){
int rc;
@@ -3850,7 +3919,7 @@ int sqlite3BtreeIncrVacuum(Btree *p){
Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
Pgno nFin = finalDbSize(pBt, nOrig, nFree);
- if( nOrig<nFin ){
+ if( nOrig<nFin || nFree>=nOrig ){
rc = SQLITE_CORRUPT_BKPT;
}else if( nFree>0 ){
rc = saveAllCursors(pBt, 0, 0);
@@ -3875,33 +3944,19 @@ int sqlite3BtreeIncrVacuum(Btree *p){
** is committed for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
-** the database file should be truncated to during the commit process.
+** the database file should be truncated to during the commit process.
** i.e. the database has been reorganized so that only the first *pnTrunc
** pages are in use.
*/
static int autoVacuumCommit(BtShared *pBt){
int rc = SQLITE_OK;
- int bShouldVacuum = pBt->autoVacuum && !pBt->incrVacuum;
Pager *pPager = pBt->pPager;
VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); )
assert( sqlite3_mutex_held(pBt->mutex) );
invalidateAllOverflowCache(pBt);
assert(pBt->autoVacuum);
- if( bShouldVacuum && pBt->autoVacuumSlack ){
- Pgno nOrig; /* Database size before freeing */
- Pgno nFree; /* Number of pages on the freelist initially */
-
- nOrig = btreePagecount(pBt);
- nFree = get4byte(&pBt->pPage1->aData[36]);
- bShouldVacuum =
- (nOrig-nFree-1)/pBt->autoVacuumSlack < (nOrig-1)/pBt->autoVacuumSlack;
- /* TODO: When integrating this test with the following code, contrive to
- ** trim to the integral chunk boundary, rather than trimming the entire free
- ** list.
- */
- }
- if( bShouldVacuum ){
+ if( !pBt->incrVacuum ){
Pgno nFin; /* Number of pages in database after autovacuuming */
Pgno nFree; /* Number of pages on the freelist initially */
Pgno iFree; /* The next page to be freed */
@@ -3961,18 +4016,18 @@ static int autoVacuumCommit(BtShared *pBt){
**
** This call is a no-op if no write-transaction is currently active on pBt.
**
-** Otherwise, sync the database file for the btree pBt. zMaster points to
-** the name of a master journal file that should be written into the
-** individual journal file, or is NULL, indicating no master journal file
+** Otherwise, sync the database file for the btree pBt. zSuperJrnl points to
+** the name of a super-journal file that should be written into the
+** individual journal file, or is NULL, indicating no super-journal file
** (single database transaction).
**
-** When this is called, the master journal should already have been
+** When this is called, the super-journal should already have been
** created, populated with this journal pointer and synced to disk.
**
** Once this is routine has returned, the only thing required to commit
** the write-transaction for this database file is to delete the journal.
*/
-int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
+int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
int rc = SQLITE_OK;
if( p->inTrans==TRANS_WRITE ){
BtShared *pBt = p->pBt;
@@ -3989,7 +4044,7 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
}
#endif
- rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
+ rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zSuperJrnl, 0);
sqlite3BtreeLeave(p);
}
return rc;
@@ -4014,8 +4069,8 @@ static void btreeEndTransaction(Btree *p){
downgradeAllSharedCacheTableLocks(p);
p->inTrans = TRANS_READ;
}else{
- /* If the handle had any kind of transaction open, decrement the
- ** transaction count of the shared btree. If the transaction count
+ /* If the handle had any kind of transaction open, decrement the
+ ** transaction count of the shared btree. If the transaction count
** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
** call below will unlock the pager. */
if( p->inTrans!=TRANS_NONE ){
@@ -4026,7 +4081,7 @@ static void btreeEndTransaction(Btree *p){
}
}
- /* Set the current transaction state to TRANS_NONE and unlock the
+ /* Set the current transaction state to TRANS_NONE and unlock the
** pager if this call closed the only read or write transaction. */
p->inTrans = TRANS_NONE;
unlockBtreeIfUnused(pBt);
@@ -4047,12 +4102,12 @@ static void btreeEndTransaction(Btree *p){
** the rollback journal (which causes the transaction to commit) and
** drop locks.
**
-** Normally, if an error occurs while the pager layer is attempting to
+** Normally, if an error occurs while the pager layer is attempting to
** finalize the underlying journal file, this function returns an error and
** the upper layer will attempt a rollback. However, if the second argument
-** is non-zero then this b-tree transaction is part of a multi-file
-** transaction. In this case, the transaction has already been committed
-** (by deleting a master journal file) and the caller will ignore this
+** is non-zero then this b-tree transaction is part of a multi-file
+** transaction. In this case, the transaction has already been committed
+** (by deleting a super-journal file) and the caller will ignore this
** functions return code. So, even if an error occurs in the pager layer,
** reset the b-tree objects internal state to indicate that the write
** transaction has been closed. This is quite safe, as the pager will have
@@ -4067,7 +4122,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
sqlite3BtreeEnter(p);
btreeIntegrity(p);
- /* If the handle has a write-transaction open, commit the shared-btrees
+ /* If the handle has a write-transaction open, commit the shared-btrees
** transaction and set the shared state to TRANS_READ.
*/
if( p->inTrans==TRANS_WRITE ){
@@ -4080,7 +4135,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
sqlite3BtreeLeave(p);
return rc;
}
- p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
+ p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
@@ -4116,15 +4171,15 @@ int sqlite3BtreeCommit(Btree *p){
**
** This routine gets called when a rollback occurs. If the writeOnly
** flag is true, then only write-cursors need be tripped - read-only
-** cursors save their current positions so that they may continue
-** following the rollback. Or, if writeOnly is false, all cursors are
+** cursors save their current positions so that they may continue
+** following the rollback. Or, if writeOnly is false, all cursors are
** tripped. In general, writeOnly is false if the transaction being
** rolled back modified the database schema. In this case b-tree root
** pages may be moved or deleted from the database altogether, making
** it unsafe for read cursors to continue.
**
-** If the writeOnly flag is true and an error is encountered while
-** saving the current position of a read-only cursor, all cursors,
+** If the writeOnly flag is true and an error is encountered while
+** saving the current position of a read-only cursor, all cursors,
** including all read-cursors are tripped.
**
** SQLITE_OK is returned if successful, or if an error occurs while
@@ -4159,6 +4214,18 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
}
/*
+** Set the pBt->nPage field correctly, according to the current
+** state of the database. Assume pBt->pPage1 is valid.
+*/
+static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
+ int nPage = get4byte(&pPage1->aData[28]);
+ testcase( nPage==0 );
+ if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
+ testcase( pBt->nPage!=nPage );
+ pBt->nPage = nPage;
+}
+
+/*
** Rollback the transaction in progress.
**
** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped).
@@ -4203,11 +4270,7 @@ int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
** call btreeGetPage() on page 1 again to make
** sure pPage1->aData is set correctly. */
if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
- int nPage = get4byte(28+(u8*)pPage1->aData);
- testcase( nPage==0 );
- if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
- testcase( pBt->nPage!=nPage );
- pBt->nPage = nPage;
+ btreeSetNPage(pBt, pPage1);
releasePageOne(pPage1);
}
assert( countValidCursors(pBt, 1)==0 );
@@ -4222,8 +4285,8 @@ int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
/*
** Start a statement subtransaction. The subtransaction can be rolled
-** back independently of the main transaction. You must start a transaction
-** before starting a subtransaction. The subtransaction is ended automatically
+** back independently of the main transaction. You must start a transaction
+** before starting a subtransaction. The subtransaction is ended automatically
** if the main transaction commits or rolls back.
**
** Statement subtransactions are used around individual SQL statements
@@ -4260,11 +4323,11 @@ int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
/*
** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
** or SAVEPOINT_RELEASE. This function either releases or rolls back the
-** savepoint identified by parameter iSavepoint, depending on the value
+** savepoint identified by parameter iSavepoint, depending on the value
** of op.
**
** Normally, iSavepoint is greater than or equal to zero. However, if op is
-** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
+** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
** contents of the entire transaction are rolled back. This is different
** from a normal transaction rollback, as no locks are released and the
** transaction remains open.
@@ -4287,12 +4350,11 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
pBt->nPage = 0;
}
rc = newDatabase(pBt);
- pBt->nPage = get4byte(28 + pBt->pPage1->aData);
+ btreeSetNPage(pBt, pBt->pPage1);
- /* The database size was written into the offset 28 of the header
- ** when the transaction started, so we know that the value at offset
- ** 28 is nonzero. */
- assert( pBt->nPage>0 );
+ /* pBt->nPage might be zero if the database was corrupt when
+ ** the transaction was started. Otherwise, it must be at least 1. */
+ assert( CORRUPT_DB || pBt->nPage>0 );
}
sqlite3BtreeLeave(p);
}
@@ -4328,10 +4390,10 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
** is set. If FORDELETE is set, that is a hint to the implementation that
** this cursor will only be used to seek to and delete entries of an index
** as part of a larger DELETE statement. The FORDELETE hint is not used by
-** this implementation. But in a hypothetical alternative storage engine
+** this implementation. But in a hypothetical alternative storage engine
** in which index entries are automatically deleted when corresponding table
** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE
-** operations on this cursor can be no-ops and all READ operations can
+** operations on this cursor can be no-ops and all READ operations can
** return a null row (2-bytes: 0x01 0x00).
**
** No checking is done to make sure that page iTable really is the
@@ -4343,7 +4405,7 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
*/
static int btreeCursor(
Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
+ Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to comparison function */
BtCursor *pCur /* Space for new cursor */
@@ -4352,16 +4414,17 @@ static int btreeCursor(
BtCursor *pX; /* Looping over other all cursors */
assert( sqlite3BtreeHoldsMutex(p) );
- assert( wrFlag==0
- || wrFlag==BTREE_WRCSR
- || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
+ assert( wrFlag==0
+ || wrFlag==BTREE_WRCSR
+ || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
);
- /* The following assert statements verify that if this is a sharable
- ** b-tree database, the connection is holding the required table locks,
- ** and that no other connection has any open cursor that conflicts with
- ** this lock. */
- assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
+ /* The following assert statements verify that if this is a sharable
+ ** b-tree database, the connection is holding the required table locks,
+ ** and that no other connection has any open cursor that conflicts with
+ ** this lock. The iTable<1 term disables the check for corrupt schemas. */
+ assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1))
+ || iTable<1 );
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
/* Assert that the caller has opened the required transaction. */
@@ -4374,14 +4437,18 @@ static int btreeCursor(
allocateTempSpace(pBt);
if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
}
- if( iTable==1 && btreePagecount(pBt)==0 ){
- assert( wrFlag==0 );
- iTable = 0;
+ if( iTable<=1 ){
+ if( iTable<1 ){
+ return SQLITE_CORRUPT_BKPT;
+ }else if( btreePagecount(pBt)==0 ){
+ assert( wrFlag==0 );
+ iTable = 0;
+ }
}
/* Now that no other errors can occur, finish filling in the BtCursor
** variables and link the cursor into the BtShared list. */
- pCur->pgnoRoot = (Pgno)iTable;
+ pCur->pgnoRoot = iTable;
pCur->iPage = -1;
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
@@ -4391,7 +4458,7 @@ static int btreeCursor(
/* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */
for(pX=pBt->pCursor; pX; pX=pX->pNext){
- if( pX->pgnoRoot==(Pgno)iTable ){
+ if( pX->pgnoRoot==iTable ){
pX->curFlags |= BTCF_Multiple;
pCur->curFlags |= BTCF_Multiple;
}
@@ -4401,22 +4468,31 @@ static int btreeCursor(
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}
+static int btreeCursorWithLock(
+ Btree *p, /* The btree */
+ Pgno iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
+ BtCursor *pCur /* Space for new cursor */
+){
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
int sqlite3BtreeCursor(
Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
+ Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
BtCursor *pCur /* Write new cursor here */
){
- int rc;
- if( iTable<1 ){
- rc = SQLITE_CORRUPT_BKPT;
+ if( p->sharable ){
+ return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur);
}else{
- sqlite3BtreeEnter(p);
- rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
- sqlite3BtreeLeave(p);
+ return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
}
- return rc;
}
/*
@@ -4469,7 +4545,15 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
sqlite3_free(pCur->pKey);
- sqlite3BtreeLeave(pBtree);
+ if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){
+ /* Since the BtShared is not sharable, there is no need to
+ ** worry about the missing sqlite3BtreeLeave() call here. */
+ assert( pBtree->sharable==0 );
+ sqlite3BtreeClose(pBtree);
+ }else{
+ sqlite3BtreeLeave(pBtree);
+ }
+ pCur->pBtree = 0;
}
return SQLITE_OK;
}
@@ -4538,6 +4622,18 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
return pCur->info.nKey;
}
+/*
+** Pin or unpin a cursor.
+*/
+void sqlite3BtreeCursorPin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)==0 );
+ pCur->curFlags |= BTCF_Pinned;
+}
+void sqlite3BtreeCursorUnpin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)!=0 );
+ pCur->curFlags &= ~BTCF_Pinned;
+}
+
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
/*
** Return the offset into the database file for the start of the
@@ -4569,16 +4665,35 @@ u32 sqlite3BtreePayloadSize(BtCursor *pCur){
}
/*
+** Return an upper bound on the size of any record for the table
+** that the cursor is pointing into.
+**
+** This is an optimization. Everything will still work if this
+** routine always returns 2147483647 (which is the largest record
+** that SQLite can handle) or more. But returning a smaller value might
+** prevent large memory allocations when trying to interpret a
+** corrupt datrabase.
+**
+** The current implementation merely returns the size of the underlying
+** database file.
+*/
+sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
+}
+
+/*
** Given the page number of an overflow page in the database (parameter
-** ovfl), this function finds the page number of the next page in the
+** ovfl), this function finds the page number of the next page in the
** linked list of overflow pages. If possible, it uses the auto-vacuum
-** pointer-map data instead of reading the content of page ovfl to do so.
+** pointer-map data instead of reading the content of page ovfl to do so.
**
** If an error occurs an SQLite error code is returned. Otherwise:
**
-** The page number of the next overflow page in the linked list is
-** written to *pPgnoNext. If page ovfl is the last page in its linked
-** list, *pPgnoNext is set to zero.
+** The page number of the next overflow page in the linked list is
+** written to *pPgnoNext. If page ovfl is the last page in its linked
+** list, *pPgnoNext is set to zero.
**
** If ppPage is not NULL, and a reference to the MemPage object corresponding
** to page number pOvfl was obtained, then *ppPage is set to point to that
@@ -4602,9 +4717,9 @@ static int getOverflowPage(
#ifndef SQLITE_OMIT_AUTOVACUUM
/* Try to find the next page in the overflow list using the
- ** autovacuum pointer-map pages. Guess that the next page in
- ** the overflow list is page number (ovfl+1). If that guess turns
- ** out to be wrong, fall back to loading the data of page
+ ** autovacuum pointer-map pages. Guess that the next page in
+ ** the overflow list is page number (ovfl+1). If that guess turns
+ ** out to be wrong, fall back to loading the data of page
** number ovfl to determine the next page number.
*/
if( pBt->autoVacuum ){
@@ -4692,8 +4807,8 @@ static int copyPayload(
**
** If the current cursor entry uses one or more overflow pages
** this function may allocate space for and lazily populate
-** the overflow page-list cache array (BtCursor.aOverflow).
-** Subsequent calls use this cache to make seeking to the supplied offset
+** the overflow page-list cache array (BtCursor.aOverflow).
+** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
** Once an overflow page-list cache has been allocated, it must be
@@ -4709,7 +4824,7 @@ static int accessPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 offset, /* Begin reading this far into payload */
u32 amt, /* Read this many bytes */
- unsigned char *pBuf, /* Write the bytes into this buffer */
+ unsigned char *pBuf, /* Write the bytes into this buffer */
int eOp /* zero to read. non-zero to write. */
){
unsigned char *aPayload;
@@ -4761,7 +4876,7 @@ static int accessPayload(
Pgno nextPage;
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
-
+
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
**
** The aOverflow[] array is sized at one entry for each overflow page
@@ -4800,6 +4915,7 @@ static int accessPayload(
assert( rc==SQLITE_OK && amt>0 );
while( nextPage ){
/* If required, populate the overflow page-list cache. */
+ if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT;
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
@@ -4832,12 +4948,12 @@ static int accessPayload(
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/* If all the following are true:
**
- ** 1) this is a read operation, and
+ ** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
** 3) there are no dirty pages in the page-cache
** 4) the database is file-backed, and
** 5) the page is not in the WAL file
- ** 6) at least 4 bytes have already been read into the output buffer
+ ** 6) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
@@ -4854,6 +4970,7 @@ static int accessPayload(
assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
+ if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
@@ -4944,7 +5061,7 @@ int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
#endif /* SQLITE_OMIT_INCRBLOB */
/*
-** Return a pointer to payload information from the entry that the
+** Return a pointer to payload information from the entry that the
** pCur cursor is pointing to. The pointer is to the beginning of
** the key if index btrees (pPage->intKey==0) and is the data for
** table btrees (pPage->intKey==1). The number of bytes of available
@@ -5036,7 +5153,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
#ifdef SQLITE_DEBUG
/*
-** Page pParent is an internal (non-leaf) tree page. This function
+** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
** cell in page pParent. Or, if iIdx is equal to the total number of
** cells in pParent, that page number iChild is the right-child of
@@ -5053,7 +5170,7 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
}
}
#else
-# define assertParentIndex(x,y,z)
+# define assertParentIndex(x,y,z)
#endif
/*
@@ -5071,8 +5188,8 @@ static void moveToParent(BtCursor *pCur){
assert( pCur->iPage>0 );
assert( pCur->pPage );
assertParentIndex(
- pCur->apPage[pCur->iPage-1],
- pCur->aiIdx[pCur->iPage-1],
+ pCur->apPage[pCur->iPage-1],
+ pCur->aiIdx[pCur->iPage-1],
pCur->pPage->pgno
);
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
@@ -5089,19 +5206,19 @@ static void moveToParent(BtCursor *pCur){
**
** If the table has a virtual root page, then the cursor is moved to point
** to the virtual root page instead of the actual root page. A table has a
-** virtual root page when the actual root page contains no cells and a
+** virtual root page when the actual root page contains no cells and a
** single child page. This can only happen with the table rooted at page 1.
**
-** If the b-tree structure is empty, the cursor state is set to
+** If the b-tree structure is empty, the cursor state is set to
** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise,
** the cursor is set to point to the first cell located on the root
** (or virtual root) page and the cursor state is set to CURSOR_VALID.
**
** If this function returns successfully, it may be assumed that the
-** page-header flags indicate that the [virtual] root-page is the expected
+** page-header flags indicate that the [virtual] root-page is the expected
** kind of b-tree page (i.e. if when opening the cursor the caller did not
** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D,
-** indicating a table b-tree, or if the caller did specify a KeyInfo
+** indicating a table b-tree, or if the caller did specify a KeyInfo
** structure the flags byte is set to 0x02 or 0x0A, indicating an index
** b-tree).
*/
@@ -5152,19 +5269,19 @@ static int moveToRoot(BtCursor *pCur){
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
** NULL, the caller expects a table b-tree. If this is not the case,
- ** return an SQLITE_CORRUPT error.
+ ** return an SQLITE_CORRUPT error.
**
** Earlier versions of SQLite assumed that this test could not fail
** if the root page was already loaded when this function was called (i.e.
- ** if pCur->iPage>=0). But this is not so if the database is corrupted
- ** in such a way that page pRoot is linked into a second b-tree table
+ ** if pCur->iPage>=0). But this is not so if the database is corrupted
+ ** in such a way that page pRoot is linked into a second b-tree table
** (or the freelist). */
assert( pRoot->intKey==1 || pRoot->intKey==0 );
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
return SQLITE_CORRUPT_PAGE(pCur->pPage);
}
-skip_init:
+skip_init:
pCur->ix = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
@@ -5258,37 +5375,20 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
return rc;
}
-/*
-** This function is a no-op if cursor pCur does not point to a valid row.
-** Otherwise, if pCur is valid, configure it so that the next call to
-** sqlite3BtreeNext() is a no-op.
-*/
-#ifndef SQLITE_OMIT_WINDOWFUNC
-void sqlite3BtreeSkipNext(BtCursor *pCur){
- /* We believe that the cursor must always be in the valid state when
- ** this routine is called, but the proof is difficult, so we add an
- ** ALWaYS() test just in case we are wrong. */
- if( ALWAYS(pCur->eState==CURSOR_VALID) ){
- pCur->eState = CURSOR_SKIPNEXT;
- pCur->skipNext = 1;
- }
-}
-#endif /* SQLITE_OMIT_WINDOWFUNC */
-
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
*/
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int rc;
-
+
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#ifdef SQLITE_DEBUG
- /* This block serves to assert() that the cursor really does point
+ /* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
int ii;
for(ii=0; ii<pCur->iPage; ii++){
@@ -5297,6 +5397,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( pCur->ix==pCur->pPage->nCell-1 );
assert( pCur->pPage->leaf );
#endif
+ *pRes = 0;
return SQLITE_OK;
}
@@ -5318,10 +5419,10 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
return rc;
}
-/* Move the cursor so that it points to an entry near the key
+/* Move the cursor so that it points to an entry near the key
** specified by pIdxKey or intKey. Return a success code.
**
-** For INTKEY tables, the intKey parameter is used. pIdxKey
+** For INTKEY tables, the intKey parameter is used. pIdxKey
** must be NULL. For index tables, pIdxKey is used and intKey
** is ignored.
**
@@ -5331,7 +5432,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** before or after the key.
**
** An integer is written into *pRes which is the result of
-** comparing the key with the entry to which the cursor is
+** comparing the key with the entry to which the cursor is
** pointing. The meaning of the integer written into
** *pRes is as follows:
**
@@ -5346,7 +5447,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** is larger than intKey/pIdxKey.
**
** For index tables, the pIdxKey->eqSeen field is set to 1 if there
-** exists an entry in the table that exactly matches pIdxKey.
+** exists an entry in the table that exactly matches pIdxKey.
*/
int sqlite3BtreeMovetoUnpacked(
BtCursor *pCur, /* The cursor to be moved */
@@ -5382,7 +5483,7 @@ int sqlite3BtreeMovetoUnpacked(
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
** is still obtained without this case, only a little more slowely */
- if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
+ if( pCur->info.nKey+1==intKey ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, 0);
if( rc==SQLITE_OK ){
@@ -5399,11 +5500,15 @@ int sqlite3BtreeMovetoUnpacked(
}
}
+#ifdef SQLITE_DEBUG
+ pCur->pBtree->nSeek++; /* Performance measurement during testing */
+#endif
+
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
- assert( pIdxKey->default_rc==1
- || pIdxKey->default_rc==0
+ assert( pIdxKey->default_rc==1
+ || pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1
);
}else{
@@ -5487,9 +5592,9 @@ int sqlite3BtreeMovetoUnpacked(
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and may be stored as a 2-byte
- ** varint. This information is used to attempt to avoid parsing
- ** the entire cell by checking for the cases where the record is
- ** stored entirely within the b-tree page by inspecting the first
+ ** varint. This information is used to attempt to avoid parsing
+ ** the entire cell by checking for the cases where the record is
+ ** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
nCell = pCell[0];
@@ -5499,10 +5604,10 @@ int sqlite3BtreeMovetoUnpacked(
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
- }else if( !(pCell[1] & 0x80)
+ }else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
- /* The record-size field is a 2 byte varint and the record
+ /* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
@@ -5510,40 +5615,42 @@ int sqlite3BtreeMovetoUnpacked(
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
** and accessPayload() used to retrieve the record into the
- ** buffer before VdbeRecordCompare() can be called.
+ ** buffer before VdbeRecordCompare() can be called.
**
** If the record is corrupt, the xRecordCompare routine may read
- ** up to two varints past the end of the buffer. An extra 18
+ ** up to two varints past the end of the buffer. An extra 18
** bytes of padding is allocated at the end of the buffer in
** case this happens. */
void *pCellKey;
u8 * const pCellBody = pCell - pPage->childPtrSize;
+ const int nOverrun = 18; /* Size of the overrun padding */
pPage->xParseCell(pPage, pCellBody, &pCur->info);
nCell = (int)pCur->info.nKey;
testcase( nCell<0 ); /* True if key size is 2^32 or more */
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
- if( nCell<2 ){
+ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
rc = SQLITE_CORRUPT_PAGE(pPage);
goto moveto_finish;
}
- pCellKey = sqlite3Malloc( nCell+18 );
+ pCellKey = sqlite3Malloc( nCell+nOverrun );
if( pCellKey==0 ){
rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
pCur->ix = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+ memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
pCur->curFlags &= ~BTCF_ValidOvfl;
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
}
- c = xRecordCompare(nCell, pCellKey, pIdxKey);
+ c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
}
- assert(
+ assert(
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
&& (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
);
@@ -5607,7 +5714,7 @@ int sqlite3BtreeEof(BtCursor *pCur){
/*
** Return an estimate for the number of rows in the table that pCur is
-** pointing to. Return a negative number if no estimate is currently
+** pointing to. Return a negative number if no estimate is currently
** available.
*/
i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
@@ -5631,7 +5738,7 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
}
/*
-** Advance the cursor to the next entry in the database.
+** Advance the cursor to the next entry in the database.
** Return value:
**
** SQLITE_OK success
@@ -5656,7 +5763,6 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
@@ -5666,20 +5772,15 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext>0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext>0 ) return SQLITE_OK;
}
}
pPage = pCur->pPage;
idx = ++pCur->ix;
- if( !pPage->isInit ){
+ if( !pPage->isInit || sqlite3FaultSim(412) ){
/* The only known way for this to happen is for there to be a
** recursive SQL function that does a DELETE operation as part of a
** SELECT which deletes content out from under an active cursor
@@ -5690,12 +5791,15 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
return SQLITE_CORRUPT_BKPT;
}
- /* If the database file is corrupt, it is possible for the value of idx
+ /* If the database file is corrupt, it is possible for the value of idx
** to be invalid here. This can only occur if a second cursor modifies
** the page while cursor pCur is holding a reference to it. Which can
** only happen if the database is corrupt in such a way as to link the
- ** page into more than one b-tree structure. */
- testcase( idx>pPage->nCell );
+ ** page into more than one b-tree structure.
+ **
+ ** Update 2019-12-23: appears to long longer be possible after the
+ ** addition of anotherValidCursor() condition on balance_deeper(). */
+ harmless( idx>pPage->nCell );
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
@@ -5728,7 +5832,6 @@ int sqlite3BtreeNext(BtCursor *pCur, int flags){
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
@@ -5769,7 +5872,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
@@ -5780,14 +5882,9 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( CURSOR_SKIPNEXT==pCur->eState ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext<0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext<0 ) return SQLITE_OK;
}
}
@@ -5822,7 +5919,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
@@ -5847,7 +5943,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int flags){
** SQLITE_OK is returned on success. Any other return value indicates
** an error. *ppPage is set to NULL in the event of an error.
**
-** If the "nearby" parameter is not 0, then an effort is made to
+** If the "nearby" parameter is not 0, then an effort is made to
** locate a page close to the page number "nearby". This can be used in an
** attempt to keep related pages close to each other in the database file,
** which in turn can make database access faster.
@@ -5889,7 +5985,7 @@ static int allocateBtreePage(
Pgno iTrunk;
u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
u32 nSearch = 0; /* Count of the number of search attempts */
-
+
/* If eMode==BTALLOC_EXACT and a query of the pointer-map
** shows that the page 'nearby' is somewhere on the free-list, then
** the entire-list will be searched for that page.
@@ -5952,8 +6048,8 @@ static int allocateBtreePage(
** is the number of leaf page pointers to follow. */
k = get4byte(&pTrunk->aData[4]);
if( k==0 && !searchList ){
- /* The trunk has no leaves and the list is not being searched.
- ** So extract the trunk page itself and use it as the newly
+ /* The trunk has no leaves and the list is not being searched.
+ ** So extract the trunk page itself and use it as the newly
** allocated page */
assert( pPrevTrunk==0 );
rc = sqlite3PagerWrite(pTrunk->pDbPage);
@@ -5970,8 +6066,8 @@ static int allocateBtreePage(
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
- }else if( searchList
- && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE))
+ }else if( searchList
+ && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE))
){
/* The list is being searched and this trunk page is the page
** to allocate, regardless of whether it has leaves.
@@ -5994,13 +6090,13 @@ static int allocateBtreePage(
memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
}
}else{
- /* The trunk page is required by the caller but it contains
+ /* The trunk page is required by the caller but it contains
** pointers to free-list leaves. The first leaf becomes a trunk
** page in this case.
*/
MemPage *pNewTrunk;
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
- if( iNewTrunk>mxPage ){
+ if( iNewTrunk>mxPage ){
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
@@ -6070,8 +6166,8 @@ static int allocateBtreePage(
goto end_allocate_page;
}
testcase( iPage==mxPage );
- if( !searchList
- || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
+ if( !searchList
+ || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
){
int noContent;
*pPgno = iPage;
@@ -6112,7 +6208,7 @@ static int allocateBtreePage(
** not set the no-content flag. This causes the pager to load and journal
** the current page content before overwriting it.
**
- ** Note that the pager will not actually attempt to load or journal
+ ** Note that the pager will not actually attempt to load or journal
** content for any page that really does lie past the end of the database
** file on disk. So the effects of disabling the no-content optimization
** here are confined to those pages that lie between the end of the
@@ -6158,7 +6254,7 @@ static int allocateBtreePage(
TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
}
- assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+ assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) );
end_allocate_page:
releasePage(pTrunk);
@@ -6169,12 +6265,12 @@ end_allocate_page:
}
/*
-** This function is used to add page iPage to the database file free-list.
+** This function is used to add page iPage to the database file free-list.
** It is assumed that the page is not already a part of the free-list.
**
** The value passed as the second argument to this function is optional.
-** If the caller happens to have a pointer to the MemPage object
-** corresponding to page iPage handy, it may pass it as the second value.
+** If the caller happens to have a pointer to the MemPage object
+** corresponding to page iPage handy, it may pass it as the second value.
** Otherwise, it may pass NULL.
**
** If a pointer to a MemPage object is passed as the second argument,
@@ -6182,17 +6278,19 @@ end_allocate_page:
*/
static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
MemPage *pTrunk = 0; /* Free-list trunk page */
- Pgno iTrunk = 0; /* Page number of free-list trunk page */
+ Pgno iTrunk = 0; /* Page number of free-list trunk page */
MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */
MemPage *pPage; /* Page being freed. May be NULL. */
int rc; /* Return Code */
- int nFree; /* Initial number of pages on free-list */
+ u32 nFree; /* Initial number of pages on free-list */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( CORRUPT_DB || iPage>1 );
assert( !pMemPage || pMemPage->pgno==iPage );
- if( iPage<2 ) return SQLITE_CORRUPT_BKPT;
+ if( iPage<2 || iPage>pBt->nPage ){
+ return SQLITE_CORRUPT_BKPT;
+ }
if( pMemPage ){
pPage = pMemPage;
sqlite3PagerRef(pPage->pDbPage);
@@ -6237,6 +6335,10 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
u32 nLeaf; /* Initial number of leaf cells on trunk page */
iTrunk = get4byte(&pPage1->aData[32]);
+ if( iTrunk>btreePagecount(pBt) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto freepage_out;
+ }
rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
if( rc!=SQLITE_OK ){
goto freepage_out;
@@ -6284,7 +6386,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
/* If control flows to this point, then it was not possible to add the
** the page being freed as a leaf page of the first trunk in the free-list.
- ** Possibly because the free-list is empty, or possibly because the
+ ** Possibly because the free-list is empty, or possibly because the
** first trunk in the free-list is full. Either way, the page being freed
** will become the new first trunk page in the free-list.
*/
@@ -6345,15 +6447,15 @@ static int clearCell(
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
- assert( nOvfl>0 ||
+ assert( nOvfl>0 ||
(CORRUPT_DB && (pInfo->nPayload + ovflPageSize)<ovflPageSize)
);
while( nOvfl-- ){
Pgno iNext = 0;
MemPage *pOvfl = 0;
if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
- /* 0 is not a legal page number and page 1 cannot be an
- ** overflow page. Therefore if ovflPgno<2 or past the end of the
+ /* 0 is not a legal page number and page 1 cannot be an
+ ** overflow page. Therefore if ovflPgno<2 or past the end of the
** file the database must be corrupt. */
return SQLITE_CORRUPT_BKPT;
}
@@ -6365,11 +6467,11 @@ static int clearCell(
if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
){
- /* There is no reason any cursor should have an outstanding reference
+ /* There is no reason any cursor should have an outstanding reference
** to an overflow page belonging to a cell that is being deleted/updated.
- ** So if there exists more than one reference to this page, then it
- ** must not really be an overflow page and the database must be corrupt.
- ** It is helpful to detect this before calling freePage2(), as
+ ** So if there exists more than one reference to this page, then it
+ ** must not really be an overflow page and the database must be corrupt.
+ ** It is helpful to detect this before calling freePage2(), as
** freePage2() may zero the page contents if secure-delete mode is
** enabled. If this 'overflow' page happens to be a page that the
** caller is iterating through or using in some other way, this
@@ -6440,7 +6542,7 @@ static int fillInCell(
pSrc = pX->pKey;
nHeader += putVarint32(&pCell[nHeader], nPayload);
}
-
+
/* Fill in the payload */
pPayload = &pCell[nHeader];
if( nPayload<=pPage->maxLocal ){
@@ -6531,8 +6633,8 @@ static int fillInCell(
if( pBt->autoVacuum ){
do{
pgnoOvfl++;
- } while(
- PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
+ } while(
+ PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
);
}
#endif
@@ -6540,9 +6642,9 @@ static int fillInCell(
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the database supports auto-vacuum, and the second or subsequent
** overflow page is being allocated, add an entry to the pointer-map
- ** for that page now.
+ ** for that page now.
**
- ** If this is the first overflow page, then write a partial entry
+ ** If this is the first overflow page, then write a partial entry
** to the pointer-map. If we write nothing to this pointer-map slot,
** then the optimistic overflow chain processing in clearCell()
** may misinterpret the uninitialized values and delete the
@@ -6603,6 +6705,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( pPage->nFree>=0 );
data = pPage->aData;
ptr = &pPage->aCellIdx[2*idx];
pc = get2byte(ptr);
@@ -6640,8 +6743,8 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
** will not fit, then make a copy of the cell content into pTemp if
** pTemp is not null. Regardless of pTemp, allocate a new entry
** in pPage->apOvfl[] and make it point to the cell content (either
-** in pTemp or the original pCell) and also record its index.
-** Allocating a new entry in pPage->aCell[] implies that
+** in pTemp or the original pCell) and also record its index.
+** Allocating a new entry in pPage->aCell[] implies that
** pPage->nOverflow is incremented.
**
** *pRC must be SQLITE_OK when this routine is called.
@@ -6667,12 +6770,8 @@ static void insertCell(
assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- /* The cell should normally be sized correctly. However, when moving a
- ** malformed cell from a leaf page to an interior page, if the cell size
- ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
- ** might be less than 8 (leaf-size + pointer) on the interior node. Hence
- ** the term after the || in the following assert(). */
- assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
+ assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB );
+ assert( pPage->nFree>=0 );
if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){
memcpy(pTemp, pCell, sz);
@@ -6713,9 +6812,16 @@ static void insertCell(
assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB );
assert( idx+sz <= (int)pPage->pBt->usableSize );
pPage->nFree -= (u16)(2 + sz);
- memcpy(&data[idx], pCell, sz);
if( iChild ){
+ /* In a corrupt database where an entry in the cell index section of
+ ** a btree page has a value of 3 or less, the pCell value might point
+ ** as many as 4 bytes in front of the start of the aData buffer for
+ ** the source page. Make sure this does not cause problems by not
+ ** reading the first 4 bytes */
+ memcpy(&data[idx+4], pCell+4, sz-4);
put4byte(&data[idx], iChild);
+ }else{
+ memcpy(&data[idx], pCell, sz);
}
pIns = pPage->aCellIdx + i*2;
memmove(pIns+2, pIns, 2*(pPage->nCell - i));
@@ -6723,21 +6829,100 @@ static void insertCell(
pPage->nCell++;
/* increment the cell count */
if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
- assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell );
+ assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB );
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pPage->pBt->autoVacuum ){
/* The cell may contain a pointer to an overflow page. If so, write
** the entry for the overflow page into the pointer map.
*/
- ptrmapPutOvflPtr(pPage, pCell, pRC);
+ ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
}
#endif
}
}
/*
+** The following parameters determine how many adjacent pages get involved
+** in a balancing operation. NN is the number of neighbors on either side
+** of the page that participate in the balancing operation. NB is the
+** total number of pages that participate, including the target page and
+** NN neighbors on either side.
+**
+** The minimum value of NN is 1 (of course). Increasing NN above 1
+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+** in exchange for a larger degradation in INSERT and UPDATE performance.
+** The value of NN appears to give the best results overall.
+**
+** (Later:) The description above makes it seem as if these values are
+** tunable - as if you could change them and recompile and it would all work.
+** But that is unlikely. NB has been 3 since the inception of SQLite and
+** we have never tested any other value.
+*/
+#define NN 1 /* Number of neighbors on either side of pPage */
+#define NB 3 /* (NN*2+1): Total pages involved in the balance */
+
+/*
** A CellArray object contains a cache of pointers and sizes for a
** consecutive sequence of cells that might be held on multiple pages.
+**
+** The cells in this array are the divider cell or cells from the pParent
+** page plus up to three child pages. There are a total of nCell cells.
+**
+** pRef is a pointer to one of the pages that contributes cells. This is
+** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
+** which should be common to all pages that contribute cells to this array.
+**
+** apCell[] and szCell[] hold, respectively, pointers to the start of each
+** cell and the size of each cell. Some of the apCell[] pointers might refer
+** to overflow cells. In other words, some apCel[] pointers might not point
+** to content area of the pages.
+**
+** A szCell[] of zero means the size of that cell has not yet been computed.
+**
+** The cells come from as many as four different pages:
+**
+** -----------
+** | Parent |
+** -----------
+** / | \
+** / | \
+** --------- --------- ---------
+** |Child-1| |Child-2| |Child-3|
+** --------- --------- ---------
+**
+** The order of cells is in the array is for an index btree is:
+**
+** 1. All cells from Child-1 in order
+** 2. The first divider cell from Parent
+** 3. All cells from Child-2 in order
+** 4. The second divider cell from Parent
+** 5. All cells from Child-3 in order
+**
+** For a table-btree (with rowids) the items 2 and 4 are empty because
+** content exists only in leaves and there are no divider cells.
+**
+** For an index btree, the apEnd[] array holds pointer to the end of page
+** for Child-1, the Parent, Child-2, the Parent (again), and Child-3,
+** respectively. The ixNx[] array holds the number of cells contained in
+** each of these 5 stages, and all stages to the left. Hence:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
+** ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+** ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
+** ixNx[4] = Total number of cells.
+**
+** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2]
+** are used and they point to the leaf pages only, and the ixNx value are:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 and Child-2.
+** ixNx[2] = Total number of cells.
+**
+** Sometimes when deleting, a child page can have zero cells. In those
+** cases, ixNx[] entries with higher indexes, and the corresponding apEnd[]
+** entries, shift down. The end result is that each ixNx[] entry should
+** be larger than the previous
*/
typedef struct CellArray CellArray;
struct CellArray {
@@ -6745,6 +6930,8 @@ struct CellArray {
MemPage *pRef; /* Reference page */
u8 **apCell; /* All cells begin balanced */
u16 *szCell; /* Local size of all cells in apCell[] */
+ u8 *apEnd[NB*2]; /* MemPage.aDataEnd values */
+ int ixNx[NB*2]; /* Index of at which we move to the next apEnd[] */
};
/*
@@ -6782,49 +6969,72 @@ static u16 cachedCellSize(CellArray *p, int N){
}
/*
-** Array apCell[] contains pointers to nCell b-tree page cells. The
+** Array apCell[] contains pointers to nCell b-tree page cells. The
** szCell[] array contains the size in bytes of each cell. This function
** replaces the current contents of page pPg with the contents of the cell
** array.
**
** Some of the cells in apCell[] may currently be stored in pPg. This
-** function works around problems caused by this by making a copy of any
+** function works around problems caused by this by making a copy of any
** such cells before overwriting the page data.
**
-** The MemPage.nFree field is invalidated by this function. It is the
+** The MemPage.nFree field is invalidated by this function. It is the
** responsibility of the caller to set it correctly.
*/
static int rebuildPage(
- MemPage *pPg, /* Edit this page */
+ CellArray *pCArray, /* Content to be added to page pPg */
+ int iFirst, /* First cell in pCArray to use */
int nCell, /* Final number of cells on page */
- u8 **apCell, /* Array of cells */
- u16 *szCell /* Array of cell sizes */
+ MemPage *pPg /* The page to be reconstructed */
){
const int hdr = pPg->hdrOffset; /* Offset of header on pPg */
u8 * const aData = pPg->aData; /* Pointer to data for pPg */
const int usableSize = pPg->pBt->usableSize;
u8 * const pEnd = &aData[usableSize];
- int i;
+ int i = iFirst; /* Which cell to copy from pCArray*/
+ u32 j; /* Start of cell content area */
+ int iEnd = i+nCell; /* Loop terminator */
u8 *pCellptr = pPg->aCellIdx;
u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
u8 *pData;
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */
- i = get2byte(&aData[hdr+5]);
- memcpy(&pTmp[i], &aData[i], usableSize - i);
+ assert( i<iEnd );
+ j = get2byte(&aData[hdr+5]);
+ if( NEVER(j>(u32)usableSize) ){ j = 0; }
+ memcpy(&pTmp[j], &aData[j], usableSize - j);
+
+ for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
- for(i=0; i<nCell; i++){
- u8 *pCell = apCell[i];
+ while( 1/*exit by break*/ ){
+ u8 *pCell = pCArray->apCell[i];
+ u16 sz = pCArray->szCell[i];
+ assert( sz>0 );
if( SQLITE_WITHIN(pCell,aData,pEnd) ){
+ if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
+ }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
+ && (uptr)(pCell)<(uptr)pSrcEnd
+ ){
+ return SQLITE_CORRUPT_BKPT;
}
- pData -= szCell[i];
+
+ pData -= sz;
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, szCell[i]);
- assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
+ memcpy(pData, pCell, sz);
+ assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
+ testcase( sz!=pPg->xCellSize(pPg,pCell) )
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pSrcEnd = pCArray->apEnd[k];
+ }
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -6839,12 +7049,11 @@ static int rebuildPage(
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function attempts to
-** add the cells stored in the array to page pPg. If it cannot (because
-** the page needs to be defragmented before the cells will fit), non-zero
-** is returned. Otherwise, if the cells are added successfully, zero is
-** returned.
+** The pCArray objects contains pointers to b-tree cells and the cell sizes.
+** This function attempts to add the cells stored in the array to page pPg.
+** If it cannot (because the page needs to be defragmented before the cells
+** will fit), non-zero is returned. Otherwise, if the cells are added
+** successfully, zero is returned.
**
** Argument pCellptr points to the first entry in the cell-pointer array
** (part of page pPg) to populate. After cell apCell[0] is written to the
@@ -6852,7 +7061,7 @@ static int rebuildPage(
** cell in the array. It is the responsibility of the caller to ensure
** that it is safe to overwrite this part of the cell-pointer array.
**
-** When this function is called, *ppData points to the start of the
+** When this function is called, *ppData points to the start of the
** content area on page pPg. If the size of the content area is extended,
** *ppData is updated to point to the new start of the content area
** before returning.
@@ -6866,21 +7075,27 @@ static int rebuildPage(
static int pageInsertArray(
MemPage *pPg, /* Page to add cells to */
u8 *pBegin, /* End of cell-pointer array */
- u8 **ppData, /* IN/OUT: Page content -area pointer */
+ u8 **ppData, /* IN/OUT: Page content-area pointer */
u8 *pCellptr, /* Pointer to cell-pointer area */
int iFirst, /* Index of first cell to add */
int nCell, /* Number of cells to add to pPg */
CellArray *pCArray /* Array of cells */
){
- int i;
- u8 *aData = pPg->aData;
- u8 *pData = *ppData;
- int iEnd = iFirst + nCell;
+ int i = iFirst; /* Loop counter - cell index to insert */
+ u8 *aData = pPg->aData; /* Complete page */
+ u8 *pData = *ppData; /* Content area. A subset of aData[] */
+ int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pEnd; /* Maximum extent of cell data */
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
- for(i=iFirst; i<iEnd; i++){
+ if( iEnd<=iFirst ) return 0;
+ for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pEnd = pCArray->apEnd[k];
+ while( 1 /*Exit by break*/ ){
int sz, rc;
u8 *pSlot;
- sz = cachedCellSize(pCArray, i);
+ assert( pCArray->szCell[i]!=0 );
+ sz = pCArray->szCell[i];
if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
if( (pData - pBegin)<sz ) return 1;
pData -= sz;
@@ -6892,20 +7107,33 @@ static int pageInsertArray(
assert( (pSlot+sz)<=pCArray->apCell[i]
|| pSlot>=(pCArray->apCell[i]+sz)
|| CORRUPT_DB );
+ if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
+ && (uptr)(pCArray->apCell[i])<(uptr)pEnd
+ ){
+ assert( CORRUPT_DB );
+ (void)SQLITE_CORRUPT_BKPT;
+ return 1;
+ }
memmove(pSlot, pCArray->apCell[i], sz);
put2byte(pCellptr, (pSlot - aData));
pCellptr += 2;
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pEnd = pCArray->apEnd[k];
+ }
}
*ppData = pData;
return 0;
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function adds the
-** space associated with each cell in the array that is currently stored
-** within the body of pPg to the pPg free-list. The cell-pointers and other
-** fields of the page are not updated.
+** The pCArray object contains pointers to b-tree cells and their sizes.
+**
+** This function adds the space associated with each cell in the array
+** that is currently stored within the body of pPg to the pPg free-list.
+** The cell-pointers and other fields of the page are not updated.
**
** This function returns the total number of cells added to the free-list.
*/
@@ -6939,7 +7167,9 @@ static int pageFreeArray(
}
pFree = pCell;
szFree = sz;
- if( pFree+sz>pEnd ) return 0;
+ if( NEVER(pFree+sz>pEnd) ){
+ return 0; /* Corruption - should be previously detected */
+ }
}else{
pFree = pCell;
szFree += sz;
@@ -6955,9 +7185,9 @@ static int pageFreeArray(
}
/*
-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
-** pages being balanced. The current page, pPg, has pPg->nCell cells starting
-** with apCell[iOld]. After balancing, this page should hold nNew cells
+** pCArray contains pointers to and sizes of all cells in the page being
+** balanced. The current page, pPg, has pPg->nCell cells starting with
+** pCArray->apCell[iOld]. After balancing, this page should hold nNew cells
** starting at apCell[iNew].
**
** This routine makes the necessary adjustments to pPg so that it contains
@@ -6989,13 +7219,17 @@ static int editPage(
#endif
/* Remove cells from the start and end of the page */
+ assert( nCell>=0 );
if( iOld<iNew ){
int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
+ if( NEVER(nShift>nCell) ) return SQLITE_CORRUPT_BKPT;
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
nCell -= nShift;
}
if( iNewEnd < iOldEnd ){
- nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ assert( nCell>=nTail );
+ nCell -= nTail;
}
pData = &aData[get2byteNotZero(&aData[hdr+5])];
@@ -7005,6 +7239,7 @@ static int editPage(
if( iNew<iOld ){
int nAdd = MIN(nNew,iOld-iNew);
assert( (iOld-iNew)<nNew || nCell==0 || CORRUPT_DB );
+ assert( nAdd>=0 );
pCellptr = pPg->aCellIdx;
memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
if( pageInsertArray(
@@ -7019,8 +7254,11 @@ static int editPage(
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCell<nNew ){
pCellptr = &pPg->aCellIdx[iCell * 2];
- memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
+ if( nCell>iCell ){
+ memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
+ }
nCell++;
+ cachedCellSize(pCArray, iCell+iNew);
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
iCell+iNew, 1, pCArray
@@ -7029,6 +7267,7 @@ static int editPage(
}
/* Append cells to the end of the page */
+ assert( nCell>=0 );
pCellptr = &pPg->aCellIdx[nCell*2];
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
@@ -7057,24 +7296,9 @@ static int editPage(
editpage_fail:
/* Unable to edit this page. Rebuild it from scratch instead. */
populateCellCache(pCArray, iNew, nNew);
- return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
+ return rebuildPage(pCArray, iNew, nNew, pPg);
}
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation. NN is the number of neighbors on either side
-** of the page that participate in the balancing operation. NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course). Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1 /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1) /* Total pages involved in the balance */
-
#ifndef SQLITE_OMIT_QUICKBALANCE
/*
@@ -7109,11 +7333,12 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
assert( pPage->nOverflow==1 );
+
+ if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* dbfuzz001.test */
+ assert( pPage->nFree>=0 );
+ assert( pParent->nFree>=0 );
- /* This error condition is now caught prior to reaching this function */
- if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT;
-
- /* Allocate a new page. This page will become the right-sibling of
+ /* Allocate a new page. This page will become the right-sibling of
** pPage. Make the parent page writable, so that the new divider cell
** may be inserted. If both these operations are successful, proceed.
*/
@@ -7125,16 +7350,26 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
u8 *pCell = pPage->apOvfl[0];
u16 szCell = pPage->xCellSize(pPage, pCell);
u8 *pStop;
+ CellArray b;
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
- assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
+ assert( CORRUPT_DB || pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
- rc = rebuildPage(pNew, 1, &pCell, &szCell);
- if( NEVER(rc) ) return rc;
+ b.nCell = 1;
+ b.pRef = pPage;
+ b.apCell = &pCell;
+ b.szCell = &szCell;
+ b.apEnd[0] = pPage->aDataEnd;
+ b.ixNx[0] = 2;
+ rc = rebuildPage(&b, 0, 1, pNew);
+ if( NEVER(rc) ){
+ releasePage(pNew);
+ return rc;
+ }
pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
/* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
+ ** with entries for the new page, and any pointer from the
** cell on the page to an overflow page. If either of these
** operations fails, the return code is set, but the contents
** of the parent page are still manipulated by thh code below.
@@ -7145,17 +7380,17 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
if( ISAUTOVACUUM ){
ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc);
if( szCell>pNew->minLocal ){
- ptrmapPutOvflPtr(pNew, pCell, &rc);
+ ptrmapPutOvflPtr(pNew, pNew, pCell, &rc);
}
}
-
+
/* Create a divider cell to insert into pParent. The divider cell
** consists of a 4-byte page number (the page number of pPage) and
** a variable length key value (which must be the same value as the
** largest key on pPage).
**
- ** To find the largest key value on pPage, first find the right-most
- ** cell on pPage. The first two fields of this cell are the
+ ** To find the largest key value on pPage, first find the right-most
+ ** cell on pPage. The first two fields of this cell are the
** record-length (a variable length integer at most 32-bits in size)
** and the key value (a variable length integer, may have any value).
** The first of the while(...) loops below skips over the record-length
@@ -7176,7 +7411,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
/* Set the right-child pointer of pParent to point to the new page. */
put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
-
+
/* Release the reference to the new page. */
releasePage(pNew);
}
@@ -7188,7 +7423,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
#if 0
/*
** This function does not contribute anything to the operation of SQLite.
-** it is sometimes activated temporarily while debugging code responsible
+** it is sometimes activated temporarily while debugging code responsible
** for setting pointer-map entries.
*/
static int ptrmapCheckPages(MemPage **apPage, int nPage){
@@ -7203,7 +7438,7 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
for(j=0; j<pPage->nCell; j++){
CellInfo info;
u8 *z;
-
+
z = findCell(pPage, j);
pPage->xParseCell(pPage, z, &info);
if( info.nLocal<info.nPayload ){
@@ -7228,7 +7463,7 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
#endif
/*
-** This function is used to copy the contents of the b-tree node stored
+** This function is used to copy the contents of the b-tree node stored
** on page pFrom to page pTo. If page pFrom was not a leaf page, then
** the pointer-map entries for each child page are updated so that the
** parent page stored in the pointer map is page pTo. If pFrom contained
@@ -7236,11 +7471,11 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
** map entries are also updated so that the parent page is page pTo.
**
** If pFrom is currently carrying any overflow cells (entries in the
-** MemPage.apOvfl[] array), they are not copied to pTo.
+** MemPage.apOvfl[] array), they are not copied to pTo.
**
** Before returning, page pTo is reinitialized using btreeInitPage().
**
-** The performance of this function is not critical. It is only used by
+** The performance of this function is not critical. It is only used by
** the balance_shallower() and balance_deeper() procedures, neither of
** which are called often under normal circumstances.
*/
@@ -7253,29 +7488,30 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
int rc;
int iData;
-
-
+
+
assert( pFrom->isInit );
assert( pFrom->nFree>=iToHdr );
assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize );
-
+
/* Copy the b-tree node content from page pFrom to page pTo. */
iData = get2byte(&aFrom[iFromHdr+5]);
memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
-
+
/* Reinitialize page pTo so that the contents of the MemPage structure
** match the new data. The initialization of pTo can actually fail under
- ** fairly obscure circumstances, even though it is a copy of initialized
+ ** fairly obscure circumstances, even though it is a copy of initialized
** page pFrom.
*/
pTo->isInit = 0;
rc = btreeInitPage(pTo);
+ if( rc==SQLITE_OK ) rc = btreeComputeFreeSpace(pTo);
if( rc!=SQLITE_OK ){
*pRC = rc;
return;
}
-
+
/* If this is an auto-vacuum database, update the pointer-map entries
** for any b-tree or overflow pages that pTo now contains the pointers to.
*/
@@ -7290,13 +7526,13 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
** (hereafter "the page") and up to 2 siblings so that all pages have about the
** same amount of free space. Usually a single sibling on either side of the
** page are used in the balancing, though both siblings might come from one
-** side if the page is the first or last child of its parent. If the page
+** side if the page is the first or last child of its parent. If the page
** has fewer than 2 siblings (something which can only happen if the page
** is a root page or a child of a root page) then all available siblings
** participate in the balancing.
**
-** The number of siblings of the page might be increased or decreased by
-** one or two in an effort to keep pages nearly full but not over full.
+** The number of siblings of the page might be increased or decreased by
+** one or two in an effort to keep pages nearly full but not over full.
**
** Note that when this routine is called, some of the cells on the page
** might not actually be stored in MemPage.aData[]. This can happen
@@ -7307,7 +7543,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
** inserted into or removed from the parent page (pParent). Doing so
** may cause the parent page to become overfull or underfull. If this
** happens, it is the responsibility of the caller to invoke the correct
-** balancing routine to fix this problem (see the balance() routine).
+** balancing routine to fix this problem (see the balance() routine).
**
** If this routine fails for any reason, it might leave the database
** in a corrupted state. So if this routine fails, the database should
@@ -7322,7 +7558,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
** of the page-size, the aOvflSpace[] buffer is guaranteed to be large
** enough for all overflow cells.
**
-** If aOvflSpace is set to a null pointer, this function returns
+** If aOvflSpace is set to a null pointer, this function returns
** SQLITE_NOMEM.
*/
static int balance_nonroot(
@@ -7368,12 +7604,8 @@ static int balance_nonroot(
assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
-#if 0
- TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
-#endif
-
/* At this point pParent may have at most one overflow cell. And if
- ** this overflow cell is present, it must be the cell with
+ ** this overflow cell is present, it must be the cell with
** index iParentIdx. This scenario comes about when this function
** is called (indirectly) from sqlite3BtreeDelete().
*/
@@ -7383,12 +7615,13 @@ static int balance_nonroot(
if( !aOvflSpace ){
return SQLITE_NOMEM_BKPT;
}
+ assert( pParent->nFree>=0 );
- /* Find the sibling pages to balance. Also locate the cells in pParent
- ** that divide the siblings. An attempt is made to find NN siblings on
- ** either side of pPage. More siblings are taken from one side, however,
+ /* Find the sibling pages to balance. Also locate the cells in pParent
+ ** that divide the siblings. An attempt is made to find NN siblings on
+ ** either side of pPage. More siblings are taken from one side, however,
** if there are fewer than NN siblings on the other side. If pParent
- ** has NB or fewer children then all children of pParent are taken.
+ ** has NB or fewer children then all children of pParent are taken.
**
** This loop also drops the divider cells from the parent page. This
** way, the remainder of the function does not have to deal with any
@@ -7400,7 +7633,7 @@ static int balance_nonroot(
nxDiv = 0;
}else{
assert( bBulk==0 || bBulk==1 );
- if( iParentIdx==0 ){
+ if( iParentIdx==0 ){
nxDiv = 0;
}else if( iParentIdx==i ){
nxDiv = i-2+bBulk;
@@ -7424,7 +7657,13 @@ static int balance_nonroot(
memset(apOld, 0, (i+1)*sizeof(MemPage*));
goto balance_cleanup;
}
- nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
+ if( apOld[i]->nFree<0 ){
+ rc = btreeComputeFreeSpace(apOld[i]);
+ if( rc ){
+ memset(apOld, 0, (i)*sizeof(MemPage*));
+ goto balance_cleanup;
+ }
+ }
if( (i--)==0 ) break;
if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
@@ -7442,7 +7681,7 @@ static int balance_nonroot(
** This is safe because dropping a cell only overwrites the first
** four bytes of it, and this function does not need the first
** four bytes of the divider cell. So the pointer is safe to use
- ** later on.
+ ** later on.
**
** But not if we are in secure-delete mode. In secure-delete mode,
** the dropCell() routine will overwrite the entire cell with zeroes.
@@ -7466,6 +7705,7 @@ static int balance_nonroot(
/* Make nMaxCells a multiple of 4 in order to preserve 8-byte
** alignment */
+ nMaxCells = nOld*(MX_CELL(pBt) + ArraySize(pParent->apOvfl));
nMaxCells = (nMaxCells + 3)&~3;
/*
@@ -7476,7 +7716,7 @@ static int balance_nonroot(
+ nMaxCells*sizeof(u16) /* b.szCell */
+ pBt->pageSize; /* aSpace1 */
- assert( szScratch<=6*(int)pBt->pageSize );
+ assert( szScratch<=7*(int)pBt->pageSize );
b.apCell = sqlite3StackAllocRaw(0, szScratch );
if( b.apCell==0 ){
rc = SQLITE_NOMEM_BKPT;
@@ -7512,6 +7752,7 @@ static int balance_nonroot(
u16 maskPage = pOld->maskPage;
u8 *piCell = aData + pOld->cellOffset;
u8 *piEnd;
+ VVA_ONLY( int nCellAtStart = b.nCell; )
/* Verify that all sibling pages are of the same "type" (table-leaf,
** table-interior, index-leaf, or index-interior).
@@ -7540,6 +7781,10 @@ static int balance_nonroot(
*/
memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
if( pOld->nOverflow>0 ){
+ if( NEVER(limit<pOld->aiOvfl[0]) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto balance_cleanup;
+ }
limit = pOld->aiOvfl[0];
for(j=0; j<limit; j++){
b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell));
@@ -7559,6 +7804,7 @@ static int balance_nonroot(
piCell += 2;
b.nCell++;
}
+ assert( (b.nCell-nCellAtStart)==(pOld->nCell+pOld->nOverflow) );
cntOld[i] = b.nCell;
if( i<nOld-1 && !leafData){
@@ -7599,7 +7845,7 @@ static int balance_nonroot(
** Figure out the number of pages needed to hold all b.nCell cells.
** Store this number in "k". Also compute szNew[] which is the total
** size of all cells on the i-th page and cntNew[] which is the index
- ** in b.apCell[] of the cell that divides page i from page i+1.
+ ** in b.apCell[] of the cell that divides page i from page i+1.
** cntNew[k] should equal b.nCell.
**
** Values computed by this block:
@@ -7609,11 +7855,22 @@ static int balance_nonroot(
** cntNew[i]: Index in b.apCell[] and b.szCell[] for the first cell to
** the right of the i-th sibling page.
** usableSpace: Number of bytes of space available on each sibling.
- **
+ **
*/
usableSpace = pBt->usableSize - 12 + leafCorrection;
- for(i=0; i<nOld; i++){
+ for(i=k=0; i<nOld; i++, k++){
MemPage *p = apOld[i];
+ b.apEnd[k] = p->aDataEnd;
+ b.ixNx[k] = cntOld[i];
+ if( k && b.ixNx[k]==b.ixNx[k-1] ){
+ k--; /* Omit b.ixNx[] entry for child pages with no cells */
+ }
+ if( !leafData ){
+ k++;
+ b.apEnd[k] = pParent->aDataEnd;
+ b.ixNx[k] = cntOld[i]+1;
+ }
+ assert( p->nFree>=0 );
szNew[i] = usableSpace - p->nFree;
for(j=0; j<p->nOverflow; j++){
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
@@ -7731,6 +7988,9 @@ static int balance_nonroot(
apOld[i] = 0;
rc = sqlite3PagerWrite(pNew->pDbPage);
nNew++;
+ if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
if( rc ) goto balance_cleanup;
}else{
assert( i>0 );
@@ -7752,24 +8012,24 @@ static int balance_nonroot(
}
/*
- ** Reassign page numbers so that the new pages are in ascending order.
+ ** Reassign page numbers so that the new pages are in ascending order.
** This helps to keep entries in the disk file in order so that a scan
- ** of the table is closer to a linear scan through the file. That in turn
+ ** of the table is closer to a linear scan through the file. That in turn
** helps the operating system to deliver pages from the disk more rapidly.
**
- ** An O(n^2) insertion sort algorithm is used, but since n is never more
+ ** An O(n^2) insertion sort algorithm is used, but since n is never more
** than (NB+2) (a small constant), that should not be a problem.
**
- ** When NB==3, this one optimization makes the database about 25% faster
+ ** When NB==3, this one optimization makes the database about 25% faster
** for large insertions and deletions.
*/
for(i=0; i<nNew; i++){
aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
aPgFlags[i] = apNew[i]->pDbPage->flags;
for(j=0; j<i; j++){
- if( aPgno[j]==aPgno[i] ){
+ if( NEVER(aPgno[j]==aPgno[i]) ){
/* This branch is taken if the set of sibling pages somehow contains
- ** duplicate entries. This can happen if the database is corrupt.
+ ** duplicate entries. This can happen if the database is corrupt.
** It would be simpler to detect this as part of the loop below, but
** we do the detection here in order to avoid populating the pager
** cache with two separate objects associated with the same
@@ -7810,17 +8070,19 @@ static int balance_nonroot(
));
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ assert( nNew>=1 && nNew<=ArraySize(apNew) );
+ assert( apNew[nNew-1]!=0 );
put4byte(pRight, apNew[nNew-1]->pgno);
/* If the sibling pages are not leaves, ensure that the right-child pointer
- ** of the right-most new sibling page is set to the value that was
+ ** of the right-most new sibling page is set to the value that was
** originally in the same field of the right-most old sibling page. */
if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){
MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
}
- /* Make any required updates to pointer map entries associated with
+ /* Make any required updates to pointer map entries associated with
** cells stored on sibling pages following the balance operation. Pointer
** map entries associated with divider cells are set by the insertCell()
** routine. The associated pointer map entries are:
@@ -7831,25 +8093,26 @@ static int balance_nonroot(
** b) if the sibling pages are not leaves, the child page associated
** with the cell.
**
- ** If the sibling pages are not leaves, then the pointer map entry
- ** associated with the right-child of each sibling may also need to be
- ** updated. This happens below, after the sibling pages have been
+ ** If the sibling pages are not leaves, then the pointer map entry
+ ** associated with the right-child of each sibling may also need to be
+ ** updated. This happens below, after the sibling pages have been
** populated, not here.
*/
if( ISAUTOVACUUM ){
- MemPage *pNew = apNew[0];
- u8 *aOld = pNew->aData;
+ MemPage *pOld;
+ MemPage *pNew = pOld = apNew[0];
int cntOldNext = pNew->nCell + pNew->nOverflow;
- int usableSize = pBt->usableSize;
int iNew = 0;
int iOld = 0;
for(i=0; i<b.nCell; i++){
u8 *pCell = b.apCell[i];
- if( i==cntOldNext ){
- MemPage *pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
+ while( i==cntOldNext ){
+ iOld++;
+ assert( iOld<nNew || iOld<nOld );
+ assert( iOld>=0 && iOld<NB );
+ pOld = iOld<nNew ? apNew[iOld] : apOld[iOld];
cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
- aOld = pOld->aData;
}
if( i==cntNew[iNew] ){
pNew = apNew[++iNew];
@@ -7857,20 +8120,20 @@ static int balance_nonroot(
}
/* Cell pCell is destined for new sibling page pNew. Originally, it
- ** was either part of sibling page iOld (possibly an overflow cell),
+ ** was either part of sibling page iOld (possibly an overflow cell),
** or else the divider cell to the left of sibling page iOld. So,
** if sibling page iOld had the same page number as pNew, and if
** pCell really was a part of sibling page iOld (not a divider or
** overflow cell), we can skip updating the pointer map entries. */
if( iOld>=nNew
|| pNew->pgno!=aPgno[iOld]
- || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize])
+ || !SQLITE_WITHIN(pCell,pOld->aData,pOld->aDataEnd)
){
if( !leafCorrection ){
ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
}
if( cachedCellSize(&b,i)>pNew->minLocal ){
- ptrmapPutOvflPtr(pNew, pCell, &rc);
+ ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
}
if( rc ) goto balance_cleanup;
}
@@ -7882,6 +8145,7 @@ static int balance_nonroot(
u8 *pCell;
u8 *pTemp;
int sz;
+ u8 *pSrcEnd;
MemPage *pNew = apNew[i];
j = cntNew[i];
@@ -7893,9 +8157,9 @@ static int balance_nonroot(
if( !pNew->leaf ){
memcpy(&pNew->aData[8], pCell, 4);
}else if( leafData ){
- /* If the tree is a leaf-data tree, and the siblings are leaves,
- ** then there is no divider cell in b.apCell[]. Instead, the divider
- ** cell consists of the integer key for the right-most cell of
+ /* If the tree is a leaf-data tree, and the siblings are leaves,
+ ** then there is no divider cell in b.apCell[]. Instead, the divider
+ ** cell consists of the integer key for the right-most cell of
** the sibling-page assembled above only.
*/
CellInfo info;
@@ -7908,9 +8172,9 @@ static int balance_nonroot(
pCell -= 4;
/* Obscure case for non-leaf-data trees: If the cell at pCell was
** previously stored on a leaf node, and its reported size was 4
- ** bytes, then it may actually be smaller than this
+ ** bytes, then it may actually be smaller than this
** (see btreeParseCellPtr(), 4 bytes is the minimum size of
- ** any cell). But it is important to pass the correct size to
+ ** any cell). But it is important to pass the correct size to
** insertCell(), so reparse the cell now.
**
** This can only happen for b-trees used to evaluate "IN (SELECT ...)"
@@ -7925,6 +8189,12 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
+ for(k=0; b.ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pSrcEnd = b.apEnd[k];
+ if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto balance_cleanup;
+ }
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -8002,8 +8272,8 @@ static int balance_nonroot(
** b-tree structure by one. This is described as the "balance-shallower"
** sub-algorithm in some documentation.
**
- ** If this is an auto-vacuum database, the call to copyNodeContent()
- ** sets all pointer-map entries corresponding to database image pages
+ ** If this is an auto-vacuum database, the call to copyNodeContent()
+ ** sets all pointer-map entries corresponding to database image pages
** for which the pointer is stored within the content being copied.
**
** It is critical that the child page be defragmented before being
@@ -8014,8 +8284,9 @@ static int balance_nonroot(
assert( nNew==1 || CORRUPT_DB );
rc = defragmentPage(apNew[0], -1);
testcase( rc!=SQLITE_OK );
- assert( apNew[0]->nFree ==
- (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
+ assert( apNew[0]->nFree ==
+ (get2byteNotZero(&apNew[0]->aData[5]) - apNew[0]->cellOffset
+ - apNew[0]->nCell*2)
|| rc!=SQLITE_OK
);
copyNodeContent(apNew[0], pParent, &rc);
@@ -8043,7 +8314,7 @@ static int balance_nonroot(
#if 0
if( ISAUTOVACUUM && rc==SQLITE_OK && apNew[0]->isInit ){
/* The ptrmapCheckPages() contains assert() statements that verify that
- ** all pointer map pages are set correctly. This is helpful while
+ ** all pointer map pages are set correctly. This is helpful while
** debugging. This is usually disabled because a corrupt database may
** cause an assert() statement to fail. */
ptrmapCheckPages(apNew, nNew);
@@ -8073,15 +8344,15 @@ balance_cleanup:
**
** A new child page is allocated and the contents of the current root
** page, including overflow cells, are copied into the child. The root
-** page is then overwritten to make it an empty page with the right-child
+** page is then overwritten to make it an empty page with the right-child
** pointer pointing to the new page.
**
-** Before returning, all pointer-map entries corresponding to pages
+** Before returning, all pointer-map entries corresponding to pages
** that the new child-page now contains pointers to are updated. The
** entry corresponding to the new right-child pointer of the root
** page is also updated.
**
-** If successful, *ppChild is set to contain a reference to the child
+** If successful, *ppChild is set to contain a reference to the child
** page and SQLITE_OK is returned. In this case the caller is required
** to call releasePage() on *ppChild exactly once. If an error occurs,
** an error code is returned and *ppChild is set to 0.
@@ -8095,7 +8366,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
assert( pRoot->nOverflow>0 );
assert( sqlite3_mutex_held(pBt->mutex) );
- /* Make pRoot, the root page of the b-tree, writable. Allocate a new
+ /* Make pRoot, the root page of the b-tree, writable. Allocate a new
** page that will become the new right-child of pPage. Copy the contents
** of the node stored on pRoot into the new child page.
*/
@@ -8114,7 +8385,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
}
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
- assert( pChild->nCell==pRoot->nCell );
+ assert( pChild->nCell==pRoot->nCell || CORRUPT_DB );
TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));
@@ -8134,9 +8405,33 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
}
/*
+** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
+** on the same B-tree as pCur.
+**
+** This can if a database is corrupt with two or more SQL tables
+** pointing to the same b-tree. If an insert occurs on one SQL table
+** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
+** table linked to the same b-tree. If the secondary insert causes a
+** rebalance, that can change content out from under the cursor on the
+** first SQL table, violating invariants on the first insert.
+*/
+static int anotherValidCursor(BtCursor *pCur){
+ BtCursor *pOther;
+ for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){
+ if( pOther!=pCur
+ && pOther->eState==CURSOR_VALID
+ && pOther->pPage==pCur->pPage
+ ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
-** tree needs to be balanced, and if so calls the appropriate balancing
+** tree needs to be balanced, and if so calls the appropriate balancing
** routine. Balancing routines are:
**
** balance_quick()
@@ -8153,16 +8448,19 @@ static int balance(BtCursor *pCur){
VVA_ONLY( int balance_deeper_called = 0 );
do {
- int iPage = pCur->iPage;
+ int iPage;
MemPage *pPage = pCur->pPage;
- if( iPage==0 ){
- if( pPage->nOverflow ){
+ if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
+ if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
+ break;
+ }else if( (iPage = pCur->iPage)==0 ){
+ if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
/* The root page of the b-tree is overfull. In this case call the
** balance_deeper() function to create a new child for the root-page
** and copy the current contents of the root-page to it. The
** next iteration of the do-loop will balance the child page.
- */
+ */
assert( balance_deeper_called==0 );
VVA_ONLY( balance_deeper_called++ );
rc = balance_deeper(pPage, &pCur->apPage[1]);
@@ -8177,13 +8475,14 @@ static int balance(BtCursor *pCur){
}else{
break;
}
- }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
- break;
}else{
MemPage * const pParent = pCur->apPage[iPage-1];
int const iIdx = pCur->aiIdx[iPage-1];
rc = sqlite3PagerWrite(pParent->pDbPage);
+ if( rc==SQLITE_OK && pParent->nFree<0 ){
+ rc = btreeComputeFreeSpace(pParent);
+ }
if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
if( pPage->intKeyLeaf
@@ -8195,17 +8494,17 @@ static int balance(BtCursor *pCur){
/* Call balance_quick() to create a new sibling of pPage on which
** to store the overflow cell. balance_quick() inserts a new cell
** into pParent, which may cause pParent overflow. If this
- ** happens, the next iteration of the do-loop will balance pParent
+ ** happens, the next iteration of the do-loop will balance pParent
** use either balance_nonroot() or balance_deeper(). Until this
** happens, the overflow cell is stored in the aBalanceQuickSpace[]
- ** buffer.
+ ** buffer.
**
** The purpose of the following assert() is to check that only a
** single call to balance_quick() is made for each call to this
** function. If this were not verified, a subtle bug involving reuse
** of the aBalanceQuickSpace[] might sneak in.
*/
- assert( balance_quick_called==0 );
+ assert( balance_quick_called==0 );
VVA_ONLY( balance_quick_called++ );
rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
}else
@@ -8216,15 +8515,15 @@ static int balance(BtCursor *pCur){
** modifying the contents of pParent, which may cause pParent to
** become overfull or underfull. The next iteration of the do-loop
** will balance the parent page to correct this.
- **
+ **
** If the parent page becomes overfull, the overflow cell or cells
- ** are stored in the pSpace buffer allocated immediately below.
+ ** are stored in the pSpace buffer allocated immediately below.
** A subsequent iteration of the do-loop will deal with this by
** calling balance_nonroot() (balance_deeper() may be called first,
** but it doesn't deal with overflow cells - just moves them to a
- ** different page). Once this subsequent call to balance_nonroot()
+ ** different page). Once this subsequent call to balance_nonroot()
** has completed, it is safe to release the pSpace buffer used by
- ** the previous call, as the overflow cell data will have been
+ ** the previous call, as the overflow cell data will have been
** copied either into the body of a database page or into the new
** pSpace buffer passed to the latter call to balance_nonroot().
*/
@@ -8232,9 +8531,9 @@ static int balance(BtCursor *pCur){
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
pCur->hints&BTREE_BULKLOAD);
if( pFree ){
- /* If pFree is not NULL, it points to the pSpace buffer used
+ /* If pFree is not NULL, it points to the pSpace buffer used
** by a previous call to balance_nonroot(). Its contents are
- ** now stored either on real database pages or within the
+ ** now stored either on real database pages or within the
** new pSpace buffer, so it may be safely freed here. */
sqlite3PageFree(pFree);
}
@@ -8294,7 +8593,11 @@ static int btreeOverwriteContent(
if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+ /* In a corrupt database, it is possible for the source and destination
+ ** buffers to overlap. This is harmless since the database is already
+ ** corrupt but it does cause valgrind and ASAN warnings. So use
+ ** memmove(). */
+ memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
}
}
return SQLITE_OK;
@@ -8313,7 +8616,9 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
Pgno ovflPgno; /* Next overflow page to write */
u32 ovflPageSize; /* Size to write on overflow page */
- if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
+ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
+ || pCur->info.pPayload < pPage->aData + pPage->cellOffset
+ ){
return SQLITE_CORRUPT_BKPT;
}
/* Overwrite the local portion first */
@@ -8347,7 +8652,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
if( rc ) return rc;
iOffset += ovflPageSize;
}while( iOffset<nTotal );
- return SQLITE_OK;
+ return SQLITE_OK;
}
@@ -8363,7 +8668,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
** hold the content of the row.
**
** For an index btree (used for indexes and WITHOUT ROWID tables), the
-** key is an arbitrary byte sequence stored in pX.pKey,nKey. The
+** key is an arbitrary byte sequence stored in pX.pKey,nKey. The
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
@@ -8397,7 +8702,8 @@ int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
- assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
+ assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
+ assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
@@ -8415,14 +8721,14 @@ int sqlite3BtreeInsert(
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
- assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
+ assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
/* Save the positions of any other cursors open on this table.
**
** In some cases, the call to btreeMoveto() below is a no-op. For
** example, when inserting data into a table with auto-generated integer
- ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
- ** integer key to use. It then calls this function to actually insert the
+ ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
+ ** integer key to use. It then calls this function to actually insert the
** data into the intkey B-Tree. In this case btreeMoveto() recognizes
** that the cursor is already where it needs to be and returns without
** doing any work. To avoid thwarting these optimizations, it is important
@@ -8435,18 +8741,17 @@ int sqlite3BtreeInsert(
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
- /* If this is an insert into a table b-tree, invalidate any incrblob
+ /* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
- /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
+ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
*/
#ifdef SQLITE_DEBUG
if( flags & BTREE_SAVEPOSITION ){
assert( pCur->curFlags & BTCF_ValidNKey );
assert( pX->nKey==pCur->info.nKey );
- assert( pCur->info.nSize!=0 );
assert( loc==0 );
}
#endif
@@ -8477,7 +8782,7 @@ int sqlite3BtreeInsert(
}else{
/* This is an index or a WITHOUT ROWID table */
- /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
+ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
*/
assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 );
@@ -8521,11 +8826,21 @@ int sqlite3BtreeInsert(
}
}
- assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
+ assert( pCur->eState==CURSOR_VALID
+ || (pCur->eState==CURSOR_INVALID && loc)
+ || CORRUPT_DB );
pPage = pCur->pPage;
- assert( pPage->intKey || pX->nKey>=0 );
+ assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
+ if( pPage->nFree<0 ){
+ if( pCur->eState>CURSOR_INVALID ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = btreeComputeFreeSpace(pPage);
+ }
+ if( rc ) return rc;
+ }
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
@@ -8533,7 +8848,21 @@ int sqlite3BtreeInsert(
assert( pPage->isInit );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
- rc = fillInCell(pPage, newCell, pX, &szNew);
+ if( flags & BTREE_PREFORMAT ){
+ rc = SQLITE_OK;
+ szNew = pBt->nPreformatSize;
+ if( szNew<4 ) szNew = 4;
+ if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
+ CellInfo info;
+ pPage->xParseCell(pPage, newCell, &info);
+ if( info.nPayload!=info.nLocal ){
+ Pgno ovfl = get4byte(&newCell[szNew-4]);
+ ptrmapPut(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
+ }
+ }
+ }else{
+ rc = fillInCell(pPage, newCell, pX, &szNew);
+ }
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
@@ -8550,20 +8879,27 @@ int sqlite3BtreeInsert(
memcpy(newCell, oldCell, 4);
}
rc = clearCell(pPage, oldCell, &info);
- if( info.nSize==szNew && info.nLocal==info.nPayload
+ testcase( pCur->curFlags & BTCF_ValidOvfl );
+ invalidateOverflowCache(pCur);
+ if( info.nSize==szNew && info.nLocal==info.nPayload
&& (!ISAUTOVACUUM || szNew<pPage->minLocal)
){
/* Overwrite the old cell with the new if they are the same size.
** We could also try to do this if the old cell is smaller, then add
** the leftover space to the free list. But experiments show that
** doing that is no faster then skipping this optimization and just
- ** calling dropCell() and insertCell().
+ ** calling dropCell() and insertCell().
**
** This optimization cannot be used on an autovacuum database if the
** new entry uses overflow pages, as the insertCell() call below is
** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
- if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+ if( oldCell < pPage->aData+pPage->hdrOffset+10 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( oldCell+szNew > pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
memcpy(oldCell, newCell, szNew);
return SQLITE_OK;
}
@@ -8580,7 +8916,7 @@ int sqlite3BtreeInsert(
assert( pPage->nOverflow==0 || rc==SQLITE_OK );
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
- /* If no error has occurred and pPage has an overflow cell, call balance()
+ /* If no error has occurred and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
** variables.
@@ -8607,7 +8943,7 @@ int sqlite3BtreeInsert(
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
- ** fails. Internal data structure corruption will result otherwise.
+ ** fails. Internal data structure corruption will result otherwise.
** Also, set the cursor state to invalid. This stops saveCursorPosition()
** from trying to save the current position of the cursor. */
pCur->pPage->nOverflow = 0;
@@ -8634,7 +8970,115 @@ end_insert:
}
/*
-** Delete the entry that the cursor is pointing to.
+** This function is used as part of copying the current row from cursor
+** pSrc into cursor pDest. If the cursors are open on intkey tables, then
+** parameter iKey is used as the rowid value when the record is copied
+** into pDest. Otherwise, the record is copied verbatim.
+**
+** This function does not actually write the new value to cursor pDest.
+** Instead, it creates and populates any required overflow pages and
+** writes the data for the new cell into the BtShared.pTmpSpace buffer
+** for the destination database. The size of the cell, in bytes, is left
+** in BtShared.nPreformatSize. The caller completes the insertion by
+** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
+ int rc = SQLITE_OK;
+ BtShared *pBt = pDest->pBt;
+ u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
+ const u8 *aIn; /* Pointer to next input buffer */
+ u32 nIn; /* Size of input buffer aIn[] */
+ u32 nRem; /* Bytes of data still to copy */
+
+ getCellInfo(pSrc);
+ aOut += putVarint32(aOut, pSrc->info.nPayload);
+ if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
+ nIn = pSrc->info.nLocal;
+ aIn = pSrc->info.pPayload;
+ if( aIn+nIn>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nRem = pSrc->info.nPayload;
+ if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
+ memcpy(aOut, aIn, nIn);
+ pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ }else{
+ Pager *pSrcPager = pSrc->pBt->pPager;
+ u8 *pPgnoOut = 0;
+ Pgno ovflIn = 0;
+ DbPage *pPageIn = 0;
+ MemPage *pPageOut = 0;
+ u32 nOut; /* Size of output buffer aOut[] */
+
+ nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
+ pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ if( nOut<pSrc->info.nPayload ){
+ pPgnoOut = &aOut[nOut];
+ pBt->nPreformatSize += 4;
+ }
+
+ if( nRem>nIn ){
+ if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
+ }
+
+ do {
+ nRem -= nOut;
+ do{
+ assert( nOut>0 );
+ if( nIn>0 ){
+ int nCopy = MIN(nOut, nIn);
+ memcpy(aOut, aIn, nCopy);
+ nOut -= nCopy;
+ nIn -= nCopy;
+ aOut += nCopy;
+ aIn += nCopy;
+ }
+ if( nOut>0 ){
+ sqlite3PagerUnref(pPageIn);
+ pPageIn = 0;
+ rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
+ if( rc==SQLITE_OK ){
+ aIn = (const u8*)sqlite3PagerGetData(pPageIn);
+ ovflIn = get4byte(aIn);
+ aIn += 4;
+ nIn = pSrc->pBt->usableSize - 4;
+ }
+ }
+ }while( rc==SQLITE_OK && nOut>0 );
+
+ if( rc==SQLITE_OK && nRem>0 ){
+ Pgno pgnoNew;
+ MemPage *pNew = 0;
+ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+ put4byte(pPgnoOut, pgnoNew);
+ if( ISAUTOVACUUM && pPageOut ){
+ ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
+ }
+ releasePage(pPageOut);
+ pPageOut = pNew;
+ if( pPageOut ){
+ pPgnoOut = pPageOut->aData;
+ put4byte(pPgnoOut, 0);
+ aOut = &pPgnoOut[4];
+ nOut = MIN(pBt->usableSize - 4, nRem);
+ }
+ }
+ }while( nRem>0 && rc==SQLITE_OK );
+
+ releasePage(pPageOut);
+ sqlite3PagerUnref(pPageIn);
+ }
+
+ return rc;
+}
+
+/*
+** Delete the entry that the cursor is pointing to.
**
** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
** the cursor is left pointing at an arbitrary location after the delete.
@@ -8652,12 +9096,12 @@ end_insert:
*/
int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
Btree *p = pCur->pBtree;
- BtShared *pBt = p->pBt;
+ BtShared *pBt = p->pBt;
int rc; /* Return code */
MemPage *pPage; /* Page to delete cell from */
unsigned char *pCell; /* Pointer to cell to delete */
int iCellIdx; /* Index of cell to delete */
- int iCellDepth; /* Depth of node containing pCell */
+ int iCellDepth; /* Depth of node containing pCell */
CellInfo info; /* Size of the cell being deleted */
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
@@ -8668,27 +9112,32 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- assert( pCur->ix<pCur->pPage->nCell );
- assert( pCur->eState==CURSOR_VALID );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
+ if( pCur->eState==CURSOR_REQUIRESEEK ){
+ rc = btreeRestoreCursorPosition(pCur);
+ if( rc ) return rc;
+ }
+ assert( pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
pPage = pCur->pPage;
pCell = findCell(pPage, iCellIdx);
+ if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT;
/* If the bPreserve flag is set to true, then the cursor position must
** be preserved following this delete operation. If the current delete
** will cause a b-tree rebalance, then this is done by saving the cursor
- ** key and leaving the cursor in CURSOR_REQUIRESEEK state before
- ** returning.
+ ** key and leaving the cursor in CURSOR_REQUIRESEEK state before
+ ** returning.
**
** Or, if the current delete will not cause a rebalance, then the cursor
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
** before or after the deleted entry. In this case set bSkipnext to true. */
if( bPreserve ){
- if( !pPage->leaf
+ if( !pPage->leaf
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
+ || pPage->nCell==1 /* See dbfuzz001.test for a test case */
){
/* A b-tree rebalance will be required after deleting this entry.
** Save the cursor key. */
@@ -8745,6 +9194,10 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
Pgno n;
unsigned char *pTmp;
+ if( pLeaf->nFree<0 ){
+ rc = btreeComputeFreeSpace(pLeaf);
+ if( rc ) return rc;
+ }
if( iCellDepth<pCur->iPage-1 ){
n = pCur->apPage[iCellDepth+1]->pgno;
}else{
@@ -8777,7 +9230,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** on the leaf node first. If the balance proceeds far enough up the
** tree that we can be sure that any problem in the internal node has
** been corrected, so be it. Otherwise, after balancing the leaf node,
- ** walk the cursor up the tree to the internal node and balance it as
+ ** walk the cursor up the tree to the internal node and balance it as
** well. */
rc = balance(pCur);
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
@@ -8825,7 +9278,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys
** BTREE_ZERODATA Used for SQL indices
*/
-static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
+static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
BtShared *pBt = p->pBt;
MemPage *pRoot;
Pgno pgnoRoot;
@@ -8858,6 +9311,9 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
** created so far, so the new root-page is (meta[3]+1).
*/
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
+ if( pgnoRoot>btreePagecount(pBt) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
pgnoRoot++;
/* The new root-page may not be allocated on a pointer-map page, or the
@@ -8867,8 +9323,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
pgnoRoot++;
}
- assert( pgnoRoot>=3 || CORRUPT_DB );
- testcase( pgnoRoot<3 );
+ assert( pgnoRoot>=3 );
/* Allocate a page. The page that currently resides at pgnoRoot will
** be moved to the allocated page (unless the allocated page happens
@@ -8931,7 +9386,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
}
}else{
pRoot = pPageMove;
- }
+ }
/* Update the pointer-map and meta-data with the new root-page number. */
ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc);
@@ -8965,10 +9420,10 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
zeroPage(pRoot, ptfFlags);
sqlite3PagerUnref(pRoot->pDbPage);
assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 );
- *piTable = (int)pgnoRoot;
+ *piTable = pgnoRoot;
return SQLITE_OK;
}
-int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
+int sqlite3BtreeCreateTable(Btree *p, Pgno *piTable, int flags){
int rc;
sqlite3BtreeEnter(p);
rc = btreeCreateTable(p, piTable, flags);
@@ -9084,12 +9539,12 @@ int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
** cursors on the table.
**
** If AUTOVACUUM is enabled and the page at iTable is not the last
-** root page in the database file, then the last root page
+** root page in the database file, then the last root page
** in the database file is moved into the slot formerly occupied by
** iTable and that last slot formerly occupied by the last root page
** is added to the freelist instead of iTable. In this say, all
** root pages are kept at the beginning of the database file, which
-** is necessary for AUTOVACUUM to work right. *piMoved is set to the
+** is necessary for AUTOVACUUM to work right. *piMoved is set to the
** page number that used to be the last root page in the file before
** the move. If no page gets moved, *piMoved is set to 0.
** The last root page is recorded in meta[3] and the value of
@@ -9103,6 +9558,9 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->inTrans==TRANS_WRITE );
assert( iTable>=2 );
+ if( iTable>btreePagecount(pBt) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
@@ -9124,7 +9582,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
if( iTable==maxRootPgno ){
/* If the table being dropped is the table with the largest root-page
- ** number in the database, put the root page on the free list.
+ ** number in the database, put the root page on the free list.
*/
freePage(pPage, &rc);
releasePage(pPage);
@@ -9133,7 +9591,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
}
}else{
/* The table being dropped does not have the largest root-page
- ** number in the database. So move the page that does into the
+ ** number in the database. So move the page that does into the
** gap left by the deleted root-page.
*/
MemPage *pMove;
@@ -9175,7 +9633,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
releasePage(pPage);
}
#endif
- return rc;
+ return rc;
}
int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
int rc;
@@ -9194,7 +9652,7 @@ int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
** is the number of free pages currently in the database. Meta[1]
** through meta[15] are available for use by higher layers. Meta[0]
** is read-only, the others are read/write.
-**
+**
** The schema layer numbers meta values differently. At the schema
** layer (and the SetCookie and ReadCookie opcodes) the number of
** free pages is not visible. So Cookie[0] is the same as Meta[1].
@@ -9211,12 +9669,12 @@ void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE );
- assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
+ assert( SQLITE_OK==querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK) );
assert( pBt->pPage1 );
assert( idx>=0 && idx<=15 );
if( idx==BTREE_DATA_VERSION ){
- *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
+ *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion;
}else{
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
}
@@ -9260,16 +9718,15 @@ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
return rc;
}
-#ifndef SQLITE_OMIT_BTREECOUNT
/*
** The first argument, pCur, is a cursor opened on some b-tree. Count the
** number of entries in the b-tree and write the result to *pnEntry.
**
-** SQLITE_OK is returned if the operation is successfully executed.
+** SQLITE_OK is returned if the operation is successfully executed.
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
-int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
+int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
@@ -9280,13 +9737,13 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
}
/* Unless an error occurs, the following loop runs one iteration for each
- ** page in the B-Tree structure (not including overflow pages).
+ ** page in the B-Tree structure (not including overflow pages).
*/
- while( rc==SQLITE_OK ){
+ while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){
int iIdx; /* Index of child node in parent */
MemPage *pPage; /* Current page of the b-tree */
- /* If this is a leaf page or the tree is not an int-key tree, then
+ /* If this is a leaf page or the tree is not an int-key tree, then
** this page contains countable entries. Increment the entry counter
** accordingly.
*/
@@ -9295,7 +9752,7 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
nEntry += pPage->nCell;
}
- /* pPage is a leaf node. This loop navigates the cursor so that it
+ /* pPage is a leaf node. This loop navigates the cursor so that it
** points to the first interior cell that it points to the parent of
** the next page in the tree that has not yet been visited. The
** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
@@ -9319,7 +9776,7 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
pPage = pCur->pPage;
}
- /* Descend to the child node of the cell that the cursor currently
+ /* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
iIdx = pCur->ix;
@@ -9333,7 +9790,6 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
/* An error has occurred. Return an error code. */
return rc;
}
-#endif
/*
** Return the pager associated with a BTree. This routine is used for
@@ -9366,7 +9822,7 @@ static void checkAppendMsg(
sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
va_end(ap);
if( pCheck->errMsg.accError==SQLITE_NOMEM ){
- pCheck->mallocFailed = 1;
+ pCheck->bOomFault = 1;
}
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -9408,13 +9864,14 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage){
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
return 1;
}
+ if( AtomicLoad(&pCheck->db->u1.isInterrupted) ) return 1;
setPageReferenced(pCheck, iPage);
return 0;
}
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
-** Check that the entry in the pointer-map for page iChild maps to
+** Check that the entry in the pointer-map for page iChild maps to
** page iParent, pointer type ptrType. If not, append an error message
** to pCheck.
*/
@@ -9430,14 +9887,14 @@ static void checkPtrmap(
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->bOomFault = 1;
checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
return;
}
if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
checkAppendMsg(pCheck,
- "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
+ "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
iChild, eType, iParent, ePtrmapType, iPtrmapParent);
}
}
@@ -9450,11 +9907,11 @@ static void checkPtrmap(
static void checkList(
IntegrityCk *pCheck, /* Integrity checking context */
int isFreeList, /* True for a freelist. False for overflow page list */
- int iPage, /* Page number for first page in the list */
- int N /* Expected number of pages in the list */
+ Pgno iPage, /* Page number for first page in the list */
+ u32 N /* Expected number of pages in the list */
){
int i;
- int expected = N;
+ u32 expected = N;
int nErrAtStart = pCheck->nErr;
while( iPage!=0 && pCheck->mxErr ){
DbPage *pOvflPage;
@@ -9467,18 +9924,18 @@ static void checkList(
}
pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
if( isFreeList ){
- int n = get4byte(&pOvflData[4]);
+ u32 n = (u32)get4byte(&pOvflData[4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pCheck->pBt->autoVacuum ){
checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
}
#endif
- if( n>(int)pCheck->pBt->usableSize/4-2 ){
+ if( n>pCheck->pBt->usableSize/4-2 ){
checkAppendMsg(pCheck,
"freelist leaf count too big on page %d", iPage);
N--;
}else{
- for(i=0; i<n; i++){
+ for(i=0; i<(int)n; i++){
Pgno iFreePage = get4byte(&pOvflData[8+i*4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pCheck->pBt->autoVacuum ){
@@ -9532,7 +9989,7 @@ static void checkList(
** property.
**
** This heap is used for cell overlap and coverage testing. Each u32
-** entry represents the span of a cell or freeblock on a btree page.
+** entry represents the span of a cell or freeblock on a btree page.
** The upper 16 bits are the index of the first byte of a range and the
** lower 16 bits are the index of the last byte of that range.
*/
@@ -9562,7 +10019,7 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
aHeap[j] = x;
i = j;
}
- return 1;
+ return 1;
}
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
@@ -9570,7 +10027,7 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
** Do various sanity checks on a single page of a tree. Return
** the tree depth. Root pages return 0. Parents of root pages
** return 1, and so forth.
-**
+**
** These checks are done:
**
** 1. Make sure that cells and freeblocks do not overlap
@@ -9582,7 +10039,7 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
*/
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
- int iPage, /* Page number of the page to check */
+ Pgno iPage, /* Page number of the page to check */
i64 *piMinKey, /* Write minimum integer primary key here */
i64 maxKey /* Error if integer primary key greater than this */
){
@@ -9618,9 +10075,9 @@ static int checkTreePage(
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage) ) return 0;
- pCheck->zPfx = "Page %d: ";
+ pCheck->zPfx = "Page %u: ";
pCheck->v1 = iPage;
- if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
+ if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck,
"unable to get the page. error code=%d", rc);
goto end_of_check;
@@ -9636,11 +10093,16 @@ static int checkTreePage(
"btreeInitPage() returns error code %d", rc);
goto end_of_check;
}
+ if( (rc = btreeComputeFreeSpace(pPage))!=0 ){
+ assert( rc==SQLITE_CORRUPT );
+ checkAppendMsg(pCheck, "free space corruption", rc);
+ goto end_of_check;
+ }
data = pPage->aData;
hdr = pPage->hdrOffset;
/* Set up for cell analysis */
- pCheck->zPfx = "On tree page %d cell %d: ";
+ pCheck->zPfx = "On tree page %u cell %d: ";
contentOffset = get2byteNotZero(&data[hdr+5]);
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
@@ -9660,7 +10122,7 @@ static int checkTreePage(
pgno = get4byte(&data[hdr+8]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
- pCheck->zPfx = "On page %d at right child: ";
+ pCheck->zPfx = "On page %u at right child: ";
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
}
#endif
@@ -9708,7 +10170,7 @@ static int checkTreePage(
/* Check the content overflow list */
if( info.nPayload>info.nLocal ){
- int nPage; /* Number of pages on the overflow chain */
+ u32 nPage; /* Number of pages on the overflow chain */
Pgno pgnoOvfl; /* First page of the overflow chain */
assert( pc + info.nSize - 4 <= usableSize );
nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
@@ -9763,14 +10225,14 @@ static int checkTreePage(
**
** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
** is the offset of the first freeblock, or zero if there are no
- ** freeblocks on the page.
+ ** freeblocks on the page.
*/
i = get2byte(&data[hdr+1]);
while( i>0 ){
int size, j;
- assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */
+ assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
size = get2byte(&data[i+2]);
- assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */
+ assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */
btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
** big-endian integer which is the offset in the b-tree page of the next
@@ -9779,17 +10241,17 @@ static int checkTreePage(
j = get2byte(&data[i]);
/* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
** increasing offset. */
- assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */
- assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */
+ assert( j==0 || j>i+size ); /* Enforced by btreeComputeFreeSpace() */
+ assert( (u32)j<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
i = j;
}
- /* Analyze the min-heap looking for overlap between cells and/or
+ /* Analyze the min-heap looking for overlap between cells and/or
** freeblocks, and counting the number of untracked bytes in nFrag.
- **
+ **
** Each min-heap entry is of the form: (start_address<<16)|end_address.
** There is an implied first entry the covers the page header, the cell
** pointer index, and the gap between the cell pointer index and the start
- ** of cell content.
+ ** of cell content.
**
** The loop below pulls entries from the min-heap in order and compares
** the start_address against the previous end_address. If there is an
@@ -9801,7 +10263,7 @@ static int checkTreePage(
while( btreeHeapPull(heap,&x) ){
if( (prev&0xffff)>=(x>>16) ){
checkAppendMsg(pCheck,
- "Multiple uses for byte %u of page %d", x>>16, iPage);
+ "Multiple uses for byte %u of page %u", x>>16, iPage);
break;
}else{
nFrag += (x>>16) - (prev&0xffff) - 1;
@@ -9816,7 +10278,7 @@ static int checkTreePage(
*/
if( heap[0]==0 && nFrag!=data[hdr+7] ){
checkAppendMsg(pCheck,
- "Fragmentation of %d bytes reported as %d on page %d",
+ "Fragmentation of %d bytes reported as %d on page %u",
nFrag, data[hdr+7], iPage);
}
}
@@ -9844,10 +10306,20 @@ end_of_check:
** allocation errors, an error message held in memory obtained from
** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
** returned. If a memory allocation error occurs, NULL is returned.
+**
+** If the first entry in aRoot[] is 0, that indicates that the list of
+** root pages is incomplete. This is a "partial integrity-check". This
+** happens when performing an integrity check on a single table. The
+** zero is skipped, of course. But in addition, the freelist checks
+** and the checks to make sure every page is referenced are also skipped,
+** since obviously it is not possible to know which pages are covered by
+** the unverified btrees. Except, if aRoot[1] is 1, then the freelist
+** checks are still performed.
*/
char *sqlite3BtreeIntegrityCheck(
+ sqlite3 *db, /* Database connection that is running the check */
Btree *p, /* The btree to be checked */
- int *aRoot, /* An array of root pages numbers for individual trees */
+ Pgno *aRoot, /* An array of root pages numbers for individual trees */
int nRoot, /* Number of entries in aRoot[] */
int mxErr, /* Stop reporting errors after this many */
int *pnErr /* Write number of errors seen to this variable */
@@ -9855,20 +10327,31 @@ char *sqlite3BtreeIntegrityCheck(
Pgno i;
IntegrityCk sCheck;
BtShared *pBt = p->pBt;
- int savedDbFlags = pBt->db->flags;
+ u64 savedDbFlags = pBt->db->flags;
char zErr[100];
+ int bPartial = 0; /* True if not checking all btrees */
+ int bCkFreelist = 1; /* True to scan the freelist */
VVA_ONLY( int nRef );
+ assert( nRoot>0 );
+
+ /* aRoot[0]==0 means this is a partial check */
+ if( aRoot[0]==0 ){
+ assert( nRoot>1 );
+ bPartial = 1;
+ if( aRoot[1]!=1 ) bCkFreelist = 0;
+ }
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
assert( nRef>=0 );
+ sCheck.db = db;
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
- sCheck.mallocFailed = 0;
+ sCheck.bOomFault = 0;
sCheck.zPfx = 0;
sCheck.v1 = 0;
sCheck.v2 = 0;
@@ -9882,12 +10365,12 @@ char *sqlite3BtreeIntegrityCheck(
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
if( !sCheck.aPgRef ){
- sCheck.mallocFailed = 1;
+ sCheck.bOomFault = 1;
goto integrity_ck_cleanup;
}
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
if( sCheck.heap==0 ){
- sCheck.mallocFailed = 1;
+ sCheck.bOomFault = 1;
goto integrity_ck_cleanup;
}
@@ -9896,38 +10379,42 @@ char *sqlite3BtreeIntegrityCheck(
/* Check the integrity of the freelist
*/
- sCheck.zPfx = "Main freelist: ";
- checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
- get4byte(&pBt->pPage1->aData[36]));
- sCheck.zPfx = 0;
+ if( bCkFreelist ){
+ sCheck.zPfx = "Main freelist: ";
+ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
+ get4byte(&pBt->pPage1->aData[36]));
+ sCheck.zPfx = 0;
+ }
/* Check all the tables.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- int mx = 0;
- int mxInHdr;
- for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
- mxInHdr = get4byte(&pBt->pPage1->aData[52]);
- if( mx!=mxInHdr ){
+ if( !bPartial ){
+ if( pBt->autoVacuum ){
+ Pgno mx = 0;
+ Pgno mxInHdr;
+ for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
+ mxInHdr = get4byte(&pBt->pPage1->aData[52]);
+ if( mx!=mxInHdr ){
+ checkAppendMsg(&sCheck,
+ "max rootpage (%d) disagrees with header (%d)",
+ mx, mxInHdr
+ );
+ }
+ }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
checkAppendMsg(&sCheck,
- "max rootpage (%d) disagrees with header (%d)",
- mx, mxInHdr
+ "incremental_vacuum enabled with a max rootpage of zero"
);
}
- }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
- checkAppendMsg(&sCheck,
- "incremental_vacuum enabled with a max rootpage of zero"
- );
}
#endif
testcase( pBt->db->flags & SQLITE_CellSizeCk );
- pBt->db->flags &= ~SQLITE_CellSizeCk;
+ pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
i64 notUsed;
if( aRoot[i]==0 ) continue;
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum && aRoot[i]>1 ){
+ if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
}
#endif
@@ -9937,24 +10424,26 @@ char *sqlite3BtreeIntegrityCheck(
/* Make sure every page in the file is referenced
*/
- for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
+ if( !bPartial ){
+ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
#ifdef SQLITE_OMIT_AUTOVACUUM
- if( getPageReferenced(&sCheck, i)==0 ){
- checkAppendMsg(&sCheck, "Page %d is never used", i);
- }
+ if( getPageReferenced(&sCheck, i)==0 ){
+ checkAppendMsg(&sCheck, "Page %d is never used", i);
+ }
#else
- /* If the database supports auto-vacuum, make sure no tables contain
- ** references to pointer-map pages.
- */
- if( getPageReferenced(&sCheck, i)==0 &&
- (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
- checkAppendMsg(&sCheck, "Page %d is never used", i);
- }
- if( getPageReferenced(&sCheck, i)!=0 &&
- (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
- checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
- }
+ /* If the database supports auto-vacuum, make sure no tables contain
+ ** references to pointer-map pages.
+ */
+ if( getPageReferenced(&sCheck, i)==0 &&
+ (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, "Page %d is never used", i);
+ }
+ if( getPageReferenced(&sCheck, i)!=0 &&
+ (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
+ }
#endif
+ }
}
/* Clean up and report errors.
@@ -9962,7 +10451,7 @@ char *sqlite3BtreeIntegrityCheck(
integrity_ck_cleanup:
sqlite3PageFree(sCheck.heap);
sqlite3_free(sCheck.aPgRef);
- if( sCheck.mallocFailed ){
+ if( sCheck.bOomFault ){
sqlite3_str_reset(&sCheck.errMsg);
sCheck.nErr++;
}
@@ -10001,18 +10490,19 @@ const char *sqlite3BtreeGetJournalname(Btree *p){
}
/*
-** Return non-zero if a transaction is active.
+** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE
+** to describe the current transaction state of Btree p.
*/
-int sqlite3BtreeIsInTrans(Btree *p){
+int sqlite3BtreeTxnState(Btree *p){
assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
- return (p && (p->inTrans==TRANS_WRITE));
+ return p ? p->inTrans : 0;
}
#ifndef SQLITE_OMIT_WAL
/*
** Run a checkpoint on the Btree passed as the first argument.
**
-** Return SQLITE_LOCKED if this or any other connection has an open
+** Return SQLITE_LOCKED if this or any other connection has an open
** transaction on the shared-cache the argument Btree is connected to.
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
@@ -10034,14 +10524,8 @@ int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
#endif
/*
-** Return non-zero if a read (or write) transaction is active.
+** Return true if there is currently a backup running on Btree p.
*/
-int sqlite3BtreeIsInReadTrans(Btree *p){
- assert( p );
- assert( sqlite3_mutex_held(p->db->mutex) );
- return p->inTrans!=TRANS_NONE;
-}
-
int sqlite3BtreeIsInBackup(Btree *p){
assert( p );
assert( sqlite3_mutex_held(p->db->mutex) );
@@ -10051,20 +10535,20 @@ int sqlite3BtreeIsInBackup(Btree *p){
/*
** This function returns a pointer to a blob of memory associated with
** a single shared-btree. The memory is used by client code for its own
-** purposes (for example, to store a high-level schema associated with
+** purposes (for example, to store a high-level schema associated with
** the shared-btree). The btree layer manages reference counting issues.
**
** The first time this is called on a shared-btree, nBytes bytes of memory
-** are allocated, zeroed, and returned to the caller. For each subsequent
+** are allocated, zeroed, and returned to the caller. For each subsequent
** call the nBytes parameter is ignored and a pointer to the same blob
-** of memory returned.
+** of memory returned.
**
** If the nBytes parameter is 0 and the blob of memory has not yet been
** allocated, a null pointer is returned. If the blob has already been
** allocated, it is returned as normal.
**
-** Just before the shared-btree is closed, the function passed as the
-** xFree argument when the memory allocation was made is invoked on the
+** Just before the shared-btree is closed, the function passed as the
+** xFree argument when the memory allocation was made is invoked on the
** blob of allocated memory. The xFree function should not call sqlite3_free()
** on the memory, the btree layer does that.
*/
@@ -10080,15 +10564,15 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
}
/*
-** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
-** btree as the argument handle holds an exclusive lock on the
-** sqlite_master table. Otherwise SQLITE_OK.
+** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
+** btree as the argument handle holds an exclusive lock on the
+** sqlite_schema table. Otherwise SQLITE_OK.
*/
int sqlite3BtreeSchemaLocked(Btree *p){
int rc;
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
- rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
+ rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE );
sqlite3BtreeLeave(p);
return rc;
@@ -10122,11 +10606,11 @@ int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
#ifndef SQLITE_OMIT_INCRBLOB
/*
-** Argument pCsr must be a cursor opened for writing on an
-** INTKEY table currently pointing at a valid table entry.
+** Argument pCsr must be a cursor opened for writing on an
+** INTKEY table currently pointing at a valid table entry.
** This function modifies the data stored as part of that entry.
**
-** Only the data content may only be modified, it is not possible to
+** Only the data content may only be modified, it is not possible to
** change the length of the data stored. If this function is called with
** parameters that attempt to write past the end of the existing data,
** no modifications are made and SQLITE_CORRUPT is returned.
@@ -10157,7 +10641,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
assert( rc==SQLITE_OK );
- /* Check some assumptions:
+ /* Check some assumptions:
** (a) the cursor is open for writing,
** (b) there is a read/write transaction open,
** (c) the connection holds a write-lock on the table (if required),
@@ -10176,7 +10660,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}
-/*
+/*
** Mark this cursor as an incremental blob cursor.
*/
void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
@@ -10186,14 +10670,14 @@ void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
#endif
/*
-** Set both the "read version" (single byte at byte offset 18) and
+** Set both the "read version" (single byte at byte offset 18) and
** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.
*/
int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
BtShared *pBt = pBtree->pBt;
int rc; /* Return code */
-
+
assert( iVersion==1 || iVersion==2 );
/* If setting the version fields to 1, do not automatically open the
@@ -10251,7 +10735,7 @@ int sqlite3BtreeSharable(Btree *p){
/*
** Return the number of connections to the BtShared object accessed by
-** the Btree handle passed as the only argument. For private caches
+** the Btree handle passed as the only argument. For private caches
** this is always 1. For shared caches it may be 1 or greater.
*/
int sqlite3BtreeConnectionCount(Btree *p){
diff --git a/chromium/third_party/sqlite/src/src/build.c b/chromium/third_party/sqlite/src/src/build.c
index 24633eb05dd..fb6f561e7d9 100644
--- a/chromium/third_party/sqlite/src/src/build.c
+++ b/chromium/third_party/sqlite/src/src/build.c
@@ -31,13 +31,13 @@
*/
struct TableLock {
int iDb; /* The database containing the table to be locked */
- int iTab; /* The root page of the table to be locked */
+ Pgno iTab; /* The root page of the table to be locked */
u8 isWriteLock; /* True for write lock. False for a read lock */
const char *zLockName; /* Name of the table */
};
/*
-** Record the fact that we want to lock a table at run-time.
+** Record the fact that we want to lock a table at run-time.
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
@@ -49,11 +49,11 @@ struct TableLock {
void sqlite3TableLock(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
- int iTab, /* Root page number of the table to be locked */
+ Pgno iTab, /* Root page number of the table to be locked */
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ Parse *pToplevel;
int i;
int nBytes;
TableLock *p;
@@ -61,6 +61,7 @@ void sqlite3TableLock(
if( iDb==1 ) return;
if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
@@ -90,10 +91,8 @@ void sqlite3TableLock(
*/
static void codeTableLocks(Parse *pParse){
int i;
- Vdbe *pVdbe;
-
- pVdbe = sqlite3GetVdbe(pParse);
- assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
+ Vdbe *pVdbe = pParse->pVdbe;
+ assert( pVdbe!=0 );
for(i=0; i<pParse->nTableLock; i++){
TableLock *p = &pParse->aTableLock[i];
@@ -144,10 +143,36 @@ void sqlite3FinishCoding(Parse *pParse){
/* Begin by generating some termination code at the end of the
** vdbe program
*/
- v = sqlite3GetVdbe(pParse);
- assert( !pParse->isMultiWrite
+ v = pParse->pVdbe;
+ if( v==0 ){
+ if( db->init.busy ){
+ pParse->rc = SQLITE_DONE;
+ return;
+ }
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) pParse->rc = SQLITE_ERROR;
+ }
+ assert( !pParse->isMultiWrite
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
+ if( pParse->bReturning ){
+ Returning *pReturning = pParse->u1.pReturning;
+ int addrRewind;
+ int i;
+ int reg;
+
+ addrRewind =
+ sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
+ VdbeCoverage(v);
+ reg = pReturning->iRetReg;
+ for(i=0; i<pReturning->nRetCol; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i);
+ }
+ sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i);
+ sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1);
+ VdbeCoverage(v);
+ sqlite3VdbeJumpHere(v, addrRewind);
+ }
sqlite3VdbeAddOp0(v, OP_Halt);
#if SQLITE_USER_AUTHENTICATION
@@ -167,7 +192,7 @@ void sqlite3FinishCoding(Parse *pParse){
** transaction on each used database and to verify the schema cookie
** on each used database.
*/
- if( db->mallocFailed==0
+ if( db->mallocFailed==0
&& (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
){
int iDb, i;
@@ -197,8 +222,8 @@ void sqlite3FinishCoding(Parse *pParse){
pParse->nVtabLock = 0;
#endif
- /* Once all the cookies have been verified and transactions opened,
- ** obtain the required table-locks. This is a no-op unless the
+ /* Once all the cookies have been verified and transactions opened,
+ ** obtain the required table-locks. This is a no-op unless the
** shared-cache feature is enabled.
*/
codeTableLocks(pParse);
@@ -207,27 +232,40 @@ void sqlite3FinishCoding(Parse *pParse){
*/
sqlite3AutoincrementBegin(pParse);
- /* Code constant expressions that where factored out of inner loops */
+ /* Code constant expressions that where factored out of inner loops.
+ **
+ ** The pConstExpr list might also contain expressions that we simply
+ ** want to keep around until the Parse object is deleted. Such
+ ** expressions have iConstExprReg==0. Do not generate code for
+ ** those expressions, of course.
+ */
if( pParse->pConstExpr ){
ExprList *pEL = pParse->pConstExpr;
pParse->okConstFactor = 0;
for(i=0; i<pEL->nExpr; i++){
- sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
+ int iReg = pEL->a[i].u.iConstExprReg;
+ if( iReg>0 ){
+ sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
+ }
}
}
+ if( pParse->bReturning ){
+ Returning *pRet = pParse->u1.pReturning;
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
+ }
+
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeGoto(v, 1);
}
}
-
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 && !db->mallocFailed ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
- if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
+ assert( pParse->pAinc==0 || pParse->nTab>0 );
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
}else{
@@ -244,7 +282,7 @@ void sqlite3FinishCoding(Parse *pParse){
** outermost parser.
**
** Not everything is nestable. This facility is designed to permit
-** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
+** INSERT, UPDATE, and DELETE operations against the schema table. Use
** care if you decide to try to use this routine for some other purposes.
*/
void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
@@ -260,7 +298,12 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
zSql = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( zSql==0 ){
- return; /* A malloc must have failed */
+ /* This can result either from an OOM or because the formatted string
+ ** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set
+ ** an error */
+ if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG;
+ pParse->nErr++;
+ return;
}
pParse->nested++;
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
@@ -307,22 +350,59 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
return 0;
}
#endif
- while(1){
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
- if( p ) return p;
+ if( zDatabase ){
+ for(i=0; i<db->nDb; i++){
+ if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
+ }
+ if( i>=db->nDb ){
+ /* No match against the official names. But always match "main"
+ ** to schema 0 as a legacy fallback. */
+ if( sqlite3StrICmp(zDatabase,"main")==0 ){
+ i = 0;
+ }else{
+ return 0;
+ }
+ }
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
+ if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
+ if( i==1 ){
+ if( sqlite3StrICmp(zName+7, &ALT_TEMP_SCHEMA_TABLE[7])==0
+ || sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0
+ || sqlite3StrICmp(zName+7, &DFLT_SCHEMA_TABLE[7])==0
+ ){
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
+ DFLT_TEMP_SCHEMA_TABLE);
+ }
+ }else{
+ if( sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0 ){
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash,
+ DFLT_SCHEMA_TABLE);
+ }
+ }
+ }
+ }else{
+ /* Match against TEMP first */
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
+ if( p ) return p;
+ /* The main database is second */
+ p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
+ if( p ) return p;
+ /* Attached databases are in order of attachment */
+ for(i=2; i<db->nDb; i++){
+ assert( sqlite3SchemaMutexHeld(db, i, 0) );
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
+ if( p ) break;
+ }
+ if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
+ if( sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0 ){
+ p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, DFLT_SCHEMA_TABLE);
+ }else if( sqlite3StrICmp(zName+7, &ALT_TEMP_SCHEMA_TABLE[7])==0 ){
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
+ DFLT_TEMP_SCHEMA_TABLE);
}
}
- /* Not found. If the name we were looking for was temp.sqlite_master
- ** then change the name to sqlite_temp_master and try again. */
- if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
- if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
- zName = TEMP_MASTER_NAME;
}
- return 0;
+ return p;
}
/*
@@ -346,7 +426,7 @@ Table *sqlite3LocateTable(
/* Read the database schema. If an error occurs, leave an error message
** and code in pParse and return NULL. */
- if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0
+ if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0
&& SQLITE_OK!=sqlite3ReadSchema(pParse)
){
return 0;
@@ -354,26 +434,32 @@ Table *sqlite3LocateTable(
p = sqlite3FindTable(db, zName, zDbase);
if( p==0 ){
- const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
- Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
- if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
- pMod = sqlite3PragmaVtabRegister(db, zName);
- }
- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
- return pMod->pEpoTab;
+ if( pParse->disableVtab==0 ){
+ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
+ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
+ pMod = sqlite3PragmaVtabRegister(db, zName);
+ }
+ if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
+ return pMod->pEpoTab;
+ }
}
#endif
- if( (flags & LOCATE_NOERR)==0 ){
- if( zDbase ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
- }else{
- sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
- }
- pParse->checkSchema = 1;
+ if( flags & LOCATE_NOERR ) return 0;
+ pParse->checkSchema = 1;
+ }else if( IsVirtual(p) && pParse->disableVtab ){
+ p = 0;
+ }
+
+ if( p==0 ){
+ const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
+ if( zDbase ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
+ }else{
+ sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
}
@@ -390,12 +476,12 @@ Table *sqlite3LocateTable(
** sqlite3FixSrcList() for details.
*/
Table *sqlite3LocateTableItem(
- Parse *pParse,
+ Parse *pParse,
u32 flags,
- struct SrcList_item *p
+ SrcItem *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
@@ -406,7 +492,7 @@ Table *sqlite3LocateTableItem(
}
/*
-** Locate the in-memory structure that describes
+** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
@@ -426,7 +512,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
Schema *pSchema = db->aDb[j].pSchema;
assert( pSchema );
- if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue;
+ if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
assert( sqlite3SchemaMutexHeld(db, j, 0) );
p = sqlite3HashFind(&pSchema->idxHash, zName);
if( p ) break;
@@ -445,7 +531,7 @@ void sqlite3FreeIndex(sqlite3 *db, Index *p){
sqlite3ExprListDelete(db, p->aColExpr);
sqlite3DbFree(db, p->zColAff);
if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifdef SQLITE_ENABLE_STAT4
sqlite3_free(p->aiRowEst);
#endif
sqlite3DbFree(db, p);
@@ -579,6 +665,7 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
+ assert( pCol->zName==0 || pCol->hName==sqlite3StrIHash(pCol->zName) );
sqlite3DbFree(db, pCol->zName);
sqlite3ExprDelete(db, pCol->pDflt);
sqlite3DbFree(db, pCol->zColl);
@@ -593,10 +680,10 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
**
** This routine just deletes the data structure. It does not unlink
** the table data structure from the hash table. But it does destroy
-** memory structures of the indices and foreign keys associated with
+** memory structures of the indices and foreign keys associated with
** the table.
**
-** The db parameter is optional. It is needed if the Table object
+** The db parameter is optional. It is needed if the Table object
** contains lookaside memory. (Table objects in the schema do not use
** lookaside memory, but some ephemeral Table objects do.) Or the
** db parameter can be used with db->pnBytesFreed to measure the memory
@@ -607,10 +694,14 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
#ifdef SQLITE_DEBUG
/* Record the number of outstanding lookaside allocations in schema Tables
- ** prior to doing any free() operations. Since schema Tables do not use
- ** lookaside, this number should not change. */
+ ** prior to doing any free() operations. Since schema Tables do not use
+ ** lookaside, this number should not change.
+ **
+ ** If malloc has already failed, it may be that it failed while allocating
+ ** a Table object that was going to be marked ephemeral. So do not check
+ ** that no lookaside memory is used in this case either. */
int nLookaside = 0;
- if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){
+ if( db && !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){
nLookaside = sqlite3LookasideUsed(db, 0);
}
#endif
@@ -621,7 +712,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
assert( pIndex->pSchema==pTable->pSchema
|| (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) );
if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){
- char *zName = pIndex->zName;
+ char *zName = pIndex->zName;
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
&pIndex->pSchema->idxHash, zName, 0
);
@@ -636,12 +727,6 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
/* Delete the Table structure itself.
*/
-#ifdef SQLITE_ENABLE_NORMALIZE
- if( pTable->pColHash ){
- sqlite3HashClear(pTable->pColHash);
- sqlite3_free(pTable->pColHash);
- }
-#endif
sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
@@ -707,13 +792,13 @@ char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
}
/*
-** Open the sqlite_master table stored in database number iDb for
+** Open the sqlite_schema table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
-void sqlite3OpenMasterTable(Parse *p, int iDb){
+void sqlite3OpenSchemaTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
- sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
- sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
+ sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, DFLT_SCHEMA_TABLE);
+ sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
}
@@ -742,7 +827,7 @@ int sqlite3FindDbName(sqlite3 *db, const char *zName){
/*
** The token *pName contains the name of a database (either "main" or
** "temp" or the name of an attached db). This routine returns the
-** index of the named database in db->aDb[], or -1 if the named db
+** index of the named database in db->aDb[], or -1 if the named db
** does not exist.
*/
int sqlite3FindDb(sqlite3 *db, Token *pName){
@@ -758,7 +843,7 @@ int sqlite3FindDb(sqlite3 *db, Token *pName){
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
-**
+**
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
@@ -820,13 +905,42 @@ int sqlite3WritableSchema(sqlite3 *db){
** trigger). All names are legal except those that begin with the string
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
** is reserved for internal use.
+**
+** When parsing the sqlite_schema table, this routine also checks to
+** make sure the "type", "name", and "tbl_name" columns are consistent
+** with the SQL.
*/
-int sqlite3CheckObjectName(Parse *pParse, const char *zName){
- if( !pParse->db->init.busy && pParse->nested==0
- && sqlite3WritableSchema(pParse->db)==0
- && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
- sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
- return SQLITE_ERROR;
+int sqlite3CheckObjectName(
+ Parse *pParse, /* Parsing context */
+ const char *zName, /* Name of the object to check */
+ const char *zType, /* Type of this object */
+ const char *zTblName /* Parent table name for triggers and indexes */
+){
+ sqlite3 *db = pParse->db;
+ if( sqlite3WritableSchema(db)
+ || db->init.imposterTable
+ || !sqlite3Config.bExtraSchemaChecks
+ ){
+ /* Skip these error checks for writable_schema=ON */
+ return SQLITE_OK;
+ }
+ if( db->init.busy ){
+ if( sqlite3_stricmp(zType, db->init.azInit[0])
+ || sqlite3_stricmp(zName, db->init.azInit[1])
+ || sqlite3_stricmp(zTblName, db->init.azInit[2])
+ ){
+ sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
+ return SQLITE_ERROR;
+ }
+ }else{
+ if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
+ || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
+ ){
+ sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
+ zName);
+ return SQLITE_ERROR;
+ }
+
}
return SQLITE_OK;
}
@@ -841,10 +955,12 @@ Index *sqlite3PrimaryKeyIndex(Table *pTab){
}
/*
-** Return the column of index pIdx that corresponds to table
-** column iCol. Return -1 if not found.
+** Convert an table column number into a index column number. That is,
+** for the column iCol in the table (as defined by the CREATE TABLE statement)
+** find the (first) offset of that column in index pIdx. Or return -1
+** if column iCol is not used in index pIdx.
*/
-i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
+i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
int i;
for(i=0; i<pIdx->nColumn; i++){
if( iCol==pIdx->aiColumn[i] ) return i;
@@ -852,6 +968,84 @@ i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
return -1;
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+/* Convert a storage column number into a table column number.
+**
+** The storage column number (0,1,2,....) is the index of the value
+** as it appears in the record on disk. The true column number
+** is the index (0,1,2,...) of the column in the CREATE TABLE statement.
+**
+** The storage column number is less than the table column number if
+** and only there are VIRTUAL columns to the left.
+**
+** If SQLITE_OMIT_GENERATED_COLUMNS, this routine is a no-op macro.
+*/
+i16 sqlite3StorageColumnToTable(Table *pTab, i16 iCol){
+ if( pTab->tabFlags & TF_HasVirtual ){
+ int i;
+ for(i=0; i<=iCol; i++){
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) iCol++;
+ }
+ }
+ return iCol;
+}
+#endif
+
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+/* Convert a table column number into a storage column number.
+**
+** The storage column number (0,1,2,....) is the index of the value
+** as it appears in the record on disk. Or, if the input column is
+** the N-th virtual column (zero-based) then the storage number is
+** the number of non-virtual columns in the table plus N.
+**
+** The true column number is the index (0,1,2,...) of the column in
+** the CREATE TABLE statement.
+**
+** If the input column is a VIRTUAL column, then it should not appear
+** in storage. But the value sometimes is cached in registers that
+** follow the range of registers used to construct storage. This
+** avoids computing the same VIRTUAL column multiple times, and provides
+** values for use by OP_Param opcodes in triggers. Hence, if the
+** input column is a VIRTUAL table, put it after all the other columns.
+**
+** In the following, N means "normal column", S means STORED, and
+** V means VIRTUAL. Suppose the CREATE TABLE has columns like this:
+**
+** CREATE TABLE ex(N,S,V,N,S,V,N,S,V);
+** -- 0 1 2 3 4 5 6 7 8
+**
+** Then the mapping from this function is as follows:
+**
+** INPUTS: 0 1 2 3 4 5 6 7 8
+** OUTPUTS: 0 1 6 2 3 7 4 5 8
+**
+** So, in other words, this routine shifts all the virtual columns to
+** the end.
+**
+** If SQLITE_OMIT_GENERATED_COLUMNS then there are no virtual columns and
+** this routine is a no-op macro. If the pTab does not have any virtual
+** columns, then this routine is no-op that always return iCol. If iCol
+** is negative (indicating the ROWID column) then this routine return iCol.
+*/
+i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
+ int i;
+ i16 n;
+ assert( iCol<pTab->nCol );
+ if( (pTab->tabFlags & TF_HasVirtual)==0 || iCol<0 ) return iCol;
+ for(i=0, n=0; i<iCol; i++){
+ if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) n++;
+ }
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){
+ /* iCol is a virtual column itself */
+ return pTab->nNVCol + i - n;
+ }else{
+ /* iCol is a normal or stored column */
+ return n;
+ }
+}
+#endif
+
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
@@ -885,7 +1079,7 @@ void sqlite3StartTable(
Token *pName; /* Unqualified name of the table to create */
if( db->init.busy && db->init.newTnum==1 ){
- /* Special case: Parsing the sqlite_master or sqlite_temp_master schema */
+ /* Special case: Parsing the sqlite_schema or sqlite_temp_schema schema */
iDb = db->init.iDb;
zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb));
pName = pName1;
@@ -894,7 +1088,7 @@ void sqlite3StartTable(
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
if( iDb<0 ) return;
if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){
- /* If creating a temp table, the name may not be qualified. Unless
+ /* If creating a temp table, the name may not be qualified. Unless
** the database name is "temp" anyway. */
sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
return;
@@ -907,7 +1101,7 @@ void sqlite3StartTable(
}
pParse->sNameToken = *pName;
if( zName==0 ) return;
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+ if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){
goto begin_table_error;
}
if( db->init.iDb==1 ) isTemp = 1;
@@ -991,10 +1185,10 @@ void sqlite3StartTable(
#endif
/* Begin generating the code that will insert the table record into
- ** the SQLITE_MASTER table. Note in particular that we must go ahead
+ ** the schema table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
- ** indices to be created and the table record must come before the
+ ** indices to be created and the table record must come before the
** indices. Hence, the record number for the table must be allocated
** now.
*/
@@ -1012,7 +1206,7 @@ void sqlite3StartTable(
}
#endif
- /* If the file format and encoding in the database have not been set,
+ /* If the file format and encoding in the database have not been set,
** set them now.
*/
reg1 = pParse->regRowid = ++pParse->nMem;
@@ -1027,7 +1221,7 @@ void sqlite3StartTable(
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db));
sqlite3VdbeJumpHere(v, addr1);
- /* This just creates a place-holder record in the sqlite_master table.
+ /* This just creates a place-holder record in the sqlite_schema table.
** The record created does not contain anything yet. It will be replaced
** by the real entry in code generated at sqlite3EndTable().
**
@@ -1042,10 +1236,11 @@ void sqlite3StartTable(
}else
#endif
{
- pParse->addrCrTab =
+ assert( !pParse->bReturning );
+ pParse->u1.addrCrTab =
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
- sqlite3OpenMasterTable(pParse, iDb);
+ sqlite3OpenSchemaTable(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC);
sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
@@ -1069,12 +1264,85 @@ begin_table_error:
void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
pCol->colFlags |= COLFLAG_HIDDEN;
+ if( pTab ) pTab->tabFlags |= TF_HasHidden;
}else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
pTab->tabFlags |= TF_OOOHidden;
}
}
#endif
+/*
+** Name of the special TEMP trigger used to implement RETURNING. The
+** name begins with "sqlite_" so that it is guaranteed not to collide
+** with any application-generated triggers.
+*/
+#define RETURNING_TRIGGER_NAME "sqlite_returning"
+
+/*
+** Clean up the data structures associated with the RETURNING clause.
+*/
+static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
+ Hash *pHash;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
+ sqlite3ExprListDelete(db, pRet->pReturnEL);
+ sqlite3DbFree(db, pRet);
+}
+
+/*
+** Add the RETURNING clause to the parse currently underway.
+**
+** This routine creates a special TEMP trigger that will fire for each row
+** of the DML statement. That TEMP trigger contains a single SELECT
+** statement with a result set that is the argument of the RETURNING clause.
+** The trigger has the Trigger.bReturning flag and an opcode of
+** TK_RETURNING instead of TK_SELECT, so that the trigger code generator
+** knows to handle it specially. The TEMP trigger is automatically
+** removed at the end of the parse.
+**
+** When this routine is called, we do not yet know if the RETURNING clause
+** is attached to a DELETE, INSERT, or UPDATE, so construct it as a
+** RETURNING trigger instead. It will then be converted into the appropriate
+** type on the first call to sqlite3TriggersExist().
+*/
+void sqlite3AddReturning(Parse *pParse, ExprList *pList){
+ Returning *pRet;
+ Hash *pHash;
+ sqlite3 *db = pParse->db;
+ if( pParse->pNewTrigger ){
+ sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger");
+ }else{
+ assert( pParse->bReturning==0 );
+ }
+ pParse->bReturning = 1;
+ pRet = sqlite3DbMallocZero(db, sizeof(*pRet));
+ if( pRet==0 ){
+ sqlite3ExprListDelete(db, pList);
+ return;
+ }
+ pParse->u1.pReturning = pRet;
+ pRet->pParse = pParse;
+ pRet->pReturnEL = pList;
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
+ testcase( pParse->earlyCleanup );
+ if( db->mallocFailed ) return;
+ pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
+ pRet->retTrig.op = TK_RETURNING;
+ pRet->retTrig.tr_tm = TRIGGER_AFTER;
+ pRet->retTrig.bReturning = 1;
+ pRet->retTrig.pSchema = db->aDb[1].pSchema;
+ pRet->retTrig.step_list = &pRet->retTStep;
+ pRet->retTStep.op = TK_RETURNING;
+ pRet->retTStep.pTrig = &pRet->retTrig;
+ pRet->retTStep.pExprList = pList;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr );
+ if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
+ ==&pRet->retTrig ){
+ sqlite3OomFault(db);
+ }
+}
/*
** Add a new column to the table currently being constructed.
@@ -1091,6 +1359,8 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
char *zType;
Column *pCol;
sqlite3 *db = pParse->db;
+ u8 hName;
+
if( (p = pParse->pNewTable)==0 ) return;
if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
@@ -1102,8 +1372,9 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
memcpy(z, pName->z, pName->n);
z[pName->n] = 0;
sqlite3Dequote(z);
+ hName = sqlite3StrIHash(z);
for(i=0; i<p->nCol; i++){
- if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
+ if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqlite3DbFree(db, z);
return;
@@ -1121,8 +1392,9 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
+ pCol->hName = hName;
sqlite3ColumnPropertiesFromName(p, pCol);
-
+
if( pType->n==0 ){
/* If there is no type specified, columns have the default affinity
** 'BLOB' with a default size of 4 bytes. */
@@ -1142,6 +1414,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
pCol->colFlags |= COLFLAG_HASTYPE;
}
p->nCol++;
+ p->nNVCol++;
pParse->constraintName.n = 0;
}
@@ -1177,11 +1450,11 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
** Scan the column type name zType (length nType) and return the
** associated affinity type.
**
-** This routine does a case-independent search of zType for the
+** This routine does a case-independent search of zType for the
** substrings in the following table. If one of the substrings is
** found, the corresponding affinity is returned. If zType contains
-** more than one of the substrings, entries toward the top of
-** the table take priority. For example, if zType is 'BLOBINT',
+** more than one of the substrings, entries toward the top of
+** the table take priority. For example, if zType is 'BLOBINT',
** SQLITE_AFF_INTEGER is returned.
**
** Substring | Affinity
@@ -1286,10 +1559,17 @@ void sqlite3AddDefaultValue(
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
if( p!=0 ){
+ int isInit = db->init.busy && db->init.iDb!=1;
pCol = &(p->aCol[p->nCol-1]);
- if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
+ if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ }else if( pCol->colFlags & COLFLAG_GENERATED ){
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pCol->colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
+#endif
}else{
/* A copy of pExpr is used instead of the original, as pExpr contains
** tokens that point to volatile memory.
@@ -1313,7 +1593,7 @@ void sqlite3AddDefaultValue(
/*
** Backwards Compatibility Hack:
-**
+**
** Historical versions of SQLite accepted strings as column names in
** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example:
**
@@ -1324,7 +1604,7 @@ void sqlite3AddDefaultValue(
** accept it. This routine does the necessary conversion. It converts
** the expression given in its argument from a TK_STRING into a TK_ID
** if the expression is just a TK_STRING with an optional COLLATE clause.
-** If the epxression is anything other than TK_STRING, the expression is
+** If the expression is anything other than TK_STRING, the expression is
** unchanged.
*/
static void sqlite3StringToId(Expr *p){
@@ -1336,7 +1616,22 @@ static void sqlite3StringToId(Expr *p){
}
/*
-** Designate the PRIMARY KEY for the table. pList is a list of names
+** Tag the given column as being part of the PRIMARY KEY
+*/
+static void makeColumnPartOfPrimaryKey(Parse *pParse, Column *pCol){
+ pCol->colFlags |= COLFLAG_PRIMKEY;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pCol->colFlags & COLFLAG_GENERATED ){
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pCol->colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse,
+ "generated columns cannot be part of the PRIMARY KEY");
+ }
+#endif
+}
+
+/*
+** Designate the PRIMARY KEY for the table. pList is a list of names
** of columns that form the primary key. If pList is NULL, then the
** most recently added column of the table is the primary key.
**
@@ -1366,7 +1661,7 @@ void sqlite3AddPrimaryKey(
int nTerm;
if( pTab==0 ) goto primary_key_exit;
if( pTab->tabFlags & TF_HasPrimaryKey ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key", pTab->zName);
goto primary_key_exit;
}
@@ -1374,7 +1669,7 @@ void sqlite3AddPrimaryKey(
if( pList==0 ){
iCol = pTab->nCol - 1;
pCol = &pTab->aCol[iCol];
- pCol->colFlags |= COLFLAG_PRIMKEY;
+ makeColumnPartOfPrimaryKey(pParse, pCol);
nTerm = 1;
}else{
nTerm = pList->nExpr;
@@ -1387,7 +1682,7 @@ void sqlite3AddPrimaryKey(
for(iCol=0; iCol<pTab->nCol; iCol++){
if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
pCol = &pTab->aCol[iCol];
- pCol->colFlags |= COLFLAG_PRIMKEY;
+ makeColumnPartOfPrimaryKey(pParse, pCol);
break;
}
}
@@ -1407,7 +1702,8 @@ void sqlite3AddPrimaryKey(
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
- if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
+ if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags;
+ (void)sqlite3HasExplicitNulls(pParse, pList);
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
@@ -1428,8 +1724,10 @@ primary_key_exit:
** Add a new CHECK constraint to the table currently under construction.
*/
void sqlite3AddCheckConstraint(
- Parse *pParse, /* Parsing context */
- Expr *pCheckExpr /* The check expression */
+ Parse *pParse, /* Parsing context */
+ Expr *pCheckExpr, /* The check expression */
+ const char *zStart, /* Opening "(" */
+ const char *zEnd /* Closing ")" */
){
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
@@ -1440,6 +1738,13 @@ void sqlite3AddCheckConstraint(
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
if( pParse->constraintName.n ){
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+ }else{
+ Token t;
+ for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
+ while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; }
+ t.z = zStart;
+ t.n = (int)(zEnd - t.z);
+ sqlite3ExprListSetName(pParse, pTab->pCheck, &t, 1);
}
}else
#endif
@@ -1458,7 +1763,7 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
char *zColl; /* Dequoted name of collation sequence */
sqlite3 *db;
- if( (p = pParse->pNewTable)==0 ) return;
+ if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
i = p->nCol-1;
db = pParse->db;
zColl = sqlite3NameFromToken(db, pToken);
@@ -1468,7 +1773,7 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
Index *pIdx;
sqlite3DbFree(db, p->aCol[i].zColl);
p->aCol[i].zColl = zColl;
-
+
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
** then an index may have been created on this column before the
** collation type was added. Correct this if it is the case.
@@ -1484,41 +1789,58 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
}
}
-/*
-** This function returns the collation sequence for database native text
-** encoding identified by the string zName, length nName.
-**
-** If the requested collation sequence is not available, or not available
-** in the database native encoding, the collation factory is invoked to
-** request it. If the collation factory does not supply such a sequence,
-** and the sequence is available in another text encoding, then that is
-** returned instead.
-**
-** If no versions of the requested collations sequence are available, or
-** another error occurs, NULL is returned and an error message written into
-** pParse.
-**
-** This routine is a wrapper around sqlite3FindCollSeq(). This routine
-** invokes the collation factory if the named collation cannot be found
-** and generates an error message.
-**
-** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
+/* Change the most recently parsed column to be a GENERATED ALWAYS AS
+** column.
*/
-CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
- sqlite3 *db = pParse->db;
- u8 enc = ENC(db);
- u8 initbusy = db->init.busy;
- CollSeq *pColl;
-
- pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
- if( !initbusy && (!pColl || !pColl->xCmp) ){
- pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
+void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ u8 eType = COLFLAG_VIRTUAL;
+ Table *pTab = pParse->pNewTable;
+ Column *pCol;
+ if( pTab==0 ){
+ /* generated column in an CREATE TABLE IF NOT EXISTS that already exists */
+ goto generated_done;
+ }
+ pCol = &(pTab->aCol[pTab->nCol-1]);
+ if( IN_DECLARE_VTAB ){
+ sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
+ goto generated_done;
+ }
+ if( pCol->pDflt ) goto generated_error;
+ if( pType ){
+ if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
+ /* no-op */
+ }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
+ eType = COLFLAG_STORED;
+ }else{
+ goto generated_error;
+ }
}
-
- return pColl;
+ if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--;
+ pCol->colFlags |= eType;
+ assert( TF_HasVirtual==COLFLAG_VIRTUAL );
+ assert( TF_HasStored==COLFLAG_STORED );
+ pTab->tabFlags |= eType;
+ if( pCol->colFlags & COLFLAG_PRIMKEY ){
+ makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
+ }
+ pCol->pDflt = pExpr;
+ pExpr = 0;
+ goto generated_done;
+
+generated_error:
+ sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
+ pCol->zName);
+generated_done:
+ sqlite3ExprDelete(pParse->db, pExpr);
+#else
+ /* Throw and error for the GENERATED ALWAYS AS clause if the
+ ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
+ sqlite3ErrorMsg(pParse, "generated columns not supported");
+ sqlite3ExprDelete(pParse->db, pExpr);
+#endif
}
-
/*
** Generate code that will increment the schema cookie.
**
@@ -1542,7 +1864,7 @@ void sqlite3ChangeCookie(Parse *pParse, int iDb){
sqlite3 *db = pParse->db;
Vdbe *v = pParse->pVdbe;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION,
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION,
(int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie));
}
@@ -1563,13 +1885,13 @@ static int identLength(const char *z){
}
/*
-** The first parameter is a pointer to an output buffer. The second
+** The first parameter is a pointer to an output buffer. The second
** parameter is a pointer to an integer that contains the offset at
** which to write into the output buffer. This function copies the
** nul-terminated string pointed to by the third parameter, zSignedIdent,
** to the specified offset in the buffer and updates *pIdx to refer
** to the first byte after the last byte written before returning.
-**
+**
** If the string zSignedIdent consists entirely of alpha-numeric
** characters, does not begin with a digit and is not an SQL keyword,
** then it is copied to the output buffer exactly as it is. Otherwise,
@@ -1613,7 +1935,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
n += identLength(pCol->zName) + 5;
}
n += identLength(p->zName);
- if( n<50 ){
+ if( n<50 ){
zSep = "";
zSep2 = ",";
zEnd = ")";
@@ -1654,10 +1976,10 @@ static char *createTableStmt(sqlite3 *db, Table *p){
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
testcase( pCol->affinity==SQLITE_AFF_REAL );
-
+
zType = azType[pCol->affinity - SQLITE_AFF_BLOB];
len = sqlite3Strlen30(zType);
- assert( pCol->affinity==SQLITE_AFF_BLOB
+ assert( pCol->affinity==SQLITE_AFF_BLOB
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
memcpy(&zStmt[k], zType, len);
k += len;
@@ -1676,12 +1998,15 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
int nByte;
if( pIdx->nColumn>=N ) return SQLITE_OK;
assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
+ nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
zExtra = sqlite3DbMallocZero(db, nByte);
if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
pIdx->azColl = (const char**)zExtra;
zExtra += sizeof(char*)*N;
+ memcpy(zExtra, pIdx->aiRowLogEst, sizeof(LogEst)*(pIdx->nKeyCol+1));
+ pIdx->aiRowLogEst = (LogEst*)zExtra;
+ zExtra += sizeof(LogEst)*N;
memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
pIdx->aiColumn = (i16*)zExtra;
zExtra += sizeof(i16)*N;
@@ -1721,10 +2046,51 @@ static void estimateIndexWidth(Index *pIdx){
pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
}
-/* Return true if value x is found any of the first nCol entries of aiCol[]
+/* Return true if column number x is any of the first nCol entries of aiCol[].
+** This is used to determine if the column number x appears in any of the
+** first nCol entries of an index.
*/
static int hasColumn(const i16 *aiCol, int nCol, int x){
- while( nCol-- > 0 ) if( x==*(aiCol++) ) return 1;
+ while( nCol-- > 0 ){
+ assert( aiCol[0]>=0 );
+ if( x==*(aiCol++) ){
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+** Return true if any of the first nKey entries of index pIdx exactly
+** match the iCol-th entry of pPk. pPk is always a WITHOUT ROWID
+** PRIMARY KEY index. pIdx is an index on the same table. pIdx may
+** or may not be the same index as pPk.
+**
+** The first nKey entries of pIdx are guaranteed to be ordinary columns,
+** not a rowid or expression.
+**
+** This routine differs from hasColumn() in that both the column and the
+** collating sequence must match for this routine, but for hasColumn() only
+** the column name must match.
+*/
+static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){
+ int i, j;
+ assert( nKey<=pIdx->nColumn );
+ assert( iCol<MAX(pPk->nColumn,pPk->nKeyCol) );
+ assert( pPk->idxType==SQLITE_IDXTYPE_PRIMARYKEY );
+ assert( pPk->pTable->tabFlags & TF_WithoutRowid );
+ assert( pPk->pTable==pIdx->pTable );
+ testcase( pPk==pIdx );
+ j = pPk->aiColumn[iCol];
+ assert( j!=XN_ROWID && j!=XN_EXPR );
+ for(i=0; i<nKey; i++){
+ assert( pIdx->aiColumn[i]>=0 || j>=0 );
+ if( pIdx->aiColumn[i]==j
+ && sqlite3StrICmp(pIdx->azColl[i], pPk->azColl[iCol])==0
+ ){
+ return 1;
+ }
+ }
return 0;
}
@@ -1735,15 +2101,24 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
** high-order bit of colNotIdxed is always 1. All unindexed columns
** of the table have a 1.
**
+** 2019-10-24: For the purpose of this computation, virtual columns are
+** not considered to be covered by the index, even if they are in the
+** index, because we do not trust the logic in whereIndexExprTrans() to be
+** able to find all instances of a reference to the indexed table column
+** and convert them into references to the index. Hence we always want
+** the actual table at hand in order to recompute the virtual column, if
+** necessary.
+**
** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask
** to determine if the index is covering index.
*/
static void recomputeColumnsNotIndexed(Index *pIdx){
Bitmask m = 0;
int j;
+ Table *pTab = pIdx->pTable;
for(j=pIdx->nColumn-1; j>=0; j--){
int x = pIdx->aiColumn[j];
- if( x>=0 ){
+ if( x>=0 && (pTab->aCol[x].colFlags & COLFLAG_VIRTUAL)==0 ){
testcase( x==BMS-1 );
testcase( x==BMS-2 );
if( x<BMS-1 ) m |= MASKBIT(x);
@@ -1761,11 +2136,11 @@ static void recomputeColumnsNotIndexed(Index *pIdx){
** Changes include:
**
** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
-** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY
+** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY
** into BTREE_BLOBKEY.
-** (3) Bypass the creation of the sqlite_master table entry
+** (3) Bypass the creation of the sqlite_schema table entry
** for the PRIMARY KEY as the primary key index is now
-** identified by the sqlite_master table entry of the table itself.
+** identified by the sqlite_schema table entry of the table itself.
** (4) Set the Index.tnum of the PRIMARY KEY Index object in the
** schema to the rootpage from the main table.
** (5) Add all table columns to the PRIMARY KEY Index object
@@ -1781,6 +2156,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
Index *pIdx;
Index *pPk;
int nPk;
+ int nExtra;
int i, j;
sqlite3 *db = pParse->db;
Vdbe *v = pParse->pVdbe;
@@ -1793,35 +2169,42 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pTab->aCol[i].notNull = OE_Abort;
}
}
+ pTab->tabFlags |= TF_HasNotNull;
}
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
- if( pParse->addrCrTab ){
+ assert( !pParse->bReturning );
+ if( pParse->u1.addrCrTab ){
assert( v );
- sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
+ sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
- ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
+ ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
*/
if( pTab->iPKey>=0 ){
ExprList *pList;
Token ipkToken;
sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
- pList = sqlite3ExprListAppend(pParse, 0,
+ pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
if( pList==0 ) return;
- pList->a[0].sortOrder = pParse->iPkSortOrder;
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
+ }
+ pList->a[0].sortFlags = pParse->iPkSortOrder;
assert( pParse->pNewTable==pTab );
+ pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
if( db->mallocFailed || pParse->nErr ) return;
pPk = sqlite3PrimaryKeyIndex(pTab);
- pTab->iPKey = -1;
+ assert( pPk->nKeyCol==1 );
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
/*
** Remove all redundant columns from the PRIMARY KEY. For example, change
@@ -1829,9 +2212,12 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** code assumes the PRIMARY KEY contains no repeated columns.
*/
for(i=j=1; i<pPk->nKeyCol; i++){
- if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){
+ if( isDupColumn(pPk, j, pPk, i) ){
pPk->nColumn--;
}else{
+ testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) );
+ pPk->azColl[j] = pPk->azColl[i];
+ pPk->aSortOrder[j] = pPk->aSortOrder[i];
pPk->aiColumn[j++] = pPk->aiColumn[i];
}
}
@@ -1840,15 +2226,15 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
assert( pPk!=0 );
pPk->isCovering = 1;
if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
- nPk = pPk->nKeyCol;
+ nPk = pPk->nColumn = pPk->nKeyCol;
- /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
+ /* Bypass the creation of the PRIMARY KEY btree and the sqlite_schema
** table entry. This is only required if currently generating VDBE
** code for a CREATE TABLE (not when parsing one as part of reading
** a database schema). */
if( v && pPk->tnum>0 ){
assert( db->init.busy==0 );
- sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
+ sqlite3VdbeChangeOpcode(v, (int)pPk->tnum, OP_Goto);
}
/* The root page of the PRIMARY KEY is the table root page */
@@ -1861,7 +2247,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
int n;
if( IsPrimaryKeyIndex(pIdx) ) continue;
for(i=n=0; i<nPk; i++){
- if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
+ if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
+ testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
+ n++;
+ }
}
if( n==0 ){
/* This index is a superset of the primary key */
@@ -1870,9 +2259,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}
if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
- if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ){
+ if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
+ testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
pIdx->aiColumn[j] = pPk->aiColumn[i];
pIdx->azColl[j] = pPk->azColl[i];
+ if( pPk->aSortOrder[i] ){
+ /* See ticket https://www.sqlite.org/src/info/bba7b69f9849b5bf */
+ pIdx->bAscKeyBug = 1;
+ }
j++;
}
}
@@ -1882,24 +2276,49 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
/* Add all table columns to the PRIMARY KEY index
*/
- if( nPk<pTab->nCol ){
- if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
- for(i=0, j=nPk; i<pTab->nCol; i++){
- if( !hasColumn(pPk->aiColumn, j, i) ){
- assert( j<pPk->nColumn );
- pPk->aiColumn[j] = i;
- pPk->azColl[j] = sqlite3StrBINARY;
- j++;
- }
+ nExtra = 0;
+ for(i=0; i<pTab->nCol; i++){
+ if( !hasColumn(pPk->aiColumn, nPk, i)
+ && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
+ }
+ if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
+ for(i=0, j=nPk; i<pTab->nCol; i++){
+ if( !hasColumn(pPk->aiColumn, j, i)
+ && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
+ ){
+ assert( j<pPk->nColumn );
+ pPk->aiColumn[j] = i;
+ pPk->azColl[j] = sqlite3StrBINARY;
+ j++;
}
- assert( pPk->nColumn==j );
- assert( pTab->nCol==j );
- }else{
- pPk->nColumn = pTab->nCol;
}
+ assert( pPk->nColumn==j );
+ assert( pTab->nNVCol<=j );
recomputeColumnsNotIndexed(pPk);
}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Return true if pTab is a virtual table and zName is a shadow table name
+** for that virtual table.
+*/
+int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
+ int nName; /* Length of zName */
+ Module *pMod; /* Module for the virtual table */
+
+ if( !IsVirtual(pTab) ) return 0;
+ nName = sqlite3Strlen30(pTab->zName);
+ if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
+ if( zName[nName]!='_' ) return 0;
+ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
+ if( pMod==0 ) return 0;
+ if( pMod->pModule->iVersion<3 ) return 0;
+ if( pMod->pModule->xShadowName==0 ) return 0;
+ return pMod->pModule->xShadowName(zName+nName+1);
+}
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return true if zName is a shadow table name in the current database
@@ -1908,11 +2327,9 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** zName is temporarily modified while this routine is running, but is
** restored to its original value prior to this routine returning.
*/
-static int isShadowTableName(sqlite3 *db, char *zName){
+int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
char *zTail; /* Pointer to the last "_" in zName */
Table *pTab; /* Table that zName is a shadow of */
- Module *pMod; /* Module for the virtual table */
-
zTail = strrchr(zName, '_');
if( zTail==0 ) return 0;
*zTail = 0;
@@ -1920,16 +2337,37 @@ static int isShadowTableName(sqlite3 *db, char *zName){
*zTail = '_';
if( pTab==0 ) return 0;
if( !IsVirtual(pTab) ) return 0;
- pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
- if( pMod==0 ) return 0;
- if( pMod->pModule->iVersion<3 ) return 0;
- if( pMod->pModule->xShadowName==0 ) return 0;
- return pMod->pModule->xShadowName(zTail+1);
+ return sqlite3IsShadowTableOf(db, pTab, zName);
}
-#else
-# define isShadowTableName(x,y) 0
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+
+#ifdef SQLITE_DEBUG
+/*
+** Mark all nodes of an expression as EP_Immutable, indicating that
+** they should not be changed. Expressions attached to a table or
+** index definition are tagged this way to help ensure that we do
+** not pass them into code generator routines by mistake.
+*/
+static int markImmutableExprStep(Walker *pWalker, Expr *pExpr){
+ ExprSetVVAProperty(pExpr, EP_Immutable);
+ return WRC_Continue;
+}
+static void markExprListImmutable(ExprList *pList){
+ if( pList ){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = markImmutableExprStep;
+ w.xSelectCallback = sqlite3SelectWalkNoop;
+ w.xSelectCallback2 = 0;
+ sqlite3WalkExprList(&w, pList);
+ }
+}
+#else
+#define markExprListImmutable(X) /* no-op */
+#endif /* SQLITE_DEBUG */
+
+
/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
@@ -1938,15 +2376,15 @@ static int isShadowTableName(sqlite3 *db, char *zName){
** is added to the internal hash tables, assuming no errors have
** occurred.
**
-** An entry for the table is made in the master table on disk, unless
+** An entry for the table is made in the schema table on disk, unless
** this is a temporary table or db->init.busy==1. When db->init.busy==1
-** it means we are reading the sqlite_master table because we just
-** connected to the database or because the sqlite_master table has
+** it means we are reading the sqlite_schema table because we just
+** connected to the database or because the sqlite_schema table has
** recently changed, so the entry for this table already exists in
-** the sqlite_master table. We do not want to create it again.
+** the sqlite_schema table. We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
-** was called to create a table generated from a
+** was called to create a table generated from a
** "CREATE TABLE ... AS SELECT ..." statement. The column names of
** the new table will match the result set of the SELECT.
*/
@@ -1969,17 +2407,17 @@ void sqlite3EndTable(
p = pParse->pNewTable;
if( p==0 ) return;
- if( pSelect==0 && isShadowTableName(db, p->zName) ){
+ if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
p->tabFlags |= TF_Shadow;
}
/* If the db->init.busy is 1 it means we are reading the SQL off the
- ** "sqlite_master" or "sqlite_temp_master" table on the disk.
+ ** "sqlite_schema" or "sqlite_temp_schema" table on the disk.
** So do not write to the disk again. Extract the root page number
** for the table from the db->init.newTnum field. (The page number
** should have been put there by the sqliteOpenCb routine.)
**
- ** If the root page number is 1, that means this is the sqlite_master
+ ** If the root page number is 1, that means this is the sqlite_schema
** table itself. So mark it read-only.
*/
if( db->init.busy ){
@@ -1991,6 +2429,11 @@ void sqlite3EndTable(
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
}
+ assert( (p->tabFlags & TF_HasPrimaryKey)==0
+ || p->iPKey>=0 || sqlite3PrimaryKeyIndex(p)!=0 );
+ assert( (p->tabFlags & TF_HasPrimaryKey)!=0
+ || (p->iPKey<0 && sqlite3PrimaryKeyIndex(p)==0) );
+
/* Special processing for WITHOUT ROWID Tables */
if( tabOpts & TF_WithoutRowid ){
if( (p->tabFlags & TF_Autoincrement) ){
@@ -2000,12 +2443,11 @@ void sqlite3EndTable(
}
if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
- }else{
- p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
- convertToWithoutRowidTable(pParse, p);
+ return;
}
+ p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
+ convertToWithoutRowidTable(pParse, p);
}
-
iDb = sqlite3SchemaToIndex(db, p->pSchema);
#ifndef SQLITE_OMIT_CHECK
@@ -2013,8 +2455,47 @@ void sqlite3EndTable(
*/
if( p->pCheck ){
sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
+ if( pParse->nErr ){
+ /* If errors are seen, delete the CHECK constraints now, else they might
+ ** actually be used if PRAGMA writable_schema=ON is set. */
+ sqlite3ExprListDelete(db, p->pCheck);
+ p->pCheck = 0;
+ }else{
+ markExprListImmutable(p->pCheck);
+ }
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( p->tabFlags & TF_HasGenerated ){
+ int ii, nNG = 0;
+ testcase( p->tabFlags & TF_HasVirtual );
+ testcase( p->tabFlags & TF_HasStored );
+ for(ii=0; ii<p->nCol; ii++){
+ u32 colFlags = p->aCol[ii].colFlags;
+ if( (colFlags & COLFLAG_GENERATED)!=0 ){
+ Expr *pX = p->aCol[ii].pDflt;
+ testcase( colFlags & COLFLAG_VIRTUAL );
+ testcase( colFlags & COLFLAG_STORED );
+ if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
+ /* If there are errors in resolving the expression, change the
+ ** expression to a NULL. This prevents code generators that operate
+ ** on the expression from inserting extra parts into the expression
+ ** tree that have been allocated from lookaside memory, which is
+ ** illegal in a schema and will lead to errors or heap corruption
+ ** when the database connection closes. */
+ sqlite3ExprDelete(db, pX);
+ p->aCol[ii].pDflt = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
+ }
+ }else{
+ nNG++;
+ }
+ }
+ if( nNG==0 ){
+ sqlite3ErrorMsg(pParse, "must have at least one non-generated column");
+ return;
+ }
+ }
+#endif
/* Estimate the average row size for the table and for all implied indices */
estimateTableWidth(p);
@@ -2023,7 +2504,7 @@ void sqlite3EndTable(
}
/* If not initializing, then create a record for the new table
- ** in the SQLITE_MASTER table of the database.
+ ** in the schema table of the database.
**
** If this is a TEMPORARY table, write the entry into the auxiliary
** file instead of into the main database file.
@@ -2040,7 +2521,7 @@ void sqlite3EndTable(
sqlite3VdbeAddOp1(v, OP_Close, 0);
- /*
+ /*
** Initialize zType for the new view or table.
*/
if( p->pSelect==0 ){
@@ -2088,10 +2569,10 @@ void sqlite3EndTable(
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
if( pParse->nErr ) return;
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
- p->nCol = pSelTab->nCol;
+ p->nCol = p->nNVCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
@@ -2119,20 +2600,20 @@ void sqlite3EndTable(
Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd;
n = (int)(pEnd2->z - pParse->sNameToken.z);
if( pEnd2->z[0]!=';' ) n += pEnd2->n;
- zStmt = sqlite3MPrintf(db,
+ zStmt = sqlite3MPrintf(db,
"CREATE %s %.*s", zType2, n, pParse->sNameToken.z
);
}
- /* A slot for the record has already been allocated in the
- ** SQLITE_MASTER table. We just need to update that slot with all
+ /* A slot for the record has already been allocated in the
+ ** schema table. We just need to update that slot with all
** the information we've collected.
*/
sqlite3NestedParse(pParse,
- "UPDATE %Q.%s "
- "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
- "WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, MASTER_NAME,
+ "UPDATE %Q." DFLT_SCHEMA_TABLE
+ " SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
+ " WHERE rowid=#%d",
+ db->aDb[iDb].zDbSName,
zType,
p->zName,
p->zName,
@@ -2161,10 +2642,9 @@ void sqlite3EndTable(
/* Reparse everything to update our internal data structures */
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
+ sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0);
}
-
/* Add the table to the in-memory representation of the database.
*/
if( db->init.busy ){
@@ -2179,20 +2659,17 @@ void sqlite3EndTable(
}
pParse->pNewTable = 0;
db->mDbFlags |= DBFLAG_SchemaChange;
+ }
#ifndef SQLITE_OMIT_ALTERTABLE
- if( !p->pSelect ){
- const char *zName = (const char *)pParse->sNameToken.z;
- int nName;
- assert( !pSelect && pCons && pEnd );
- if( pCons->z==0 ){
- pCons = pEnd;
- }
- nName = (int)((const char *)pCons->z - zName);
- p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
+ if( !pSelect && !p->pSelect ){
+ assert( pCons && pEnd );
+ if( pCons->z==0 ){
+ pCons = pEnd;
}
-#endif
+ p->addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
}
+#endif
}
#ifndef SQLITE_OMIT_VIEW
@@ -2235,6 +2712,7 @@ void sqlite3CreateView(
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
+ pSelect->selFlags |= SF_View;
if( IN_RENAME_OBJECT ){
p->pSelect = pSelect;
pSelect = 0;
@@ -2260,7 +2738,7 @@ void sqlite3CreateView(
sEnd.z = &z[n-1];
sEnd.n = 1;
- /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
+ /* Use sqlite3EndTable() to add the view to the schema table */
sqlite3EndTable(pParse, 0, &sEnd, 0, 0);
create_view_fail:
@@ -2320,7 +2798,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** Actually, the error above is now caught prior to reaching this point.
** But the following test is still important as it does come up
** in the following:
- **
+ **
** CREATE TABLE main.ex1(a);
** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
** SELECT * FROM temp.ex1;
@@ -2341,58 +2819,57 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable->pSelect );
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){
-#ifndef SQLITE_OMIT_ALTERTABLE
u8 eParseMode = pParse->eParseMode;
pParse->eParseMode = PARSE_MODE_NORMAL;
-#endif
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
- db->lookaside.bDisable++;
+ DisableLookaside;
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
db->xAuth = xAuth;
#else
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
pParse->nTab = n;
- if( pTable->pCheck ){
+ if( pSelTab==0 ){
+ pTable->nCol = 0;
+ nErr++;
+ }else if( pTable->pCheck ){
/* CREATE VIEW name(arglist) AS ...
** The names of the columns in the table are taken from
** arglist which is stored in pTable->pCheck. The pCheck field
** normally holds CHECK constraints on an ordinary table, but for
** a VIEW it holds the list of column names.
*/
- sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
+ sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
- if( db->mallocFailed==0
+ if( db->mallocFailed==0
&& pParse->nErr==0
&& pTable->nCol==pSel->pEList->nExpr
){
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel);
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
+ SQLITE_AFF_NONE);
}
- }else if( pSelTab ){
+ }else{
/* CREATE VIEW name AS... without an argument list. Construct
** the column names from the SELECT statement that defines the view.
*/
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
+ pTable->tabFlags |= (pSelTab->tabFlags & COLFLAG_NOINSERT);
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
- }else{
- pTable->nCol = 0;
- nErr++;
}
+ pTable->nNVCol = pTable->nCol;
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
- db->lookaside.bDisable--;
-#ifndef SQLITE_OMIT_ALTERTABLE
+ EnableLookaside;
pParse->eParseMode = eParseMode;
-#endif
} else {
nErr++;
}
@@ -2403,7 +2880,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pTable->nCol = 0;
}
#endif /* SQLITE_OMIT_VIEW */
- return nErr;
+ return nErr;
}
#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
@@ -2439,7 +2916,7 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
** on tables and/or indices that are the process of being deleted.
** If you are unlucky, one of those deleted indices or tables might
** have the same rootpage number as the real table or index that is
-** being moved. So we cannot stop searching after the first match
+** being moved. So we cannot stop searching after the first match
** because the first match might be for one of the deleted indices
** or tables and not the table/index that is actually being moved.
** We must continue looping until all tables and indices with
@@ -2447,7 +2924,7 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
** in order to be certain that we got the right one.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
-void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
+void sqlite3RootPageMoved(sqlite3 *db, int iDb, Pgno iFrom, Pgno iTo){
HashElem *pElem;
Hash *pHash;
Db *pDb;
@@ -2473,10 +2950,10 @@ void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
/*
** Write code to erase the table with root-page iTable from database iDb.
-** Also write code to modify the sqlite_master table and internal schema
+** Also write code to modify the sqlite_schema table and internal schema
** if a root-page of another table is moved by the btree-layer whilst
** erasing iTable (this can happen with an auto-vacuum database).
-*/
+*/
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse);
@@ -2486,30 +2963,31 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
#ifndef SQLITE_OMIT_AUTOVACUUM
/* OP_Destroy stores an in integer r1. If this integer
** is non-zero, then it is the root page number of a table moved to
- ** location iTable. The following code modifies the sqlite_master table to
+ ** location iTable. The following code modifies the sqlite_schema table to
** reflect this.
**
** The "#NNN" in the SQL is a special constant that means whatever value
** is in register NNN. See grammar rules associated with the TK_REGISTER
** token for additional information.
*/
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
- pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q." DFLT_SCHEMA_TABLE
+ " SET rootpage=%d WHERE #%d AND rootpage=#%d",
+ pParse->db->aDb[iDb].zDbSName, iTable, r1, r1);
#endif
sqlite3ReleaseTempReg(pParse, r1);
}
/*
** Write VDBE code to erase table pTab and all associated indices on disk.
-** Code to update the sqlite_master tables and internal schema definitions
+** Code to update the sqlite_schema tables and internal schema definitions
** in case a root-page belonging to another table is moved by the btree layer
** is also added (this can happen with an auto-vacuum database).
*/
static void destroyTable(Parse *pParse, Table *pTab){
/* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
** is not defined), then it is important to call OP_Destroy on the
- ** table and index root-pages in order, starting with the numerically
+ ** table and index root-pages in order, starting with the numerically
** largest root-page number. This guarantees that none of the root-pages
** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
** following were coded:
@@ -2519,22 +2997,22 @@ static void destroyTable(Parse *pParse, Table *pTab){
** OP_Destroy 5 0
**
** and root page 5 happened to be the largest root-page number in the
- ** database, then root page 5 would be moved to page 4 by the
+ ** database, then root page 5 would be moved to page 4 by the
** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
** a free-list page.
*/
- int iTab = pTab->tnum;
- int iDestroyed = 0;
+ Pgno iTab = pTab->tnum;
+ Pgno iDestroyed = 0;
while( 1 ){
Index *pIdx;
- int iLargest = 0;
+ Pgno iLargest = 0;
if( iDestroyed==0 || iTab<iDestroyed ){
iLargest = iTab;
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int iIdx = pIdx->tnum;
+ Pgno iIdx = pIdx->tnum;
assert( pIdx->pSchema==pTab->pSchema );
if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
iLargest = iIdx;
@@ -2595,12 +3073,12 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
#endif
/* Drop all triggers associated with the table being dropped. Code
- ** is generated to remove entries from sqlite_master and/or
- ** sqlite_temp_master if required.
+ ** is generated to remove entries from sqlite_schema and/or
+ ** sqlite_temp_schema if required.
*/
pTrigger = sqlite3TriggerList(pParse, pTab);
while( pTrigger ){
- assert( pTrigger->pSchema==pTab->pSchema ||
+ assert( pTrigger->pSchema==pTab->pSchema ||
pTrigger->pSchema==db->aDb[1].pSchema );
sqlite3DropTriggerPtr(pParse, pTrigger);
pTrigger = pTrigger->pNext;
@@ -2620,16 +3098,17 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
}
#endif
- /* Drop all SQLITE_MASTER table and index entries that refer to the
- ** table. The program name loops through the master table and deletes
+ /* Drop all entries in the schema table that refer to the
+ ** table. The program name loops through the schema table and deletes
** every row that refers to a table of the same name as the one being
** dropped. Triggers are handled separately because a trigger can be
** created in the temp database that refers to a table in another
** database.
*/
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
- pDb->zDbSName, MASTER_NAME, pTab->zName);
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q." DFLT_SCHEMA_TABLE
+ " WHERE tbl_name=%Q and type!='trigger'",
+ pDb->zDbSName, pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
@@ -2639,6 +3118,7 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
*/
if( IsVirtual(pTab) ){
sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
+ sqlite3MayAbort(pParse);
}
sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
sqlite3ChangeCookie(pParse, iDb);
@@ -2646,6 +3126,37 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
}
/*
+** Return TRUE if shadow tables should be read-only in the current
+** context.
+*/
+int sqlite3ReadOnlyShadowTables(sqlite3 *db){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( (db->flags & SQLITE_Defensive)!=0
+ && db->pVtabCtx==0
+ && db->nVdbeExec==0
+ ){
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+** Return true if it is not allowed to drop the given table
+*/
+static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
+ if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
+ if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
+ return 1;
+ }
+ if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){
+ return 1;
+ }
+ return 0;
+}
+
+/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
@@ -2714,8 +3225,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
}
#endif
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
- && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
+ if( tableMayNotBeDropped(db, pTab) ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
@@ -2734,7 +3244,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
#endif
- /* Generate code to remove the table from the master table
+ /* Generate code to remove the table from the schema table
** on disk.
*/
v = sqlite3GetVdbe(pParse);
@@ -2807,7 +3317,7 @@ void sqlite3CreateForeignKey(
nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
if( pToCol ){
for(i=0; i<pToCol->nExpr; i++){
- nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
+ nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
}
}
pFKey = sqlite3DbMallocZero(db, nByte );
@@ -2832,30 +3342,30 @@ void sqlite3CreateForeignKey(
for(i=0; i<nCol; i++){
int j;
for(j=0; j<p->nCol; j++){
- if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
+ if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zEName)==0 ){
pFKey->aCol[i].iFrom = j;
break;
}
}
if( j>=p->nCol ){
- sqlite3ErrorMsg(pParse,
- "unknown column \"%s\" in foreign key definition",
- pFromCol->a[i].zName);
+ sqlite3ErrorMsg(pParse,
+ "unknown column \"%s\" in foreign key definition",
+ pFromCol->a[i].zEName);
goto fk_end;
}
if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName);
+ sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zEName);
}
}
}
if( pToCol ){
for(i=0; i<nCol; i++){
- int n = sqlite3Strlen30(pToCol->a[i].zName);
+ int n = sqlite3Strlen30(pToCol->a[i].zEName);
pFKey->aCol[i].zCol = z;
if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName);
+ sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zEName);
}
- memcpy(z, pToCol->a[i].zName, n);
+ memcpy(z, pToCol->a[i].zEName, n);
z[n] = 0;
z += n+1;
}
@@ -2865,7 +3375,7 @@ void sqlite3CreateForeignKey(
pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */
assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
- pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
+ pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
pFKey->zTo, (void *)pFKey
);
if( pNextTo==pFKey ){
@@ -2925,7 +3435,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int iSorter; /* Cursor opened by OpenSorter (if in use) */
int addr1; /* Address of top of loop */
int addr2; /* Address to jump to for next iteration */
- int tnum; /* Root page of index */
+ Pgno tnum; /* Root page of index */
int iPartIdxLabel; /* Jump to this label to skip a row */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
@@ -2946,7 +3456,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
if( memRootPage>=0 ){
- tnum = memRootPage;
+ tnum = (Pgno)memRootPage;
}else{
tnum = pIndex->tnum;
}
@@ -2971,7 +3481,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
- sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
+ sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, (int)tnum, iDb,
(char *)pKey, P4_KEYINFO);
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
@@ -2985,10 +3495,27 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
sqlite3VdbeJumpHere(v, j2);
}else{
+ /* Most CREATE INDEX and REINDEX statements that are not UNIQUE can not
+ ** abort. The exception is if one of the indexed expressions contains a
+ ** user function that throws an exception when it is evaluated. But the
+ ** overhead of adding a statement journal to a CREATE INDEX statement is
+ ** very small (since most of the pages written do not contain content that
+ ** needs to be restored if the statement aborts), so we call
+ ** sqlite3MayAbort() for all CREATE INDEX statements. */
+ sqlite3MayAbort(pParse);
addr2 = sqlite3VdbeCurrentAddr(v);
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
- sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
+ if( !pIndex->bAscKeyBug ){
+ /* This OP_SeekEnd opcode makes index insert for a REINDEX go much
+ ** faster by avoiding unnecessary seeks. But the optimization does
+ ** not work for UNIQUE constraint indexes on WITHOUT ROWID tables
+ ** with DESC primary keys, since those indexes have there keys in
+ ** a different order from the main table.
+ ** See ticket: https://www.sqlite.org/src/info/bba7b69f9849b5bf
+ */
+ sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
+ }
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
@@ -3036,8 +3563,29 @@ Index *sqlite3AllocateIndexObject(
}
/*
-** Create a new index for an SQL table. pName1.pName2 is the name of the index
-** and pTblList is the name of the table that is to be indexed. Both will
+** If expression list pList contains an expression that was parsed with
+** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in
+** pParse and return non-zero. Otherwise, return zero.
+*/
+int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){
+ if( pList ){
+ int i;
+ for(i=0; i<pList->nExpr; i++){
+ if( pList->a[i].bNulls ){
+ u8 sf = pList->a[i].sortFlags;
+ sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s",
+ (sf==0 || sf==3) ? "FIRST" : "LAST"
+ );
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Create a new index for an SQL table. pName1.pName2 is the name of the index
+** and pTblList is the name of the table that is to be indexed. Both will
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed. pParse->pNewTable is a table that is
@@ -3045,7 +3593,7 @@ Index *sqlite3AllocateIndexObject(
**
** pList is a list of columns to be indexed. pList will be NULL if this
** is a primary key or unique-constraint on the most recent column added
-** to the table currently under construction.
+** to the table currently under construction.
*/
void sqlite3CreateIndex(
Parse *pParse, /* All information about this parse */
@@ -3086,13 +3634,16 @@ void sqlite3CreateIndex(
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_create_index;
}
+ if( sqlite3HasExplicitNulls(pParse, pList) ){
+ goto exit_create_index;
+ }
/*
** Find the table that is to be indexed. Return early if not found.
*/
if( pTblName!=0 ){
- /* Use the two-part index name to determine the database
+ /* Use the two-part index name to determine the database
** to search for the table. 'Fix' the table name to this db
** before looking up the table.
*/
@@ -3124,7 +3675,7 @@ void sqlite3CreateIndex(
assert( db->mallocFailed==0 || pTab==0 );
if( pTab==0 ) goto exit_create_index;
if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"cannot create a TEMP index on non-TEMP table \"%s\"",
pTab->zName);
goto exit_create_index;
@@ -3141,16 +3692,13 @@ void sqlite3CreateIndex(
assert( pTab!=0 );
assert( pParse->nErr==0 );
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
+ && pTblName!=0
#if SQLITE_USER_AUTHENTICATION
&& sqlite3UserAuthTable(pTab->zName)==0
#endif
-#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX
- && sqlite3StrICmp(&pTab->zName[7],"master")!=0
-#endif
- && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0
- ){
+ ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
@@ -3169,10 +3717,10 @@ void sqlite3CreateIndex(
/*
** Find the name of the index. Make sure there is not already another
- ** index or table with the same name.
+ ** index or table with the same name.
**
** Exception: If we are reading the names of permanent indices from the
- ** sqlite_master table (because some other process changed the schema) and
+ ** sqlite_schema table (because some other process changed the schema) and
** one of the index names collides with the name of a temporary table or
** index, then we will continue to process this index.
**
@@ -3184,7 +3732,7 @@ void sqlite3CreateIndex(
zName = sqlite3NameFromToken(db, pName);
if( zName==0 ) goto exit_create_index;
assert( pName->z!=0 );
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){
goto exit_create_index;
}
if( !IN_RENAME_OBJECT ){
@@ -3250,9 +3798,10 @@ void sqlite3CreateIndex(
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
if( pList==0 ) goto exit_create_index;
assert( pList->nExpr==1 );
- sqlite3ExprListSetSortOrder(pList, sortOrder);
+ sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED);
}else{
sqlite3ExprListCheckLength(pParse, pList, "index");
+ if( pParse->nErr ) goto exit_create_index;
}
/* Figure out how many bytes of space are required to store explicitly
@@ -3266,11 +3815,12 @@ void sqlite3CreateIndex(
}
}
- /*
- ** Allocate the index structure.
+ /*
+ ** Allocate the index structure.
*/
nName = sqlite3Strlen30(zName);
nExtraCol = pPk ? pPk->nKeyCol : 1;
+ assert( pList->nExpr + nExtraCol <= 32767 /* Fits in i16 */ );
pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol,
nName + nExtra + 1, &zExtra);
if( db->mallocFailed ){
@@ -3343,8 +3893,13 @@ void sqlite3CreateIndex(
assert( j<=0x7fff );
if( j<0 ){
j = pTab->iPKey;
- }else if( pTab->aCol[j].notNull==0 ){
- pIndex->uniqNotNull = 0;
+ }else{
+ if( pTab->aCol[j].notNull==0 ){
+ pIndex->uniqNotNull = 0;
+ }
+ if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){
+ pIndex->bHasVCol = 1;
+ }
}
pIndex->aiColumn[i] = (i16)j;
}
@@ -3366,7 +3921,7 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
pIndex->azColl[i] = zColl;
- requestedSortOrder = pListItem->sortOrder & sortOrderMask;
+ requestedSortOrder = pListItem->sortFlags & sortOrderMask;
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
}
@@ -3378,9 +3933,10 @@ void sqlite3CreateIndex(
for(j=0; j<pPk->nKeyCol; j++){
int x = pPk->aiColumn[j];
assert( x>=0 );
- if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){
- pIndex->nColumn--;
+ if( isDupColumn(pIndex, pIndex->nKeyCol, pPk, j) ){
+ pIndex->nColumn--;
}else{
+ testcase( hasColumn(pIndex->aiColumn,pIndex->nKeyCol,x) );
pIndex->aiColumn[i] = x;
pIndex->azColl[i] = pPk->azColl[j];
pIndex->aSortOrder[i] = pPk->aSortOrder[j];
@@ -3397,14 +3953,14 @@ void sqlite3CreateIndex(
/* If this index contains every column of its table, then mark
** it as a covering index */
- assert( HasRowid(pTab)
- || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 );
+ assert( HasRowid(pTab)
+ || pTab->iPKey<0 || sqlite3TableColumnToIndex(pIndex, pTab->iPKey)>=0 );
recomputeColumnsNotIndexed(pIndex);
if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){
pIndex->isCovering = 1;
for(j=0; j<pTab->nCol; j++){
if( j==pTab->iPKey ) continue;
- if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue;
+ if( sqlite3TableColumnToIndex(pIndex,j)>=0 ) continue;
pIndex->isCovering = 0;
break;
}
@@ -3453,13 +4009,13 @@ void sqlite3CreateIndex(
if( pIdx->onError!=pIndex->onError ){
/* This constraint creates the same index as a previous
** constraint specified somewhere in the CREATE TABLE statement.
- ** However the ON CONFLICT clauses are different. If both this
+ ** However the ON CONFLICT clauses are different. If both this
** constraint and the previous equivalent constraint have explicit
** ON CONFLICT clauses this is an error. Otherwise, use the
** explicitly specified behavior for the index.
*/
if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"conflicting ON CONFLICT clauses specified", 0);
}
if( pIdx->onError==OE_Default ){
@@ -3467,6 +4023,11 @@ void sqlite3CreateIndex(
}
}
if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
+ if( IN_RENAME_OBJECT ){
+ pIndex->pNext = pParse->pNewIndex;
+ pParse->pNewIndex = pIndex;
+ pIndex = 0;
+ }
goto exit_create_index;
}
}
@@ -3475,14 +4036,22 @@ void sqlite3CreateIndex(
if( !IN_RENAME_OBJECT ){
/* Link the new Index structure to its table and to the other
- ** in-memory database structures.
+ ** in-memory database structures.
*/
assert( pParse->nErr==0 );
if( db->init.busy ){
Index *p;
assert( !IN_SPECIAL_PARSE );
assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
- p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
+ if( pTblName!=0 ){
+ pIndex->tnum = db->init.newTnum;
+ if( sqlite3IndexHasDuplicateRootPage(pIndex) ){
+ sqlite3ErrorMsg(pParse, "invalid rootpage");
+ pParse->rc = SQLITE_CORRUPT_BKPT;
+ goto exit_create_index;
+ }
+ }
+ p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
pIndex->zName, pIndex);
if( p ){
assert( p==pIndex ); /* Malloc must have failed */
@@ -3490,16 +4059,13 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
db->mDbFlags |= DBFLAG_SchemaChange;
- if( pTblName!=0 ){
- pIndex->tnum = db->init.newTnum;
- }
}
/* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
** emit code to allocate the index rootpage on disk and make an entry for
- ** the index in the sqlite_master table and populate the index with
- ** content. But, do not do this if we are simply reading the sqlite_master
+ ** the index in the sqlite_schema table and populate the index with
+ ** content. But, do not do this if we are simply reading the sqlite_schema
** table to parse the schema, or if this index is the PRIMARY KEY index
** of a WITHOUT ROWID table.
**
@@ -3519,17 +4085,18 @@ void sqlite3CreateIndex(
sqlite3BeginWriteOperation(pParse, 1, iDb);
/* Create the rootpage for the index using CreateIndex. But before
- ** doing so, code a Noop instruction and store its address in
- ** Index.tnum. This is required in case this index is actually a
- ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In
+ ** doing so, code a Noop instruction and store its address in
+ ** Index.tnum. This is required in case this index is actually a
+ ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In
** that case the convertToWithoutRowidTable() routine will replace
** the Noop with a Goto to jump over the VDBE code generated below. */
- pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
+ pIndex->tnum = (Pgno)sqlite3VdbeAddOp0(v, OP_Noop);
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
/* Gather the complete text of the CREATE INDEX statement into
** the zStmt variable
*/
+ assert( pName!=0 || pStart==0 );
if( pStart ){
int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
if( pName->z[n-1]==';' ) n--;
@@ -3542,11 +4109,11 @@ void sqlite3CreateIndex(
zStmt = 0;
}
- /* Add an entry in sqlite_master for this index
+ /* Add an entry in sqlite_schema for this index
*/
- sqlite3NestedParse(pParse,
- "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
- db->aDb[iDb].zDbSName, MASTER_NAME,
+ sqlite3NestedParse(pParse,
+ "INSERT INTO %Q." DFLT_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
+ db->aDb[iDb].zDbSName,
pIndex->zName,
pTab->zName,
iMem,
@@ -3561,33 +4128,16 @@ void sqlite3CreateIndex(
sqlite3RefillIndex(pParse, pIndex, iMem);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
+ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0);
sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
}
- sqlite3VdbeJumpHere(v, pIndex->tnum);
+ sqlite3VdbeJumpHere(v, (int)pIndex->tnum);
}
}
-
- /* When adding an index to the list of indices for a table, make
- ** sure all indices labeled OE_Replace come after all those labeled
- ** OE_Ignore. This is necessary for the correct constraint check
- ** processing (in sqlite3GenerateConstraintChecks()) as part of
- ** UPDATE and INSERT statements.
- */
if( db->init.busy || pTblName==0 ){
- if( onError!=OE_Replace || pTab->pIndex==0
- || pTab->pIndex->onError==OE_Replace){
- pIndex->pNext = pTab->pIndex;
- pTab->pIndex = pIndex;
- }else{
- Index *pOther = pTab->pIndex;
- while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
- pOther = pOther->pNext;
- }
- pIndex->pNext = pOther->pNext;
- pOther->pNext = pIndex;
- }
+ pIndex->pNext = pTab->pIndex;
+ pTab->pIndex = pIndex;
pIndex = 0;
}
else if( IN_RENAME_OBJECT ){
@@ -3599,6 +4149,35 @@ void sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
if( pIndex ) sqlite3FreeIndex(db, pIndex);
+ if( pTab ){
+ /* Ensure all REPLACE indexes on pTab are at the end of the pIndex list.
+ ** The list was already ordered when this routine was entered, so at this
+ ** point at most a single index (the newly added index) will be out of
+ ** order. So we have to reorder at most one index. */
+ Index **ppFrom = &pTab->pIndex;
+ Index *pThis;
+ for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
+ Index *pNext;
+ if( pThis->onError!=OE_Replace ) continue;
+ while( (pNext = pThis->pNext)!=0 && pNext->onError!=OE_Replace ){
+ *ppFrom = pNext;
+ pThis->pNext = pNext->pNext;
+ pNext->pNext = pThis;
+ ppFrom = &pNext->pNext;
+ }
+ break;
+ }
+#ifdef SQLITE_DEBUG
+ /* Verify that all REPLACE indexes really are now at the end
+ ** of the index list. In other words, no other index type ever
+ ** comes after a REPLACE index on the list. */
+ for(pThis = pTab->pIndex; pThis; pThis=pThis->pNext){
+ assert( pThis->onError!=OE_Replace
+ || pThis->pNext==0
+ || pThis->pNext->onError==OE_Replace );
+ }
+#endif
+ }
sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
sqlite3SrcListDelete(db, pTblName);
@@ -3624,21 +4203,33 @@ exit_create_index:
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
- /* 10, 9, 8, 7, 6 */
- LogEst aVal[] = { 33, 32, 30, 28, 26 };
+ /* 10, 9, 8, 7, 6 */
+ static const LogEst aVal[] = { 33, 32, 30, 28, 26 };
LogEst *a = pIdx->aiRowLogEst;
+ LogEst x;
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
int i;
/* Indexes with default row estimates should not have stat1 data */
assert( !pIdx->hasStat1 );
- /* Set the first entry (number of rows in the index) to the estimated
+ /* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table, or half the number of rows in the table
- ** for a partial index. But do not let the estimate drop below 10. */
- a[0] = pIdx->pTable->nRowLogEst;
- if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) );
- if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
+ ** for a partial index.
+ **
+ ** 2020-05-27: If some of the stat data is coming from the sqlite_stat1
+ ** table but other parts we are having to guess at, then do not let the
+ ** estimated number of rows in the table be less than 1000 (LogEst 99).
+ ** Failure to do this can cause the indexes for which we do not have
+ ** stat1 data to be ignored by the query planner.
+ */
+ x = pIdx->pTable->nRowLogEst;
+ assert( 99==sqlite3LogEst(1000) );
+ if( x<99 ){
+ pIdx->pTable->nRowLogEst = x = 99;
+ }
+ if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
+ a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
** 6 and each subsequent value (if any) is 5. */
@@ -3701,13 +4292,13 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
}
#endif
- /* Generate code to remove the index and from the master table */
+ /* Generate code to remove the index and from the schema table */
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
- db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
+ "DELETE FROM %Q." DFLT_SCHEMA_TABLE " WHERE name=%Q AND type='index'",
+ db->aDb[iDb].zDbSName, pIndex->zName
);
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
@@ -3744,9 +4335,9 @@ void *sqlite3ArrayAllocate(
int *pIdx /* Write the index of a new slot here */
){
char *z;
- int n = *pnEntry;
+ sqlite3_int64 n = *pIdx = *pnEntry;
if( (n & (n-1))==0 ){
- int sz = (n==0) ? 1 : 2*n;
+ sqlite3_int64 sz = (n==0) ? 1 : 2*n;
void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry);
if( pNew==0 ){
*pIdx = -1;
@@ -3756,7 +4347,6 @@ void *sqlite3ArrayAllocate(
}
z = (char*)pArray;
memset(&z[n * szEntry], 0, szEntry);
- *pIdx = n;
++*pnEntry;
return pArray;
}
@@ -3819,6 +4409,18 @@ int sqlite3IdListIndex(IdList *pList, const char *zName){
}
/*
+** Maximum size of a SrcList object.
+** The SrcList object is used to represent the FROM clause of a
+** SELECT statement, and the query planner cannot deal with more
+** than 64 tables in a join. So any value larger than 64 here
+** is sufficient for most uses. Smaller values, like say 10, are
+** appropriate for small and memory-limited applications.
+*/
+#ifndef SQLITE_MAX_SRCLIST
+# define SQLITE_MAX_SRCLIST 200
+#endif
+
+/*
** Expand the space allocated for the given SrcList object by
** creating nExtra new slots beginning at iStart. iStart is zero based.
** New slots are zeroed.
@@ -3834,11 +4436,12 @@ int sqlite3IdListIndex(IdList *pList, const char *zName){
** the iStart value would be 0. The result then would
** be: nil, nil, nil, A, B.
**
-** If a memory allocation fails the SrcList is unchanged. The
-** db->mallocFailed flag will be set to true.
+** If a memory allocation fails or the SrcList becomes too large, leave
+** the original SrcList unchanged, return NULL, and leave an error message
+** in pParse.
*/
SrcList *sqlite3SrcListEnlarge(
- sqlite3 *db, /* Database connection to notify of OOM errors */
+ Parse *pParse, /* Parsing context into which errors are reported */
SrcList *pSrc, /* The SrcList to be enlarged */
int nExtra, /* Number of new slots to add to pSrc->a[] */
int iStart /* Index in pSrc->a[] of first new slot */
@@ -3854,17 +4457,23 @@ SrcList *sqlite3SrcListEnlarge(
/* Allocate additional space if needed */
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
- int nAlloc = pSrc->nSrc*2+nExtra;
- int nGot;
+ sqlite3_int64 nAlloc = 2*(sqlite3_int64)pSrc->nSrc+nExtra;
+ sqlite3 *db = pParse->db;
+
+ if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){
+ sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
+ SQLITE_MAX_SRCLIST);
+ return 0;
+ }
+ if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
if( pNew==0 ){
assert( db->mallocFailed );
- return pSrc;
+ return 0;
}
pSrc = pNew;
- nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
- pSrc->nAlloc = nGot;
+ pSrc->nAlloc = nAlloc;
}
/* Move existing slots that come after the newly inserted slots
@@ -3889,7 +4498,8 @@ SrcList *sqlite3SrcListEnlarge(
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pTable is NULL.
**
-** A SrcList is returned, or NULL if there is an OOM error. The returned
+** A SrcList is returned, or NULL if there is an OOM error or if the
+** SrcList grows to large. The returned
** SrcList might be the same as the SrcList that was input or it might be
** a new one. If an OOM error does occurs, then the prior value of pList
** that is input to this routine is automatically freed.
@@ -3898,7 +4508,7 @@ SrcList *sqlite3SrcListEnlarge(
** database name prefix. Like this: "database.table". The pDatabase
** points to the table name and the pTable points to the database name.
** The SrcList.a[].zName field is filled with the table name which might
-** come from pTable (if pDatabase is NULL) or from pDatabase.
+** come from pTable (if pDatabase is NULL) or from pDatabase.
** SrcList.a[].zDatabase is filled with the database name from pTable,
** or with NULL if no database is specified.
**
@@ -3920,27 +4530,32 @@ SrcList *sqlite3SrcListEnlarge(
** before being added to the SrcList.
*/
SrcList *sqlite3SrcListAppend(
- sqlite3 *db, /* Connection to notify of malloc failures */
+ Parse *pParse, /* Parsing context, in which errors are reported */
SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
+ sqlite3 *db;
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
- assert( db!=0 );
+ assert( pParse!=0 );
+ assert( pParse->db!=0 );
+ db = pParse->db;
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
+ pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
pList->nSrc = 1;
memset(&pList->a[0], 0, sizeof(pList->a[0]));
pList->a[0].iCursor = -1;
}else{
- pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
- }
- if( db->mallocFailed ){
- sqlite3SrcListDelete(db, pList);
- return 0;
+ SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc);
+ if( pNew==0 ){
+ sqlite3SrcListDelete(db, pList);
+ return 0;
+ }else{
+ pList = pNew;
+ }
}
pItem = &pList->a[pList->nSrc-1];
if( pDatabase && pDatabase->z==0 ){
@@ -3961,11 +4576,11 @@ SrcList *sqlite3SrcListAppend(
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert(pList || pParse->db->mallocFailed );
if( pList ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pItem->iCursor>=0 ) break;
+ if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
if( pItem->pSelect ){
sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
@@ -3979,18 +4594,18 @@ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
*/
void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- sqlite3DbFree(db, pItem->zDatabase);
+ if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
- sqlite3DbFree(db, pItem->zAlias);
+ if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias);
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlite3DeleteTable(db, pItem->pTab);
- sqlite3SelectDelete(db, pItem->pSelect);
- sqlite3ExprDelete(db, pItem->pOn);
- sqlite3IdListDelete(db, pItem->pUsing);
+ if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+ if( pItem->pOn ) sqlite3ExprDelete(db, pItem->pOn);
+ if( pItem->pUsing ) sqlite3IdListDelete(db, pItem->pUsing);
}
sqlite3DbFreeNN(db, pList);
}
@@ -4021,15 +4636,15 @@ SrcList *sqlite3SrcListAppendFromTerm(
Expr *pOn, /* The ON clause of a join */
IdList *pUsing /* The USING clause of a join */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
sqlite3 *db = pParse->db;
if( !p && (pOn || pUsing) ){
- sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
+ sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
(pOn ? "ON" : "USING")
);
goto append_from_error;
}
- p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
+ p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase);
if( p==0 ){
goto append_from_error;
}
@@ -4059,20 +4674,20 @@ SrcList *sqlite3SrcListAppendFromTerm(
}
/*
-** Add an INDEXED BY or NOT INDEXED clause to the most recently added
+** Add an INDEXED BY or NOT INDEXED clause to the most recently added
** element of the source-list passed as the second argument.
*/
void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
if( p && pIndexedBy->n>0 ){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert( p->nSrc>0 );
pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
assert( pItem->fg.isIndexedBy==0 );
assert( pItem->fg.isTabFunc==0 );
if( pIndexedBy->n==1 && !pIndexedBy->z ){
- /* A "NOT INDEXED" clause was supplied. See parse.y
+ /* A "NOT INDEXED" clause was supplied. See parse.y
** construct "indexed_opt" for details. */
pItem->fg.notIndexed = 1;
}else{
@@ -4083,12 +4698,32 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
}
/*
+** Append the contents of SrcList p2 to SrcList p1 and return the resulting
+** SrcList. Or, if an error occurs, return NULL. In all cases, p1 and p2
+** are deleted by this function.
+*/
+SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
+ assert( p1 && p1->nSrc==1 );
+ if( p2 ){
+ SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1);
+ if( pNew==0 ){
+ sqlite3SrcListDelete(pParse->db, p2);
+ }else{
+ p1 = pNew;
+ memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
+ sqlite3DbFree(pParse->db, p2);
+ }
+ }
+ return p1;
+}
+
+/*
** Add the list of function arguments to the SrcList entry for a
** table-valued-function.
*/
void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
if( p ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
+ SrcItem *pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
assert( pItem->fg.isIndexedBy==0 );
assert( pItem->fg.isTabFunc==0 );
@@ -4142,7 +4777,16 @@ void sqlite3BeginTransaction(Parse *pParse, int type){
if( !v ) return;
if( type!=TK_DEFERRED ){
for(i=0; i<db->nDb; i++){
- sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
+ int eTxnType;
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt && sqlite3BtreeIsReadonly(pBt) ){
+ eTxnType = 0; /* Read txn */
+ }else if( type==TK_EXCLUSIVE ){
+ eTxnType = 2; /* Exclusive txn */
+ }else{
+ eTxnType = 1; /* Write txn */
+ }
+ sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
sqlite3VdbeUsesBtree(v, i);
}
}
@@ -4162,7 +4806,7 @@ void sqlite3EndTransaction(Parse *pParse, int eType){
assert( pParse->db!=0 );
assert( eType==TK_COMMIT || eType==TK_END || eType==TK_ROLLBACK );
isRollback = eType==TK_ROLLBACK;
- if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION,
+ if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION,
isRollback ? "ROLLBACK" : "COMMIT", 0, 0) ){
return;
}
@@ -4174,7 +4818,7 @@ void sqlite3EndTransaction(Parse *pParse, int eType){
/*
** This function is called by the parser when it parses a command to create,
-** release or rollback an SQL savepoint.
+** release or rollback an SQL savepoint.
*/
void sqlite3Savepoint(Parse *pParse, int op, Token *pName){
char *zName = sqlite3NameFromToken(pParse->db, pName);
@@ -4201,7 +4845,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc;
Btree *pBt;
- static const int flags =
+ static const int flags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
@@ -4217,7 +4861,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
}
db->aDb[1].pBt = pBt;
assert( db->aDb[1].pSchema );
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, 0, 0) ){
sqlite3OomFault(db);
return 1;
}
@@ -4231,13 +4875,11 @@ int sqlite3OpenTempDatabase(Parse *pParse){
** will occur at the end of the top-level VDBE and will be generated
** later, by sqlite3FinishCoding().
*/
-void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
-
- assert( iDb>=0 && iDb<pParse->db->nDb );
- assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
- assert( iDb<SQLITE_MAX_ATTACHED+2 );
- assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
+static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
+ assert( iDb>=0 && iDb<pToplevel->db->nDb );
+ assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
+ assert( iDb<SQLITE_MAX_DB );
+ assert( sqlite3SchemaMutexHeld(pToplevel->db, iDb, 0) );
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
DbMaskSet(pToplevel->cookieMask, iDb);
if( !OMIT_TEMPDB && iDb==1 ){
@@ -4245,9 +4887,13 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
}
}
}
+void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
+ sqlite3CodeVerifySchemaAtToplevel(sqlite3ParseToplevel(pParse), iDb);
+}
+
/*
-** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
+** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
** attached database. Otherwise, invoke it for the database named zDb only.
*/
void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
@@ -4276,7 +4922,7 @@ void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
*/
void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchemaAtToplevel(pToplevel, iDb);
DbMaskSet(pToplevel->writeMask, iDb);
pToplevel->isMultiWrite |= setStatement;
}
@@ -4293,9 +4939,9 @@ void sqlite3MultiWrite(Parse *pParse){
pToplevel->isMultiWrite = 1;
}
-/*
+/*
** The code generator calls this routine if is discovers that it is
-** possible to abort a statement prior to completion. In order to
+** possible to abort a statement prior to completion. In order to
** perform this abort without corrupting the database, we need to make
** sure that the statement is protected by a statement transaction.
**
@@ -4304,7 +4950,7 @@ void sqlite3MultiWrite(Parse *pParse){
** such that the abort must occur after the multiwrite. This makes
** some statements involving the REPLACE conflict resolution algorithm
** go a little faster. But taking advantage of this time dependency
-** makes it more difficult to prove that the code is correct (in
+** makes it more difficult to prove that the code is correct (in
** particular, it prevents us from writing an effective
** implementation of sqlite3AssertMayAbort()) and so we have chosen
** to take the safe route and skip the optimization.
@@ -4327,8 +4973,10 @@ void sqlite3HaltConstraint(
i8 p4type, /* P4_STATIC or P4_TRANSIENT */
u8 p5Errmsg /* P5_ErrMsg type */
){
- Vdbe *v = sqlite3GetVdbe(pParse);
- assert( (errCode&0xff)==SQLITE_CONSTRAINT );
+ Vdbe *v;
+ assert( pParse->pVdbe!=0 );
+ v = sqlite3GetVdbe(pParse);
+ assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
if( onError==OE_Abort ){
sqlite3MayAbort(pParse);
}
@@ -4349,7 +4997,8 @@ void sqlite3UniqueConstraint(
StrAccum errMsg;
Table *pTab = pIdx->pTable;
- sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
+ sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0,
+ pParse->db->aLimit[SQLITE_LIMIT_LENGTH]);
if( pIdx->aColExpr ){
sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName);
}else{
@@ -4364,8 +5013,8 @@ void sqlite3UniqueConstraint(
}
}
zErr = sqlite3StrAccumFinish(&errMsg);
- sqlite3HaltConstraint(pParse,
- IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY
+ sqlite3HaltConstraint(pParse,
+ IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY
: SQLITE_CONSTRAINT_UNIQUE,
onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
}
@@ -4377,7 +5026,7 @@ void sqlite3UniqueConstraint(
void sqlite3RowidConstraint(
Parse *pParse, /* Parsing context */
int onError, /* Conflict resolution algorithm */
- Table *pTab /* The table with the non-unique rowid */
+ Table *pTab /* The table with the non-unique rowid */
){
char *zMsg;
int rc;
@@ -4418,13 +5067,15 @@ static int collationMatch(const char *zColl, Index *pIndex){
*/
#ifndef SQLITE_OMIT_REINDEX
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
- Index *pIndex; /* An index associated with pTab */
-
- for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
- if( zColl==0 || collationMatch(zColl, pIndex) ){
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3RefillIndex(pParse, pIndex, -1);
+ if( !IsVirtual(pTab) ){
+ Index *pIndex; /* An index associated with pTab */
+
+ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
+ if( zColl==0 || collationMatch(zColl, pIndex) ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3RefillIndex(pParse, pIndex, -1);
+ }
}
}
}
@@ -4545,7 +5196,8 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
const char *zColl = pIdx->azColl[i];
pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
sqlite3LocateCollSeq(pParse, zColl);
- pKey->aSortOrder[i] = pIdx->aSortOrder[i];
+ pKey->aSortFlags[i] = pIdx->aSortOrder[i];
+ assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) );
}
if( pParse->nErr ){
assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
@@ -4569,23 +5221,75 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
#ifndef SQLITE_OMIT_CTE
/*
-** This routine is invoked once per CTE by the parser while parsing a
-** WITH clause.
+** Create a new CTE object
*/
-With *sqlite3WithAdd(
+Cte *sqlite3CteNew(
Parse *pParse, /* Parsing context */
- With *pWith, /* Existing WITH clause, or NULL */
Token *pName, /* Name of the common-table */
ExprList *pArglist, /* Optional column name list for the table */
- Select *pQuery /* Query used to initialize the table */
+ Select *pQuery, /* Query used to initialize the table */
+ u8 eM10d /* The MATERIALIZED flag */
+){
+ Cte *pNew;
+ sqlite3 *db = pParse->db;
+
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew));
+ assert( pNew!=0 || db->mallocFailed );
+
+ if( db->mallocFailed ){
+ sqlite3ExprListDelete(db, pArglist);
+ sqlite3SelectDelete(db, pQuery);
+ }else{
+ pNew->pSelect = pQuery;
+ pNew->pCols = pArglist;
+ pNew->zName = sqlite3NameFromToken(pParse->db, pName);
+ pNew->eM10d = eM10d;
+ }
+ return pNew;
+}
+
+/*
+** Clear information from a Cte object, but do not deallocate storage
+** for the object itself.
+*/
+static void cteClear(sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ sqlite3ExprListDelete(db, pCte->pCols);
+ sqlite3SelectDelete(db, pCte->pSelect);
+ sqlite3DbFree(db, pCte->zName);
+}
+
+/*
+** Free the contents of the CTE object passed as the second argument.
+*/
+void sqlite3CteDelete(sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ cteClear(db, pCte);
+ sqlite3DbFree(db, pCte);
+}
+
+/*
+** This routine is invoked once per CTE by the parser while parsing a
+** WITH clause. The CTE described by teh third argument is added to
+** the WITH clause of the second argument. If the second argument is
+** NULL, then a new WITH argument is created.
+*/
+With *sqlite3WithAdd(
+ Parse *pParse, /* Parsing context */
+ With *pWith, /* Existing WITH clause, or NULL */
+ Cte *pCte /* CTE to add to the WITH clause */
){
sqlite3 *db = pParse->db;
With *pNew;
char *zName;
+ if( pCte==0 ){
+ return pWith;
+ }
+
/* Check that the CTE name is unique within this WITH clause. If
** not, store an error in the Parse structure. */
- zName = sqlite3NameFromToken(pParse->db, pName);
+ zName = pCte->zName;
if( zName && pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
@@ -4596,7 +5300,7 @@ With *sqlite3WithAdd(
}
if( pWith ){
- int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
+ sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
pNew = sqlite3DbRealloc(db, pWith, nByte);
}else{
pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
@@ -4604,16 +5308,11 @@ With *sqlite3WithAdd(
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
if( db->mallocFailed ){
- sqlite3ExprListDelete(db, pArglist);
- sqlite3SelectDelete(db, pQuery);
- sqlite3DbFree(db, zName);
+ sqlite3CteDelete(db, pCte);
pNew = pWith;
}else{
- pNew->a[pNew->nCte].pSelect = pQuery;
- pNew->a[pNew->nCte].pCols = pArglist;
- pNew->a[pNew->nCte].zName = zName;
- pNew->a[pNew->nCte].zCteErr = 0;
- pNew->nCte++;
+ pNew->a[pNew->nCte++] = *pCte;
+ sqlite3DbFree(db, pCte);
}
return pNew;
@@ -4626,10 +5325,7 @@ void sqlite3WithDelete(sqlite3 *db, With *pWith){
if( pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
- struct Cte *pCte = &pWith->a[i];
- sqlite3ExprListDelete(db, pCte->pCols);
- sqlite3SelectDelete(db, pCte->pSelect);
- sqlite3DbFree(db, pCte->zName);
+ cteClear(db, &pWith->a[i]);
}
sqlite3DbFree(db, pWith);
}
diff --git a/chromium/third_party/sqlite/src/src/select.c b/chromium/third_party/sqlite/src/src/select.c
index 11285db3211..9e18db9e8fb 100644
--- a/chromium/third_party/sqlite/src/src/select.c
+++ b/chromium/third_party/sqlite/src/src/select.c
@@ -15,20 +15,6 @@
#include "sqliteInt.h"
/*
-** Trace output macros
-*/
-#if SELECTTRACE_ENABLED
-/***/ int sqlite3SelectTrace = 0;
-# define SELECTTRACE(K,P,S,X) \
- if(sqlite3SelectTrace&(K)) \
- sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
- sqlite3DebugPrintf X
-#else
-# define SELECTTRACE(K,P,S,X)
-#endif
-
-
-/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
** into the selectInnerLoop() routine.
@@ -84,7 +70,10 @@ struct SortCtx {
/*
** Delete all the content of a Select structure. Deallocate the structure
-** itself only if bFree is true.
+** itself depending on the value of bFree
+**
+** If bFree==1, call sqlite3DbFree() on the p object.
+** If bFree==0, Leave the first Select object unfreed
*/
static void clearSelect(sqlite3 *db, Select *p, int bFree){
while( p ){
@@ -96,12 +85,16 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
+ if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
sqlite3WindowListDelete(db, p->pWinDefn);
}
+ while( p->pWin ){
+ assert( p->pWin->ppThis==&p->pWin );
+ sqlite3WindowUnlinkFromSelect(p->pWin);
+ }
#endif
- if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
@@ -114,6 +107,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
pDest->eDest = (u8)eDest;
pDest->iSDParm = iParm;
+ pDest->iSDParm2 = 0;
pDest->zAffSdst = 0;
pDest->iSdst = 0;
pDest->nSdst = 0;
@@ -135,9 +129,9 @@ Select *sqlite3SelectNew(
u32 selFlags, /* Flag parameters, such as SF_Distinct */
Expr *pLimit /* LIMIT value. NULL means not used */
){
- Select *pNew;
+ Select *pNew, *pAllocated;
Select standin;
- pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
+ pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
if( pNew==0 ){
assert( pParse->db->mallocFailed );
pNew = &standin;
@@ -171,12 +165,11 @@ Select *sqlite3SelectNew(
#endif
if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin);
- pNew = 0;
+ pAllocated = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
}
- assert( pNew!=&standin );
- return pNew;
+ return pAllocated;
}
@@ -238,7 +231,7 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
for(i=0; i<3 && apAll[i]; i++){
p = apAll[i];
for(j=0; j<ArraySize(aKeyword); j++){
- if( p->n==aKeyword[j].nChar
+ if( p->n==aKeyword[j].nChar
&& sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){
jointype |= aKeyword[j].code;
break;
@@ -260,9 +253,9 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
"%T %T%s%T", pA, pB, zSp, pC);
jointype = JT_INNER;
- }else if( (jointype & JT_OUTER)!=0
+ }else if( (jointype & JT_OUTER)!=0
&& (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"RIGHT and FULL OUTER JOINs are not currently supported");
jointype = JT_INNER;
}
@@ -273,17 +266,19 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
** Return the index of a column in a table. Return -1 if the column
** is not contained in the table.
*/
-static int columnIndex(Table *pTab, const char *zCol){
+int sqlite3ColumnIndex(Table *pTab, const char *zCol){
int i;
- for(i=0; i<pTab->nCol; i++){
- if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
+ u8 h = sqlite3StrIHash(zCol);
+ Column *pCol;
+ for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
+ if( pCol->hName==h && sqlite3StrICmp(pCol->zName, zCol)==0 ) return i;
}
return -1;
}
/*
** Search the first N tables in pSrc, from left to right, looking for a
-** table that has a column named zCol.
+** table that has a column named zCol.
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
@@ -295,15 +290,18 @@ static int tableAndColumnIndex(
int N, /* Number of tables in pSrc->a[] to search */
const char *zCol, /* Name of the column we are looking for */
int *piTab, /* Write index of pSrc->a[] here */
- int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+ int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+ int bIgnoreHidden /* True to ignore hidden columns */
){
int i; /* For looping over tables in pSrc */
int iCol; /* Index of column matching zCol */
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=0; i<N; i++){
- iCol = columnIndex(pSrc->a[i].pTab, zCol);
- if( iCol>=0 ){
+ iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
+ if( iCol>=0
+ && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
+ ){
if( piTab ){
*piTab = i;
*piCol = iCol;
@@ -321,7 +319,7 @@ static int tableAndColumnIndex(
**
** (tab1.col1 = tab2.col2)
**
-** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
+** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
** column iColRight of tab2.
*/
@@ -353,9 +351,9 @@ static void addWhereTerm(
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pEq, EP_NoReduce);
- pEq->iRightJoinTable = (i16)pE2->iTable;
+ pEq->iRightJoinTable = pE2->iTable;
}
- *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
+ *ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq);
}
/*
@@ -384,24 +382,24 @@ static void addWhereTerm(
** after the t1 loop and rows with t1.x!=5 will never appear in
** the output, which is incorrect.
*/
-static void setJoinExpr(Expr *p, int iTable){
+void sqlite3SetJoinExpr(Expr *p, int iTable){
while( p ){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
- p->iRightJoinTable = (i16)iTable;
+ p->iRightJoinTable = iTable;
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
- setJoinExpr(p->x.pList->a[i].pExpr, iTable);
+ sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable);
}
}
- setJoinExpr(p->pLeft, iTable);
+ sqlite3SetJoinExpr(p->pLeft, iTable);
p = p->pRight;
- }
+ }
}
-/* Undo the work of setJoinExpr(). In the expression tree p, convert every
+/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every
** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
** an ordinary term that omits the EP_FromJoin mark.
**
@@ -413,6 +411,9 @@ static void unsetJoinExpr(Expr *p, int iTable){
&& (iTable<0 || p->iRightJoinTable==iTable) ){
ExprClearProperty(p, EP_FromJoin);
}
+ if( p->op==TK_COLUMN && p->iTable==iTable ){
+ ExprClearProperty(p, EP_CanBeNull);
+ }
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
@@ -421,7 +422,7 @@ static void unsetJoinExpr(Expr *p, int iTable){
}
unsetJoinExpr(p->pLeft, iTable);
p = p->pRight;
- }
+ }
}
/*
@@ -441,8 +442,8 @@ static void unsetJoinExpr(Expr *p, int iTable){
static int sqliteProcessJoin(Parse *pParse, Select *p){
SrcList *pSrc; /* All tables in the FROM clause */
int i, j; /* Loop counters */
- struct SrcList_item *pLeft; /* Left table being joined */
- struct SrcList_item *pRight; /* Right table being joined */
+ SrcItem *pLeft; /* Left table being joined */
+ SrcItem *pRight; /* Right table being joined */
pSrc = p->pSrc;
pLeft = &pSrc->a[0];
@@ -468,10 +469,11 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
int iLeft; /* Matching left table */
int iLeftCol; /* Matching column in the left table */
+ if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
zName = pRightTab->aCol[j].zName;
- if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
+ if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
- isOuter, &p->pWhere);
+ isOuter, &p->pWhere);
}
}
}
@@ -488,13 +490,13 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
** an AND operator.
*/
if( pRight->pOn ){
- if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
- p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
+ if( isOuter ) sqlite3SetJoinExpr(pRight->pOn, pRight->iCursor);
+ p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->pOn);
pRight->pOn = 0;
}
/* Create extra terms on the WHERE clause for each column named
- ** in the USING clause. Example: If the two tables to be joined are
+ ** in the USING clause. Example: If the two tables to be joined are
** A and B and the USING clause names X, Y, and Z, then add this
** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
** Report an error if any column mentioned in the USING clause is
@@ -509,9 +511,9 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
int iRightCol; /* Column number of matching column on the right */
zName = pList->a[j].zName;
- iRightCol = columnIndex(pRightTab, zName);
+ iRightCol = sqlite3ColumnIndex(pRightTab, zName);
if( iRightCol<0
- || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
+ || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
){
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName);
@@ -615,7 +617,7 @@ static void pushOntoSorter(
** case regData==regOrigData.
** (3) Some output columns are omitted from the sort record due to
** the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the
- ** SQLITE_ECEL_OMITREF optimization, or due to the
+ ** SQLITE_ECEL_OMITREF optimization, or due to the
** SortCtx.pDeferredRowLoad optimiation. In any of these cases
** regOrigData is 0 to prevent this routine from trying to copy
** values that might not yet exist.
@@ -631,7 +633,7 @@ static void pushOntoSorter(
}
assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
- pSort->labelDone = sqlite3VdbeMakeLabel(v);
+ pSort->labelDone = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
if( bSeq ){
@@ -653,7 +655,7 @@ static void pushOntoSorter(
pParse->nMem += pSort->nOBSat;
nKey = nExpr - pSort->nOBSat + bSeq;
if( bSeq ){
- addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr);
+ addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr);
}else{
addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor);
}
@@ -663,14 +665,15 @@ static void pushOntoSorter(
if( pParse->db->mallocFailed ) return;
pOp->p2 = nKey + nData;
pKI = pOp->p4.pKeyInfo;
- memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
+ memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
testcase( pKI->nAllField > pKI->nKeyField+2 );
pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat,
pKI->nAllField-pKI->nKeyField-1);
+ pOp = 0; /* Ensure pOp not used after sqltie3VdbeAddOp3() */
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
- pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
+ pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse);
pSort->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
@@ -686,10 +689,10 @@ static void pushOntoSorter(
/* At this point the values for the new sorter entry are stored
** in an array of registers. They need to be composed into a record
** and inserted into the sorter if either (a) there are currently
- ** less than LIMIT+OFFSET items or (b) the new record is smaller than
+ ** less than LIMIT+OFFSET items or (b) the new record is smaller than
** the largest record currently in the sorter. If (b) is true and there
** are already LIMIT+OFFSET items in the sorter, delete the largest
- ** entry before inserting the new one. This way there are never more
+ ** entry before inserting the new one. This way there are never more
** than LIMIT+OFFSET items in the sorter.
**
** If the new record does not need to be inserted into the sorter,
@@ -768,8 +771,8 @@ static void codeDistinct(
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
/*
** This function is called as part of inner-loop generation for a SELECT
-** statement with an ORDER BY that is not optimized by an index. It
-** determines the expressions, if any, that the sorter-reference
+** statement with an ORDER BY that is not optimized by an index. It
+** determines the expressions, if any, that the sorter-reference
** optimization should be used for. The sorter-reference optimization
** is used for SELECT queries like:
**
@@ -779,11 +782,11 @@ static void codeDistinct(
** storing values read from that column in the sorter records, the PK of
** the row from table t1 is stored instead. Then, as records are extracted from
** the sorter to return to the user, the required value of bigblob is
-** retrieved directly from table t1. If the values are very large, this
+** retrieved directly from table t1. If the values are very large, this
** can be more efficient than storing them directly in the sorter records.
**
-** The ExprList_item.bSorterRef flag is set for each expression in pEList
-** for which the sorter-reference optimization should be enabled.
+** The ExprList_item.bSorterRef flag is set for each expression in pEList
+** for which the sorter-reference optimization should be enabled.
** Additionally, the pSort->aDefer[] array is populated with entries
** for all cursors required to evaluate all selected expressions. Finally.
** output variable (*ppExtra) is set to an expression list containing
@@ -852,7 +855,7 @@ static void selectExprDefer(
**
** If srcTab is negative, then the p->pEList expressions
** are evaluated in order to get the data for this row. If srcTab is
-** zero or more, then data is pulled from srcTab and p->pEList is used only
+** zero or more, then data is pulled from srcTab and p->pEList is used only
** to get the number of columns and the collation sequence for each column.
*/
static void selectInnerLoop(
@@ -916,7 +919,7 @@ static void selectInnerLoop(
if( srcTab>=0 ){
for(i=0; i<nResultCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
- VdbeComment((v, "%s", p->pEList->a[i].zName));
+ VdbeComment((v, "%s", p->pEList->a[i].zEName));
}
}else if( eDest!=SRT_Exists ){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
@@ -934,8 +937,8 @@ static void selectInnerLoop(
}
if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
/* For each expression in p->pEList that is a copy of an expression in
- ** the ORDER BY clause (pSort->pOrderBy), set the associated
- ** iOrderByCol value to one more than the index of the ORDER BY
+ ** the ORDER BY clause (pSort->pOrderBy), set the associated
+ ** iOrderByCol value to one more than the index of the ORDER BY
** expression within the sort-key that pushOntoSorter() will generate.
** This allows the p->pEList field to be omitted from the sorted record,
** saving space and CPU cycles. */
@@ -951,7 +954,7 @@ static void selectInnerLoop(
selectExprDefer(pParse, pSort, p->pEList, &pExtra);
if( pExtra && pParse->db->mallocFailed==0 ){
/* If there are any extra PK columns to add to the sorter records,
- ** allocate extra memory cells and adjust the OpenEphemeral
+ ** allocate extra memory cells and adjust the OpenEphemeral
** instruction to account for the larger records. This is only
** required if there are one or more WITHOUT ROWID tables with
** composite primary keys in the SortCtx.aDefer[] array. */
@@ -981,8 +984,9 @@ static void selectInnerLoop(
testcase( eDest==SRT_Mem );
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
- assert( eDest==SRT_Set || eDest==SRT_Mem
- || eDest==SRT_Coroutine || eDest==SRT_Output );
+ assert( eDest==SRT_Set || eDest==SRT_Mem
+ || eDest==SRT_Coroutine || eDest==SRT_Output
+ || eDest==SRT_Upfrom );
}
sRowLoadInfo.regResult = regResult;
sRowLoadInfo.ecelFlags = ecelFlags;
@@ -992,7 +996,7 @@ static void selectInnerLoop(
if( pExtra ) nResultCol += pExtra->nExpr;
#endif
if( p->iLimit
- && (ecelFlags & SQLITE_ECEL_OMITREF)!=0
+ && (ecelFlags & SQLITE_ECEL_OMITREF)!=0
&& nPrefixReg>0
){
assert( pSort!=0 );
@@ -1030,6 +1034,7 @@ static void selectInnerLoop(
pOp->opcode = OP_Null;
pOp->p1 = 1;
pOp->p2 = regPrev;
+ pOp = 0; /* Ensure pOp is not used after sqlite3VdbeAddOp() */
iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
for(i=0; i<nResultCol; i++){
@@ -1130,6 +1135,30 @@ static void selectInnerLoop(
break;
}
+ case SRT_Upfrom: {
+ if( pSort ){
+ pushOntoSorter(
+ pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
+ }else{
+ int i2 = pDest->iSDParm2;
+ int r1 = sqlite3GetTempReg(pParse);
+
+ /* If the UPDATE FROM join is an aggregate that matches no rows, it
+ ** might still be trying to return one row, because that is what
+ ** aggregates do. Don't record that empty row in the output table. */
+ sqlite3VdbeAddOp2(v, OP_IsNull, regResult, iBreak); VdbeCoverage(v);
+
+ sqlite3VdbeAddOp3(v, OP_MakeRecord,
+ regResult+(i2<0), nResultCol-(i2<0), r1);
+ if( i2<0 ){
+ sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult);
+ }else{
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2);
+ }
+ }
+ break;
+ }
+
#ifndef SQLITE_OMIT_SUBQUERY
/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack. Write this
@@ -1146,7 +1175,7 @@ static void selectInnerLoop(
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
@@ -1154,6 +1183,7 @@ static void selectInnerLoop(
break;
}
+
/* If any row exist in the result set, record that fact and abort.
*/
case SRT_Exists: {
@@ -1163,7 +1193,7 @@ static void selectInnerLoop(
}
/* If this is a scalar select that is part of an expression, then
- ** store the results in the appropriate memory cell or array of
+ ** store the results in the appropriate memory cell or array of
** memory cells and break out of the scan loop.
*/
case SRT_Mem: {
@@ -1218,7 +1248,7 @@ static void selectInnerLoop(
/* If the destination is DistQueue, then cursor (iParm+1) is open
** on a second ephemeral index that holds all values every previously
** added to the queue. */
- addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0,
+ addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0,
regResult, nResultCol);
VdbeCoverage(v);
}
@@ -1274,7 +1304,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
if( p ){
- p->aSortOrder = (u8*)&p->aColl[N+X];
+ p->aSortFlags = (u8*)&p->aColl[N+X];
p->nKeyField = (u16)N;
p->nAllField = (u16)(N+X);
p->enc = ENC(db);
@@ -1351,7 +1381,7 @@ KeyInfo *sqlite3KeyInfoFromExprList(
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
- pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
+ pInfo->aSortFlags[i-iStart] = pItem->sortFlags;
}
}
return pInfo;
@@ -1360,7 +1390,7 @@ KeyInfo *sqlite3KeyInfoFromExprList(
/*
** Name of the connection operator, used for error messages.
*/
-static const char *selectOpName(int id){
+const char *sqlite3SelectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
@@ -1417,7 +1447,7 @@ static void generateSortTail(
){
Vdbe *v = pParse->pVdbe; /* The prepared statement */
int addrBreak = pSort->labelDone; /* Jump here to exit loop */
- int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
+ int addrContinue = sqlite3VdbeMakeLabel(pParse);/* Jump here for next cycle */
int addr; /* Top of output loop. Jump for Next. */
int addrOnce = 0;
int iTab;
@@ -1457,7 +1487,12 @@ static void generateSortTail(
regRow = pDest->iSdst;
}else{
regRowid = sqlite3GetTempReg(pParse);
- regRow = sqlite3GetTempRange(pParse, nColumn);
+ if( eDest==SRT_EphemTab || eDest==SRT_Table ){
+ regRow = sqlite3GetTempReg(pParse);
+ nColumn = 0;
+ }else{
+ regRow = sqlite3GetTempRange(pParse, nColumn);
+ }
}
nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->sortFlags & SORTFLAG_UseSorter ){
@@ -1466,7 +1501,7 @@ static void generateSortTail(
if( pSort->labelBkOut ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
- sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut,
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut,
nKey+1+nColumn+nRefKey);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
@@ -1499,7 +1534,7 @@ static void generateSortTail(
sqlite3VdbeAddOp1(v, OP_NullRow, iCsr);
if( HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey);
- sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr,
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr,
sqlite3VdbeCurrentAddr(v)+1, regKey);
}else{
int k;
@@ -1531,12 +1566,13 @@ static void generateSortTail(
iRead = iCol--;
}
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
- VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan));
+ VdbeComment((v, "%s", aOutEx[i].zEName));
}
}
switch( eDest ){
case SRT_Table:
case SRT_EphemTab: {
+ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq, regRow);
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
@@ -1555,8 +1591,19 @@ static void generateSortTail(
break;
}
#endif
+ case SRT_Upfrom: {
+ int i2 = pDest->iSDParm2;
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord,regRow+(i2<0),nColumn-(i2<0),r1);
+ if( i2<0 ){
+ sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regRow);
+ }else{
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regRow, i2);
+ }
+ break;
+ }
default: {
- assert( eDest==SRT_Output || eDest==SRT_Coroutine );
+ assert( eDest==SRT_Output || eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
testcase( eDest==SRT_Coroutine );
if( eDest==SRT_Output ){
@@ -1598,14 +1645,14 @@ static void generateSortTail(
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
** is considered a column can be complex in the presence of subqueries. The
-** result-set expression in all of the following SELECT statements is
+** result-set expression in all of the following SELECT statements is
** considered a column by this function.
**
** SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl);
** SELECT abc FROM (SELECT col AS abc FROM tbl);
-**
+**
** The declaration type for any expression other than a column is NULL.
**
** This routine has either 3 or 6 parameters depending on whether or not
@@ -1617,7 +1664,7 @@ static void generateSortTail(
# define columnType(A,B,C,D,E) columnTypeImpl(A,B)
#endif
static const char *columnTypeImpl(
- NameContext *pNC,
+ NameContext *pNC,
#ifndef SQLITE_ENABLE_COLUMN_METADATA
Expr *pExpr
#else
@@ -1637,8 +1684,6 @@ static const char *columnTypeImpl(
assert( pExpr!=0 );
assert( pNC->pSrcList!=0 );
- assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates
- ** are processed */
switch( pExpr->op ){
case TK_COLUMN: {
/* The expression is a column. Locate the table the column is being
@@ -1662,19 +1707,19 @@ static const char *columnTypeImpl(
if( pTab==0 ){
/* At one time, code such as "SELECT new.x" within a trigger would
** cause this condition to run. Since then, we have restructured how
- ** trigger code is generated and so this condition is no longer
+ ** trigger code is generated and so this condition is no longer
** possible. However, it can still be true for statements like
** the following:
**
** CREATE TABLE t1(col INTEGER);
** SELECT (SELECT t1.col) FROM FROM t1;
**
- ** when columnType() is called on the expression "t1.col" in the
+ ** when columnType() is called on the expression "t1.col" in the
** sub-select. In this case, set the column type to NULL, even
** though it should really be "INTEGER".
**
** This is not a problem, as the column type of "t1.col" is never
- ** used. When columnType() is called on the expression
+ ** used. When columnType() is called on the expression
** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
** branch below. */
break;
@@ -1688,7 +1733,7 @@ static const char *columnTypeImpl(
*/
if( iCol>=0 && iCol<pS->pEList->nExpr ){
/* If iCol is less than zero, then the expression requests the
- ** rowid of the sub-select or view. This expression is legal (see
+ ** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
*/
NameContext sNC;
@@ -1696,7 +1741,7 @@ static const char *columnTypeImpl(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol);
+ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol);
}
}else{
/* A real table or a CTE table */
@@ -1740,13 +1785,13 @@ static const char *columnTypeImpl(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
break;
}
#endif
}
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
if( pzOrigDb ){
assert( pzOrigTab && pzOrigCol );
*pzOrigDb = zOrigDb;
@@ -1782,7 +1827,7 @@ static void generateColumnTypes(
const char *zOrigCol = 0;
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
- /* The vdbe must make its own copy of the column-type and other
+ /* The vdbe must make its own copy of the column-type and other
** column specific strings, in case the schema is reset before this
** virtual machine is deleted.
*/
@@ -1866,9 +1911,9 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
- if( pEList->a[i].zName ){
+ if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){
/* An AS clause always takes first priority */
- char *zName = pEList->a[i].zName;
+ char *zName = pEList->a[i].zEName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
@@ -1890,7 +1935,7 @@ static void generateColumnNames(
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
}
}else{
- const char *z = pEList->a[i].zSpan;
+ const char *z = pEList->a[i].zEName;
z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
}
@@ -1934,13 +1979,14 @@ int sqlite3ColumnsFromExprList(
char *zName; /* Column name */
int nName; /* Size of name in zName[] */
Hash ht; /* Hash table of column names */
+ Table *pTab;
sqlite3HashInit(&ht);
if( pEList ){
nCol = pEList->nExpr;
aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
testcase( aCol==0 );
- if( nCol>32767 ) nCol = 32767;
+ if( NEVER(nCol>32767) ) nCol = 32767;
}else{
nCol = 0;
aCol = 0;
@@ -1952,20 +1998,17 @@ int sqlite3ColumnsFromExprList(
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
/* Get an appropriate name for the column
*/
- if( (zName = pEList->a[i].zName)!=0 ){
+ if( (zName = pEList->a[i].zEName)!=0 && pEList->a[i].eEName==ENAME_NAME ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
- Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
- while( pColExpr->op==TK_DOT ){
+ Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
+ while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
- assert( pColExpr->op!=TK_AGG_COLUMN );
- if( pColExpr->op==TK_COLUMN ){
+ if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- Table *pTab = pColExpr->y.pTab;
- assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
}else if( pColExpr->op==TK_ID ){
@@ -1973,10 +2016,10 @@ int sqlite3ColumnsFromExprList(
zName = pColExpr->u.zToken;
}else{
/* Use the original text of the column expression as its name */
- zName = pEList->a[i].zSpan;
+ zName = pEList->a[i].zEName;
}
}
- if( zName ){
+ if( zName && !sqlite3IsTrueOrFalse(zName) ){
zName = sqlite3DbStrDup(db, zName);
}else{
zName = sqlite3MPrintf(db,"column%d",i+1);
@@ -1996,6 +2039,7 @@ int sqlite3ColumnsFromExprList(
if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
}
pCol->zName = zName;
+ pCol->hName = sqlite3StrIHash(zName);
sqlite3ColumnPropertiesFromName(0, pCol);
if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
sqlite3OomFault(db);
@@ -2017,7 +2061,7 @@ int sqlite3ColumnsFromExprList(
/*
** Add type and collation information to a column list based on
** a SELECT statement.
-**
+**
** The column list presumably came from selectColumnNamesFromExprList().
** The column list has only names, not types or collations. This
** routine goes through and adds the types and collations.
@@ -2028,7 +2072,8 @@ int sqlite3ColumnsFromExprList(
void sqlite3SelectAddColumnTypeAndCollation(
Parse *pParse, /* Parsing contexts */
Table *pTab, /* Add column type information to this table */
- Select *pSelect /* SELECT used to determine types and collations */
+ Select *pSelect, /* SELECT used to determine types and collations */
+ char aff /* Default affinity for columns */
){
sqlite3 *db = pParse->db;
NameContext sNC;
@@ -2048,6 +2093,7 @@ void sqlite3SelectAddColumnTypeAndCollation(
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const char *zType;
int n, m;
+ pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
p = a[i].pExpr;
zType = columnType(&sNC, p, 0, 0, 0);
/* pCol->szEst = ... // Column size est for SELECT tables never used */
@@ -2061,7 +2107,7 @@ void sqlite3SelectAddColumnTypeAndCollation(
pCol->colFlags |= COLFLAG_HASTYPE;
}
}
- if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
+ if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl && pCol->zColl==0 ){
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
@@ -2074,30 +2120,27 @@ void sqlite3SelectAddColumnTypeAndCollation(
** Given a SELECT statement, generate a Table structure that describes
** the result set of that SELECT.
*/
-Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
+Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
Table *pTab;
sqlite3 *db = pParse->db;
- int savedFlags;
+ u64 savedFlags;
savedFlags = db->flags;
- db->flags &= ~SQLITE_FullColNames;
+ db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
sqlite3SelectPrep(pParse, pSelect, 0);
+ db->flags = savedFlags;
if( pParse->nErr ) return 0;
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- db->flags = savedFlags;
pTab = sqlite3DbMallocZero(db, sizeof(Table) );
if( pTab==0 ){
return 0;
}
- /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
- ** is disabled */
- assert( db->lookaside.bDisable );
pTab->nTabRef = 1;
pTab->zName = 0;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect, aff);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(db, pTab);
@@ -2127,9 +2170,9 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
** Compute the iLimit and iOffset fields of the SELECT based on the
** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET
-** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
-** are the integer memory register numbers for counters used to compute
-** the limit and offset. If there is no limit and/or offset, then
+** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
+** are the integer memory register numbers for counters used to compute
+** the limit and offset. If there is no limit and/or offset, then
** iLimit and iOffset are negative.
**
** This routine changes the values of iLimit and iOffset only if
@@ -2155,7 +2198,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
if( p->iLimit ) return;
- /*
+ /*
** "LIMIT -1" always shows all rows. There is some
** controversy about what the correct behavior should be.
** The current implementation interprets "LIMIT 0" to mean
@@ -2251,7 +2294,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
}
assert( sqlite3KeyInfoIsWriteable(pRet) );
pRet->aColl[i] = pColl;
- pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
+ pRet->aSortFlags[i] = pOrderBy->a[i].sortFlags;
}
}
@@ -2283,7 +2326,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
** inserted into the Queue table. The iDistinct table keeps a copy of all rows
** that have ever been inserted into Queue and causes duplicates to be
** discarded. If the operator is UNION ALL, then duplicates are allowed.
-**
+**
** If the query has an ORDER BY, then entries in the Queue table are kept in
** ORDER BY order and the first entry is extracted for each cycle. Without
** an ORDER BY, the Queue table is just a FIFO.
@@ -2304,6 +2347,7 @@ static void generateWithRecursiveQuery(
int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */
Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
Select *pSetup = p->pPrior; /* The setup query */
+ Select *pFirstRec; /* Left-most recursive term */
int addrTop; /* Top of the loop */
int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
int iCurrent = 0; /* The Current table */
@@ -2329,7 +2373,7 @@ static void generateWithRecursiveQuery(
if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
/* Process the LIMIT and OFFSET clauses, if they exist */
- addrBreak = sqlite3VdbeMakeLabel(v);
+ addrBreak = sqlite3VdbeMakeLabel(pParse);
p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
@@ -2379,7 +2423,25 @@ static void generateWithRecursiveQuery(
/* Detach the ORDER BY clause from the compound SELECT */
p->pOrderBy = 0;
+ /* Figure out how many elements of the compound SELECT are part of the
+ ** recursive query. Make sure no recursive elements use aggregate
+ ** functions. Mark the recursive elements as UNION ALL even if they
+ ** are really UNION because the distinctness will be enforced by the
+ ** iDistinct table. pFirstRec is left pointing to the left-most
+ ** recursive term of the CTE.
+ */
+ pFirstRec = p;
+ for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){
+ if( pFirstRec->selFlags & SF_Aggregate ){
+ sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
+ goto end_of_recursive_query;
+ }
+ pFirstRec->op = TK_ALL;
+ if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break;
+ }
+
/* Store the results of the setup-query in Queue. */
+ pSetup = pFirstRec->pPrior;
pSetup->pNext = 0;
ExplainQueryPlan((pParse, 1, "SETUP"));
rc = sqlite3Select(pParse, pSetup, &destQueue);
@@ -2399,7 +2461,7 @@ static void generateWithRecursiveQuery(
sqlite3VdbeAddOp1(v, OP_Delete, iQueue);
/* Output the single row in Current */
- addrCont = sqlite3VdbeMakeLabel(v);
+ addrCont = sqlite3VdbeMakeLabel(pParse);
codeOffset(v, regOffset, addrCont);
selectInnerLoop(pParse, p, iCurrent,
0, 0, pDest, addrCont, addrBreak);
@@ -2412,15 +2474,11 @@ static void generateWithRecursiveQuery(
/* Execute the recursive SELECT taking the single row in Current as
** the value for the recursive-table. Store the results in the Queue.
*/
- if( p->selFlags & SF_Aggregate ){
- sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
- }else{
- p->pPrior = 0;
- ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
- sqlite3Select(pParse, p, &destQueue);
- assert( p->pPrior==0 );
- p->pPrior = pSetup;
- }
+ pFirstRec->pPrior = 0;
+ ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
+ sqlite3Select(pParse, p, &destQueue);
+ assert( pFirstRec->pPrior==0 );
+ pFirstRec->pPrior = pSetup;
/* Keep running the loop until the Queue is empty */
sqlite3VdbeGoto(v, addrTop);
@@ -2470,6 +2528,9 @@ static int multiSelectValues(
assert( p->selFlags & SF_Values );
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( p->pWin ) return -1;
+#endif
if( p->pPrior==0 ) break;
assert( p->pPrior->pNext==p );
p = p->pPrior;
@@ -2487,13 +2548,23 @@ static int multiSelectValues(
}
/*
+** Return true if the SELECT statement which is known to be the recursive
+** part of a recursive CTE still has its anchor terms attached. If the
+** anchor terms have already been removed, then return false.
+*/
+static int hasAnchor(Select *p){
+ while( p && (p->selFlags & SF_Recursive)!=0 ){ p = p->pPrior; }
+ return p!=0;
+}
+
+/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
** INTERSECT
**
** "p" points to the right-most of the two queries. the query on the
** left is p->pPrior. The left query could also be a compound query
-** in which case this routine will be called recursively.
+** in which case this routine will be called recursively.
**
** The results of the total query are to be written into a destination
** of type eDest with parameter iParm.
@@ -2534,15 +2605,12 @@ static int multiSelect(
*/
assert( p && p->pPrior ); /* Calling function guarantees this much */
assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
+ assert( p->selFlags & SF_Compound );
db = pParse->db;
pPrior = p->pPrior;
dest = *pDest;
- if( pPrior->pOrderBy || pPrior->pLimit ){
- sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
- pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op));
- rc = 1;
- goto multi_select_end;
- }
+ assert( pPrior->pOrderBy==0 );
+ assert( pPrior->pLimit==0 );
v = sqlite3GetVdbe(pParse);
assert( v!=0 ); /* The VDBE already created by calling function */
@@ -2559,7 +2627,8 @@ static int multiSelect(
*/
if( p->selFlags & SF_MultiValue ){
rc = multiSelectValues(pParse, p, &dest);
- goto multi_select_end;
+ if( rc>=0 ) goto multi_select_end;
+ rc = SQLITE_OK;
}
/* Make sure all SELECTs in the statement have the same number of elements
@@ -2569,7 +2638,7 @@ static int multiSelect(
assert( p->pEList->nExpr==pPrior->pEList->nExpr );
#ifndef SQLITE_OMIT_CTE
- if( p->selFlags & SF_Recursive ){
+ if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
generateWithRecursiveQuery(pParse, p, &dest);
}else
#endif
@@ -2598,7 +2667,7 @@ static int multiSelect(
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
rc = sqlite3Select(pParse, pPrior, &dest);
- p->pLimit = 0;
+ pPrior->pLimit = 0;
if( rc ){
goto multi_select_end;
}
@@ -2619,9 +2688,9 @@ static int multiSelect(
pDelete = p->pPrior;
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- if( pPrior->pLimit
- && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
- && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
+ if( p->pLimit
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
+ && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlite3LogEst((u64)nLimit);
}
@@ -2638,7 +2707,7 @@ static int multiSelect(
Expr *pLimit; /* Saved values of p->nLimit */
int addr;
SelectDest uniondest;
-
+
testcase( p->op==TK_EXCEPT );
testcase( p->op==TK_UNION );
priorOp = SRT_Union;
@@ -2660,7 +2729,8 @@ static int multiSelect(
findRightmost(p)->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
}
-
+
+
/* Code the SELECT statements to our left
*/
assert( !pPrior->pOrderBy );
@@ -2669,7 +2739,7 @@ static int multiSelect(
if( rc ){
goto multi_select_end;
}
-
+
/* Code the current SELECT statement
*/
if( p->op==TK_EXCEPT ){
@@ -2683,12 +2753,10 @@ static int multiSelect(
p->pLimit = 0;
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlite3SelectOpName(p->op)));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
- /* Query flattening in sqlite3Select() might refill p->pOrderBy.
- ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
- sqlite3ExprListDelete(db, p->pOrderBy);
+ assert( p->pOrderBy==0 );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
@@ -2699,16 +2767,16 @@ static int multiSelect(
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 );
- if( dest.eDest!=priorOp ){
+ assert( p->pEList || db->mallocFailed );
+ if( dest.eDest!=priorOp && db->mallocFailed==0 ){
int iCont, iBreak, iStart;
- assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
iStart = sqlite3VdbeCurrentAddr(v);
@@ -2728,7 +2796,7 @@ static int multiSelect(
int addr;
SelectDest intersectdest;
int r1;
-
+
/* 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.
@@ -2736,13 +2804,13 @@ static int multiSelect(
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);
@@ -2750,7 +2818,7 @@ static int multiSelect(
if( rc ){
goto multi_select_end;
}
-
+
/* Code the current SELECT into temporary table "tab2"
*/
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
@@ -2761,7 +2829,7 @@ static int multiSelect(
p->pLimit = 0;
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlite3SelectOpName(p->op)));
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -2771,13 +2839,14 @@ static int multiSelect(
}
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
-
+
/* Generate code to take the intersection of the two temporary
** tables.
*/
+ if( rc ) break;
assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
r1 = sqlite3GetTempReg(pParse);
@@ -2795,15 +2864,16 @@ static int multiSelect(
break;
}
}
-
+
#ifndef SQLITE_OMIT_EXPLAIN
if( p->pNext==0 ){
ExplainQueryPlanPop(pParse);
}
#endif
}
-
- /* Compute collating sequences used by
+ 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.
**
@@ -2868,7 +2938,8 @@ void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
}else{
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
- " do not have the same number of result columns", selectOpName(p->op));
+ " do not have the same number of result columns",
+ sqlite3SelectOpName(p->op));
}
}
@@ -2907,9 +2978,9 @@ static int generateOutputSubroutine(
int addr;
addr = sqlite3VdbeCurrentAddr(v);
- iContinue = sqlite3VdbeMakeLabel(v);
+ iContinue = sqlite3VdbeMakeLabel(pParse);
- /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
+ /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
*/
if( regPrev ){
int addr1, addr2;
@@ -2951,7 +3022,7 @@ static int generateOutputSubroutine(
int r1;
testcase( pIn->nSdst>1 );
r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
@@ -2961,11 +3032,12 @@ static int generateOutputSubroutine(
/* If this is a scalar select that is part of an expression, then
** store the results in the appropriate memory cell and break out
- ** of the scan loop.
+ ** of the scan loop. Note that the select might return multiple columns
+ ** if it is the RHS of a row-value IN operator.
*/
case SRT_Mem: {
- assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 );
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
+ testcase( pIn->nSdst>1 );
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
/* The LIMIT clause will jump out of the loop for us */
break;
}
@@ -2988,7 +3060,7 @@ static int generateOutputSubroutine(
** 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.
+ ** For SRT_Output, results are stored in a sequence of registers.
** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
** return the next row of result.
*/
@@ -3045,7 +3117,7 @@ static int generateOutputSubroutine(
**
** EofB: Called when data is exhausted from selectB.
**
-** The implementation of the latter five subroutines depend on which
+** The implementation of the latter five subroutines depend on which
** <operator> is used:
**
**
@@ -3137,20 +3209,20 @@ static int multiSelectOrderBy(
sqlite3 *db; /* Database connection */
ExprList *pOrderBy; /* The ORDER BY clause */
int nOrderBy; /* Number of terms in the ORDER BY clause */
- int *aPermute; /* Mapping from ORDER BY terms to result set columns */
+ u32 *aPermute; /* Mapping from ORDER BY terms to result set columns */
assert( p->pOrderBy!=0 );
assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */
db = pParse->db;
v = pParse->pVdbe;
assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */
- labelEnd = sqlite3VdbeMakeLabel(v);
- labelCmpr = sqlite3VdbeMakeLabel(v);
+ labelEnd = sqlite3VdbeMakeLabel(pParse);
+ labelCmpr = sqlite3VdbeMakeLabel(pParse);
/* Patch up the ORDER BY clause
*/
- op = p->op;
+ op = p->op;
pPrior = p->pPrior;
assert( pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
@@ -3186,7 +3258,7 @@ static int multiSelectOrderBy(
** to the right and the left are evaluated, they use the correct
** collation.
*/
- aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1));
+ aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
if( aPermute ){
struct ExprList_item *pItem;
aPermute[0] = nOrderBy;
@@ -3222,11 +3294,11 @@ static int multiSelectOrderBy(
assert( sqlite3KeyInfoIsWriteable(pKeyDup) );
for(i=0; i<nExpr; i++){
pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
- pKeyDup->aSortOrder[i] = 0;
+ pKeyDup->aSortFlags[i] = 0;
}
}
}
-
+
/* Separate the left and the right query from one another
*/
p->pPrior = 0;
@@ -3257,7 +3329,7 @@ static int multiSelectOrderBy(
sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
- ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op)));
+ ExplainQueryPlan((pParse, 1, "MERGE (%s)", sqlite3SelectOpName(p->op)));
/* Generate a coroutine to evaluate the SELECT statement to the
** left of the compound operator - the "A" select.
@@ -3271,7 +3343,7 @@ static int multiSelectOrderBy(
sqlite3VdbeEndCoroutine(v, regAddrA);
sqlite3VdbeJumpHere(v, addr1);
- /* Generate a coroutine to evaluate the SELECT statement on
+ /* Generate a coroutine to evaluate the SELECT statement on
** the right - the "B" select
*/
addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
@@ -3280,7 +3352,7 @@ static int multiSelectOrderBy(
savedLimit = p->iLimit;
savedOffset = p->iOffset;
p->iLimit = regLimitB;
- p->iOffset = 0;
+ p->iOffset = 0;
ExplainQueryPlan((pParse, 1, "RIGHT"));
sqlite3Select(pParse, p, &destB);
p->iLimit = savedLimit;
@@ -3294,7 +3366,7 @@ static int multiSelectOrderBy(
addrOutA = generateOutputSubroutine(pParse,
p, &destA, pDest, regOutA,
regPrev, pKeyDup, labelEnd);
-
+
/* Generate a subroutine that outputs the current row of the B
** select as the next output row of the compound select.
*/
@@ -3311,7 +3383,7 @@ static int multiSelectOrderBy(
*/
if( op==TK_EXCEPT || op==TK_INTERSECT ){
addrEofA_noB = addrEofA = labelEnd;
- }else{
+ }else{
VdbeNoopComment((v, "eof-A subroutine"));
addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
@@ -3326,7 +3398,7 @@ static int multiSelectOrderBy(
if( op==TK_INTERSECT ){
addrEofB = addrEofA;
if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
- }else{
+ }else{
VdbeNoopComment((v, "eof-B subroutine"));
addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
@@ -3421,13 +3493,13 @@ static void substSelect(SubstContext*, Select*, int);
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
-** entry in pEList. (But leave references to the ROWID column
+** entry in pEList. (But leave references to the ROWID column
** unchanged.)
**
** This routine is part of the flattening procedure. A subquery
** whose result set is defined by pEList appears as entry in the
** FROM clause of a SELECT such that the VDBE cursor assigned to that
-** FORM clause entry is iTable. This routine makes the necessary
+** FORM clause entry is iTable. This routine makes the necessary
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
@@ -3441,7 +3513,10 @@ static Expr *substExpr(
){
pExpr->iRightJoinTable = pSubst->iNewTable;
}
- if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
+ if( pExpr->op==TK_COLUMN
+ && pExpr->iTable==pSubst->iTable
+ && !ExprHasProperty(pExpr, EP_FixedCol)
+ ){
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else{
@@ -3459,18 +3534,31 @@ static Expr *substExpr(
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
+ ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
+ testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
if( pNew && pSubst->isLeftJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
- pNew->iRightJoinTable = pExpr->iRightJoinTable;
- ExprSetProperty(pNew, EP_FromJoin);
+ sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
+
+ /* Ensure that the expression now has an implicit collation sequence,
+ ** just as it did when it was a column of a view or sub-query. */
+ if( pExpr ){
+ if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+ pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+ (pColl ? pColl->zName : "BINARY")
+ );
+ }
+ ExprClearProperty(pExpr, EP_Collate);
+ }
}
}
}else{
@@ -3484,6 +3572,14 @@ static Expr *substExpr(
}else{
substExprList(pSubst, pExpr->x.pList);
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ Window *pWin = pExpr->y.pWin;
+ pWin->pFilter = substExpr(pSubst, pWin->pFilter);
+ substExprList(pSubst, pWin->pPartition);
+ substExprList(pSubst, pWin->pOrderBy);
+ }
+#endif
}
return pExpr;
}
@@ -3503,7 +3599,7 @@ static void substSelect(
int doPrior /* Do substitutes on p->pPrior too */
){
SrcList *pSrc;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
int i;
if( !p ) return;
do{
@@ -3526,6 +3622,124 @@ static void substSelect(
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
+** pSelect is a SELECT statement and pSrcItem is one item in the FROM
+** clause of that SELECT.
+**
+** This routine scans the entire SELECT statement and recomputes the
+** pSrcItem->colUsed mask.
+*/
+static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
+ SrcItem *pItem;
+ if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
+ pItem = pWalker->u.pSrcItem;
+ if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
+ if( pExpr->iColumn<0 ) return WRC_Continue;
+ pItem->colUsed |= sqlite3ExprColUsed(pExpr);
+ return WRC_Continue;
+}
+static void recomputeColumnsUsed(
+ Select *pSelect, /* The complete SELECT statement */
+ SrcItem *pSrcItem /* Which FROM clause item to recompute */
+){
+ Walker w;
+ if( NEVER(pSrcItem->pTab==0) ) return;
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = recomputeColumnsUsedExpr;
+ w.xSelectCallback = sqlite3SelectWalkNoop;
+ w.u.pSrcItem = pSrcItem;
+ pSrcItem->colUsed = 0;
+ sqlite3WalkSelect(&w, pSelect);
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/*
+** Assign new cursor numbers to each of the items in pSrc. For each
+** new cursor number assigned, set an entry in the aCsrMap[] array
+** to map the old cursor number to the new:
+**
+** aCsrMap[iOld] = iNew;
+**
+** The array is guaranteed by the caller to be large enough for all
+** existing cursor numbers in pSrc.
+**
+** If pSrc contains any sub-selects, call this routine recursively
+** on the FROM clause of each such sub-select, with iExcept set to -1.
+*/
+static void srclistRenumberCursors(
+ Parse *pParse, /* Parse context */
+ int *aCsrMap, /* Array to store cursor mappings in */
+ SrcList *pSrc, /* FROM clause to renumber */
+ int iExcept /* FROM clause item to skip */
+){
+ int i;
+ SrcItem *pItem;
+ for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
+ if( i!=iExcept ){
+ Select *p;
+ if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
+ aCsrMap[pItem->iCursor] = pParse->nTab++;
+ }
+ pItem->iCursor = aCsrMap[pItem->iCursor];
+ for(p=pItem->pSelect; p; p=p->pPrior){
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ }
+ }
+ }
+}
+
+/*
+** Expression walker callback used by renumberCursors() to update
+** Expr objects to match newly assigned cursor numbers.
+*/
+static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
+ int *aCsrMap = pWalker->u.aiCol;
+ int op = pExpr->op;
+ if( (op==TK_COLUMN || op==TK_IF_NULL_ROW) && aCsrMap[pExpr->iTable] ){
+ pExpr->iTable = aCsrMap[pExpr->iTable];
+ }
+ if( ExprHasProperty(pExpr, EP_FromJoin) && aCsrMap[pExpr->iRightJoinTable] ){
+ pExpr->iRightJoinTable = aCsrMap[pExpr->iRightJoinTable];
+ }
+ return WRC_Continue;
+}
+
+/*
+** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
+** of the SELECT statement passed as the second argument, and to each
+** cursor in the FROM clause of any FROM clause sub-selects, recursively.
+** Except, do not assign a new cursor number to the iExcept'th element in
+** the FROM clause of (*p). Update all expressions and other references
+** to refer to the new cursor numbers.
+**
+** Argument aCsrMap is an array that may be used for temporary working
+** space. Two guarantees are made by the caller:
+**
+** * the array is larger than the largest cursor number used within the
+** select statement passed as an argument, and
+**
+** * the array entries for all cursor numbers that do *not* appear in
+** FROM clauses of the select statement as described above are
+** initialized to zero.
+*/
+static void renumberCursors(
+ Parse *pParse, /* Parse context */
+ Select *p, /* Select to renumber cursors within */
+ int iExcept, /* FROM clause item to skip */
+ int *aCsrMap /* Working space */
+){
+ Walker w;
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
+ memset(&w, 0, sizeof(w));
+ w.u.aiCol = aCsrMap;
+ w.xExprCallback = renumberCursorsCb;
+ w.xSelectCallback = sqlite3SelectWalkNoop;
+ sqlite3WalkSelect(&w, p);
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/*
** This routine attempts to flatten subqueries as a performance optimization.
** This routine returns 1 if it makes changes and 0 if no flattening occurs.
**
@@ -3547,7 +3761,7 @@ static void substSelect(
** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
**
** The code generated for this simplification gives the same result
-** but only has to scan the data once. And because indices might
+** but only has to scan the data once. And because indices might
** exist on the table t1, a complete scan of the data might be
** avoided.
**
@@ -3569,11 +3783,12 @@ static void substSelect(
** (3b) the FROM clause of the subquery may not contain a virtual
** table and
** (3c) the outer query may not be an aggregate.
+** (3d) the outer query may not be DISTINCT.
**
** (4) The subquery can not be DISTINCT.
**
** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
-** sub-queries that were excluded from this optimization. Restriction
+** sub-queries that were excluded from this optimization. Restriction
** (4) has since been expanded to exclude all DISTINCT subqueries.
**
** (**) We no longer attempt to flatten aggregate subqueries. Was:
@@ -3590,7 +3805,7 @@ static void substSelect(
**
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
** accidently carried the comment forward until 2014-09-15. Original
-** constraint: "If the subquery is aggregate then the outer query
+** constraint: "If the subquery is aggregate then the outer query
** may not use LIMIT."
**
** (11) The subquery and the outer query may not both have ORDER BY clauses.
@@ -3608,7 +3823,7 @@ static void substSelect(
**
** (16) If the outer query is aggregate, then the subquery may not
** use ORDER BY. (Ticket #2942) This used to not matter
-** until we introduced the group_concat() function.
+** until we introduced the group_concat() function.
**
** (17) If the subquery is a compound select, then
** (17a) all compound operators must be a UNION ALL, and
@@ -3617,8 +3832,9 @@ static void substSelect(
** (17c) every term within the subquery compound must have a FROM clause
** (17d) the outer query may not be
** (17d1) aggregate, or
-** (17d2) DISTINCT, or
-** (17d3) a join.
+** (17d2) DISTINCT
+** (17e) the subquery may not contain window functions, and
+** (17f) the subquery must not be the RHS of a LEFT JOIN.
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -3634,8 +3850,8 @@ static void substSelect(
** syntax error and return a detailed message.
**
** (18) If the sub-query is a compound select, then all terms of the
-** ORDER BY clause of the parent must be simple references to
-** columns of the sub-query.
+** ORDER BY clause of the parent must be copies of a term returned
+** by the parent query.
**
** (19) If the subquery uses LIMIT then the outer query may not
** have a WHERE clause.
@@ -3651,14 +3867,13 @@ static void substSelect(
**
** (22) The subquery may not be a recursive CTE.
**
-** (**) Subsumed into restriction (17d3). Was: If the outer query is
-** a recursive CTE, then the sub-query may not be a compound query.
-** This restriction is because transforming the
+** (23) If the outer query is a recursive CTE, then the sub-query may not be
+** a compound query. This restriction is because transforming the
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
** (**) We no longer attempt to flatten aggregate subqueries. Was:
-** The subquery may not be an aggregate that uses the built-in min() or
+** The subquery may not be an aggregate that uses the built-in min() or
** or max() functions. (Without this restriction, a query like:
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
** return the value X for which Y was maximal.)
@@ -3692,11 +3907,13 @@ static int flattenSubquery(
SrcList *pSubSrc; /* The FROM clause of the subquery */
int iParent; /* VDBE cursor number of the pSub result set temp table */
int iNewParent = -1;/* Replacement table for iParent */
- int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
+ int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
int i; /* Loop counter */
Expr *pWhere; /* The WHERE clause */
- struct SrcList_item *pSubitem; /* The subquery */
+ SrcItem *pSubitem; /* The subquery */
sqlite3 *db = pParse->db;
+ Walker w; /* Walker to persist agginfo data */
+ int *aCsrMap = 0;
/* Check to see if flattening is permitted. Return 0 if not.
*/
@@ -3765,8 +3982,11 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
isLeftJoin = 1;
- if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
- /* (3a) (3c) (3b) */
+ if( pSubSrc->nSrc>1 /* (3a) */
+ || isAgg /* (3b) */
+ || IsVirtual(pSubSrc->a[0].pTab) /* (3c) */
+ || (p->selFlags & SF_Distinct)!=0 /* (3d) */
+ ){
return 0;
}
}
@@ -3774,7 +3994,7 @@ static int flattenSubquery(
else if( iFrom>0 && !isAgg ){
/* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
** every reference to any result column from subquery in a join, even
- ** though they are not necessary. This will stress-test the OP_IfNullRow
+ ** though they are not necessary. This will stress-test the OP_IfNullRow
** opcode. */
isLeftJoin = -1;
}
@@ -3789,17 +4009,21 @@ static int flattenSubquery(
if( pSub->pOrderBy ){
return 0; /* Restriction (20) */
}
- if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
- return 0; /* (17d1), (17d2), or (17d3) */
+ if( isAgg || (p->selFlags & SF_Distinct)!=0 || isLeftJoin>0 ){
+ return 0; /* (17d1), (17d2), or (17f) */
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
+ assert( (pSub->selFlags & SF_Recursive)==0 );
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
|| pSub1->pSrc->nSrc<1 /* (17c) */
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ || pSub1->pWin /* (17e) */
+#endif
){
return 0;
}
@@ -3813,15 +4037,15 @@ static int flattenSubquery(
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
- }
- /* Ex-restriction (23):
- ** The only way that the recursive part of a CTE can contain a compound
- ** subquery is for the subquery to be one term of a join. But if the
- ** subquery is a join, then the flattening has already been stopped by
- ** restriction (17d3)
- */
- assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
+ /* Restriction (23) */
+ if( (p->selFlags & SF_Recursive) ) return 0;
+
+ if( pSrc->nSrc>1 ){
+ if( pParse->nSelect>500 ) return 0;
+ aCsrMap = sqlite3DbMallocZero(db, pParse->nTab*sizeof(int));
+ }
+ }
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
@@ -3833,14 +4057,25 @@ static int flattenSubquery(
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
+ /* Delete the transient structures associated with thesubquery */
+ pSub1 = pSubitem->pSelect;
+ sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlite3DbFree(db, pSubitem->zName);
+ sqlite3DbFree(db, pSubitem->zAlias);
+ pSubitem->zDatabase = 0;
+ pSubitem->zName = 0;
+ pSubitem->zAlias = 0;
+ pSubitem->pSelect = 0;
+ assert( pSubitem->pOn==0 );
+
/* If the sub-query is a compound SELECT statement, then (by restrictions
- ** 17 and 18 above) it must be a UNION ALL and the parent query must
+ ** 17 and 18 above) it must be a UNION ALL and the parent query must
** be of the form:
**
- ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
+ ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
**
** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
- ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
+ ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
** OFFSET clauses and joins them to the left-hand-side of the original
** using UNION ALL operators. In this case N is the number of simple
** select statements in the compound sub-query.
@@ -3871,18 +4106,23 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
+ Table *pItemTab = pSubitem->pTab;
+ pSubitem->pTab = 0;
p->pOrderBy = 0;
- p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p, 0);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
- p->pSrc = pSrc;
p->op = TK_ALL;
+ pSubitem->pTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
+ pNew->selId = ++pParse->nSelect;
+ if( aCsrMap && db->mallocFailed==0 ){
+ renumberCursors(pParse, pNew, iFrom, aCsrMap);
+ }
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
@@ -3890,24 +4130,13 @@ static int flattenSubquery(
SELECTTRACE(2,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
- if( db->mallocFailed ) return 1;
+ assert( pSubitem->pSelect==0 );
+ }
+ sqlite3DbFree(db, aCsrMap);
+ if( db->mallocFailed ){
+ pSubitem->pSelect = pSub1;
+ return 1;
}
-
- /* Begin flattening the iFrom-th entry of the FROM clause
- ** in the outer query.
- */
- pSub = pSub1 = pSubitem->pSelect;
-
- /* Delete the transient table structure associated with the
- ** subquery
- */
- sqlite3DbFree(db, pSubitem->zDatabase);
- sqlite3DbFree(db, pSubitem->zName);
- sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
- pSubitem->zName = 0;
- pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
/* Defer deleting the Table object associated with the
** subquery until code generation is
@@ -3920,8 +4149,10 @@ static int flattenSubquery(
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- pTabToDel->pNextZombie = pToplevel->pZombieTab;
- pToplevel->pZombieTab = pTabToDel;
+ sqlite3ParserAddCleanup(pToplevel,
+ (void(*)(sqlite3*,void*))sqlite3DeleteTable,
+ pTabToDel);
+ testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
}
@@ -3941,25 +4172,19 @@ static int flattenSubquery(
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
+ pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
+ assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
- if( pSrc ){
- assert( pParent==p ); /* First time through the loop */
- jointype = pSubitem->fg.jointype;
- }else{
- assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pSrc==0 ){
- assert( db->mallocFailed );
- break;
- }
+ if( pParent==p ){
+ jointype = pSubitem->fg.jointype; /* First time through the loop */
}
-
+
/* The subquery uses a single slot of the FROM clause of the outer
** query. If the subquery has more than one element in its FROM clause,
** then expand the outer query to make space for it to hold all elements
@@ -3976,10 +4201,9 @@ static int flattenSubquery(
** for the two elements in the FROM clause of the subquery.
*/
if( nSubSrc>1 ){
- pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
- if( db->mallocFailed ){
- break;
- }
+ pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
+ if( pSrc==0 ) break;
+ pParent->pSrc = pSrc;
}
/* Transfer the FROM clause terms from the subquery into the
@@ -3993,10 +4217,10 @@ static int flattenSubquery(
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].fg.jointype = jointype;
-
- /* Now begin substituting subquery result set expressions for
+
+ /* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
- **
+ **
** Example:
**
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
@@ -4006,7 +4230,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
@@ -4025,11 +4249,18 @@ static int flattenSubquery(
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}
- pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
+ pWhere = pSub->pWhere;
+ pSub->pWhere = 0;
if( isLeftJoin>0 ){
- setJoinExpr(pWhere, iNewParent);
+ sqlite3SetJoinExpr(pWhere, iNewParent);
+ }
+ if( pWhere ){
+ if( pParent->pWhere ){
+ pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere);
+ }else{
+ pParent->pWhere = pWhere;
+ }
}
- pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
if( db->mallocFailed==0 ){
SubstContext x;
x.pParse = pParse;
@@ -4039,12 +4270,12 @@ static int flattenSubquery(
x.pEList = pSub->pEList;
substSelect(&x, pParent, 0);
}
-
- /* The flattened query is distinct if either the inner or the
- ** outer query is distinct.
- */
- pParent->selFlags |= pSub->selFlags & SF_Distinct;
-
+
+ /* The flattened query is a compound if either the inner or the
+ ** outer query is a compound. */
+ pParent->selFlags |= pSub->selFlags & SF_Compound;
+ assert( (pSub->selFlags & SF_Distinct)==0 ); /* restriction (17b) */
+
/*
** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
**
@@ -4055,11 +4286,19 @@ static int flattenSubquery(
pParent->pLimit = pSub->pLimit;
pSub->pLimit = 0;
}
+
+ /* Recompute the SrcList_item.colUsed masks for the flattened
+ ** tables. */
+ for(i=0; i<nSubSrc; i++){
+ recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]);
+ }
}
/* Finially, delete what is left of the subquery and return
** success.
*/
+ sqlite3AggInfoPersistWalkerInit(&w, pParse);
+ sqlite3WalkSelect(&w,pSub1);
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
@@ -4087,23 +4326,35 @@ struct WhereConst {
/*
** Add a new entry to the pConst object. Except, do not add duplicate
-** pColumn entires.
+** pColumn entires. Also, do not add if doing so would not be appropriate.
+**
+** The caller guarantees the pColumn is a column and pValue is a constant.
+** This routine has to do some additional checks before completing the
+** insert.
*/
static void constInsert(
- WhereConst *pConst, /* The WhereConst into which we are inserting */
- Expr *pColumn, /* The COLUMN part of the constraint */
- Expr *pValue /* The VALUE part of the constraint */
+ WhereConst *pConst, /* The WhereConst into which we are inserting */
+ Expr *pColumn, /* The COLUMN part of the constraint */
+ Expr *pValue, /* The VALUE part of the constraint */
+ Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */
){
int i;
assert( pColumn->op==TK_COLUMN );
+ assert( sqlite3ExprIsConstant(pValue) );
+
+ if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
+ if( sqlite3ExprAffinity(pValue)!=0 ) return;
+ if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){
+ return;
+ }
/* 2018-10-25 ticket [cf5ed20f]
** Make sure the same pColumn is not inserted more than once */
for(i=0; i<pConst->nConst; i++){
- const Expr *pExpr = pConst->apExpr[i*2];
- assert( pExpr->op==TK_COLUMN );
- if( pExpr->iTable==pColumn->iTable
- && pExpr->iColumn==pColumn->iColumn
+ const Expr *pE2 = pConst->apExpr[i*2];
+ assert( pE2->op==TK_COLUMN );
+ if( pE2->iTable==pColumn->iTable
+ && pE2->iColumn==pColumn->iColumn
){
return; /* Already present. Return without doing anything. */
}
@@ -4115,7 +4366,6 @@ static void constInsert(
if( pConst->apExpr==0 ){
pConst->nConst = 0;
}else{
- if( ExprHasProperty(pValue, EP_FixedCol) ) pValue = pValue->pLeft;
pConst->apExpr[pConst->nConst*2-2] = pColumn;
pConst->apExpr[pConst->nConst*2-1] = pValue;
}
@@ -4141,19 +4391,11 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
pLeft = pExpr->pLeft;
assert( pRight!=0 );
assert( pLeft!=0 );
- if( pRight->op==TK_COLUMN
- && !ExprHasProperty(pRight, EP_FixedCol)
- && sqlite3ExprIsConstant(pLeft)
- && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
- ){
- constInsert(pConst, pRight, pLeft);
- }else
- if( pLeft->op==TK_COLUMN
- && !ExprHasProperty(pLeft, EP_FixedCol)
- && sqlite3ExprIsConstant(pRight)
- && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
- ){
- constInsert(pConst, pLeft, pRight);
+ if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
+ constInsert(pConst,pRight,pLeft,pExpr);
+ }
+ if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
+ constInsert(pConst,pLeft,pRight,pExpr);
}
}
@@ -4167,7 +4409,11 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
int i;
WhereConst *pConst;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
- if( ExprHasProperty(pExpr, EP_FixedCol) ) return WRC_Continue;
+ if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){
+ testcase( ExprHasProperty(pExpr, EP_FixedCol) );
+ testcase( ExprHasProperty(pExpr, EP_FromJoin) );
+ return WRC_Continue;
+ }
pConst = pWalker->u.pConst;
for(i=0; i<pConst->nConst; i++){
Expr *pColumn = pConst->apExpr[i*2];
@@ -4189,10 +4435,9 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
** The WHERE-clause constant propagation optimization.
**
** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
-** CONSTANT=COLUMN that must be tree (in other words, if the terms top-level
-** AND-connected terms that are not part of a ON clause from a LEFT JOIN)
-** then throughout the query replace all other occurrences of COLUMN
-** with CONSTANT within the WHERE clause.
+** CONSTANT=COLUMN that are top-level AND-connected terms that are not
+** part of a ON clause from a LEFT JOIN, then throughout the query
+** replace all other occurrences of COLUMN with CONSTANT.
**
** For example, the query:
**
@@ -4247,11 +4492,40 @@ static int propagateConstants(
sqlite3DbFree(x.pParse->db, x.apExpr);
nChng += x.nChng;
}
- }while( x.nChng );
+ }while( x.nChng );
return nChng;
}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+# if !defined(SQLITE_OMIT_WINDOWFUNC)
+/*
+** This function is called to determine whether or not it is safe to
+** push WHERE clause expression pExpr down to FROM clause sub-query
+** pSubq, which contains at least one window function. Return 1
+** if it is safe and the expression should be pushed down, or 0
+** otherwise.
+**
+** It is only safe to push the expression down if it consists only
+** of constants and copies of expressions that appear in the PARTITION
+** BY clause of all window function used by the sub-query. It is safe
+** to filter out entire partitions, but not rows within partitions, as
+** this may change the results of the window functions.
+**
+** At the time this function is called it is guaranteed that
+**
+** * the sub-query uses only one distinct window frame, and
+** * that the window frame has a PARTITION BY clase.
+*/
+static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
+ assert( pSubq->pWin->pPartition );
+ assert( (pSubq->selFlags & SF_MultiPart)==0 );
+ assert( pSubq->pPrior==0 );
+ return sqlite3ExprIsConstantOrGroupBy(pParse, pExpr, pSubq->pWin->pPartition);
+}
+# endif /* SQLITE_OMIT_WINDOWFUNC */
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
** the WHERE clause of subquery. Example:
@@ -4298,9 +4572,24 @@ static int propagateConstants(
** But if the (b2=2) term were to be pushed down into the bb subquery,
** then the (1,1,NULL) row would be suppressed.
**
-** (6) The inner query features one or more window-functions (since
-** changes to the WHERE clause of the inner query could change the
-** window over which window functions are calculated).
+** (6) Window functions make things tricky as changes to the WHERE clause
+** of the inner query could change the window over which window
+** functions are calculated. Therefore, do not attempt the optimization
+** if:
+**
+** (6a) The inner query uses multiple incompatible window partitions.
+**
+** (6b) The inner query is a compound and uses window-functions.
+**
+** (6c) The WHERE clause does not consist entirely of constants and
+** copies of expressions found in the PARTITION BY clause of
+** all window-functions used by the sub-query. It is safe to
+** filter out entire partitions, as this does not change the
+** window over which any window-function is calculated.
+**
+** (7) The inner query is a Common Table Expression (CTE) that should
+** be materialized. (This restriction is implemented in the calling
+** routine.)
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
@@ -4315,10 +4604,17 @@ static int pushDownWhereTerms(
Expr *pNew;
int nChng = 0;
if( pWhere==0 ) return 0;
- if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
+ if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pSubq->pWin ) return 0; /* restriction (6) */
+ if( pSubq->pPrior ){
+ Select *pSel;
+ for(pSel=pSubq; pSel; pSel=pSel->pPrior){
+ if( pSel->pWin ) return 0; /* restriction (6b) */
+ }
+ }else{
+ if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0;
+ }
#endif
#ifdef SQLITE_DEBUG
@@ -4327,7 +4623,7 @@ static int pushDownWhereTerms(
** in the future.
*/
{
- Select *pX;
+ Select *pX;
for(pX=pSubq; pX; pX=pX->pPrior){
assert( (pX->selFlags & (SF_Recursive))==0 );
}
@@ -4353,6 +4649,7 @@ static int pushDownWhereTerms(
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
+ pSubq->selFlags |= SF_PushDown;
while( pSubq ){
SubstContext x;
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -4363,10 +4660,18 @@ static int pushDownWhereTerms(
x.isLeftJoin = 0;
x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
+ /* Restriction 6c has prevented push-down in this case */
+ sqlite3ExprDelete(pParse->db, pNew);
+ nChng--;
+ break;
+ }
+#endif
if( pSubq->selFlags & SF_Aggregate ){
- pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew);
+ pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew);
}else{
- pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
+ pSubq->pWhere = sqlite3ExprAnd(pParse, pSubq->pWhere, pNew);
}
pSubq = pSubq->pPrior;
}
@@ -4377,7 +4682,7 @@ static int pushDownWhereTerms(
/*
** The pFunc is the only aggregate function in the query. Check to see
-** if the query is a candidate for the min/max optimization.
+** if the query is a candidate for the min/max optimization.
**
** If the query is a candidate for the min/max optimization, then set
** *ppMinMax to be an ORDER BY clause to be used for the optimization
@@ -4396,30 +4701,39 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */
const char *zFunc; /* Name of aggregate function pFunc */
ExprList *pOrderBy;
- u8 sortOrder;
+ u8 sortFlags = 0;
assert( *ppMinMax==0 );
assert( pFunc->op==TK_AGG_FUNCTION );
- if( pEList==0 || pEList->nExpr!=1 ) return eRet;
+ assert( !IsWindowFunc(pFunc) );
+ if( pEList==0
+ || pEList->nExpr!=1
+ || ExprHasProperty(pFunc, EP_WinFunc)
+ || OptimizationDisabled(db, SQLITE_MinMaxOpt)
+ ){
+ return eRet;
+ }
zFunc = pFunc->u.zToken;
if( sqlite3StrICmp(zFunc, "min")==0 ){
eRet = WHERE_ORDERBY_MIN;
- sortOrder = SQLITE_SO_ASC;
+ if( sqlite3ExprCanBeNull(pEList->a[0].pExpr) ){
+ sortFlags = KEYINFO_ORDER_BIGNULL;
+ }
}else if( sqlite3StrICmp(zFunc, "max")==0 ){
eRet = WHERE_ORDERBY_MAX;
- sortOrder = SQLITE_SO_DESC;
+ sortFlags = KEYINFO_ORDER_DESC;
}else{
return eRet;
}
*ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
assert( pOrderBy!=0 || db->mallocFailed );
- if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder;
+ if( pOrderBy ) pOrderBy->a[0].sortFlags = sortFlags;
return eRet;
}
/*
** The select statement passed as the first argument is an aggregate query.
-** The second argument is the associated aggregate-info object. This
+** The second argument is the associated aggregate-info object. This
** function tests if the SELECT is of the form:
**
** SELECT count(*) FROM <tbl>
@@ -4434,7 +4748,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
assert( !p->pGroupBy );
- if( p->pWhere || p->pEList->nExpr!=1
+ if( p->pWhere || p->pEList->nExpr!=1
|| p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
){
return 0;
@@ -4447,7 +4761,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
if( NEVER(pAggInfo->nFunc==0) ) return 0;
if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
- if( pExpr->flags&EP_Distinct ) return 0;
+ if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0;
return pTab;
}
@@ -4455,30 +4769,32 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
/*
** If the source-list item passed as an argument was augmented with an
** INDEXED BY clause, then try to locate the specified index. If there
-** was such a clause and the named index cannot be found, return
-** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
+** was such a clause and the named index cannot be found, return
+** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
** pFrom->pIndex and return SQLITE_OK.
*/
-int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
- if( pFrom->pTab && pFrom->fg.isIndexedBy ){
- Table *pTab = pFrom->pTab;
- char *zIndexedBy = pFrom->u1.zIndexedBy;
- Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
- pIdx=pIdx->pNext
- );
- if( !pIdx ){
- sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
- pParse->checkSchema = 1;
- return SQLITE_ERROR;
- }
- pFrom->pIBIndex = pIdx;
- }
+int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
+ Table *pTab = pFrom->pTab;
+ char *zIndexedBy = pFrom->u1.zIndexedBy;
+ Index *pIdx;
+ assert( pTab!=0 );
+ assert( pFrom->fg.isIndexedBy!=0 );
+
+ for(pIdx=pTab->pIndex;
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
+ pIdx=pIdx->pNext
+ );
+ if( !pIdx ){
+ sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
+ pParse->checkSchema = 1;
+ return SQLITE_ERROR;
+ }
+ pFrom->u2.pIBIndex = pIdx;
return SQLITE_OK;
}
+
/*
-** Detect compound SELECT statements that use an ORDER BY clause with
+** Detect compound SELECT statements that use an ORDER BY clause with
** an alternative collating sequence.
**
** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ...
@@ -4513,6 +4829,14 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){}
if( pX==0 ) return WRC_Continue;
a = p->pOrderBy->a;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ /* If iOrderByCol is already non-zero, then it has already been matched
+ ** to a result column of the SELECT statement. This occurs when the
+ ** SELECT is rewritten for window-functions processing and then passed
+ ** to sqlite3SelectPrep() and similar a second time. The rewriting done
+ ** by this function is not required in this case. */
+ if( a[0].u.x.iOrderByCol ) return WRC_Continue;
+#endif
for(i=p->pOrderBy->nExpr-1; i>=0; i--){
if( a[i].pExpr->flags & EP_Collate ) break;
}
@@ -4538,6 +4862,9 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
p->pPrior = 0;
p->pNext = 0;
p->pWith = 0;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ p->pWinDefn = 0;
+#endif
p->selFlags &= ~SF_Compound;
assert( (p->selFlags & SF_Converted)==0 );
p->selFlags |= SF_Converted;
@@ -4552,7 +4879,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
** arguments. If it does, leave an error message in pParse and return
** non-zero, since pFrom is not allowed to be a table-valued function.
*/
-static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
+static int cannotBeFunction(Parse *pParse, SrcItem *pFrom){
if( pFrom->fg.isTabFunc ){
sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName);
return 1;
@@ -4562,9 +4889,9 @@ static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
#ifndef SQLITE_OMIT_CTE
/*
-** Argument pWith (which may be NULL) points to a linked list of nested
-** WITH contexts, from inner to outermost. If the table identified by
-** FROM clause element pItem is really a common-table-expression (CTE)
+** Argument pWith (which may be NULL) points to a linked list of nested
+** WITH contexts, from inner to outermost. If the table identified by
+** FROM clause element pItem is really a common-table-expression (CTE)
** then return a pointer to the CTE definition for that table. Otherwise
** return NULL.
**
@@ -4573,19 +4900,19 @@ static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
*/
static struct Cte *searchWith(
With *pWith, /* Current innermost WITH clause */
- struct SrcList_item *pItem, /* FROM clause element to resolve */
+ SrcItem *pItem, /* FROM clause element to resolve */
With **ppContext /* OUT: WITH clause return value belongs to */
){
- const char *zName;
- if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
- With *p;
- for(p=pWith; p; p=p->pOuter){
- int i;
- for(i=0; i<p->nCte; i++){
- if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
- *ppContext = p;
- return &p->a[i];
- }
+ const char *zName = pItem->zName;
+ With *p;
+ assert( pItem->zDatabase==0 );
+ assert( zName!=0 );
+ for(p=pWith; p; p=p->pOuter){
+ int i;
+ for(i=0; i<p->nCte; i++){
+ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
+ *ppContext = p;
+ return &p->a[i];
}
}
}
@@ -4599,53 +4926,67 @@ static struct Cte *searchWith(
** onto the top of the stack. If argument bFree is true, then this
** WITH clause will never be popped from the stack. In this case it
** should be freed along with the Parse object. In other cases, when
-** bFree==0, the With object will be freed along with the SELECT
+** bFree==0, the With object will be freed along with the SELECT
** statement with which it is associated.
*/
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
- assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
if( pWith ){
assert( pParse->pWith!=pWith );
pWith->pOuter = pParse->pWith;
pParse->pWith = pWith;
- if( bFree ) pParse->pWithToFree = pWith;
+ if( bFree ){
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3WithDelete,
+ pWith);
+ testcase( pParse->earlyCleanup );
+ }
}
}
/*
-** This function checks if argument pFrom refers to a CTE declared by
-** a WITH clause on the stack currently maintained by the parser. And,
-** if currently processing a CTE expression, if it is a recursive
-** reference to the current CTE.
-**
-** If pFrom falls into either of the two categories above, pFrom->pTab
-** and other fields are populated accordingly. The caller should check
-** (pFrom->pTab!=0) to determine whether or not a successful match
-** was found.
-**
-** Whether or not a match is found, SQLITE_OK is returned if no error
-** occurs. If an error does occur, an error message is stored in the
-** parser and some error code other than SQLITE_OK returned.
+** This function checks if argument pFrom refers to a CTE declared by
+** a WITH clause on the stack currently maintained by the parser (on the
+** pParse->pWith linked list). And if currently processing a CTE
+** CTE expression, through routine checks to see if the reference is
+** a recursive reference to the CTE.
+**
+** If pFrom matches a CTE according to either of these two above, pFrom->pTab
+** and other fields are populated accordingly.
+**
+** Return 0 if no match is found.
+** Return 1 if a match is found.
+** Return 2 if an error condition is detected.
*/
-static int withExpand(
- Walker *pWalker,
- struct SrcList_item *pFrom
+static int resolveFromTermToCte(
+ Parse *pParse, /* The parsing context */
+ Walker *pWalker, /* Current tree walker */
+ SrcItem *pFrom /* The FROM clause term to check */
){
- Parse *pParse = pWalker->pParse;
- sqlite3 *db = pParse->db;
- struct Cte *pCte; /* Matched CTE (or NULL if no match) */
- With *pWith; /* WITH clause that pCte belongs to */
+ Cte *pCte; /* Matched CTE (or NULL if no match) */
+ With *pWith; /* The matching WITH */
assert( pFrom->pTab==0 );
-
+ if( pParse->pWith==0 ){
+ /* There are no WITH clauses in the stack. No match is possible */
+ return 0;
+ }
+ if( pFrom->zDatabase!=0 ){
+ /* The FROM term contains a schema qualifier (ex: main.t1) and so
+ ** it cannot possibly be a CTE reference. */
+ return 0;
+ }
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
+ sqlite3 *db = pParse->db;
Table *pTab;
ExprList *pEList;
Select *pSel;
Select *pLeft; /* Left-most SELECT statement */
+ Select *pRecTerm; /* Left-most recursive term */
int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
+ int iRecTab = -1; /* Cursor for recursive table */
+ CteUse *pCteUse;
/* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -4653,63 +4994,93 @@ static int withExpand(
** In this case, proceed. */
if( pCte->zCteErr ){
sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName);
- return SQLITE_ERROR;
+ return 2;
}
- if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;
+ if( cannotBeFunction(pParse, pFrom) ) return 2;
assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
+ pTab = sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTab==0 ) return 2;
+ pCteUse = pCte->pUse;
+ if( pCteUse==0 ){
+ pCte->pUse = pCteUse = sqlite3DbMallocZero(db, sizeof(pCteUse[0]));
+ if( pCteUse==0
+ || sqlite3ParserAddCleanup(pParse,sqlite3DbFree,pCteUse)==0
+ ){
+ sqlite3DbFree(db, pTab);
+ return 2;
+ }
+ pCteUse->eM10d = pCte->eM10d;
+ }
+ pFrom->pTab = pTab;
pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
- if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
+ if( db->mallocFailed ) return 2;
assert( pFrom->pSelect );
+ pFrom->fg.isCte = 1;
+ pFrom->u2.pCteUse = pCteUse;
+ pCteUse->nUse++;
+ if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){
+ pCteUse->eM10d = M10d_Yes;
+ }
/* Check if this is a recursive CTE. */
- pSel = pFrom->pSelect;
+ pRecTerm = pSel = pFrom->pSelect;
bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
- if( bMayRecursive ){
+ while( bMayRecursive && pRecTerm->op==pSel->op ){
int i;
- SrcList *pSrc = pFrom->pSelect->pSrc;
+ SrcList *pSrc = pRecTerm->pSrc;
+ assert( pRecTerm->pPrior!=0 );
for(i=0; i<pSrc->nSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
- if( pItem->zDatabase==0
- && pItem->zName!=0
+ SrcItem *pItem = &pSrc->a[i];
+ if( pItem->zDatabase==0
+ && pItem->zName!=0
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
- ){
+ ){
pItem->pTab = pTab;
- pItem->fg.isRecursive = 1;
pTab->nTabRef++;
- pSel->selFlags |= SF_Recursive;
+ pItem->fg.isRecursive = 1;
+ if( pRecTerm->selFlags & SF_Recursive ){
+ sqlite3ErrorMsg(pParse,
+ "multiple references to recursive table: %s", pCte->zName
+ );
+ return 2;
+ }
+ pRecTerm->selFlags |= SF_Recursive;
+ if( iRecTab<0 ) iRecTab = pParse->nTab++;
+ pItem->iCursor = iRecTab;
}
}
+ if( (pRecTerm->selFlags & SF_Recursive)==0 ) break;
+ pRecTerm = pRecTerm->pPrior;
}
- /* Only one recursive reference is permitted. */
- if( pTab->nTabRef>2 ){
- sqlite3ErrorMsg(
- pParse, "multiple references to recursive table: %s", pCte->zName
- );
- return SQLITE_ERROR;
- }
- assert( pTab->nTabRef==1 ||
- ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
-
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
- if( bMayRecursive ){
- Select *pPrior = pSel->pPrior;
- assert( pPrior->pWith==0 );
- pPrior->pWith = pSel->pWith;
- sqlite3WalkSelect(pWalker, pPrior);
- pPrior->pWith = 0;
+ if( pSel->selFlags & SF_Recursive ){
+ int rc;
+ assert( pRecTerm!=0 );
+ assert( (pRecTerm->selFlags & SF_Recursive)==0 );
+ assert( pRecTerm->pNext!=0 );
+ assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
+ assert( pRecTerm->pWith==0 );
+ pRecTerm->pWith = pSel->pWith;
+ rc = sqlite3WalkSelect(pWalker, pRecTerm);
+ pRecTerm->pWith = 0;
+ if( rc ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}else{
- sqlite3WalkSelect(pWalker, pSel);
+ if( sqlite3WalkSelect(pWalker, pSel) ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}
pParse->pWith = pWith;
@@ -4721,7 +5092,7 @@ static int withExpand(
pCte->zName, pEList->nExpr, pCte->pCols->nExpr
);
pParse->pWith = pSavedWith;
- return SQLITE_ERROR;
+ return 2;
}
pEList = pCte->pCols;
}
@@ -4737,27 +5108,27 @@ static int withExpand(
}
pCte->zCteErr = 0;
pParse->pWith = pSavedWith;
+ return 1; /* Success */
}
-
- return SQLITE_OK;
+ return 0; /* No match */
}
#endif
#ifndef SQLITE_OMIT_CTE
/*
-** If the SELECT passed as the second argument has an associated WITH
+** If the SELECT passed as the second argument has an associated WITH
** clause, pop it from the stack stored as part of the Parse object.
**
** This function is used as the xSelectCallback2() callback by
** sqlite3SelectExpand() when walking a SELECT tree to resolve table
-** names and other FROM clause elements.
+** names and other FROM clause elements.
*/
static void selectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
if( pWith!=0 ){
- assert( pParse->pWith==pWith );
+ assert( pParse->pWith==pWith || pParse->nErr );
pParse->pWith = pWith->pOuter;
}
}
@@ -4773,7 +5144,7 @@ static void selectPopWith(Walker *pWalker, Select *p){
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
** SQLITE_NOMEM.
*/
-int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
+int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
Select *pSel = pFrom->pSelect;
Table *pTab;
@@ -4792,7 +5163,7 @@ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral;
- return SQLITE_OK;
+ return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
/*
@@ -4802,7 +5173,7 @@ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
** (1) Make sure VDBE cursor numbers have been assigned to every
** element of the FROM clause.
**
-** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
+** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
** defines FROM clause. When views appear in the FROM clause,
** fill pTabList->a[].pSelect with a copy of the SELECT statement
** that implements the view. A copy is made of the view's SELECT
@@ -4821,10 +5192,10 @@ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
*/
static int selectExpander(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
- int i, j, k;
+ int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
sqlite3 *db = pParse->db;
Expr *pE, *pRight, *pExpr;
u16 selFlags = p->selFlags;
@@ -4838,6 +5209,10 @@ static int selectExpander(Walker *pWalker, Select *p){
if( (selFlags & SF_Expanded)!=0 ){
return WRC_Prune;
}
+ if( pWalker->eCode ){
+ /* Renumber selId because it has been copied from a view */
+ p->selId = ++pParse->nSelect;
+ }
pTabList = p->pSrc;
pEList = p->pEList;
sqlite3WithPush(pParse, p->pWith, 0);
@@ -4854,12 +5229,8 @@ static int selectExpander(Walker *pWalker, Select *p){
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab;
assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
- if( pFrom->fg.isRecursive ) continue;
- assert( pFrom->pTab==0 );
-#ifndef SQLITE_OMIT_CTE
- if( withExpand(pWalker, pFrom) ) return WRC_Abort;
- if( pFrom->pTab ) {} else
-#endif
+ if( pFrom->pTab ) continue;
+ assert( pFrom->fg.isRecursive==0 );
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
Select *pSel = pFrom->pSelect;
@@ -4869,6 +5240,12 @@ static int selectExpander(Walker *pWalker, Select *p){
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
+#ifndef SQLITE_OMIT_CTE
+ }else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
+ if( rc>1 ) return WRC_Abort;
+ pTab = pFrom->pTab;
+ assert( pTab!=0 );
+#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
@@ -4884,29 +5261,49 @@ static int selectExpander(Walker *pWalker, Select *p){
if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
return WRC_Abort;
}
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
if( IsVirtual(pTab) || pTab->pSelect ){
i16 nCol;
+ u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
+ if( pTab->pSelect
+ && (db->flags & SQLITE_EnableView)==0
+ && pTab->pSchema!=db->aDb[1].pSchema
+ ){
+ sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
+ pTab->zName);
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab)
+ && pFrom->fg.fromDDL
+ && ALWAYS(pTab->pVTable!=0)
+ && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
+ ){
+ sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
+ pTab->zName);
+ }
+#endif
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
nCol = pTab->nCol;
pTab->nCol = -1;
+ pWalker->eCode = 1; /* Turn on Select.selId renumbering */
sqlite3WalkSelect(pWalker, pFrom->pSelect);
+ pWalker->eCode = eCodeOrig;
pTab->nCol = nCol;
}
#endif
}
/* Locate the index named by the INDEXED BY clause, if any. */
- if( sqlite3IndexedByLookup(pParse, pFrom) ){
+ if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){
return WRC_Abort;
}
}
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
- if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+ if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){
return WRC_Abort;
}
@@ -4953,10 +5350,9 @@ static int selectExpander(Walker *pWalker, Select *p){
*/
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
- a[k].zName = 0;
- a[k].zSpan = 0;
+ pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
+ pNew->a[pNew->nExpr-1].eEName = a[k].eEName;
+ a[k].zEName = 0;
}
a[k].pExpr = 0;
}else{
@@ -4995,7 +5391,7 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( zName );
if( zTName && pSub
- && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
+ && sqlite3MatchEName(&pSub->pEList->a[j], 0, zTName, 0)==0
){
continue;
}
@@ -5005,7 +5401,7 @@ static int selectExpander(Walker *pWalker, Select *p){
** bit set.
*/
if( (p->selFlags & SF_IncludeHidden)==0
- && IsHiddenColumn(&pTab->aCol[j])
+ && IsHiddenColumn(&pTab->aCol[j])
){
continue;
}
@@ -5013,9 +5409,9 @@ static int selectExpander(Walker *pWalker, Select *p){
if( i>0 && zTName==0 ){
if( (pFrom->fg.jointype & JT_NATURAL)!=0
- && tableAndColumnIndex(pTabList, i, zName, 0, 0)
+ && tableAndColumnIndex(pTabList, i, zName, 0, 0, 1)
){
- /* In a NATURAL join, omit the join columns from the
+ /* In a NATURAL join, omit the join columns from the
** table to the right of the join */
continue;
}
@@ -5046,17 +5442,18 @@ static int selectExpander(Walker *pWalker, Select *p){
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
sqlite3TokenInit(&sColname, zColname);
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
- if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
+ if( pNew && (p->selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+ sqlite3DbFree(db, pX->zEName);
if( pSub ){
- pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
- testcase( pX->zSpan==0 );
+ pX->zEName = sqlite3DbStrDup(db, pSub->pEList->a[j].zEName);
+ testcase( pX->zEName==0 );
}else{
- pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
+ pX->zEName = sqlite3MPrintf(db, "%s.%s.%s",
zSchemaName, zTabName, zColname);
- testcase( pX->zSpan==0 );
+ testcase( pX->zEName==0 );
}
- pX->bSpanIsTab = 1;
+ pX->eEName = ENAME_TAB;
}
sqlite3DbFree(db, zToFree);
}
@@ -5085,29 +5482,6 @@ static int selectExpander(Walker *pWalker, Select *p){
return WRC_Continue;
}
-/*
-** No-op routine for the parse-tree walker.
-**
-** When this routine is the Walker.xExprCallback then expression trees
-** are walked without any actions being taken at each node. Presumably,
-** when this routine is used for Walker.xExprCallback then
-** Walker.xSelectCallback is set to do something useful for every
-** subquery in the parser tree.
-*/
-int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return WRC_Continue;
-}
-
-/*
-** No-op routine for the parse-tree walker for SELECT statements.
-** subquery in the parser tree.
-*/
-int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return WRC_Continue;
-}
-
#if SQLITE_DEBUG
/*
** Always assert. This xSelectCallback2 implementation proves that the
@@ -5142,6 +5516,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
}
w.xSelectCallback = selectExpander;
w.xSelectCallback2 = selectPopWith;
+ w.eCode = 0;
sqlite3WalkSelect(&w, pSelect);
}
@@ -5164,7 +5539,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Parse *pParse;
int i;
SrcList *pTabList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
assert( p->selFlags & SF_Resolved );
if( p->selFlags & SF_HasTypeInfo ) return;
@@ -5179,7 +5554,8 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Select *pSel = pFrom->pSelect;
if( pSel ){
while( pSel->pPrior ) pSel = pSel->pPrior;
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel);
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel,
+ SQLITE_AFF_NONE);
}
}
}
@@ -5247,6 +5623,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
struct AggInfo_func *pFunc;
int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
if( nReg==0 ) return;
+ if( pParse->nErr || pParse->db->mallocFailed ) return;
#ifdef SQLITE_DEBUG
/* Verify that all AggInfo registers are within the range specified by
** AggInfo.mnReg..AggInfo.mxReg */
@@ -5263,7 +5640,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg);
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
if( pFunc->iDistinct>=0 ){
- Expr *pE = pFunc->pExpr;
+ Expr *pE = pFunc->pFExpr;
assert( !ExprHasProperty(pE, EP_xIsSelect) );
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
@@ -5287,8 +5664,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
- ExprList *pList = pF->pExpr->x.pList;
- assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
+ ExprList *pList = pF->pFExpr->x.pList;
+ assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
}
@@ -5301,7 +5678,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
-** registers i register regAcc contains 0. The caller will take care
+** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
@@ -5317,8 +5694,31 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
int nArg;
int addrNext = 0;
int regAgg;
- ExprList *pList = pF->pExpr->x.pList;
- assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
+ ExprList *pList = pF->pFExpr->x.pList;
+ assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
+ assert( !IsWindowFunc(pF->pFExpr) );
+ if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
+ Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
+ if( pAggInfo->nAccumulator
+ && (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
+ && regAcc
+ ){
+ /* If regAcc==0, there there exists some min() or max() function
+ ** without a FILTER clause that will ensure the magnet registers
+ ** are populated. */
+ if( regHit==0 ) regHit = ++pParse->nMem;
+ /* If this is the first row of the group (regAcc contains 0), clear the
+ ** "magnet" register regHit so that the accumulator registers
+ ** are populated if the FILTER clause jumps over the the
+ ** invocation of min() or max() altogether. Or, if this is not
+ ** the first row (regAcc contains 1), set the magnet register so that
+ ** the accumulators are not populated unless the min()/max() is invoked
+ ** and indicates that they should be. */
+ sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit);
+ }
+ addrNext = sqlite3VdbeMakeLabel(pParse);
+ sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL);
+ }
if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
@@ -5328,7 +5728,9 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
regAgg = 0;
}
if( pF->iDistinct>=0 ){
- addrNext = sqlite3VdbeMakeLabel(v);
+ if( addrNext==0 ){
+ addrNext = sqlite3VdbeMakeLabel(pParse);
+ }
testcase( nArg==0 ); /* Error condition */
testcase( nArg>1 ); /* Also an error */
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
@@ -5362,11 +5764,12 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
}
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
- sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
+ sqlite3ExprCode(pParse, pC->pCExpr, pC->iMem);
}
+
pAggInfo->directMode = 0;
if( addrHitTest ){
- sqlite3VdbeJumpHere(v, addrHitTest);
+ sqlite3VdbeJumpHereOrPopInst(v, addrHitTest);
}
}
@@ -5396,10 +5799,10 @@ static void explainSimpleCount(
/*
** sqlite3WalkExpr() callback used by havingToWhere().
**
-** If the node passed to the callback is a TK_AND node, return
+** If the node passed to the callback is a TK_AND node, return
** WRC_Continue to tell sqlite3WalkExpr() to iterate through child nodes.
**
-** Otherwise, return WRC_Prune. In this case, also check if the
+** Otherwise, return WRC_Prune. In this case, also check if the
** sub-expression matches the criteria for being moved to the WHERE
** clause. If so, add it to the WHERE clause and replace the sub-expression
** within the HAVING expression with a constant "1".
@@ -5407,15 +5810,15 @@ static void explainSimpleCount(
static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op!=TK_AND ){
Select *pS = pWalker->u.pSelect;
- if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
+ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
&& ExprAlwaysFalse(pExpr)==0
){
sqlite3 *db = pWalker->pParse->db;
- Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
if( pNew ){
Expr *pWhere = pS->pWhere;
SWAP(Expr, *pNew, *pExpr);
- pNew = sqlite3ExprAnd(db, pWhere, pNew);
+ pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew);
pS->pWhere = pNew;
pWalker->eCode = 1;
}
@@ -5460,25 +5863,29 @@ static void havingToWhere(Parse *pParse, Select *p){
** If it is, then return the SrcList_item for the prior view. If it is not,
** then return 0.
*/
-static struct SrcList_item *isSelfJoinView(
+static SrcItem *isSelfJoinView(
SrcList *pTabList, /* Search for self-joins in this FROM clause */
- struct SrcList_item *pThis /* Search for prior reference to this subquery */
+ SrcItem *pThis /* Search for prior reference to this subquery */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
+ assert( pThis->pSelect!=0 );
+ if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
for(pItem = pTabList->a; pItem<pThis; pItem++){
Select *pS1;
if( pItem->pSelect==0 ) continue;
if( pItem->fg.viaCoroutine ) continue;
if( pItem->zName==0 ) continue;
- if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
+ assert( pItem->pTab!=0 );
+ assert( pThis->pTab!=0 );
+ if( pItem->pTab->pSchema!=pThis->pTab->pSchema ) continue;
if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
pS1 = pItem->pSelect;
- if( pThis->pSelect->selId!=pS1->selId ){
+ if( pItem->pTab->pSchema==0 && pThis->pSelect->selId!=pS1->selId ){
/* The query flattener left two different CTE tables with identical
** names in the same FROM clause. */
continue;
}
- if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) ){
+ if( pItem->pSelect->selFlags & SF_PushDown ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -5488,6 +5895,15 @@ static struct SrcList_item *isSelfJoinView(
return 0;
}
+/*
+** Deallocate a single AggInfo object
+*/
+static void agginfoFree(sqlite3 *db, AggInfo *p){
+ sqlite3DbFree(db, p->aCol);
+ sqlite3DbFree(db, p->aFunc);
+ sqlite3DbFreeNN(db, p);
+}
+
#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
/*
** Attempt to transform a query of the form
@@ -5503,7 +5919,8 @@ static struct SrcList_item *isSelfJoinView(
** * The subquery is a UNION ALL of two or more terms
** * The subquery does not have a LIMIT clause
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
-** * The outer query is a simple count(*)
+** * The outer query is a simple count(*) with no WHERE clause or other
+** extraneous syntax.
**
** Return TRUE if the optimization is undertaken.
*/
@@ -5514,6 +5931,8 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
sqlite3 *db;
if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
+ if( p->pWhere ) return 0;
+ if( p->pGroupBy ) return 0;
pExpr = p->pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
@@ -5573,7 +5992,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */
/*
-** Generate code for the SELECT statement given in the p argument.
+** Generate code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
@@ -5599,10 +6018,10 @@ int sqlite3Select(
Expr *pWhere; /* The WHERE clause. May be NULL */
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
Expr *pHaving; /* The HAVING clause. May be NULL */
+ AggInfo *pAggInfo = 0; /* Aggregate information */
int rc = 1; /* Value to return from this function */
DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
SortCtx sSort; /* Info on how to code the ORDER BY clause */
- AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
sqlite3 *db; /* The database connection */
ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */
@@ -5614,7 +6033,6 @@ int sqlite3Select(
return 1;
}
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
- memset(&sAggInfo, 0, sizeof(sAggInfo));
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
if( sqlite3SelectTrace & 0x100 ){
@@ -5626,16 +6044,26 @@ int sqlite3Select(
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
- if( IgnorableOrderby(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
- pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
- pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo ||
- pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
- /* If ORDER BY makes no difference in the output then neither does
- ** DISTINCT so it can be removed too. */
- sqlite3ExprListDelete(db, p->pOrderBy);
- p->pOrderBy = 0;
+ if( IgnorableDistinct(pDest) ){
+ 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 ){
+#if SELECTTRACE_ENABLED
+ SELECTTRACE(1,pParse,p, ("dropping superfluous ORDER BY:\n"));
+ if( sqlite3SelectTrace & 0x100 ){
+ sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
+ }
+#endif
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
+ p->pOrderBy);
+ testcase( pParse->earlyCleanup );
+ p->pOrderBy = 0;
+ }
p->selFlags &= ~SF_Distinct;
+ p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
if( pParse->nErr || db->mallocFailed ){
@@ -5649,16 +6077,36 @@ int sqlite3Select(
}
#endif
+ /* If the SF_UpdateFrom 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
+ ** or alias is duplicated within FROM clause (pSrc->a[1..n]). */
+ if( p->selFlags & SF_UpdateFrom ){
+ SrcItem *p0 = &p->pSrc->a[0];
+ for(i=1; i<p->pSrc->nSrc; i++){
+ SrcItem *p1 = &p->pSrc->a[i];
+ if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
+ sqlite3ErrorMsg(pParse,
+ "target object/alias may not appear in FROM clause: %s",
+ p0->zAlias ? p0->zAlias : p0->pTab->zName
+ );
+ goto select_end;
+ }
+ }
+ }
+
if( pDest->eDest==SRT_Output ){
generateColumnNames(pParse, p);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( sqlite3WindowRewrite(pParse, p) ){
+ rc = sqlite3WindowRewrite(pParse, p);
+ if( rc ){
+ assert( db->mallocFailed || pParse->nErr>0 );
goto select_end;
}
#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x108 ){
+ if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5669,15 +6117,20 @@ int sqlite3Select(
memset(&sSort, 0, sizeof(sSort));
sSort.pOrderBy = p->pOrderBy;
- /* Try to various optimizations (flattening subqueries, and strength
+ /* Try to do various optimizations (flattening subqueries, and strength
** reduction of join operators) in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
Table *pTab = pItem->pTab;
+ /* The expander should have already created transient Table objects
+ ** even for FROM clause elements such as subqueries that do not correspond
+ ** to a real table */
+ assert( pTab!=0 );
+
/* Convert LEFT JOIN into JOIN if there are terms of the right table
** of the LEFT JOIN used in the WHERE clause.
*/
@@ -5740,6 +6193,7 @@ int sqlite3Select(
}
if( flattenSubquery(pParse, p, i, isAgg) ){
+ if( pParse->nErr ) goto select_end;
/* This subquery can be absorbed into its parent. */
i = -1;
}
@@ -5802,7 +6256,8 @@ int sqlite3Select(
** (2) Generate code for all sub-queries
*/
for(i=0; i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
+ SrcItem *pPrior;
SelectDest dest;
Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@@ -5825,7 +6280,7 @@ int sqlite3Select(
** assume the column name is non-NULL and segfault. The use of an empty
** string for the fake column name seems safer.
*/
- if( pItem->colUsed==0 ){
+ if( pItem->colUsed==0 && pItem->zName!=0 ){
sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
}
@@ -5835,22 +6290,19 @@ int sqlite3Select(
pSub = pItem->pSelect;
if( pSub==0 ) continue;
- /* Sometimes the code for a subquery will be generated more than
- ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
- ** for example. In that case, do not regenerate the code to manifest
- ** a view or the co-routine to implement a view. The first instance
- ** is sufficient, though the subroutine to manifest the view does need
- ** to be invoked again. */
- if( pItem->addrFillSub ){
- if( pItem->fg.viaCoroutine==0 ){
- /* The subroutine that manifests the view might be a one-time routine,
- ** or it might need to be rerun on each iteration because it
- ** encodes a correlated subquery. */
- testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once );
- sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
- }
- continue;
- }
+ /* The code for a subquery should only be generated once, though it is
+ ** technically harmless for it to be generated multiple times. The
+ ** following assert() will detect if something changes to cause
+ ** the same subquery to be coded multiple times, as a signal to the
+ ** developers to try to optimize the situation.
+ **
+ ** Update 2019-07-24:
+ ** See ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311cec40.
+ ** The dbsqlfuzz fuzzer found a case where the same subquery gets
+ ** coded twice. So this assert() now becomes a testcase(). It should
+ ** be very rare, though.
+ */
+ testcase( pItem->addrFillSub!=0 );
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@@ -5865,6 +6317,7 @@ int sqlite3Select(
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
+ && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes)
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
(pItem->fg.jointype & JT_OUTER)!=0)
){
@@ -5875,6 +6328,7 @@ int sqlite3Select(
sqlite3TreeViewSelect(0, p, 0);
}
#endif
+ assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
}else{
SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
}
@@ -5884,22 +6338,24 @@ int sqlite3Select(
/* Generate code to implement the subquery
**
- ** The subquery is implemented as a co-routine if the subquery is
- ** guaranteed to be the outer loop (so that it does not need to be
- ** computed more than once)
+ ** The subquery is implemented as a co-routine if:
+ ** (1) the subquery is guaranteed to be the outer loop (so that
+ ** it does not need to be computed more than once), and
+ ** (2) the subquery is not a CTE that should be materialized
**
- ** TODO: Are there other reasons beside (1) to use a co-routine
+ ** TODO: Are there other reasons beside (1) and (2) to use a co-routine
** implementation?
*/
if( i==0
&& (pTabList->nSrc==1
|| (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
+ && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
-
+
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
VdbeComment((v, "%s", pItem->pTab->zName));
@@ -5913,18 +6369,34 @@ int sqlite3Select(
sqlite3VdbeEndCoroutine(v, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
+ }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
+ /* This is a CTE for which materialization code has already been
+ ** generated. Invoke the subroutine to compute the materialization,
+ ** the make the pItem->iCursor be a copy of the ephemerial table that
+ ** holds the result of the materialization. */
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
+ if( pItem->iCursor!=pCteUse->iCur ){
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pCteUse->iCur);
+ }
+ pSub->nSelectRow = pCteUse->nRowEst;
+ }else if( (pPrior = isSelfJoinView(pTabList, pItem))!=0 ){
+ /* This view has already been materialized by a prior entry in
+ ** this same FROM clause. Reuse it. */
+ if( pPrior->addrFillSub ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
+ }
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
+ pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
- /* Generate a subroutine that will fill an ephemeral table with
- ** the content of this subquery. pItem->addrFillSub will point
- ** to the address of the generated subroutine. pItem->regReturn
- ** is a register allocated to hold the subroutine return address
- */
+ /* Materalize the view. If the view is not correlated, generate a
+ ** subroutine to do the materialization so that subsequent uses of
+ ** the same view can reuse the materialization. */
int topAddr;
int onceAddr = 0;
int retAddr;
- struct SrcList_item *pPrior;
- assert( pItem->addrFillSub==0 );
+ testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
@@ -5937,22 +6409,22 @@ int sqlite3Select(
}else{
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
}
- pPrior = isSelfJoinView(pTabList, pItem);
- if( pPrior ){
- sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
- assert( pPrior->pSelect!=0 );
- pSub->nSelectRow = pPrior->pSelect->nSelectRow;
- }else{
- sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
- sqlite3Select(pParse, pSub, &dest);
- }
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
+ ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
+ sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
+ if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ pCteUse->addrM9e = pItem->addrFillSub;
+ pCteUse->regRtn = pItem->regReturn;
+ pCteUse->iCur = pItem->iCursor;
+ pCteUse->nRowEst = pSub->nSelectRow;
+ }
}
if( db->mallocFailed ) goto select_end;
pParse->nHeight -= sqlite3SelectExprHeight(p);
@@ -5975,7 +6447,7 @@ int sqlite3Select(
}
#endif
- /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
+ /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
**
@@ -5985,16 +6457,20 @@ int sqlite3Select(
**
** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz
**
- ** The second form is preferred as a single index (or temp-table) may be
- ** used for both the ORDER BY and DISTINCT processing. As originally
- ** written the query must use a temp-table for at least one of the ORDER
+ ** The second form is preferred as a single index (or temp-table) may be
+ ** used for both the ORDER BY and DISTINCT processing. As originally
+ ** written the query must use a temp-table for at least one of the ORDER
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ && p->pWin==0
+#endif
){
p->selFlags &= ~SF_Distinct;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
+ p->selFlags |= SF_Aggregate;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
@@ -6038,7 +6514,7 @@ int sqlite3Select(
/* Set the limiter.
*/
- iEnd = sqlite3VdbeMakeLabel(v);
+ iEnd = sqlite3VdbeMakeLabel(pParse);
if( (p->selFlags & SF_FixedLimit)==0 ){
p->nSelectRow = 320; /* 4 billion rows */
}
@@ -6067,9 +6543,9 @@ int sqlite3Select(
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
| (p->selFlags & SF_FixedLimit);
#ifndef SQLITE_OMIT_WINDOWFUNC
- Window *pWin = p->pWin; /* Master window object (or NULL) */
+ Window *pWin = p->pWin; /* Main window object (or NULL) */
if( pWin ){
- sqlite3WindowCodeInit(pParse, pWin);
+ sqlite3WindowCodeInit(pParse, p);
}
#endif
assert( WHERE_USE_LIMIT==SF_FixedLimit );
@@ -6093,8 +6569,9 @@ int sqlite3Select(
sSort.pOrderBy = 0;
}
}
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
- /* If sorting index that was created by a prior OP_OpenEphemeral
+ /* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
** into an OP_Noop.
*/
@@ -6105,9 +6582,9 @@ int sqlite3Select(
assert( p->pEList==pEList );
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
- int addrGosub = sqlite3VdbeMakeLabel(v);
- int iCont = sqlite3VdbeMakeLabel(v);
- int iBreak = sqlite3VdbeMakeLabel(v);
+ int addrGosub = sqlite3VdbeMakeLabel(pParse);
+ int iCont = sqlite3VdbeMakeLabel(pParse);
+ int iBreak = sqlite3VdbeMakeLabel(pParse);
int regGosub = ++pParse->nMem;
sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);
@@ -6131,6 +6608,7 @@ int sqlite3Select(
/* End the database scan loop.
*/
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
}
}else{
@@ -6164,38 +6642,60 @@ int sqlite3Select(
}
assert( 66==sqlite3LogEst(100) );
if( p->nSelectRow>66 ) p->nSelectRow = 66;
+
+ /* If there is both a GROUP BY and an ORDER BY clause and they are
+ ** identical, then it may be possible to disable the ORDER BY clause
+ ** on the grounds that the GROUP BY will cause elements to come out
+ ** in the correct order. It also may not - the GROUP BY might use a
+ ** database index that causes rows to be grouped together as required
+ ** 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( 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 = sSort.pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_DESC;
+ pGroupBy->a[ii].sortFlags = sortFlags;
+ }
+ if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
+ orderByGrp = 1;
+ }
+ }
}else{
assert( 0==sqlite3LogEst(1) );
p->nSelectRow = 0;
}
- /* If there is both a GROUP BY and an ORDER BY clause and they are
- ** identical, then it may be possible to disable the ORDER BY clause
- ** on the grounds that the GROUP BY will cause elements to come out
- ** in the correct order. It also may not - the GROUP BY might use a
- ** database index that causes rows to be grouped together as required
- ** 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( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
- orderByGrp = 1;
- }
-
/* Create a label to jump to when we want to abort the query */
- addrEnd = sqlite3VdbeMakeLabel(v);
+ addrEnd = sqlite3VdbeMakeLabel(pParse);
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
** SELECT statement.
*/
+ pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
+ if( pAggInfo ){
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))agginfoFree, pAggInfo);
+ testcase( pParse->earlyCleanup );
+ }
+ if( db->mallocFailed ){
+ goto select_end;
+ }
+ pAggInfo->selId = p->selId;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
- sNC.uNC.pAggInfo = &sAggInfo;
+ sNC.uNC.pAggInfo = pAggInfo;
VVA_ONLY( sNC.ncFlags = NC_UAggInfo; )
- sAggInfo.mnReg = pParse->nMem+1;
- sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
- sAggInfo.pGroupBy = pGroupBy;
+ pAggInfo->mnReg = pParse->nMem+1;
+ pAggInfo->nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
+ pAggInfo->pGroupBy = pGroupBy;
sqlite3ExprAnalyzeAggList(&sNC, pEList);
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
if( pHaving ){
@@ -6208,34 +6708,45 @@ int sqlite3Select(
}
sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
}
- sAggInfo.nAccumulator = sAggInfo.nColumn;
- if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){
- minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy);
+ pAggInfo->nAccumulator = pAggInfo->nColumn;
+ if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){
+ minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pFExpr, &pMinMaxOrderBy);
}else{
minMaxFlag = WHERE_ORDERBY_NORMAL;
}
- for(i=0; i<sAggInfo.nFunc; i++){
- assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
+ for(i=0; i<pAggInfo->nFunc; i++){
+ Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
sNC.ncFlags |= NC_InAggFunc;
- sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
+ sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ assert( !IsWindowFunc(pExpr) );
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter);
+ }
+#endif
sNC.ncFlags &= ~NC_InAggFunc;
}
- sAggInfo.mxReg = pParse->nMem;
+ pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
int ii;
- SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
+ SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0);
- for(ii=0; ii<sAggInfo.nColumn; ii++){
+ if( minMaxFlag ){
+ sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag);
+ sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
+ }
+ for(ii=0; ii<pAggInfo->nColumn; ii++){
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
- ii, sAggInfo.aCol[ii].iMem);
- sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
+ ii, pAggInfo->aCol[ii].iMem);
+ sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0);
}
- for(ii=0; ii<sAggInfo.nFunc; ii++){
+ for(ii=0; ii<pAggInfo->nFunc; ii++){
sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
- ii, sAggInfo.aFunc[ii].iMem);
- sqlite3TreeViewExpr(0, sAggInfo.aFunc[ii].pExpr, 0);
+ ii, pAggInfo->aFunc[ii].iMem);
+ sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0);
}
}
#endif
@@ -6258,12 +6769,13 @@ int sqlite3Select(
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
** that we do not need it after all, the OP_SorterOpen instruction
- ** will be converted into a Noop.
+ ** will be converted into a Noop.
*/
- sAggInfo.sortingIdx = pParse->nTab++;
- pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn);
- addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
- sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
+ pAggInfo->sortingIdx = pParse->nTab++;
+ pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pGroupBy,
+ 0, pAggInfo->nColumn);
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
+ pAggInfo->sortingIdx, pAggInfo->nSortingColumn,
0, (char*)pKeyInfo, P4_KEYINFO);
/* Initialize memory locations used by GROUP BY aggregate processing
@@ -6271,9 +6783,9 @@ int sqlite3Select(
iUseFlag = ++pParse->nMem;
iAbortFlag = ++pParse->nMem;
regOutputRow = ++pParse->nMem;
- addrOutputRow = sqlite3VdbeMakeLabel(v);
+ addrOutputRow = sqlite3VdbeMakeLabel(pParse);
regReset = ++pParse->nMem;
- addrReset = sqlite3VdbeMakeLabel(v);
+ addrReset = sqlite3VdbeMakeLabel(pParse);
iAMem = pParse->nMem + 1;
pParse->nMem += pGroupBy->nExpr;
iBMem = pParse->nMem + 1;
@@ -6293,6 +6805,7 @@ int sqlite3Select(
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
);
if( pWInfo==0 ) goto select_end;
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
@@ -6310,7 +6823,7 @@ int sqlite3Select(
int nCol;
int nGroupBy;
- explainTempTable(pParse,
+ explainTempTable(pParse,
(sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
"DISTINCT" : "GROUP BY");
@@ -6318,8 +6831,8 @@ int sqlite3Select(
nGroupBy = pGroupBy->nExpr;
nCol = nGroupBy;
j = nGroupBy;
- for(i=0; i<sAggInfo.nColumn; i++){
- if( sAggInfo.aCol[i].iSorterColumn>=j ){
+ for(i=0; i<pAggInfo->nColumn; i++){
+ if( pAggInfo->aCol[i].iSorterColumn>=j ){
nCol++;
j++;
}
@@ -6327,8 +6840,8 @@ int sqlite3Select(
regBase = sqlite3GetTempRange(pParse, nCol);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
j = nGroupBy;
- for(i=0; i<sAggInfo.nColumn; i++){
- struct AggInfo_col *pCol = &sAggInfo.aCol[i];
+ for(i=0; i<pAggInfo->nColumn; i++){
+ struct AggInfo_col *pCol = &pAggInfo->aCol[i];
if( pCol->iSorterColumn>=j ){
int r1 = j + regBase;
sqlite3ExprCodeGetColumnOfTable(v,
@@ -6338,16 +6851,17 @@ int sqlite3Select(
}
regRecord = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
- sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nCol);
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
- sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
+ pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++;
sortOut = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
- sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
+ sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
- sAggInfo.useSortingIdx = 1;
+ pAggInfo->useSortingIdx = 1;
}
/* If the index or temporary table used by the GROUP BY sort
@@ -6355,9 +6869,9 @@ int sqlite3Select(
** clause, cancel the ephemeral table open coded earlier.
**
** This is an optimization - the correct answer should result regardless.
- ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to
+ ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to
** disable this optimization for testing purposes. */
- if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder)
+ if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder)
&& (groupBySort || sqlite3WhereIsSorted(pWInfo))
){
sSort.pOrderBy = 0;
@@ -6371,14 +6885,14 @@ int sqlite3Select(
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
if( groupBySort ){
- sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
+ sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx,
sortOut, sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
}else{
- sAggInfo.directMode = 1;
+ pAggInfo->directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
}
}
@@ -6408,16 +6922,17 @@ int sqlite3Select(
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
- updateAccumulator(pParse, iUseFlag, &sAggInfo);
+ updateAccumulator(pParse, iUseFlag, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
/* End of the loop
*/
if( groupBySort ){
- sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
+ sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
VdbeCoverage(v);
}else{
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
@@ -6448,7 +6963,7 @@ int sqlite3Select(
VdbeCoverage(v);
VdbeComment((v, "Groupby result generator entry point"));
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- finalizeAggFunctions(pParse, &sAggInfo);
+ finalizeAggFunctions(pParse, pAggInfo);
sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
selectInnerLoop(pParse, p, -1, &sSort,
&sDistinct, pDest,
@@ -6459,16 +6974,15 @@ int sqlite3Select(
/* Generate a subroutine that will reset the group-by accumulator
*/
sqlite3VdbeResolveLabel(v, addrReset);
- resetAccumulator(pParse, &sAggInfo);
+ resetAccumulator(pParse, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
-
+
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
-#ifndef SQLITE_OMIT_BTREECOUNT
Table *pTab;
- if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
+ if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
/* If isSimpleCount() returns a pointer to a Table structure, then
** the SQL statement is of the form:
**
@@ -6487,7 +7001,7 @@ int sqlite3Select(
Index *pIdx; /* Iterator variable */
KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */
Index *pBest = 0; /* Best index found so far */
- int iRoot = pTab->tnum; /* Root page of scanned b-tree */
+ Pgno iRoot = pTab->tnum; /* Root page of scanned b-tree */
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -6498,17 +7012,19 @@ int sqlite3Select(
**
** (2013-10-03) Do not count the entries in a partial index.
**
- ** In practice the KeyInfo structure will not be used. It is only
+ ** In practice the KeyInfo structure will not be used. It is only
** passed to keep OP_OpenRead happy.
*/
if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->bUnordered==0
- && pIdx->szIdxRow<pTab->szTabRow
- && pIdx->pPartIdxWhere==0
- && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
- ){
- pBest = pIdx;
+ if( !p->pSrc->a[0].fg.notIndexed ){
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->bUnordered==0
+ && pIdx->szIdxRow<pTab->szTabRow
+ && pIdx->pPartIdxWhere==0
+ && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
+ ){
+ pBest = pIdx;
+ }
}
}
if( pBest ){
@@ -6517,28 +7033,35 @@ int sqlite3Select(
}
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
- sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
+ sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, (int)iRoot, iDb, 1);
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
}
- sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
+ sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
- }else
-#endif /* SQLITE_OMIT_BTREECOUNT */
- {
+ }else{
int regAcc = 0; /* "populate accumulators" flag */
- /* If there are accumulator registers but no min() or max() functions,
- ** allocate register regAcc. Register regAcc will contain 0 the first
- ** time the inner loop runs, and 1 thereafter. The code generated
- ** by updateAccumulator() only updates the accumulator registers if
- ** regAcc contains 0. */
- if( sAggInfo.nAccumulator ){
- for(i=0; i<sAggInfo.nFunc; i++){
- if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
+ /* If there are accumulator registers but no min() or max() functions
+ ** without FILTER clauses, allocate register regAcc. Register regAcc
+ ** will contain 0 the first time the inner loop runs, and 1 thereafter.
+ ** The code generated by updateAccumulator() uses this to ensure
+ ** that the accumulator registers are (a) updated only once if
+ ** there are no min() or max functions or (b) always updated for the
+ ** first row visited by the aggregate, so that they are updated at
+ ** least once even if the FILTER clause means the min() or max()
+ ** function visits zero rows. */
+ if( pAggInfo->nAccumulator ){
+ for(i=0; i<pAggInfo->nFunc; i++){
+ if( ExprHasProperty(pAggInfo->aFunc[i].pFExpr, EP_WinFunc) ){
+ continue;
+ }
+ if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){
+ break;
+ }
}
- if( i==sAggInfo.nFunc ){
+ if( i==pAggInfo->nFunc ){
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
@@ -6549,7 +7072,7 @@ int sqlite3Select(
** of output.
*/
assert( p->pGroupBy==0 );
- resetAccumulator(pParse, &sAggInfo);
+ resetAccumulator(pParse, pAggInfo);
/* If this query is a candidate for the min/max optimization, then
** minMaxFlag will have been previously set to either
@@ -6565,24 +7088,24 @@ int sqlite3Select(
if( pWInfo==0 ){
goto select_end;
}
- updateAccumulator(pParse, regAcc, &sAggInfo);
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
+ updateAccumulator(pParse, regAcc, pAggInfo);
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
- if( sqlite3WhereIsOrdered(pWInfo)>0 ){
- sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
- VdbeComment((v, "%s() by index",
- (minMaxFlag==WHERE_ORDERBY_MIN?"min":"max")));
+ if( minMaxFlag ){
+ sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
}
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
- finalizeAggFunctions(pParse, &sAggInfo);
+ finalizeAggFunctions(pParse, pAggInfo);
}
sSort.pOrderBy = 0;
sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, -1, 0, 0,
+ selectInnerLoop(pParse, p, -1, 0, 0,
pDest, addrEnd, addrEnd);
}
sqlite3VdbeResolveLabel(v, addrEnd);
-
+
} /* endif aggregate query */
if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
@@ -6612,8 +7135,23 @@ int sqlite3Select(
*/
select_end:
sqlite3ExprListDelete(db, pMinMaxOrderBy);
- sqlite3DbFree(db, sAggInfo.aCol);
- sqlite3DbFree(db, sAggInfo.aFunc);
+#ifdef SQLITE_DEBUG
+ if( pAggInfo && !db->mallocFailed ){
+ for(i=0; i<pAggInfo->nColumn; i++){
+ Expr *pExpr = pAggInfo->aCol[i].pCExpr;
+ assert( pExpr!=0 );
+ assert( pExpr->pAggInfo==pAggInfo );
+ assert( pExpr->iAgg==i );
+ }
+ for(i=0; i<pAggInfo->nFunc; i++){
+ Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
+ assert( pExpr!=0 );
+ assert( pExpr->pAggInfo==pAggInfo );
+ assert( pExpr->iAgg==i );
+ }
+ }
+#endif
+
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
diff --git a/chromium/third_party/sqlite/src/src/update.c b/chromium/third_party/sqlite/src/src/update.c
index b328d3b229b..d22fd683e39 100644
--- a/chromium/third_party/sqlite/src/src/update.c
+++ b/chromium/third_party/sqlite/src/src/update.c
@@ -30,10 +30,10 @@ static void updateVirtualTable(
/*
** The most recently coded instruction was an OP_Column to retrieve the
-** i-th column of table pTab. This routine sets the P4 parameter of the
+** i-th column of table pTab. This routine sets the P4 parameter of the
** OP_Column to the default value, if any.
**
-** The default value of a column is specified by a DEFAULT clause in the
+** The default value of a column is specified by a DEFAULT clause in the
** column definition. This was either supplied by the user when the table
** was created, or added later to the table definition by an ALTER TABLE
** command. If the latter, then the row-records in the table btree on disk
@@ -42,21 +42,21 @@ static void updateVirtualTable(
** If the former, then all row-records are guaranteed to include a value
** for the column and the P4 value is not required.
**
-** Column definitions created by an ALTER TABLE command may only have
+** Column definitions created by an ALTER TABLE command may only have
** literal default values specified: a number, null or a string. (If a more
-** complicated default expression value was provided, it is evaluated
+** complicated default expression value was provided, it is evaluated
** when the ALTER TABLE is executed and one of the literal values written
-** into the sqlite_master table.)
+** into the sqlite_schema table.)
**
** Therefore, the P4 parameter is only required if the default value for
** the column is a literal number, string or null. The sqlite3ValueFromExpr()
** function is capable of transforming these types of expressions into
** sqlite3_value objects.
**
-** If parameter iReg is not negative, code an OP_RealAffinity instruction
-** on register iReg. This is used when an equivalent integer value is
-** stored in place of an 8-byte floating point value in order to save
-** space.
+** If column as REAL affinity and the table is an ordinary b-tree table
+** (not a virtual table) then the value might have been stored as an
+** integer. In that case, add an OP_RealAffinity opcode to make sure
+** it has been converted into REAL.
*/
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
assert( pTab!=0 );
@@ -66,14 +66,14 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
Column *pCol = &pTab->aCol[i];
VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
assert( i<pTab->nCol );
- sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
+ sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
pCol->affinity, &pValue);
if( pValue ){
sqlite3VdbeAppendP4(v, pValue, P4_MEM);
}
}
#ifndef SQLITE_OMIT_FLOATING_POINT
- if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
+ if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
@@ -131,11 +131,152 @@ static int indexWhereClauseMightChange(
}
/*
+** Allocate and return a pointer to an expression of type TK_ROW with
+** Expr.iColumn set to value (iCol+1). The resolver will modify the
+** expression to be a TK_COLUMN reading column iCol of the first
+** table in the source-list (pSrc->a[0]).
+*/
+static Expr *exprRowColumn(Parse *pParse, int iCol){
+ Expr *pRet = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ if( pRet ) pRet->iColumn = iCol+1;
+ return pRet;
+}
+
+/*
+** Assuming both the pLimit and pOrderBy parameters are NULL, this function
+** generates VM code to run the query:
+**
+** SELECT <other-columns>, pChanges FROM pTabList WHERE pWhere
+**
+** and write the results to the ephemeral table already opened as cursor
+** iEph. None of pChanges, pTabList or pWhere are modified or consumed by
+** this function, they must be deleted by the caller.
+**
+** Or, if pLimit and pOrderBy are not NULL, and pTab is not a view:
+**
+** SELECT <other-columns>, pChanges FROM pTabList
+** WHERE pWhere
+** GROUP BY <other-columns>
+** ORDER BY pOrderBy LIMIT pLimit
+**
+** If pTab is a view, the GROUP BY clause is omitted.
+**
+** Exactly how results are written to table iEph, and exactly what
+** the <other-columns> in the query above are is determined by the type
+** of table pTabList->a[0].pTab.
+**
+** If the table is a WITHOUT ROWID table, then argument pPk must be its
+** PRIMARY KEY. In this case <other-columns> are the primary key columns
+** of the table, in order. The results of the query are written to ephemeral
+** table iEph as index keys, using OP_IdxInsert.
+**
+** If the table is actually a view, then <other-columns> are all columns of
+** the view. The results are written to the ephemeral table iEph as records
+** with automatically assigned integer keys.
+**
+** If the table is a virtual or ordinary intkey table, then <other-columns>
+** is its rowid. For a virtual table, the results are written to iEph as
+** records with automatically assigned integer keys For intkey tables, the
+** rowid value in <other-columns> is used as the integer key, and the
+** remaining fields make up the table record.
+*/
+static void updateFromSelect(
+ Parse *pParse, /* Parse context */
+ int iEph, /* Cursor for open eph. table */
+ Index *pPk, /* PK if table 0 is WITHOUT ROWID */
+ ExprList *pChanges, /* List of expressions to return */
+ SrcList *pTabList, /* List of tables to select from */
+ Expr *pWhere, /* WHERE clause for query */
+ ExprList *pOrderBy, /* ORDER BY clause */
+ Expr *pLimit /* LIMIT clause */
+){
+ int i;
+ SelectDest dest;
+ Select *pSelect = 0;
+ ExprList *pList = 0;
+ ExprList *pGrp = 0;
+ Expr *pLimit2 = 0;
+ ExprList *pOrderBy2 = 0;
+ sqlite3 *db = pParse->db;
+ Table *pTab = pTabList->a[0].pTab;
+ SrcList *pSrc;
+ Expr *pWhere2;
+ int eDest;
+
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ if( pOrderBy && pLimit==0 ) {
+ sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on UPDATE");
+ return;
+ }
+ pOrderBy2 = sqlite3ExprListDup(db, pOrderBy, 0);
+ pLimit2 = sqlite3ExprDup(db, pLimit, 0);
+#else
+ UNUSED_PARAMETER(pOrderBy);
+ UNUSED_PARAMETER(pLimit);
+#endif
+
+ pSrc = sqlite3SrcListDup(db, pTabList, 0);
+ pWhere2 = sqlite3ExprDup(db, pWhere, 0);
+
+ assert( pTabList->nSrc>1 );
+ if( pSrc ){
+ if( pSrc->a[0].zDatabase==0 ){
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
+ }
+ pSrc->a[0].iCursor = -1;
+ pSrc->a[0].pTab->nTabRef--;
+ pSrc->a[0].pTab = 0;
+ }
+ if( pPk ){
+ for(i=0; i<pPk->nKeyCol; i++){
+ Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]);
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ if( pLimit ){
+ pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
+ }
+#endif
+ pList = sqlite3ExprListAppend(pParse, pList, pNew);
+ }
+ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
+ }else if( pTab->pSelect ){
+ for(i=0; i<pTab->nCol; i++){
+ pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
+ }
+ eDest = SRT_Table;
+ }else{
+ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
+ pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ if( pLimit ){
+ pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
+ }
+#endif
+ }
+ if( ALWAYS(pChanges) ){
+ for(i=0; i<pChanges->nExpr; i++){
+ pList = sqlite3ExprListAppend(pParse, pList,
+ sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
+ );
+ }
+ }
+ pSelect = sqlite3SelectNew(pParse, pList,
+ pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UpdateFrom|SF_IncludeHidden, pLimit2
+ );
+ sqlite3SelectDestInit(&dest, eDest, iEph);
+ dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
+ sqlite3Select(pParse, pSelect, &dest);
+ sqlite3SelectDelete(db, pSelect);
+}
+
+/*
** Process an UPDATE statement.
**
-** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
-** \_______/ \________/ \______/ \________________/
-* onError pTabList pChanges pWhere
+** UPDATE OR IGNORE tbl SET a=b, c=d FROM tbl2... WHERE e<5 AND f NOT NULL;
+** \_______/ \_/ \______/ \_____/ \________________/
+** onError | pChanges | pWhere
+** \_______________________/
+** pTabList
*/
void sqlite3Update(
Parse *pParse, /* The parser context */
@@ -147,19 +288,20 @@ void sqlite3Update(
Expr *pLimit, /* LIMIT clause. May be null */
Upsert *pUpsert /* ON CONFLICT clause, or null */
){
- int i, j; /* Loop counters */
+ int i, j, k; /* Loop counters */
Table *pTab; /* The table to be updated */
int addrTop = 0; /* VDBE instruction address of the start of the loop */
- WhereInfo *pWInfo; /* Information about the WHERE clause */
+ WhereInfo *pWInfo = 0; /* Information about the WHERE clause */
Vdbe *v; /* The virtual database engine */
Index *pIdx; /* For looping over indices */
Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
int nIdx; /* Number of indices that need updating */
+ int nAllIdx; /* Total number of indexes */
int iBaseCur; /* Base cursor number */
int iDataCur; /* Cursor for the canonical data btree */
int iIdxCur; /* Cursor for the first index */
sqlite3 *db; /* The database structure */
- int *aRegIdx = 0; /* First register in array assigned to each index */
+ int *aRegIdx = 0; /* Registers for to each index and the main table */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
@@ -168,6 +310,7 @@ void sqlite3Update(
u8 chngRowid; /* Rowid changed in a normal table */
u8 chngKey; /* Either chngPk or chngRowid */
Expr *pRowidExpr = 0; /* Expression defining the new record number */
+ int iRowidExpr = -1; /* Index of "rowid=" (or IPK) assignment in pChanges */
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
@@ -190,6 +333,8 @@ void sqlite3Update(
int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
+ int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */
+ int nChangeFrom = 0; /* If there is a FROM, pChanges->nExpr, else 0 */
/* Register Allocations */
int regRowCount = 0; /* A count of rows changed */
@@ -205,9 +350,8 @@ void sqlite3Update(
if( pParse->nErr || db->mallocFailed ){
goto update_cleanup;
}
- assert( pTabList->nSrc==1 );
- /* Locate the table which we want to update.
+ /* Locate the table which we want to update.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
@@ -230,8 +374,15 @@ void sqlite3Update(
# define isView 0
#endif
+ /* If there was a FROM clause, set nChangeFrom to the number of expressions
+ ** in the change-list. Otherwise, set it to 0. There cannot be a FROM
+ ** clause if this function is being called to generate code for part of
+ ** an UPSERT statement. */
+ nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0;
+ assert( nChangeFrom==0 || pUpsert==0 );
+
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- if( !isView ){
+ if( !isView && nChangeFrom==0 ){
pWhere = sqlite3LimitWhere(
pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE"
);
@@ -270,13 +421,13 @@ void sqlite3Update(
}
pTabList->a[0].iCursor = iDataCur;
- /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
+ /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
** Initialize aXRef[] and aToOpen[] to their default values.
*/
- aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
+ aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx+1) + nIdx+2 );
if( aXRef==0 ) goto update_cleanup;
aRegIdx = aXRef+pTab->nCol;
- aToOpen = (u8*)(aRegIdx+nIdx);
+ aToOpen = (u8*)(aRegIdx+nIdx+1);
memset(aToOpen, 1, nIdx+1);
aToOpen[nIdx+1] = 0;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
@@ -288,6 +439,10 @@ void sqlite3Update(
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
+ /* Begin generating code. */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto update_cleanup;
+
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
@@ -296,28 +451,42 @@ void sqlite3Update(
*/
chngRowid = chngPk = 0;
for(i=0; i<pChanges->nExpr; i++){
- if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
+ /* If this is an UPDATE with a FROM clause, do not resolve expressions
+ ** here. The call to sqlite3Select() below will do that. */
+ if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
- if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
+ if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zEName)==0 ){
if( j==pTab->iPKey ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
+ iRowidExpr = i;
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
chngPk = 1;
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
+ testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
+ testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse,
+ "cannot UPDATE generated column \"%s\"",
+ pTab->aCol[j].zName);
+ goto update_cleanup;
+ }
+#endif
aXRef[j] = i;
break;
}
}
if( j>=pTab->nCol ){
- if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
+ if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
j = -1;
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
+ iRowidExpr = i;
}else{
- sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
+ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zEName);
pParse->checkSchema = 1;
goto update_cleanup;
}
@@ -341,7 +510,34 @@ void sqlite3Update(
assert( chngPk==0 || chngPk==1 );
chngKey = chngRowid + chngPk;
- /* The SET expressions are not actually used inside the WHERE loop.
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ /* Mark generated columns as changing if their generator expressions
+ ** reference any changing column. The actual aXRef[] value for
+ ** generated expressions is not used, other than to check to see that it
+ ** is non-negative, so the value of aXRef[] for generated columns can be
+ ** set to any non-negative number. We use 99999 so that the value is
+ ** obvious when looking at aXRef[] in a symbolic debugger.
+ */
+ if( pTab->tabFlags & TF_HasGenerated ){
+ int bProgress;
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ do{
+ bProgress = 0;
+ for(i=0; i<pTab->nCol; i++){
+ if( aXRef[i]>=0 ) continue;
+ if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
+ if( sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
+ aXRef, chngRowid) ){
+ aXRef[i] = 99999;
+ bProgress = 1;
+ }
+ }
+ }while( bProgress );
+ }
+#endif
+
+ /* The SET expressions are not actually used inside the WHERE loop.
** So reset the colUsed mask. Unless this is a virtual table. In that
** case, set all bits of the colUsed mask (to ensure that the virtual
** table implementation makes all columns available).
@@ -354,7 +550,8 @@ void sqlite3Update(
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
*/
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ if( onError==OE_Replace ) bReplace = 1;
+ for(nAllIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nAllIdx++){
int reg;
if( chngKey || hasFK>1 || pIdx==pPk
|| indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
@@ -367,33 +564,35 @@ void sqlite3Update(
if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
- if( (onError==OE_Replace)
- || (onError==OE_Default && pIdx->onError==OE_Replace)
- ){
+ if( onError==OE_Default && pIdx->onError==OE_Replace ){
bReplace = 1;
}
break;
}
}
}
- if( reg==0 ) aToOpen[j+1] = 0;
- aRegIdx[j] = reg;
+ if( reg==0 ) aToOpen[nAllIdx+1] = 0;
+ aRegIdx[nAllIdx] = reg;
}
+ aRegIdx[nAllIdx] = ++pParse->nMem; /* Register storing the table record */
if( bReplace ){
- /* If REPLACE conflict resolution might be invoked, open cursors on all
+ /* If REPLACE conflict resolution might be invoked, open cursors on all
** indexes in case they are needed to delete records. */
memset(aToOpen, 1, nIdx+1);
}
- /* Begin generating code. */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto update_cleanup;
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);
/* Allocate required registers. */
if( !IsVirtual(pTab) ){
- regRowSet = ++pParse->nMem;
+ /* For now, regRowSet and aRegIdx[nAllIdx] share the same register.
+ ** If regRowSet turns out to be needed, then aRegIdx[nAllIdx] will be
+ ** reallocated. aRegIdx[nAllIdx] is the register in which the main
+ ** table record is written. regRowSet holds the RowSet for the
+ ** two-pass update algorithm. */
+ assert( aRegIdx[nAllIdx]==pParse->nMem );
+ regRowSet = aRegIdx[nAllIdx];
regOldRowid = regNewRowid = ++pParse->nMem;
if( chngPk || pTrigger || hasFK ){
regOld = pParse->nMem + 1;
@@ -415,8 +614,8 @@ void sqlite3Update(
** an ephemeral table.
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
- if( isView ){
- sqlite3MaterializeView(pParse, pTab,
+ if( nChangeFrom==0 && isView ){
+ sqlite3MaterializeView(pParse, pTab,
pWhere, pOrderBy, pLimit, iDataCur
);
pOrderBy = 0;
@@ -427,7 +626,7 @@ void sqlite3Update(
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
- if( sqlite3ResolveExprNames(&sNC, pWhere) ){
+ if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pWhere) ){
goto update_cleanup;
}
@@ -441,133 +640,167 @@ void sqlite3Update(
#endif
/* Jump to labelBreak to abandon further processing of this UPDATE */
- labelContinue = labelBreak = sqlite3VdbeMakeLabel(v);
+ labelContinue = labelBreak = sqlite3VdbeMakeLabel(pParse);
/* Not an UPSERT. Normal processing. Begin by
** initialize the count of updated rows */
if( (db->flags&SQLITE_CountRows)!=0
&& !pParse->pTriggerTab
&& !pParse->nested
+ && !pParse->bReturning
&& pUpsert==0
){
regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
}
- if( HasRowid(pTab) ){
+ if( nChangeFrom==0 && HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
+ iEph = pParse->nTab++;
+ addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet);
}else{
- assert( pPk!=0 );
- nPk = pPk->nKeyCol;
+ assert( pPk!=0 || HasRowid(pTab) );
+ nPk = pPk ? pPk->nKeyCol : 0;
iPk = pParse->nMem+1;
pParse->nMem += nPk;
+ pParse->nMem += nChangeFrom;
regKey = ++pParse->nMem;
if( pUpsert==0 ){
+ int nEphCol = nPk + nChangeFrom + (isView ? pTab->nCol : 0);
iEph = pParse->nTab++;
- sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
- addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
- sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+ if( pPk ) sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
+ addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nEphCol);
+ if( pPk ){
+ KeyInfo *pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pPk);
+ if( pKeyInfo ){
+ pKeyInfo->nAllField = nEphCol;
+ sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
+ }
+ }
+ if( nChangeFrom ){
+ updateFromSelect(
+ pParse, iEph, pPk, pChanges, pTabList, pWhere, pOrderBy, pLimit
+ );
+#ifndef SQLITE_OMIT_SUBQUERY
+ if( isView ) iDataCur = iEph;
+#endif
+ }
}
}
-
- if( pUpsert ){
- /* If this is an UPSERT, then all cursors have already been opened by
- ** the outer INSERT and the data cursor should be pointing at the row
- ** that is to be updated. So bypass the code that searches for the
- ** row(s) to be updated.
- */
- pWInfo = 0;
- eOnePass = ONEPASS_SINGLE;
- sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
+
+ if( nChangeFrom ){
+ sqlite3MultiWrite(pParse);
+ eOnePass = ONEPASS_OFF;
+ nKey = nPk;
+ regKey = iPk;
}else{
- /* Begin the database scan.
- **
- ** Do not consider a single-pass strategy for a multi-row update if
- ** there are any triggers or foreign keys to process, or rows may
- ** be deleted as a result of REPLACE conflict handling. Any of these
- ** things might disturb a cursor being used to scan through the table
- ** or index, causing a single-pass approach to malfunction. */
- flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
- if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
- flags |= WHERE_ONEPASS_MULTIROW;
- }
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur);
- if( pWInfo==0 ) goto update_cleanup;
-
- /* A one-pass strategy that might update more than one row may not
- ** be used if any column of the index used for the scan is being
- ** updated. Otherwise, if there is an index on "b", statements like
- ** the following could create an infinite loop:
- **
- ** UPDATE t1 SET b=b+1 WHERE b>?
- **
- ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
- ** strategy that uses an index for which one or more columns are being
- ** updated. */
- eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
- if( eOnePass!=ONEPASS_SINGLE ){
- sqlite3MultiWrite(pParse);
- if( eOnePass==ONEPASS_MULTI ){
- int iCur = aiCurOnePass[1];
- if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
- eOnePass = ONEPASS_OFF;
+ if( pUpsert ){
+ /* If this is an UPSERT, then all cursors have already been opened by
+ ** the outer INSERT and the data cursor should be pointing at the row
+ ** that is to be updated. So bypass the code that searches for the
+ ** row(s) to be updated.
+ */
+ pWInfo = 0;
+ eOnePass = ONEPASS_SINGLE;
+ sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
+ bFinishSeek = 0;
+ }else{
+ /* Begin the database scan.
+ **
+ ** Do not consider a single-pass strategy for a multi-row update if
+ ** there are any triggers or foreign keys to process, or rows may
+ ** be deleted as a result of REPLACE conflict handling. Any of these
+ ** things might disturb a cursor being used to scan through the table
+ ** or index, causing a single-pass approach to malfunction. */
+ flags = WHERE_ONEPASS_DESIRED;
+ if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
+ flags |= WHERE_ONEPASS_MULTIROW;
+ }
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags,iIdxCur);
+ if( pWInfo==0 ) goto update_cleanup;
+
+ /* A one-pass strategy that might update more than one row may not
+ ** be used if any column of the index used for the scan is being
+ ** updated. Otherwise, if there is an index on "b", statements like
+ ** the following could create an infinite loop:
+ **
+ ** UPDATE t1 SET b=b+1 WHERE b>?
+ **
+ ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
+ ** strategy that uses an index for which one or more columns are being
+ ** updated. */
+ eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+ bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo);
+ if( eOnePass!=ONEPASS_SINGLE ){
+ sqlite3MultiWrite(pParse);
+ if( eOnePass==ONEPASS_MULTI ){
+ int iCur = aiCurOnePass[1];
+ if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
+ eOnePass = ONEPASS_OFF;
+ }
+ assert( iCur!=iDataCur || !HasRowid(pTab) );
}
- assert( iCur!=iDataCur || !HasRowid(pTab) );
}
}
- }
- if( HasRowid(pTab) ){
- /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
- ** mode, write the rowid into the FIFO. In either of the one-pass modes,
- ** leave it in register regOldRowid. */
- sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
- if( eOnePass==ONEPASS_OFF ){
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
- }
- }else{
- /* Read the PK of the current row into an array of registers. In
- ** ONEPASS_OFF mode, serialize the array into a record and store it in
- ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
- ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table
- ** is not required) and leave the PK fields in the array of registers. */
- for(i=0; i<nPk; i++){
- assert( pPk->aiColumn[i]>=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
- }
- if( eOnePass ){
- if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
- nKey = nPk;
- regKey = iPk;
+ if( HasRowid(pTab) ){
+ /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
+ ** mode, write the rowid into the FIFO. In either of the one-pass modes,
+ ** leave it in register regOldRowid. */
+ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
+ if( eOnePass==ONEPASS_OFF ){
+ aRegIdx[nAllIdx] = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid);
+ }else{
+ if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen);
+ }
}else{
- sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
- sqlite3IndexAffinityStr(db, pPk), nPk);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
+ /* Read the PK of the current row into an array of registers. In
+ ** ONEPASS_OFF mode, serialize the array into a record and store it in
+ ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
+ ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table
+ ** is not required) and leave the PK fields in the array of registers. */
+ for(i=0; i<nPk; i++){
+ assert( pPk->aiColumn[i]>=0 );
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,
+ pPk->aiColumn[i], iPk+i);
+ }
+ if( eOnePass ){
+ if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
+ nKey = nPk;
+ regKey = iPk;
+ }else{
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
+ sqlite3IndexAffinityStr(db, pPk), nPk);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
+ }
}
}
if( pUpsert==0 ){
- if( eOnePass!=ONEPASS_MULTI ){
+ if( nChangeFrom==0 && eOnePass!=ONEPASS_MULTI ){
sqlite3WhereEnd(pWInfo);
}
-
+
if( !isView ){
int addrOnce = 0;
-
+
/* Open every index that needs updating. */
if( eOnePass!=ONEPASS_OFF ){
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
}
-
+
if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur,
aToOpen, 0, 0);
- if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
+ if( addrOnce ){
+ sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
+ }
}
-
+
/* Top of the update loop */
if( eOnePass!=ONEPASS_OFF ){
if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
@@ -576,20 +809,40 @@ void sqlite3Update(
VdbeCoverage(v);
}
if( eOnePass!=ONEPASS_SINGLE ){
- labelContinue = sqlite3VdbeMakeLabel(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
}
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
VdbeCoverageIf(v, pPk==0);
VdbeCoverageIf(v, pPk!=0);
- }else if( pPk ){
- labelContinue = sqlite3VdbeMakeLabel(v);
+ }else if( pPk || nChangeFrom ){
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
- addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
- VdbeCoverage(v);
+ addrTop = sqlite3VdbeCurrentAddr(v);
+ if( nChangeFrom ){
+ if( !isView ){
+ if( pPk ){
+ for(i=0; i<nPk; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, iEph, i, iPk+i);
+ }
+ sqlite3VdbeAddOp4Int(
+ v, OP_NotFound, iDataCur, labelContinue, iPk, nPk
+ ); VdbeCoverage(v);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
+ sqlite3VdbeAddOp3(
+ v, OP_NotExists, iDataCur, labelContinue, regOldRowid
+ ); VdbeCoverage(v);
+ }
+ }
+ }else{
+ sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey,0);
+ VdbeCoverage(v);
+ }
}else{
- labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak,
- regOldRowid);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
VdbeCoverage(v);
@@ -602,7 +855,12 @@ void sqlite3Update(
** already populated. */
assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid );
if( chngRowid ){
- sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
+ assert( iRowidExpr>=0 );
+ if( nChangeFrom==0 ){
+ sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_Column, iEph, iRowidExpr, regNewRowid);
+ }
sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v);
}
@@ -610,18 +868,20 @@ void sqlite3Update(
** information is needed */
if( chngPk || hasFK || pTrigger ){
u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
- oldmask |= sqlite3TriggerColmask(pParse,
+ oldmask |= sqlite3TriggerColmask(pParse,
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
);
for(i=0; i<pTab->nCol; i++){
+ u32 colFlags = pTab->aCol[i].colFlags;
+ k = sqlite3TableColumnToStorage(pTab, i) + regOld;
if( oldmask==0xffffffff
|| (i<32 && (oldmask & MASKBIT32(i))!=0)
- || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
+ || (colFlags & COLFLAG_PRIMKEY)!=0
){
testcase( oldmask!=0xffffffff && i==31 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
}else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
}
}
if( chngRowid==0 && pPk==0 ){
@@ -637,104 +897,142 @@ void sqlite3Update(
** If there are one or more BEFORE triggers, then do not populate the
** registers associated with columns that are (a) not modified by
** this UPDATE statement and (b) not accessed by new.* references. The
- ** values for registers not modified by the UPDATE must be reloaded from
- ** the database after the BEFORE triggers are fired anyway (as the trigger
+ ** values for registers not modified by the UPDATE must be reloaded from
+ ** the database after the BEFORE triggers are fired anyway (as the trigger
** may have modified them). So not loading those that are not going to
** be used eliminates some redundant opcodes.
*/
newmask = sqlite3TriggerColmask(
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
);
- for(i=0; i<pTab->nCol; i++){
+ for(i=0, k=regNew; i<pTab->nCol; i++, k++){
if( i==pTab->iPKey ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
+ }else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
}else{
j = aXRef[i];
if( j>=0 ){
- sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
+ if( nChangeFrom ){
+ int nOff = (isView ? pTab->nCol : nPk);
+ assert( eOnePass==ONEPASS_OFF );
+ sqlite3VdbeAddOp3(v, OP_Column, iEph, nOff+j, k);
+ }else{
+ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k);
+ }
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
- /* This branch loads the value of a column that will not be changed
+ /* This branch loads the value of a column that will not be changed
** into a register. This is done if there are no BEFORE triggers, or
** if there are one or more BEFORE triggers that use this value via
** a new.* reference in a trigger program.
*/
testcase( i==31 );
testcase( i==32 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
+ bFinishSeek = 0;
}else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
}
}
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pTab->tabFlags & TF_HasGenerated ){
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
+ }
+#endif
/* Fire any BEFORE UPDATE triggers. This happens before constraints are
** verified. One could argue that this is wrong.
*/
if( tmask&TRIGGER_BEFORE ){
sqlite3TableAffinity(v, pTab, regNew);
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);
- /* The row-trigger may have deleted the row being updated. In this
- ** case, jump to the next row. No updates or AFTER triggers are
- ** required. This behavior - what happens when the row being updated
- ** is deleted or renamed by a BEFORE trigger - is left undefined in the
- ** documentation.
- */
- if( pPk ){
- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey);
- VdbeCoverage(v);
- }else{
- sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
- VdbeCoverage(v);
- }
+ if( !isView ){
+ /* The row-trigger may have deleted the row being updated. In this
+ ** case, jump to the next row. No updates or AFTER triggers are
+ ** required. This behavior - what happens when the row being updated
+ ** is deleted or renamed by a BEFORE trigger - is left undefined in the
+ ** documentation.
+ */
+ if( pPk ){
+ sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
+ VdbeCoverage(v);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
+ VdbeCoverage(v);
+ }
- /* After-BEFORE-trigger-reload-loop:
- ** If it did not delete it, the BEFORE trigger may still have modified
- ** some of the columns of the row being updated. Load the values for
- ** all columns not modified by the update statement into their registers
- ** in case this has happened. Only unmodified columns are reloaded.
- ** The values computed for modified columns use the values before the
- ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
- ** for an example.
- */
- for(i=0; i<pTab->nCol; i++){
- if( aXRef[i]<0 && i!=pTab->iPKey ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
+ /* After-BEFORE-trigger-reload-loop:
+ ** If it did not delete it, the BEFORE trigger may still have modified
+ ** some of the columns of the row being updated. Load the values for
+ ** all columns not modified by the update statement into their registers
+ ** in case this has happened. Only unmodified columns are reloaded.
+ ** The values computed for modified columns use the values before the
+ ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
+ ** for an example.
+ */
+ for(i=0, k=regNew; i<pTab->nCol; i++, k++){
+ if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
+ }else if( aXRef[i]<0 && i!=pTab->iPKey ){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
+ }
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pTab->tabFlags & TF_HasGenerated ){
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
+ }
+#endif
}
}
if( !isView ){
- int addr1 = 0; /* Address of jump instruction */
-
/* Do constraint checks. */
assert( regOldRowid>0 );
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,
aXRef, 0);
- /* Do FK constraint checks. */
- if( hasFK ){
- sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
- }
-
- /* Delete the index entries associated with the current record. */
+ /* If REPLACE conflict handling may have been used, or if the PK of the
+ ** row is changing, then the GenerateConstraintChecks() above may have
+ ** moved cursor iDataCur. Reseek it. */
if( bReplace || chngKey ){
if( pPk ){
- addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
}else{
- addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
}
VdbeCoverageNeverTaken(v);
}
+
+ /* Do FK constraint checks. */
+ if( hasFK ){
+ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
+ }
+
+ /* Delete the index entries associated with the current record. */
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
+ /* We must run the OP_FinishSeek opcode to resolve a prior
+ ** OP_DeferredSeek if there is any possibility that there have been
+ ** no OP_Column opcodes since the OP_DeferredSeek was issued. But
+ ** we want to avoid the OP_FinishSeek if possible, as running it
+ ** costs CPU cycles. */
+ if( bFinishSeek ){
+ sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur);
+ }
+
/* If changing the rowid value, or if there are foreign key constraints
** to process, delete the old record. Otherwise, add a noop OP_Delete
** to invoke the pre-update hook.
**
- ** That (regNew==regnewRowid+1) is true is also important for the
+ ** That (regNew==regnewRowid+1) is true is also important for the
** pre-update hook. If the caller invokes preupdate_new(), the returned
** value is copied from memory cell (regNewRowid+1+iCol), where iCol
** is the column index supplied by the user.
@@ -757,36 +1055,33 @@ void sqlite3Update(
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
}
#endif
- if( bReplace || chngKey ){
- sqlite3VdbeJumpHere(v, addr1);
- }
if( hasFK ){
sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
}
-
+
/* Insert the new index entries and the new record. */
sqlite3CompleteInsertion(
- pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx,
- OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0),
+ pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx,
+ OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0),
0, 0
);
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
- ** to the row just updated. */
+ ** to the row just updated. */
if( hasFK ){
sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey);
}
}
- /* Increment the row counter
+ /* Increment the row counter
*/
if( regRowCount ){
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue);
/* Repeat the above with the next record to be updated, until
@@ -797,11 +1092,9 @@ void sqlite3Update(
}else if( eOnePass==ONEPASS_MULTI ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3WhereEnd(pWInfo);
- }else if( pPk ){
+ }else{
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
- }else{
- sqlite3VdbeGoto(v, labelContinue);
}
sqlite3VdbeResolveLabel(v, labelBreak);
@@ -818,7 +1111,7 @@ void sqlite3Update(
** that information.
*/
if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
+ sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
}
@@ -829,7 +1122,7 @@ update_cleanup:
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprListDelete(db, pChanges);
sqlite3ExprDelete(db, pWhere);
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
sqlite3ExprListDelete(db, pOrderBy);
sqlite3ExprDelete(db, pLimit);
#endif
@@ -849,8 +1142,8 @@ update_cleanup:
/*
** Generate code for an UPDATE of a virtual table.
**
-** There are two possible strategies - the default and the special
-** "onepass" strategy. Onepass is only used if the virtual table
+** There are two possible strategies - the default and the special
+** "onepass" strategy. Onepass is only used if the virtual table
** implementation indicates that pWhere may match at most one row.
**
** The default strategy is to create an ephemeral table that contains
@@ -882,7 +1175,7 @@ static void updateVirtualTable(
int i; /* Loop counter */
sqlite3 *db = pParse->db; /* Database connection */
const char *pVTab = (const char*)sqlite3GetVTable(db, pTab);
- WhereInfo *pWInfo;
+ WhereInfo *pWInfo = 0;
int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */
int regArg; /* First register in VUpdate arg array */
int regRec; /* Register in which to assemble record */
@@ -900,73 +1193,115 @@ static void updateVirtualTable(
addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
regArg = pParse->nMem + 1;
pParse->nMem += nArg;
- regRec = ++pParse->nMem;
- regRowid = ++pParse->nMem;
+ if( pSrc->nSrc>1 ){
+ Index *pPk = 0;
+ Expr *pRow;
+ ExprList *pList;
+ if( HasRowid(pTab) ){
+ if( pRowid ){
+ pRow = sqlite3ExprDup(db, pRowid, 0);
+ }else{
+ pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ }
+ }else{
+ i16 iPk; /* PRIMARY KEY column */
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ assert( pPk->nKeyCol==1 );
+ iPk = pPk->aiColumn[0];
+ if( aXRef[iPk]>=0 ){
+ pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
+ }else{
+ pRow = exprRowColumn(pParse, iPk);
+ }
+ }
+ pList = sqlite3ExprListAppend(pParse, 0, pRow);
- /* Start scanning the virtual table */
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0);
- if( pWInfo==0 ) return;
+ for(i=0; i<pTab->nCol; i++){
+ if( aXRef[i]>=0 ){
+ pList = sqlite3ExprListAppend(pParse, pList,
+ sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0)
+ );
+ }else{
+ pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
+ }
+ }
- /* Populate the argument registers. */
- for(i=0; i<pTab->nCol; i++){
- if( aXRef[i]>=0 ){
- sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
- }else{
- sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
- sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */
+ updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
+ sqlite3ExprListDelete(db, pList);
+ eOnePass = ONEPASS_OFF;
+ }else{
+ regRec = ++pParse->nMem;
+ regRowid = ++pParse->nMem;
+
+ /* Start scanning the virtual table */
+ pWInfo = sqlite3WhereBegin(pParse, pSrc,pWhere,0,0,WHERE_ONEPASS_DESIRED,0);
+ if( pWInfo==0 ) return;
+
+ /* Populate the argument registers. */
+ for(i=0; i<pTab->nCol; i++){
+ assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 );
+ if( aXRef[i]>=0 ){
+ sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
+ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* For sqlite3_vtab_nochange() */
+ }
}
- }
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
- if( pRowid ){
- sqlite3ExprCode(pParse, pRowid, regArg+1);
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
+ if( pRowid ){
+ sqlite3ExprCode(pParse, pRowid, regArg+1);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
+ }
}else{
- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
+ Index *pPk; /* PRIMARY KEY index */
+ i16 iPk; /* PRIMARY KEY column */
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ assert( pPk->nKeyCol==1 );
+ iPk = pPk->aiColumn[0];
+ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg);
+ sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
}
- }else{
- Index *pPk; /* PRIMARY KEY index */
- i16 iPk; /* PRIMARY KEY column */
- pPk = sqlite3PrimaryKeyIndex(pTab);
- assert( pPk!=0 );
- assert( pPk->nKeyCol==1 );
- iPk = pPk->aiColumn[0];
- sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg);
- sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
- }
-
- eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
-
- /* There is no ONEPASS_MULTI on virtual tables */
- assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
-
- if( eOnePass ){
- /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
- ** above. */
- sqlite3VdbeChangeToNoop(v, addr);
- sqlite3VdbeAddOp1(v, OP_Close, iCsr);
- }else{
- /* Create a record from the argument register contents and insert it into
- ** the ephemeral table. */
- sqlite3MultiWrite(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
-#ifdef SQLITE_DEBUG
- /* Signal an assert() within OP_MakeRecord that it is allowed to
- ** accept no-change records with serial_type 10 */
- sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
+
+ eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
+
+ /* There is no ONEPASS_MULTI on virtual tables */
+ assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
+
+ if( eOnePass ){
+ /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
+ ** above. */
+ sqlite3VdbeChangeToNoop(v, addr);
+ sqlite3VdbeAddOp1(v, OP_Close, iCsr);
+ }else{
+ /* Create a record from the argument register contents and insert it into
+ ** the ephemeral table. */
+ sqlite3MultiWrite(pParse);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_NULL_TRIM)
+ /* Signal an assert() within OP_MakeRecord that it is allowed to
+ ** accept no-change records with serial_type 10 */
+ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
#endif
- sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
+ }
}
if( eOnePass==ONEPASS_OFF ){
/* End the virtual table scan */
- sqlite3WhereEnd(pWInfo);
+ if( pSrc->nSrc==1 ){
+ sqlite3WhereEnd(pWInfo);
+ }
/* Begin scannning through the ephemeral table. */
addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v);
- /* Extract arguments from the current row of the ephemeral table and
+ /* Extract arguments from the current row of the ephemeral table and
** invoke the VUpdate method. */
for(i=0; i<nArg; i++){
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i);