| 1 | no | yes | no
@@ -10627,8 +10833,8 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
**
**
** ^For the purposes of comparing virtual table output values to see if the
-** values are the same value for sorting purposes, two NULL values are considered
-** to be the same. In other words, the comparison operator is "IS"
+** values are the same value for sorting purposes, two NULL values are
+** considered to be the same. In other words, the comparison operator is "IS"
** (or "IS NOT DISTINCT FROM") and not "==".
**
** If a virtual table implementation is unable to meet the requirements
@@ -10921,9 +11127,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **
** a variable pointed to by the "pOut" parameter.
**
** The "flags" parameter must be passed a mask of flags. At present only
-** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX
+** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX
** is specified, then status information is available for all elements
-** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If
+** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If
** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements
** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of
** the EXPLAIN QUERY PLAN output) are available. Invoking API
@@ -10937,7 +11143,8 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **
** elements used to implement the statement - a non-zero value is returned and
** the variable that pOut points to is unchanged.
**
-** See also: [sqlite3_stmt_scanstatus_reset()]
+** See also: [sqlite3_stmt_scanstatus_reset()] and the
+** [nexec and ncycle] columns of the [bytecode virtual table].
*/
SQLITE_API int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
@@ -11408,8 +11615,19 @@ SQLITE_API unsigned char *sqlite3_serialize(
** used. The serialized database P is N bytes in size. M is the size
** of the buffer P, which might be larger than N. If M is larger than
** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
-** SQLite is permitted to add content to the in-memory database as
-** long as the total size does not exceed M bytes.
+** SQLite is permitted to add content to the in-memory database, in
+** page-sized chunks, as long as the total size does not exceed M bytes.
+**
+** The parameter M must be greater than or equal to N. Ideally, M
+** should have a value which is N+(512×K)+20 where K determines how
+** must extra space is available to hold new content as the database
+** grows. K can be 0 if the database is read-only.
+**
+** If the database content in P is malformed in a malicious way then
+** it is possible that SQLite might try to read a few more than N bytes
+** from P. If the veracity of the database content P is uncertain,
+** then applications are advised to allocate about 20 extra bytes on
+** the end of the P buffer to avoid a memory error.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
@@ -11479,19 +11697,42 @@ SQLITE_API int sqlite3_deserialize(
/*
** CAPI3REF: Bind array values to the CARRAY table-valued function
**
-** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to
-** one of the first argument of the [carray() table-valued function]. The
-** S parameter is a pointer to the [prepared statement] that uses the carray()
-** functions. I is the parameter index to be bound. P is a pointer to the
-** array to be bound, and N is the number of eements in the array. The
-** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
-** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
-** indicate the datatype of the array being bound. The X argument is not a
-** NULL pointer, then SQLite will invoke the function X on the P parameter
-** after it has finished using P, even if the call to
-** sqlite3_carray_bind() fails. The special-case finalizer
-** SQLITE_TRANSIENT has no effect here.
-*/
+** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to
+** parameter that is the first argument of the [carray() table-valued function].
+** The S parameter is a pointer to the [prepared statement] that uses the
+** carray() functions. I is the parameter index to be bound. I must be the
+** index of the parameter that is the first argument to the carray()
+** table-valued function. P is a pointer to the array to be bound, and N
+** is the number of elements in the array. The F argument is one of
+** constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
+** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT],
+** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P.
+**
+** If the X argument is not a NULL pointer or one of the special
+** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke
+** the function X with argument D when it is finished using the data in P.
+** The call to X(D) is a destructor for the array P. The destructor X(D)
+** is invoked even if the call to sqlite3_carray_bind_v2() fails. If the X
+** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes
+** that the data static and the destructor is never invoked. If the X
+** parameter is the special-case value [SQLITE_TRANSIENT], then
+** sqlite3_carray_bind_v2() makes its own private copy of the data prior
+** to returning and never invokes the destructor X.
+**
+** The sqlite3_carray_bind() function works the same as sqlite3_carray_bind_v2()
+** with a D parameter set to P. In other words,
+** sqlite3_carray_bind(S,I,P,N,F,X) is same as
+** sqlite3_carray_bind_v2(S,I,P,N,F,X,P).
+*/
+SQLITE_API int sqlite3_carray_bind_v2(
+ sqlite3_stmt *pStmt, /* Statement to be bound */
+ int i, /* Parameter index */
+ void *aData, /* Pointer to array data */
+ int nData, /* Number of data elements */
+ int mFlags, /* CARRAY flags */
+ void (*xDel)(void*), /* Destructor for aData */
+ void *pDel /* Optional argument to xDel() */
+);
SQLITE_API int sqlite3_carray_bind(
sqlite3_stmt *pStmt, /* Statement to be bound */
int i, /* Parameter index */
@@ -13035,11 +13276,23 @@ SQLITE_API int sqlite3changeset_apply_v3(
** database behave as if they were declared with "ON UPDATE NO ACTION ON
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
** or SET DEFAULT.
+**
+** SQLITE_CHANGESETAPPLY_NOUPDATELOOP
+** Sometimes, a changeset contains two or more update statements such that
+** although after applying all updates the database will contain no
+** constraint violations, no single update can be applied before the others.
+** The simplest example of this is a pair of UPDATEs that have "swapped"
+** two column values with a UNIQUE constraint.
+**
+** Usually, sqlite3changeset_apply() and similar functions work hard to try
+** to find a way to apply such a changeset. However, if this flag is set,
+** then all such updates are considered CONSTRAINT conflicts.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
+#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
/*
** CAPI3REF: Constants Passed To The Conflict Handler
@@ -13522,6 +13775,232 @@ SQLITE_API int sqlite3session_config(int op, void *pArg);
*/
#define SQLITE_SESSION_CONFIG_STRMSIZE 1
+/*
+** CAPI3REF: Configure a changegroup object
+**
+** Configure the changegroup object passed as the first argument.
+** At present the only valid value for the second parameter is
+** [SQLITE_CHANGEGROUP_CONFIG_PATCHSET].
+*/
+SQLITE_API int sqlite3changegroup_config(sqlite3_changegroup*, int, void *pArg);
+
+/*
+** CAPI3REF: Options for sqlite3changegroup_config().
+**
+** The following values may be passed as the 2nd parameter to
+** sqlite3changegroup_config().
+**
+** SQLITE_CHANGEGROUP_CONFIG_PATCHSET
+** A changegroup object generates either a changeset or patchset. Usually,
+** this is determined by whether the first call to sqlite3changegroup_add()
+** is passed a changeset or a patchset. Or, if the first changes are added
+** to the changegroup object using the sqlite3changegroup_change_xxx()
+** APIs, then this option may be used to configure whether the changegroup
+** object generates a changeset or patchset.
+**
+** When this option is invoked, parameter pArg must point to a value of
+** type int. If the changegroup currently contains zero changes, and the
+** value of the int variable is zero or greater than zero, then the
+** changegroup is configured to generate a changeset or patchset,
+** respectively. It is a no-op, not an error, if the changegroup is not
+** configured because it has already started accumulating changes.
+**
+** Before returning, the int variable is set to 0 if the changegroup is
+** configured to generate a changeset, or 1 if it is configured to generate
+** a patchset.
+*/
+#define SQLITE_CHANGEGROUP_CONFIG_PATCHSET 1
+
+
+/*
+** CAPI3REF: Begin adding a change to a changegroup
+**
+** This API is used, in concert with other sqlite3changegroup_change_xxx()
+** APIs, to add changes to a changegroup object one at a time. To add a
+** single change, the caller must:
+**
+** 1. Invoke sqlite3changegroup_change_begin() to indicate the type of
+** change (INSERT, UPDATE or DELETE), the affected table and whether
+** or not the change should be marked as indirect.
+**
+** 2. Invoke sqlite3changegroup_change_int64() or one of the other four
+** value functions - _null(), _double(), _text() or _blob() - one or
+** more times to specify old.* and new.* values for the change being
+** constructed.
+**
+** 3. Invoke sqlite3changegroup_change_finish() to either finish adding
+** the change to the group, or to discard the change altogether.
+**
+** The first argument to this function must be a pointer to the existing
+** changegroup object that the change will be added to. The second argument
+** must be SQLITE_INSERT, SQLITE_UPDATE or SQLITE_DELETE. The third is the
+** name of the table that the change affects, and the fourth is a boolean
+** flag specifying whether the change should be marked as "indirect" (if
+** bIndirect is non-zero) or not indirect (if bIndirect is zero).
+**
+** Following a successful call to this function, this function may not be
+** called again on the same changegroup object until after
+** sqlite3changegroup_change_finish() has been called. Doing so is an
+** SQLITE_MISUSE error.
+**
+** The changegroup object passed as the first argument must be already
+** configured with schema data for the specified table. It may be configured
+** either by calling sqlite3changegroup_schema() with a database that contains
+** the table, or sqlite3changegroup_add() with a changeset that contains the
+** table. If the changegroup object has not been configured with a schema for
+** the specified table when this function is called, SQLITE_ERROR is returned.
+**
+** If successful, SQLITE_OK is returned. Otherwise, if an error occurs, an
+** SQLite error code is returned. In this case, if argument pzErr is non-NULL,
+** then (*pzErr) may be set to point to a buffer containing a utf-8 formated,
+** nul-terminated, English language error message. It is the responsibility
+** of the caller to eventually free this buffer using sqlite3_free().
+*/
+SQLITE_API int sqlite3changegroup_change_begin(
+ sqlite3_changegroup*,
+ int eOp,
+ const char *zTab,
+ int bIndirect,
+ char **pzErr
+);
+
+/*
+** CAPI3REF: Add a 64-bit integer to a changegroup
+**
+** This function may only be called between a successful call to
+** sqlite3changegroup_change_begin() and its matching
+** sqlite3changegroup_change_finish() call. If it is called at any
+** other time, it is an SQLITE_MISUSE error. Calling this function
+** specifies a 64-bit integer value to be used in the change currently being
+** added to the changegroup object passed as the first argument.
+**
+** The second parameter, bNew, specifies whether the value is to be part of
+** the new.* (if bNew is non-zero) or old.* (if bNew is zero) record of
+** the change under construction. If this does not match the type of change
+** specified by the preceding call to sqlite3changegroup_change_begin() (i.e.
+** an old.* value for an SQLITE_INSERT change, or a new.* value for an
+** SQLITE_DELETE), then SQLITE_ERROR is returned.
+**
+** The third parameter specifies the column of the old.* or new.* record that
+** the value will be a part of. If the specified table has an explicit primary
+** key, then this is the index of the table column, numbered from 0 in the order
+** specified within the CREATE TABLE statement. Or, if the table uses an
+** implicit rowid key, then the column 0 is the rowid and the explicit columns
+** are numbered starting from 1. If the iCol parameter is less than 0 or greater
+** than the index of the last column in the table, SQLITE_RANGE is returned.
+**
+** The fourth parameter is the integer value to use as part of the old.* or
+** new.* record.
+**
+** If this call is successful, SQLITE_OK is returned. Otherwise, if an
+** error occurs, an SQLite error code is returned.
+*/
+SQLITE_API int sqlite3changegroup_change_int64(
+ sqlite3_changegroup*,
+ int bNew,
+ int iCol,
+ sqlite3_int64 iVal
+);
+
+/*
+** CAPI3REF: Add a NULL to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). Except that
+** it configures the change currently under construction with a NULL value
+** instead of a 64-bit integer.
+*/
+SQLITE_API int sqlite3changegroup_change_null(sqlite3_changegroup*, int, int);
+
+/*
+** CAPI3REF: Add an double to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). Except that
+** it configures the change currently being constructed with a real value
+** instead of a 64-bit integer.
+*/
+SQLITE_API int sqlite3changegroup_change_double(sqlite3_changegroup*, int, int, double);
+
+/*
+** CAPI3REF: Add a text value to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). It configures
+** the currently accumulated change with a text value instead of a 64-bit
+** integer. Parameter pVal points to a buffer containing the text encoded using
+** utf-8. Parameter nVal may either be the size of the text value in bytes, or
+** else a negative value, in which case the buffer pVal points to is assumed to
+** be nul-terminated.
+*/
+SQLITE_API int sqlite3changegroup_change_text(
+ sqlite3_changegroup*, int, int, const char *pVal, int nVal
+);
+
+/*
+** CAPI3REF: Add a blob to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). It configures
+** the currently accumulated change with a blob value instead of a 64-bit
+** integer. Parameter pVal points to a buffer containing the blob. Parameter
+** nVal is the size of the blob in bytes.
+*/
+SQLITE_API int sqlite3changegroup_change_blob(
+ sqlite3_changegroup*, int, int, const void *pVal, int nVal
+);
+
+/*
+** CAPI3REF: Finish adding one-at-at-time changes to a changegroup
+**
+** This function may only be called following a successful call to
+** sqlite3changegroup_change_begin(). Otherwise, it is an SQLITE_MISUSE error.
+**
+** If parameter bDiscard is non-zero, then the current change is simply
+** discarded. In this case this function is always successful and SQLITE_OK
+** returned.
+**
+** If parameter bDiscard is zero, then an attempt is made to add the current
+** change to the changegroup. Assuming the changegroup is configured to
+** produce a changeset (not a patchset), this requires that:
+**
+** * If the change is an INSERT or DELETE, then a value must be specified
+** for all columns of the new.* or old.* record, respectively.
+**
+** * If the change is an UPDATE record, then values must be provided for
+** the PRIMARY KEY columns of the old.* record, but must not be provided
+** for PRIMARY KEY columns of the new.* record.
+**
+** * If the change is an UPDATE record, then for each non-PRIMARY KEY
+** column in the old.* record for which a value has been provided, a
+** value must also be provided for the same column in the new.* record.
+** Similarly, for each non-PK column in the old.* record for which
+** a value is not provided, a value must not be provided for the same
+** column in the new.* record.
+**
+** * All values specified for PRIMARY KEY columns must be non-NULL.
+**
+** Otherwise, it is an error.
+**
+** If the changegroup already contains a change for the same row (identified
+** by PRIMARY KEY columns), then the current change is combined with the
+** existing change in the same way as for sqlite3changegroup_add().
+**
+** For a patchset, all of the above rules apply except that it doesn't matter
+** whether or not values are provided for the non-PK old.* record columns
+** for an UPDATE or DELETE change. This means that code used to produce
+** a changeset using the sqlite3changegroup_change_xxx() APIs may also
+** be used to produce patchsets.
+**
+** If the call is successful, SQLITE_OK is returned. Otherwise, if an error
+** occurs, an SQLite error code is returned. If an error is returned and
+** parameter pzErr is not NULL, then (*pzErr) may be set to point to a buffer
+** containing a nul-terminated, utf-8 encoded, English language error message.
+** It is the responsibility of the caller to eventually free any such error
+** message buffer using sqlite3_free().
+*/
+SQLITE_API int sqlite3changegroup_change_finish(
+ sqlite3_changegroup*,
+ int bDiscard,
+ char **pzErr
+);
+
/*
** Make sure we can call this stuff from C++.
*/
@@ -14294,7 +14773,7 @@ struct fts5_api {
/************** Continuing where we left off in sqliteInt.h ******************/
/*
-** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory.
+** Reuse the STATIC_VFS1 for mutex access to sqlite3_temp_directory.
*/
#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1
@@ -14336,6 +14815,27 @@ struct fts5_api {
#endif
#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
+/*
+** Maximum size of any single memory allocation.
+**
+** This is not a limit on the total amount of memory used. This is
+** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
+**
+** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
+** This provides a 256-byte safety margin for defense against 32-bit
+** signed integer overflow bugs when computing memory allocation sizes.
+** Paranoid applications might want to reduce the maximum allocation size
+** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
+** or even smaller would be reasonable upper bounds on the size of a memory
+** allocations for most applications.
+*/
+#ifndef SQLITE_MAX_ALLOCATION_SIZE
+# define SQLITE_MAX_ALLOCATION_SIZE 2147483391
+#endif
+#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
+# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
+#endif
+
/*
** This is the maximum number of
**
@@ -14371,21 +14871,42 @@ struct fts5_api {
** It used to be the case that setting this value to zero would
** turn the limit off. That is no longer true. It is not possible
** to turn this limit off.
+**
+** The hard limit is the largest possible 32-bit signed integer less
+** 1024, or 2147482624.
*/
#ifndef SQLITE_MAX_SQL_LENGTH
# define SQLITE_MAX_SQL_LENGTH 1000000000
#endif
/*
-** The maximum depth of an expression tree. This is limited to
-** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
-** want to place more severe limits on the complexity of an
-** expression. A value of 0 means that there is no limit.
+** The maximum depth of an expression tree. The expression tree depth
+** is also limited indirectly by SQLITE_MAX_SQL_LENGTH and by
+** SQLITE_MAX_PARSER_DEPTH. Reducing the maximum complexity of
+** expressions can help prevent excess memory usage by hostile SQL.
+**
+** A value of 0 for this compile-time option causes all expression
+** depth limiting code to be omitted.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
#endif
+/*
+** The maximum depth of the LALR(1) stack used in the parser that
+** interprets SQL inputs. The parser stack depth can also be limited
+** indirectly by SQLITE_MAX_SQL_LENGTH. Limiting the parser stack
+** depth can help prevent excess memory usage and excess CPU stack
+** usage when processing hostile SQL.
+**
+** Prior to version 3.45.0 (2024-01-15), the parser stack was
+** hard-coded to 100 entries, and that worked fine for almost all
+** applications. So the upper bound on this limit need not be large.
+*/
+#ifndef SQLITE_MAX_PARSER_DEPTH
+# define SQLITE_MAX_PARSER_DEPTH 2500
+#endif
+
/*
** The maximum number of terms in a compound SELECT statement.
** The code generator for compound SELECT statements does one
@@ -14501,6 +15022,10 @@ struct fts5_api {
# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
#endif
+#if SQLITE_MAX_DEFAULT_PAGE_SIZE
-#endif
#ifdef HAVE_INTTYPES_H
#include
#endif
@@ -14603,22 +15161,50 @@ struct fts5_api {
#endif
/*
-** Macros to hint to the compiler that a function should or should not be
-** inlined.
+** Hint to the compiler that a function should or should not be inlined:
+**
+** SQLITE_NOINLINE Never in-line this function
+**
+** SQLITE_INLINE Strive to in-line this function
+**
+** SQLITE_OPT_INLINE In-line this function if building the
+** amalgamation.
+**
+** SQLITE_USES_INLINE Set to 1 or 0 according to whether or not
+** inline functions are supported.
*/
-#if defined(__GNUC__)
-# define SQLITE_NOINLINE __attribute__((noinline))
-# define SQLITE_INLINE __attribute__((always_inline)) inline
+#if defined(SQLITE_DISABLE_INLINE)
+# define SQLITE_NOINLINE
+# define SQLITE_INLINE
+# define SQLITE_OPT_INLINE
+# define SQLITE_USES_INLINE 0
+#elif defined(__GNUC__)
+# define SQLITE_NOINLINE __attribute__((noinline))
+# define SQLITE_INLINE __attribute__((always_inline)) inline
+# define SQLITE_OPT_INLINE __attribute__((always_inline)) inline
+# define SQLITE_USES_INLINE 1
#elif defined(_MSC_VER) && _MSC_VER>=1310
-# define SQLITE_NOINLINE __declspec(noinline)
-# define SQLITE_INLINE __forceinline
+# define SQLITE_NOINLINE __declspec(noinline)
+# define SQLITE_INLINE __forceinline
+# define SQLITE_OPT_INLINE __forceinline
+# define SQLITE_USES_INLINE 1
#else
# define SQLITE_NOINLINE
# define SQLITE_INLINE
+# define SQLITE_OPT_INLINE
+# define SQLITE_USES_INLINE 0
#endif
#if defined(SQLITE_COVERAGE_TEST) || defined(__STRICT_ANSI__)
# undef SQLITE_INLINE
# define SQLITE_INLINE
+# undef SQLITE_OPT_INLINE
+# define SQLITE_OPT_INLINE
+# undef SQLITE_USES_INLINE
+# define SQLITE_USES_INLINE 0
+#endif
+#if !defined(SQLITE_AMALGAMATION)
+# undef SQLITE_OPT_INLINE
+# define SQLITE_OPT_INLINE
#endif
/*
@@ -14793,7 +15379,9 @@ struct fts5_api {
** where multiple cases go to the same block of code, testcase()
** can insure that all cases are evaluated.
*/
-#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+#if defined(SQLITE_MUTATION_TEST)
+# define testcase(X)
+#elif defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
# ifndef SQLITE_AMALGAMATION
extern unsigned int sqlite3CoverageCounter;
# endif
@@ -15271,6 +15859,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define float sqlite_int64
# define fabs(X) ((X)<0?-(X):(X))
# define sqlite3IsOverflow(X) 0
+# define INFINITY (9223372036854775807LL)
# ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
# endif
@@ -15378,6 +15967,13 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
+/*
+** sizeof64() is like sizeof(), but always returns a 64-bit value, even
+** on 32-bit builds. This can help to avoid overflow by ensuring 64-bit
+** arithmetic is used consistently in both 32-bit and 64-bit builds.
+*/
+#define sizeof64(X) ((sqlite3_int64)sizeof(X))
+
/*
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
** to avoid complaints from -fsanitize=strict-bounds.
@@ -15680,6 +16276,7 @@ typedef INT16_TYPE LogEst;
#else
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
#endif
+#define TWO_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&1)==0)
/*
** Disable MMAP on platforms where it is known to not work
@@ -16625,6 +17222,10 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*);
#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_WALSTAT)
+SQLITE_PRIVATE void sqlite3PagerWalStat(Pager*,sqlite3_str*);
+#endif
+
#endif /* SQLITE_PAGER_H */
/************** End of pager.h ***********************************************/
@@ -16738,7 +17339,7 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
-SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
+SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree*, Btree*);
SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
@@ -16815,12 +17416,19 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
** implementations with limits on what needs to be prefetched and thereby
** reduce network bandwidth.
**
+** BTREE_HINT_TABLECURSOR (arguments: BtCursor*)
+**
+** This hint is invoked on a non-covering index cursor soon after it
+** is opened. The only argument is a pointer to the table cursor used to
+** obtain non-covered fields from the database.
+**
** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
** standard SQLite. The other hints are provided for extensions that use
** the SQLite parser and code generator but substitute their own storage
** engine.
*/
#define BTREE_HINT_RANGE 0 /* Range constraints on queries */
+#define BTREE_HINT_TABLECURSOR 1 /* Table csr associated with this index csr */
/*
** Values that may be OR'd together to form the argument to the
@@ -16880,6 +17488,9 @@ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
+ #ifdef SQLITE_DEBUG
+SQLITE_PRIVATE BtCursor *sqlite3BtreeCursorHintTblCsr(BtCursor*);
+ #endif
#endif
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
@@ -17126,8 +17737,6 @@ struct VdbeOp {
int i; /* Integer value if p4type==P4_INT32 */
void *p; /* Generic pointer */
char *z; /* Pointer to data for string (char array) types */
- i64 *pI64; /* Used when p4type is P4_INT64 */
- double *pReal; /* Used when p4type is P4_REAL */
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
@@ -17138,6 +17747,7 @@ struct VdbeOp {
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
Table *pTab; /* Used when p4type is P4_TABLE */
SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
+ Index *pIdx; /* Used when p4type is P4_INDEX */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
@@ -17182,6 +17792,19 @@ struct VdbeOpList {
};
typedef struct VdbeOpList VdbeOpList;
+/*
+** Combine two int32 values into a single int64. The least significant
+** term comes first.
+*/
+#define INT32_TO_64(a,b) (i64)(((u64)(u32)(b)<<32)|(u32)(a))
+
+/*
+** Return an int32 that is the lower or upper 32-bits of an int64.
+*/
+#define LOWER32(x) (int)(((u64)(x))&0xffffffff)
+#define UPPER32(x) (int)(((u64)(x))>>32)
+
+
/*
** Allowed values of VdbeOp.p4type
*/
@@ -17192,20 +17815,19 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
#define P4_TABLE (-5) /* P4 is a pointer to a Table structure */
+#define P4_INDEX (-6) /* P4 is a pointer to an Index structure */
/* Above do not own any resources. Must free those below */
-#define P4_FREE_IF_LE (-6)
-#define P4_DYNAMIC (-6) /* Pointer to memory from sqliteMalloc() */
-#define P4_FUNCDEF (-7) /* P4 is a pointer to a FuncDef structure */
-#define P4_KEYINFO (-8) /* P4 is a pointer to a KeyInfo structure */
-#define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */
-#define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */
-#define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */
-#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
-#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
-#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
-#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
-#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
-#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */
+#define P4_FREE_IF_LE (-7)
+#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */
+#define P4_FUNCDEF (-8) /* P4 is a pointer to a FuncDef structure */
+#define P4_KEYINFO (-9) /* P4 is a pointer to a KeyInfo structure */
+#define P4_EXPR (-10) /* P4 is a pointer to an Expr tree */
+#define P4_MEM (-11) /* P4 is a pointer to a Mem* structure */
+#define P4_VTAB (-12) /* P4 is a pointer to an sqlite3_vtab structure */
+#define P4_INTARRAY (-13) /* P4 is a vector of 32-bit integers */
+#define P4_FUNCCTX (-14) /* P4 is a pointer to an sqlite3_context object */
+#define P4_TABLEREF (-15) /* Like P4_TABLE, but reference counted */
+#define P4_SUBRTNSIG (-16) /* P4 is a SubrtnSig pointer */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -17272,28 +17894,28 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_SeekLE 22 /* jump0, synopsis: key=r[P3@P4] */
#define OP_SeekGE 23 /* jump0, synopsis: key=r[P3@P4] */
#define OP_SeekGT 24 /* jump0, synopsis: key=r[P3@P4] */
-#define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */
-#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
-#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 30 /* jump0, synopsis: intkey=r[P3] */
-#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
-#define OP_Last 32 /* jump0 */
-#define OP_IfSizeBetween 33 /* jump */
-#define OP_SorterSort 34 /* jump */
-#define OP_Sort 35 /* jump */
-#define OP_Rewind 36 /* jump0 */
-#define OP_IfEmpty 37 /* jump, synopsis: if( empty(P1) ) goto P2 */
-#define OP_SorterNext 38 /* jump */
-#define OP_Prev 39 /* jump */
-#define OP_Next 40 /* jump */
-#define OP_IdxLE 41 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGT 42 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IfNoHope 25 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NoConflict 26 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NotFound 27 /* jump, synopsis: key=r[P3@P4] */
+#define OP_Found 28 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekRowid 29 /* jump0, synopsis: intkey=r[P3] */
+#define OP_NotExists 30 /* jump, synopsis: intkey=r[P3] */
+#define OP_Last 31 /* jump0 */
+#define OP_IfSizeBetween 32 /* jump */
+#define OP_SorterSort 33 /* jump */
+#define OP_Sort 34 /* jump */
+#define OP_Rewind 35 /* jump0 */
+#define OP_IfEmpty 36 /* jump, synopsis: if( empty(P1) ) goto P2 */
+#define OP_SorterNext 37 /* jump */
+#define OP_Prev 38 /* jump */
+#define OP_Next 39 /* jump */
+#define OP_IdxLE 40 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 41 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxLT 42 /* jump, synopsis: key=r[P3@P4] */
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_IdxLT 45 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGE 46 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IFindKey 46 /* jump */
#define OP_RowSetRead 47 /* jump, synopsis: r[P3]=rowset(P1) */
#define OP_RowSetTest 48 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
#define OP_Program 49 /* jump0 */
@@ -17320,7 +17942,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_HaltIfNull 70 /* synopsis: if r[P3]=null halt */
#define OP_Halt 71
#define OP_Integer 72 /* synopsis: r[P2]=P1 */
-#define OP_Int64 73 /* synopsis: r[P2]=P4 */
+#define OP_Int64 73 /* synopsis: r[P2]=PINT13 */
#define OP_String 74 /* synopsis: r[P2]='P4' (len=P1) */
#define OP_BeginSubrtn 75 /* synopsis: r[P2]=NULL */
#define OP_Null 76 /* synopsis: r[P2..P3]=NULL */
@@ -17371,7 +17993,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_SequenceTest 121 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
#define OP_OpenPseudo 122 /* synopsis: P3 columns in r[P2] */
#define OP_Close 123
-#define OP_ColumnsUsed 124
+#define OP_ColumnsUsed 124 /* synopsis: Cursor P1 uses columns PHEX23 */
#define OP_SeekScan 125 /* synopsis: Scan-ahead up to P1 rows */
#define OP_SeekHit 126 /* synopsis: set P2<=seekHit<=P3 */
#define OP_Sequence 127 /* synopsis: r[P2]=cursor[P1].ctr++ */
@@ -17388,7 +18010,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_SeekEnd 138
#define OP_IdxInsert 139 /* synopsis: key=r[P2] */
#define OP_SorterInsert 140 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 141 /* synopsis: key=r[P2@P3] */
+#define OP_IdxDelete 141 /* synopsis: key=r[P2@P5] */
#define OP_DeferredSeek 142 /* synopsis: Move P3 to P1.rowid if needed */
#define OP_IdxRowid 143 /* synopsis: r[P2]=rowid */
#define OP_FinishSeek 144
@@ -17401,7 +18023,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_LoadAnalysis 151
#define OP_DropTable 152
#define OP_DropIndex 153
-#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=PDBL13 */
#define OP_DropTrigger 155
#define OP_IntegrityCk 156
#define OP_RowSetAdd 157 /* synopsis: rowset(P1)=r[P2] */
@@ -17455,9 +18077,9 @@ typedef struct VdbeOpList VdbeOpList;
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\
/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\
/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\
-/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
-/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x01, 0x41,\
-/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x41, 0x23,\
+/* 24 */ 0xc9, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49, 0xc1,\
+/* 32 */ 0x01, 0x41, 0x41, 0xc1, 0x01, 0x01, 0x41, 0x41,\
+/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x09, 0x23,\
/* 48 */ 0x0b, 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01,\
/* 64 */ 0x41, 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00,\
@@ -17492,7 +18114,7 @@ typedef struct VdbeOpList VdbeOpList;
** Additional non-public SQLITE_PREPARE_* flags
*/
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
-#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
+#define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */
/*
** Prototypes for the VDBE interface. See comments on the implementation
@@ -17507,8 +18129,9 @@ SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe*,int,const char*);
SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...);
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
+SQLITE_PRIVATE int sqlite3VdbeAddInt64(Vdbe*,int,i64);
+SQLITE_PRIVATE int sqlite3VdbeAddDouble(Vdbe*,int,double);
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
-SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int);
SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int);
@@ -17600,7 +18223,7 @@ SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*);
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
-SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
+SQLITE_PRIVATE void sqlite3VdbeReprepareOnBind(Vdbe*, int, int);
#ifndef SQLITE_OMIT_TRACE
SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
@@ -17759,6 +18382,7 @@ SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr)
*/
#ifndef _PCACHE_H_
+#define _PCACHE_H_
typedef struct PgHdr PgHdr;
typedef struct PCache PCache;
@@ -17774,10 +18398,10 @@ struct PgHdr {
PCache *pCache; /* PRIVATE: Cache that owns this page */
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
Pager *pPager; /* The pager this page is part of */
- Pgno pgno; /* Page number for this page */
#ifdef SQLITE_CHECK_PAGES
- u32 pageHash; /* Hash of page content */
+ u64 pageHash; /* Hash of page content */
#endif
+ Pgno pgno; /* Page number for this page */
u16 flags; /* PGHDR flags defined below */
/**********************************************************************
@@ -17981,7 +18605,7 @@ SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache);
# define SQLITE_MUTEX_OMIT
#endif
#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP)
-# if SQLITE_OS_UNIX
+# if SQLITE_OS_UNIX || defined(__CYGWIN__)
# define SQLITE_MUTEX_PTHREADS
# elif SQLITE_OS_WIN
# define SQLITE_MUTEX_W32
@@ -18117,7 +18741,7 @@ struct Schema {
** The number of different kinds of things that can be limited
** using the sqlite3_limit() interface.
*/
-#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
+#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_STEPS+1)
/*
** Lookaside malloc is a set of fixed-size buffers that can be used
@@ -18271,6 +18895,7 @@ struct sqlite3 {
u8 noSharedCache; /* True if no shared-cache backends */
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
u8 eOpenState; /* Current condition of the connection */
+ u8 nFpDigit; /* Significant digits to keep on double->text */
int nextPagesize; /* Pagesize after VACUUM if >0 */
i64 nChange; /* Value returned by sqlite3_changes() */
i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
@@ -18279,7 +18904,7 @@ struct sqlite3 {
struct sqlite3InitInfo { /* Information used during initialization */
Pgno newTnum; /* Rootpage of table being initialized */
u8 iDb; /* Which db file is being initialized */
- u8 busy; /* TRUE if currently initializing */
+ u8 busy; /* TRUE if initing. 2 if due to ADD COLUMN */
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 2; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
@@ -18478,7 +19103,7 @@ struct sqlite3 {
#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 */
+ /* 0x00000008 -- Available for reuse */
#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
@@ -18487,7 +19112,7 @@ struct sqlite3 {
#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 */
+ /* TH3 expects this value ^^^^^^^^^^ */
#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
@@ -18495,13 +19120,14 @@ struct sqlite3 {
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
- /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */
-#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */
-#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */
+ /* TH3 expects this value ^^^^^^^^^^ */
+#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filters */
+ /* TH3 expects this value ^^^^^^^^^^ */
+ /* 0x00100000 -- Available for reuse */
#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */
#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */
#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */
- /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */
+ /* TH3 expects this value ^^^^^^^^^^ */
#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */
#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
@@ -18509,6 +19135,7 @@ struct sqlite3 {
#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */
#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */
#define SQLITE_ExistsToJoin 0x40000000 /* The EXISTS-to-JOIN optimization */
+#define SQLITE_UnionLimit 0x80000000 /* Optimizations for UNION + LIMIT */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
@@ -20165,19 +20792,6 @@ struct Upsert {
/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
-**
-** See the header comment on the computeLimitRegisters() routine for a
-** detailed description of the meaning of the iLimit and iOffset fields.
-**
-** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
-** These addresses must be stored so that we can go back and fill in
-** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
-** the number of columns in P2 can be computed at the same time
-** as the OP_OpenEphm instruction is coded because not
-** enough information about the compound query is known at that point.
-** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
-** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
-** sequences for the ORDER BY clause.
*/
struct Select {
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
@@ -20185,7 +20799,6 @@ struct Select {
u32 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
u32 selId; /* Unique identifier number for this SELECT */
- int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
ExprList *pEList; /* The fields of the result */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
@@ -20217,7 +20830,7 @@ struct Select {
#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
#define SF_HasAgg 0x0000010 /* Contains aggregate functions */
-#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
+#define SF_ClonedRhsIn 0x0000020 /* Cloned RHS of an IN operator */
#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
#define SF_Compound 0x0000100 /* Part of a compound query */
@@ -20227,14 +20840,14 @@ struct Select {
#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
-#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
+/* 0x0008000 // available for reuse */
#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
#define SF_View 0x0200000 /* SELECT statement is a view */
-#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
+/* 0x0400000 // available for reuse */
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
@@ -20254,11 +20867,6 @@ struct Select {
** by one of the following macros. The "SRT" prefix means "SELECT Result
** Type".
**
-** SRT_Union Store results as a key in a temporary index
-** identified by pDest->iSDParm.
-**
-** SRT_Except Remove results from the temporary index pDest->iSDParm.
-**
** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
** set is not empty.
**
@@ -20322,30 +20930,28 @@ struct Select {
** table. (pDest->iSDParm) is the number of key columns in
** each index record in this case.
*/
-#define SRT_Union 1 /* Store result as keys in an index */
-#define SRT_Except 2 /* Remove result from a UNION index */
-#define SRT_Exists 3 /* Store 1 if the result is not empty */
-#define SRT_Discard 4 /* Do not save the results anywhere */
-#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
-#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
+#define SRT_Exists 1 /* Store 1 if the result is not empty */
+#define SRT_Discard 2 /* Do not save the results anywhere */
+#define SRT_DistFifo 3 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistQueue 4 /* Like SRT_Queue, but unique results only */
/* The DISTINCT clause is ignored for all of the above. Not that
** IgnorableDistinct() implies IgnorableOrderby() */
#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
-#define SRT_Queue 7 /* Store result in an queue */
-#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
+#define SRT_Queue 5 /* Store result in an queue */
+#define SRT_Fifo 6 /* Store result as data with an automatic rowid */
/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
-#define SRT_Output 9 /* Output each row of result */
-#define SRT_Mem 10 /* Store result in a memory cell */
-#define SRT_Set 11 /* Store results as keys in an index */
-#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
-#define SRT_Coroutine 13 /* Generate a single row of result */
-#define SRT_Table 14 /* Store result as data with an automatic rowid */
-#define SRT_Upfrom 15 /* Store result as data with rowid */
+#define SRT_Output 7 /* Output each row of result */
+#define SRT_Mem 8 /* Store result in a memory cell */
+#define SRT_Set 9 /* Store results as keys in an index */
+#define SRT_EphemTab 10 /* Create transient tab and store like SRT_Table */
+#define SRT_Coroutine 11 /* Generate a single row of result */
+#define SRT_Table 12 /* Store result as data with an automatic rowid */
+#define SRT_Upfrom 13 /* Store result as data with rowid */
/*
** An instance of this object describes where to put of the results of
@@ -20456,6 +21062,13 @@ struct ParseCleanup {
void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
};
+/*
+** Number of 64-bit entried in the variable number bitmap cache (VNBMC).
+*/
+#ifndef SQLITE_VNBMC
+# define SQLITE_VNBMC 2
+#endif
+
/*
** 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
@@ -20481,17 +21094,12 @@ struct Parse {
u8 nested; /* Number of nested calls to the parser/code generator */
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
- u8 mayAbort; /* True if statement may throw an ABORT exception */
- u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
- u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */
u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
- u8 bReturning; /* Coding a RETURNING trigger */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
- u8 disableTriggers; /* True to disable triggers */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
#endif
@@ -20500,10 +21108,16 @@ struct Parse {
u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER)
** and ALTER TABLE ADD COLUMN. */
#endif
- bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
- bft bHasWith :1; /* True if statement contains WITH */
- bft okConstFactor :1; /* OK to factor out constants */
- bft checkSchema :1; /* Causes schema cookie check after an error */
+ bft disableTriggers:1; /* True to disable triggers */
+ bft mayAbort :1; /* True if statement may throw an ABORT exception */
+ bft hasCompound :1; /* Need to invoke convertCompoundSelectToSubquery() */
+ bft bReturning :1; /* Coding a RETURNING trigger */
+ bft bHasExists :1; /* Has a correlated "EXISTS (SELECT ....)" expression */
+ bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
+ bft bHasWith :1; /* True if statement contains WITH */
+ bft okConstFactor:1; /* OK to factor out constants */
+ bft checkSchema :1; /* Causes schema cookie check after an error */
+ bft usesAinc :1; /* True if pAinc is valid */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -20512,6 +21126,7 @@ struct Parse {
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
+ int nNestSel; /* Number of nested SELECT statements and/or VIEWs */
int nLabel; /* The *negative* of the number of labels used */
int nLabelAlloc; /* Number of slots in aLabel */
int *aLabel; /* Space to hold the labels */
@@ -20527,9 +21142,7 @@ struct Parse {
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
- TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
- AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
@@ -20558,6 +21171,13 @@ struct Parse {
Returning *pReturning; /* The RETURNING clause */
} d;
} u1;
+ AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters. Only
+ ** valid if Parse.usesAinc is true */
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ TableLock *aTableLock; /* Required table locks for shared-cache mode. Only
+ ** valid if Parse.nTableLock>0 */
+#endif
+
/************************************************************************
** Above is constant between recursions. Below is reset before and after
@@ -20568,6 +21188,7 @@ struct Parse {
Token sLastToken; /* The last token parsed */
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
+ u64 aVnbmc[SQLITE_VNBMC]; /* Varible Number Bitmap Cache */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
u8 eParseMode; /* PARSE_MODE_XXX constant */
@@ -20732,19 +21353,19 @@ struct Trigger {
** orconf -> stores the ON CONFLICT algorithm
** pSelect -> The content to be inserted - either a SELECT statement or
** a VALUES clause.
-** zTarget -> Dequoted name of the table to insert into.
+** pSrc -> Table to insert into.
** pIdList -> If this is an INSERT INTO ... () VALUES ...
** statement, then this stores the column-names to be
** inserted into.
** pUpsert -> The ON CONFLICT clauses for an Upsert
**
** (op == TK_DELETE)
-** zTarget -> Dequoted name of the table to delete from.
+** pSrc -> Table to delete from
** pWhere -> The WHERE clause of the DELETE statement if one is specified.
** Otherwise NULL.
**
** (op == TK_UPDATE)
-** zTarget -> Dequoted name of the table to update.
+** pSrc -> Table to update, followed by any FROM clause tables.
** pWhere -> The WHERE clause of the UPDATE statement if one is specified.
** Otherwise NULL.
** pExprList -> A list of the columns to update and the expressions to update
@@ -20764,8 +21385,7 @@ struct TriggerStep {
u8 orconf; /* OE_Rollback etc. */
Trigger *pTrig; /* The trigger that this step is a part of */
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
- char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
- SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */
+ SrcList *pSrc; /* Table to insert/update/delete */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
IdList *pIdList; /* Column names for INSERT */
@@ -20848,10 +21468,11 @@ typedef struct {
/*
** Allowed values for mInitFlags
*/
-#define INITFLAG_AlterMask 0x0003 /* Types of ALTER */
+#define INITFLAG_AlterMask 0x0007 /* Types of ALTER */
#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
#define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */
+#define INITFLAG_AlterDropCons 0x0004 /* Reparse after a DROP CONSTRAINT */
/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
@@ -20981,6 +21602,7 @@ struct Walker {
NameContext *pNC; /* Naming context */
int n; /* A counter */
int iCur; /* A cursor number */
+ int sz; /* String literal length */
SrcList *pSrcList; /* FROM clause */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
@@ -21211,6 +21833,57 @@ SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprLis
/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
+**
+** # Dividing malformed UTF-8 into characters (tag-20260418-01)
+**
+** If a text input is malformed UTF-8, SQLite does not make any guarantees
+** about how the bytes are divided up into characters. The system promises
+** to not overflow an array or cause other memory errors when presented
+** with malformed UTF-8. And it promises to preserve the specific
+** sequence of bytes as long as no conversion occur. But beyond that,
+** there are no guarantees. Results can vary from one version to the
+** next.
+**
+** The SQLITE_SKIP_UTF8 macro below is one technique for dividing UTF-8
+** into characters. The length() and substr() SQL functions use a
+** different technique when searching across multiple characters, a
+** technique that exchanges a subtraction for comparison of z and results
+** in faster machine code on some compilers and architectures. The code
+** in substr() to skip over p1 characters goes something like this:
+**
+** for( ; p1>0; p1--){
+** // vvvv--- tag-20260418-01
+** if( (u8)(z[0]-1)<(0x80-1) ){
+** z++;
+** }else if( z[0]==0 ){
+** break;
+** }else{
+** do{ z++; }while( (z[0]&0xc0)==0x80 );
+** }
+** }
+**
+** In valid UTF-8, multibyte characters always begin with a byte with the
+** two most significant bits set and that is followed by one or more bytes
+** for which the two most significant bits are 10. In other words:
+**
+** First byte: (BYTE & 0xc0)==0xc0
+** Following bytes: (BYTE & 0xc0)==0x80
+**
+** What to do if the input byte sequence contain a "following byte" that
+** is not preceded by a "first byte"? How many characters are in the
+** byte sequence: 0x61 0x81 0x82 0x7a? 3 or 4 or something else?
+**
+** If you use the macro below, the answer will be 4. If you use the code
+** snippet demonstrated at tag-20260418-01, then answer is 3. If you
+** use a variant of tag-20260418-01 where the constant of comparison is
+** 0xc0-1 instead of 0x80-1 then the answer is again 4. The key point is
+** that because the input is malformed UTF-8, so is no "correct" answer.
+** SQLite is free to use either value.
+**
+** It turns out that GCC 13.3.0 is able to generate faster code (at least
+** on x86-64) if the constant at tag-20260418-01 is (0x80-1). If you make
+** that constant (0xc0-1) instead, gcc 13.3.0 generates code that runs slower.
+** So the (0x80-1) constant is used for substr() and length().
*/
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
@@ -21385,7 +22058,20 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*);
SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void);
SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void);
-#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
+
+/* The SQLITE_THREAD_MISUSE_WARNINGS compile-time option used to be called
+** SQLITE_ENABLE_MULTITHREADED_CHECKS. Keep that older macro for backwards
+** compatibility, at least for a while... */
+#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+# define SQLITE_THREAD_MISUSE_WARNINGS 1
+#endif
+
+/* SQLITE_THREAD_MISUSE_ABORT implies SQLITE_THREAD_MISUSE_WARNINGS */
+#ifdef SQLITE_THREAD_MISUSE_ABORT
+# define SQLITE_THREAD_MISUSE_WARNINGS 1
+#endif
+
+#if defined(SQLITE_THREAD_MISUSE_WARNINGS) && !defined(SQLITE_MUTEX_OMIT)
SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
#else
# define sqlite3MutexWarnOnContention(x)
@@ -21414,17 +22100,22 @@ struct PrintfArguments {
sqlite3_value **apArg; /* The argument values */
};
+/*
+** Maxium number of base-10 digits in an unsigned 64-bit integer
+*/
+#define SQLITE_U64_DIGITS 20
+
/*
** An instance of this object receives the decoding of a floating point
** value into an approximate decimal representation.
*/
struct FpDecode {
- char sign; /* '+' or '-' */
- char isSpecial; /* 1: Infinity 2: NaN */
- int n; /* Significant digits in the decode */
- int iDP; /* Location of the decimal point */
- char *z; /* Start of significant digits */
- char zBuf[24]; /* Storage for significant digits */
+ int n; /* Significant digits in the decode */
+ int iDP; /* Location of the decimal point */
+ char *z; /* Start of significant digits */
+ char zBuf[SQLITE_U64_DIGITS+1]; /* Storage for significant digits */
+ char sign; /* '+' or '-' */
+ char isSpecial; /* 1: Infinity 2: NaN */
};
SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int);
@@ -21435,6 +22126,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
+SQLITE_PRIVATE const char *sqlite3TestPtrToText(void*);
#endif
#if defined(SQLITE_DEBUG)
@@ -21513,6 +22205,7 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int);
#endif
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
+SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3*,int);
SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
@@ -21535,6 +22228,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int);
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*);
+SQLITE_PRIVATE int sqlite3ExprCanReturnSubtype(Parse*,Expr*);
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
@@ -21550,6 +22244,7 @@ SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*);
+SQLITE_PRIVATE Expr *sqlite3ColumnExprAuth(Table*,Column*,Parse*);
SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl);
SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*);
SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
@@ -21658,6 +22353,7 @@ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
+SQLITE_PRIVATE int sqlite3IndexBloomable(const Index*,int);
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
@@ -21666,6 +22362,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList
Expr*,ExprList*,u32,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*);
+SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
@@ -21757,12 +22454,14 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
+SQLITE_PRIVATE int sqlite3ExprListIsConstant(Parse *pParse, ExprList *pList, int bNoIs);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
#endif
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*, int);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
+SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
@@ -21831,17 +22530,16 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i
SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,SrcList*, IdList*,
Select*,u8,Upsert*,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,SrcList*,SrcList*,ExprList*,
Expr*, u8, const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,SrcList*, Expr*,
const char*,const char*);
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
-SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
#else
@@ -21855,7 +22553,6 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
# define sqlite3ParseToplevel(p) p
# define sqlite3IsToplevel(p) 1
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
-# define sqlite3TriggerStepSrc(A,B) 0
#endif
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
@@ -21888,7 +22585,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64);
SQLITE_PRIVATE i64 sqlite3RealToI64(double);
SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*);
-SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
+SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*);
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
@@ -21913,6 +22610,7 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int);
*/
SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64);
SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *, u64 *);
+SQLITE_PRIVATE i64 sqlite3VarintValue(const unsigned char*);
SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *, u32 *);
SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
@@ -21928,9 +22626,6 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
#define putVarint32(A,B) \
(u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
sqlite3PutVarint((A),(B)))
-#define getVarint sqlite3GetVarint
-#define putVarint sqlite3PutVarint
-
SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3*,const Table*);
@@ -21966,14 +22661,23 @@ SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs*);
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
+SQLITE_PRIVATE int sqlite3BinaryCompare(void*,int,const void*,int,const void*);
+#if SQLITE_USES_INLINE
+static SQLITE_INLINE int sqlite3IsBinary(const CollSeq *p){
+ assert( p==0 || p->xCmp!=sqlite3BinaryCompare
+ || strcmp(p->zName,"BINARY")==0 );
+ return p==0 || p->xCmp==sqlite3BinaryCompare;
+}
+#else
SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*);
+#endif
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
-SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(const Parse *pParse, Expr*, const Token*, int);
-SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(const Parse*,Expr*,const char*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
@@ -22020,6 +22724,7 @@ SQLITE_PRIVATE const unsigned char *sqlite3aGTb;
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
+SQLITE_PRIVATE const sqlite3_str sqlite3OomStr;
#ifndef SQLITE_OMIT_WSD
SQLITE_PRIVATE int sqlite3PendingByte;
#endif
@@ -22032,10 +22737,21 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
+SQLITE_PRIVATE void sqlite3AlterAddConstraint(
+ Parse *pParse, /* Parse context */
+ SrcList *pSrc, /* Table to add constraint to */
+ Token *pFirst, /* First token of new constraint */
+ Token *pName, /* Name of new constraint. NULL if name omitted. */
+ const char *zExpr, /* Text of CHECK expression */
+ int nExpr, /* Size of pExpr in bytes */
+ Expr *pExpr /* The parsed CHECK expression */
+);
+SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
-SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*);
@@ -22108,9 +22824,9 @@ SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64);
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64);
+SQLITE_PRIVATE int sqlite3StrAccumEnlargeIfNeeded(StrAccum*, i64);
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum*, u8);
-SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);
SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int);
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3*,const char*);
@@ -22203,10 +22919,12 @@ SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3*, Table*);
+SQLITE_PRIVATE void sqlite3VtabEponymousTableClearAll(sqlite3*);
#else
# define sqlite3ShadowTableName(A,B) 0
# define sqlite3IsShadowTableOf(A,B,C) 0
# define sqlite3MarkAllShadowTablesOf(A,B)
+# define sqlite3VtabEponymousTableClearAll(X)
#endif
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
@@ -22361,6 +23079,10 @@ SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr*,int);
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
+SQLITE_PRIVATE SQLITE_OPT_INLINE u64 sqlite3Get8byte(const u8*);
+#if SQLITE_BYTEORDER!=4321
+SQLITE_PRIVATE SQLITE_OPT_INLINE u64 sqlite3BSwap64(u64);
+#endif
SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32);
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
@@ -23058,6 +23780,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_MAX_PAGE_SIZE
"MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
#endif
+#ifdef SQLITE_MAX_SCHEMA
+ "MAX_SCHEMA=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA),
+#endif
#ifdef SQLITE_MAX_SCHEMA_RETRY
"MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
#endif
@@ -23335,6 +24060,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_STMTJRNL_SPILL
"STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
#endif
+#ifdef SQLITE_STRICT_SUBTYPE
+ "STRICT_SUBTYPE",
+#endif
#ifdef SQLITE_SUBSTR_COMPATIBILITY
"SUBSTR_COMPATIBILITY",
#endif
@@ -23706,6 +24434,16 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
*/
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
+/*
+** This singleton is an sqlite3_str object that is returned if
+** sqlite3_malloc() fails to provide space for a real one. This
+** sqlite3_str object accepts no new text and always returns
+** an SQLITE_NOMEM error.
+*/
+SQLITE_PRIVATE const sqlite3_str sqlite3OomStr = {
+ 0, 0, 0, 0, 0, SQLITE_NOMEM, 0
+};
+
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
/*
** Counter used for coverage testing. Does not come into play for
@@ -24339,7 +25077,9 @@ struct Vdbe {
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
int nFrame; /* Number of frames in pFrame list */
- u32 expmask; /* Binding to these vars invalidates VM */
+ u32 expmask; /* Binding to these vars might invalidate VM */
+ u32 smimask; /* Only invalid if changing to/from small integer */
+ /* Note: smimask is always a subset of expmask */
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
AuxData *pAuxData; /* Linked list of auxdata allocations */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
@@ -24407,6 +25147,17 @@ struct ValueList {
SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[];
#endif
+/* Input "x" is a sequence of unsigned characters that represent a
+** big-endian integer. Return the equivalent native integer
+*/
+#define ONE_BYTE_INT(x) ((i8)(x)[0])
+#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
+#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
+#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
+#define FOUR_BYTE_U64(x) (((u64)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
+#define FOUR_BYTE_INT(x) ((int)FOUR_BYTE_UINT(x))
+#define SIX_BYTE_INT(x) (FOUR_BYTE_UINT(x+2)+4294967296LL*TWO_BYTE_INT(x))
+
/*
** Function prototypes
*/
@@ -24450,6 +25201,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
+SQLITE_PRIVATE int sqlite3VdbeMemSetText(Mem*, const char*, i64, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
@@ -24468,13 +25220,14 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int);
SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
#endif
SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
-SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double);
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
+SQLITE_PRIVATE int sqlite3MemRealValueRC(Mem*, double*);
SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
@@ -24505,6 +25258,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
+SQLITE_PRIVATE int sqlite3VdbeFindIndexKey(BtCursor*, Index*, UnpackedRecord*, int*, int);
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
@@ -25238,6 +25992,7 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
}else{
s = 0;
}
+ if( h==24 && (m!=0 || s!=0 || ms!=0.0) ) return 1;
p->validJD = 0;
p->rawS = 0;
p->validHMS = 1;
@@ -25274,6 +26029,10 @@ static void computeJD(DateTime *p){
Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */
M = 1;
D = 1;
+ if( p->validHMS && p->h==24 ){
+ p->h = 0;
+ D = 2;
+ }
}
if( Y<-4713 || Y>9999 || p->rawS ){
datetimeError(p);
@@ -25302,6 +26061,21 @@ static void computeJD(DateTime *p){
}
}
+/*
+** Return the number of dates in a specific month.
+*/
+static int daysOfMonth(int Y, int M){
+ if( (1<validYMD || p->isError );
- assert( p->D>=0 && p->D<=31 );
+ assert( p->D>=0 && p->D<=32 );
assert( p->M>=0 && p->M<=12 );
- if( p->D<=28 ){
- p->nFloor = 0;
- }else if( (1<M) & 0x15aa ){
- p->nFloor = 0;
- }else if( p->M!=2 ){
- p->nFloor = (p->D==31);
- }else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){
- p->nFloor = p->D - 28;
- }else{
- p->nFloor = p->D - 29;
- }
+ mxD = daysOfMonth(p->Y, p->M);
+ p->nFloor = p->D>mxD ? p->D - mxD : 0;
}
/*
@@ -25352,7 +26118,19 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
zDate += 10;
while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
if( parseHhMmSs(zDate, p)==0 ){
- /* We got the time */
+ if( p->h==24 ){
+ int mxD = daysOfMonth(Y,M);
+ p->h = 0;
+ D++;
+ if( D>mxD ){
+ D -= mxD;
+ M++;
+ if( M>12 ){
+ M = 1;
+ Y++;
+ }
+ }
+ }
}else if( *zDate==0 ){
p->validHMS = 0;
}else{
@@ -25434,7 +26212,7 @@ static int parseDateOrTime(
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
return setDateTimeToCurrent(context, p);
- }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
+ }else if( sqlite3AtoF(zDate, &r)>0 ){
setRawDateNumber(p, r);
return 0;
}else if( (sqlite3StrICmp(zDate,"subsec")==0
@@ -25772,6 +26550,49 @@ static int parseModifier(
}
break;
}
+ case 'e': {
+ /*
+ ** end of day
+ ** end of month
+ ** end of year
+ **
+ ** Move the date forwards to the last millisecond of the current
+ ** day, month or year.
+ */
+ if( sqlite3_strnicmp(z, "end of ", 7)!=0 ){
+ break;
+ }
+ if( !p->validJD && !p->validYMD && !p->validHMS ) break;
+ z += 7;
+ computeYMD(p);
+ p->validHMS = 1;
+ p->h = 23;
+ p->m = 59;
+ p->s = 59.999;
+ p->rawS = 0;
+ p->tz = 0;
+ p->validJD = 0;
+ if( sqlite3_stricmp(z,"month")==0 ){
+ p->D = 1;
+ p->M++;
+ if( p->M>12 ){
+ p->Y++;
+ p->M = 1;
+ }
+ computeFloor(p);
+ computeJD(p);
+ p->iJD -= (p->nFloor+1)*86400000;
+ clearYMD_HMS_TZ(p);
+ rc = 0;
+ }else if( sqlite3_stricmp(z,"year")==0 ){
+ p->M = 12;
+ p->D = 31;
+ rc = 0;
+ }else if( sqlite3_stricmp(z,"day")==0 ){
+ rc = 0;
+ }
+ break;
+ }
case 'f': {
/*
** floor
@@ -25874,22 +26695,30 @@ static int parseModifier(
case 'w': {
/*
** weekday N
+ ** weekday -N
**
- ** Move the date to the same time on the next occurrence of
- ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
- ** date is already on the appropriate weekday, this is a no-op.
+ ** Move the date forward (for N>=0) or backward (for N<=-0) to the
+ ** same time on the next/previous occurrence of weekday abs(N)
+ ** where 0==Sunday, 1==Monday, and so forth. If the date is already
+ ** on the appropriate weekday, this is a no-op.
*/
if( sqlite3_strnicmp(z, "weekday ", 8)==0
- && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
- && r>=0.0 && r<7.0 && (n=(int)r)==r ){
+ && sqlite3AtoF(&z[8], &r)>0
+ && r>=-6.0 && r<=6.0
+ && sqlite3RealSameAsInt(r,(i64)(n=(int)r))
+ ){
sqlite3_int64 Z;
computeYMD_HMS(p);
p->tz = 0;
p->validJD = 0;
computeJD(p);
Z = ((p->iJD + 129600000)/86400000) % 7;
- if( Z>n ) Z -= 7;
- p->iJD += (n - Z)*86400000;
+ if( n<0 ) n = -n;
+ if( Z!=n ){
+ if( Z>n ) Z -= 7;
+ p->iJD += (n - Z)*86400000;
+ if( strchr(z+8,'-')!=0 ) p->iJD -= 7*86400000;
+ }
clearYMD_HMS_TZ(p);
rc = 0;
}
@@ -25897,7 +26726,9 @@ static int parseModifier(
}
case 's': {
/*
- ** start of TTTTT
+ ** start of day
+ ** start of month
+ ** start of year
**
** Move the date backwards to the beginning of the current day,
** or month or year.
@@ -25951,9 +26782,11 @@ static int parseModifier(
case '8':
case '9': {
double rRounder;
- int i;
+ int i, rx;
int Y,M,D,h,m,x;
const char *z2 = z;
+ char *zCopy;
+ sqlite3 *db = sqlite3_context_db_handle(pCtx);
char z0 = z[0];
for(n=1; z[n]; n++){
if( z[n]==':' ) break;
@@ -25963,7 +26796,11 @@ static int parseModifier(
if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
}
}
- if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
+ zCopy = sqlite3DbStrNDup(db, z, n);
+ if( zCopy==0 ) break;
+ rx = sqlite3AtoF(zCopy, &r)<=0;
+ sqlite3DbFree(db, zCopy);
+ if( rx ){
assert( rc==1 );
break;
}
@@ -26415,38 +27252,38 @@ static void strftimeFunc(
size_t i,j;
sqlite3 *db;
const char *zFmt;
- sqlite3_str sRes;
+ sqlite3_str *pRes;
if( argc==0 ) return;
zFmt = (const char*)sqlite3_value_text(argv[0]);
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
db = sqlite3_context_db_handle(context);
- sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
+ pRes = sqlite3_str_new(db);
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
char cf;
if( zFmt[i]!='%' ) continue;
- if( j59.999) ) s = 59.999;
- sqlite3_str_appendf(&sRes, "%06.3f", s);
+ sqlite3_str_appendf(pRes, "%06.3f", s);
break;
}
case 'F': {
- sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
+ sqlite3_str_appendf(pRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
break;
}
case 'G': /* Fall thru */
@@ -26458,15 +27295,15 @@ static void strftimeFunc(
y.validYMD = 0;
computeYMD(&y);
if( cf=='g' ){
- sqlite3_str_appendf(&sRes, "%02d", y.Y%100);
+ sqlite3_str_appendf(pRes, "%02d", y.Y%100);
}else{
- sqlite3_str_appendf(&sRes, "%04d", y.Y);
+ sqlite3_str_appendf(pRes, "%04d", y.Y);
}
break;
}
case 'H':
case 'k': {
- sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h);
+ sqlite3_str_appendf(pRes, cf=='H' ? "%02d" : "%2d", x.h);
break;
}
case 'I': /* Fall thru */
@@ -26474,65 +27311,65 @@ static void strftimeFunc(
int h = x.h;
if( h>12 ) h -= 12;
if( h==0 ) h = 12;
- sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h);
+ sqlite3_str_appendf(pRes, cf=='I' ? "%02d" : "%2d", h);
break;
}
case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */
- sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1);
+ sqlite3_str_appendf(pRes,"%03d",daysAfterJan01(&x)+1);
break;
}
case 'J': { /* Julian day number. (Non-standard) */
- sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
+ sqlite3_str_appendf(pRes,"%.16g",x.iJD/86400000.0);
break;
}
case 'm': {
- sqlite3_str_appendf(&sRes,"%02d",x.M);
+ sqlite3_str_appendf(pRes,"%02d",x.M);
break;
}
case 'M': {
- sqlite3_str_appendf(&sRes,"%02d",x.m);
+ sqlite3_str_appendf(pRes,"%02d",x.m);
break;
}
case 'p': /* Fall thru */
case 'P': {
if( x.h>=12 ){
- sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2);
+ sqlite3_str_append(pRes, cf=='p' ? "PM" : "pm", 2);
}else{
- sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2);
+ sqlite3_str_append(pRes, cf=='p' ? "AM" : "am", 2);
}
break;
}
case 'R': {
- sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m);
+ sqlite3_str_appendf(pRes, "%02d:%02d", x.h, x.m);
break;
}
case 's': {
if( x.useSubsec ){
- sqlite3_str_appendf(&sRes,"%.3f",
+ sqlite3_str_appendf(pRes,"%.3f",
(x.iJD - 21086676*(i64)10000000)/1000.0);
}else{
i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
- sqlite3_str_appendf(&sRes,"%lld",iS);
+ sqlite3_str_appendf(pRes,"%lld",iS);
}
break;
}
case 'S': {
- sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
+ sqlite3_str_appendf(pRes,"%02d",(int)x.s);
break;
}
case 'T': {
- sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
+ sqlite3_str_appendf(pRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
break;
}
case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */
case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */
char c = (char)daysAfterSunday(&x) + '0';
if( c=='0' && cf=='u' ) c = '7';
- sqlite3_str_appendchar(&sRes, 1, c);
+ sqlite3_str_appendchar(pRes, 1, c);
break;
}
case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */
- sqlite3_str_appendf(&sRes,"%02d",
+ sqlite3_str_appendf(pRes,"%02d",
(daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7);
break;
}
@@ -26543,30 +27380,30 @@ static void strftimeFunc(
y.iJD += (3 - daysAfterMonday(&x))*86400000;
y.validYMD = 0;
computeYMD(&y);
- sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1);
+ sqlite3_str_appendf(pRes,"%02d", daysAfterJan01(&y)/7+1);
break;
}
case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */
- sqlite3_str_appendf(&sRes,"%02d",
+ sqlite3_str_appendf(pRes,"%02d",
(daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7);
break;
}
case 'Y': {
- sqlite3_str_appendf(&sRes,"%04d",x.Y);
+ sqlite3_str_appendf(pRes,"%04d",x.Y);
break;
}
case '%': {
- sqlite3_str_appendchar(&sRes, 1, '%');
+ sqlite3_str_appendchar(pRes, 1, '%');
break;
}
default: {
- sqlite3_str_reset(&sRes);
+ sqlite3_str_free(pRes);
return;
}
}
}
- if( jxCurrentTime(pVfs, &r);
- *pTimeOut = (sqlite3_int64)(r*86400000.0);
+ *pTimeOut = sqlite3RealToI64(r*86400000.0);
}
return rc;
}
@@ -29562,23 +30399,28 @@ static SQLITE_WSD int mutexIsInit = 0;
#ifndef SQLITE_MUTEX_OMIT
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+#ifdef SQLITE_THREAD_MISUSE_WARNINGS
/*
-** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
+** This block (enclosed by SQLITE_THREAD_MISUSE_WARNINGS) contains
** the implementation of a wrapper around the system default mutex
** implementation (sqlite3DefaultMutex()).
**
** Most calls are passed directly through to the underlying default
** mutex implementation. Except, if a mutex is configured by calling
** sqlite3MutexWarnOnContention() on it, then if contention is ever
-** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
+** encountered within xMutexEnter() then a warning is emitted via
+** sqlite3_log(). Furthermore, if SQLITE_THREAD_MISUSE_ABORT is
+** defined then abort() is called after the sqlite3_log() warning.
**
-** This type of mutex is used as the database handle mutex when testing
-** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
+** This type of mutex is used on the database handle mutex when testing
+** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. A failure
+** indicates that the app ought to be using SQLITE_OPEN_FULLMUTEX or
+** similar because it is trying to use the same database handle from
+** two different connections at the same time.
*/
/*
-** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
+** Type for all mutexes used when SQLITE_THREAD_MISUSE_WARNINGS
** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
** allocated by the system mutex implementation. Variable iType is usually set
** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
@@ -29614,11 +30456,12 @@ static int checkMutexNotheld(sqlite3_mutex *p){
*/
static int checkMutexInit(void){
pGlobalMutexMethods = sqlite3DefaultMutex();
- return SQLITE_OK;
+ return pGlobalMutexMethods->xMutexInit();
}
static int checkMutexEnd(void){
+ int rc = pGlobalMutexMethods->xMutexEnd();
pGlobalMutexMethods = 0;
- return SQLITE_OK;
+ return rc;
}
/*
@@ -29695,6 +30538,9 @@ static void checkMutexEnter(sqlite3_mutex *p){
sqlite3_log(SQLITE_MISUSE,
"illegal multi-threaded access to database connection"
);
+#if SQLITE_THREAD_MISUSE_ABORT
+ abort();
+#endif
}
pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
}
@@ -29746,7 +30592,7 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
}
}
-#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
+#endif /* ifdef SQLITE_THREAD_MISUSE_WARNINGS */
/*
** Initialize the mutex system.
@@ -29763,7 +30609,7 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){
sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
if( sqlite3GlobalConfig.bCoreMutex ){
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+#ifdef SQLITE_THREAD_MISUSE_WARNINGS
pFrom = multiThreadedCheckMutex();
#else
pFrom = sqlite3DefaultMutex();
@@ -30165,8 +31011,15 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
# define SQLITE_MUTEX_NREF 0
#endif
+#if GCC_VERSION>0
+# define ALIGN128 __attribute__((aligned(128)))
+#else
+# define ALIGN128
+#endif
+
/*
-** Each recursive mutex is an instance of the following structure.
+** Each SQLite mutex is an instance of the following structure.
+**
*/
struct sqlite3_mutex {
pthread_mutex_t mutex; /* Mutex controlling the lock */
@@ -30281,19 +31134,31 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
** the same type number.
*/
static sqlite3_mutex *pthreadMutexAlloc(int iType){
- static sqlite3_mutex staticMutexes[] = {
- SQLITE3_MUTEX_INITIALIZER(2),
- SQLITE3_MUTEX_INITIALIZER(3),
- SQLITE3_MUTEX_INITIALIZER(4),
- SQLITE3_MUTEX_INITIALIZER(5),
- SQLITE3_MUTEX_INITIALIZER(6),
- SQLITE3_MUTEX_INITIALIZER(7),
- SQLITE3_MUTEX_INITIALIZER(8),
- SQLITE3_MUTEX_INITIALIZER(9),
- SQLITE3_MUTEX_INITIALIZER(10),
- SQLITE3_MUTEX_INITIALIZER(11),
- SQLITE3_MUTEX_INITIALIZER(12),
- SQLITE3_MUTEX_INITIALIZER(13)
+ /* Static mutexes - those with IDs of 2 or more...
+ **
+ ** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
+ ** so that adjacent mutex objects are always on different cache lines
+ ** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
+ ** seems to work well for all contemporary processors. Experiments show
+ ** that 64 works just as well most of the time, but the internet says
+ ** that 128-byte alignment works better.
+ */
+ static ALIGN128 union staticMutex {
+ sqlite3_mutex m;
+ char aSpacer[128];
+ } aMutex[] = {
+ { .m = SQLITE3_MUTEX_INITIALIZER(2) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(3) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(4) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(5) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(6) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(7) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(8) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(9) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(10) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(11) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(12) },
+ { .m = SQLITE3_MUTEX_INITIALIZER(13) },
};
sqlite3_mutex *p;
switch( iType ){
@@ -30330,12 +31195,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
}
default: {
#ifdef SQLITE_ENABLE_API_ARMOR
- if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
+ if( iType-2<0 || iType-2>=ArraySize(aMutex) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- p = &staticMutexes[iType-2];
+ p = &aMutex[iType-2].m;
break;
}
}
@@ -30580,61 +31445,11 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
# include /* amalgamator: dontcache */
#endif
-/*
-** Determine if we are dealing with Windows NT.
-**
-** We ought to be able to determine if we are compiling for Windows 9x or
-** Windows NT using the _WIN32_WINNT macro as follows:
-**
-** #if defined(_WIN32_WINNT)
-** # define SQLITE_OS_WINNT 1
-** #else
-** # define SQLITE_OS_WINNT 0
-** #endif
-**
-** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
-** it ought to, so the above test does not work. We'll just assume that
-** everything is Windows NT unless the programmer explicitly says otherwise
-** by setting SQLITE_OS_WINNT to 0.
-*/
-#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
-# define SQLITE_OS_WINNT 1
-#endif
-
-/*
-** Determine if we are dealing with Windows CE - which has a much reduced
-** API.
-*/
-#if defined(_WIN32_WCE)
-# define SQLITE_OS_WINCE 1
-#else
-# define SQLITE_OS_WINCE 0
-#endif
-
-/*
-** Determine if we are dealing with WinRT, which provides only a subset of
-** the full Win32 API.
-*/
-#if !defined(SQLITE_OS_WINRT)
-# define SQLITE_OS_WINRT 0
-#endif
-
-/*
-** For WinCE, some API function parameters do not appear to be declared as
-** volatile.
-*/
-#if SQLITE_OS_WINCE
-# define SQLITE_WIN32_VOLATILE
-#else
-# define SQLITE_WIN32_VOLATILE volatile
-#endif
-
/*
** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
** functions are not available (e.g. those not using MSVC, Cygwin, etc).
*/
-#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
- SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
+#if SQLITE_OS_WIN && SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
# define SQLITE_OS_WIN_THREADS 1
#else
# define SQLITE_OS_WIN_THREADS 0
@@ -30652,11 +31467,32 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
*/
#ifdef SQLITE_MUTEX_W32
+#if MSVC_VERSION>0
+# define ALIGN128 __declspec(align(128))
+#else
+# define ALIGN128
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4324)
+#endif /* _MSC_VER */
+
/*
-** Each recursive mutex is an instance of the following structure.
+** Each SQLite mutex is an instance of the following structure.
+**
+** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
+** so that adjacent mutex objects are always on different cache lines
+** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
+** seems to work well for all contemporary processors. Experiments show
+** that 64 works just as well most of the time, but the internet says
+** that 128-byte alignment works better.
*/
struct sqlite3_mutex {
- CRITICAL_SECTION mutex; /* Mutex controlling the lock */
+ union {
+ CRITICAL_SECTION cs; /* The CRITICAL_SECTION mutex. id==1 */
+ SRWLOCK srwl; /* The Slim reader/writer lock. id!=1 */
+ } u;
int id; /* Mutex type */
#ifdef SQLITE_DEBUG
volatile int nRef; /* Number of entrances */
@@ -30664,20 +31500,9 @@ struct sqlite3_mutex {
volatile LONG trace; /* True to trace changes */
#endif
};
-
-/*
-** These are the initializer values used when declaring a "static" mutex
-** on Win32. It should be noted that all mutexes require initialization
-** on the Win32 platform.
-*/
-#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
-
-#ifdef SQLITE_DEBUG
-#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
- 0L, (DWORD)0, 0 }
-#else
-#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
-#endif
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif /* _MSC_VER */
#ifdef SQLITE_DEBUG
/*
@@ -30688,13 +31513,8 @@ static int winMutexHeld(sqlite3_mutex *p){
return p->nRef!=0 && p->owner==GetCurrentThreadId();
}
-static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
- return p->nRef==0 || p->owner!=tid;
-}
-
static int winMutexNotheld(sqlite3_mutex *p){
- DWORD tid = GetCurrentThreadId();
- return winMutexNotheld2(p, tid);
+ return p->nRef==0 || p->owner!=GetCurrentThreadId();
}
#endif
@@ -30716,44 +31536,41 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
}
/*
-** Initialize and deinitialize the mutex subsystem.
+** Static mutexes.
+**
+** The ALIGN128 macro on the static mutex array forces 128-byte alignment
+** on the mutexes so that adjacent mutex objects are always on different
+** cache lines in the CPU. This is CPU-dependent, of course, but 128-byte
+** alignment seems to work well for all contemporary processors.
+** Experiments show that 64 works just as well most of the time, but
+** the internet says that 128-byte alignment works better.
*/
-static sqlite3_mutex winMutex_staticMutexes[] = {
- SQLITE3_MUTEX_INITIALIZER(2),
- SQLITE3_MUTEX_INITIALIZER(3),
- SQLITE3_MUTEX_INITIALIZER(4),
- SQLITE3_MUTEX_INITIALIZER(5),
- SQLITE3_MUTEX_INITIALIZER(6),
- SQLITE3_MUTEX_INITIALIZER(7),
- SQLITE3_MUTEX_INITIALIZER(8),
- SQLITE3_MUTEX_INITIALIZER(9),
- SQLITE3_MUTEX_INITIALIZER(10),
- SQLITE3_MUTEX_INITIALIZER(11),
- SQLITE3_MUTEX_INITIALIZER(12),
- SQLITE3_MUTEX_INITIALIZER(13)
-};
-
+static ALIGN128 union staticMutexes {
+ sqlite3_mutex m;
+ char spacer[128];
+} aWindowsMutex[12];
static int winMutex_isInit = 0;
-static int winMutex_isNt = -1; /* <0 means "need to query" */
/* As the winMutexInit() and winMutexEnd() functions are called as part
** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
** "interlocked" magic used here is probably not strictly necessary.
*/
-static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
+static LONG volatile winMutex_lock = 0;
-SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
static int winMutexInit(void){
/* The first to increment to 1 does actual initialization */
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
int i;
- for(i=0; iid = i+2;
+ InitializeSRWLock(&p->u.srwl);
+#ifdef SQLITE_DEBUG
+ p->nRef = 0;
+ p->owner = 0;
+ p->trace = 0;
#endif
}
winMutex_isInit = 1;
@@ -30772,10 +31589,6 @@ static int winMutexEnd(void){
** (which should be the last to shutdown.) */
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
if( winMutex_isInit==1 ){
- int i;
- for(i=0; itrace = 1;
#endif
#endif
-#if SQLITE_OS_WINRT
- InitializeCriticalSectionEx(&p->mutex, 0, 0);
-#else
- InitializeCriticalSection(&p->mutex);
-#endif
+ if( iType==SQLITE_MUTEX_RECURSIVE ){
+ InitializeCriticalSection(&p->u.cs);
+ }else{
+ InitializeSRWLock(&p->u.srwl);
+ }
}
break;
}
default: {
#ifdef SQLITE_ENABLE_API_ARMOR
- if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
+ if( iType-2<0 || iType-2>=ArraySize(aWindowsMutex) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- p = &winMutex_staticMutexes[iType-2];
+ p = &aWindowsMutex[iType-2].m;
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
InterlockedCompareExchange(&p->trace, 1, 0);
@@ -30881,8 +31694,10 @@ static sqlite3_mutex *winMutexAlloc(int iType){
static void winMutexFree(sqlite3_mutex *p){
assert( p );
assert( p->nRef==0 && p->owner==0 );
- if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
- DeleteCriticalSection(&p->mutex);
+ if( p->id==SQLITE_MUTEX_FAST ){
+ sqlite3_free(p);
+ }else if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ DeleteCriticalSection(&p->u.cs);
sqlite3_free(p);
}else{
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -30903,67 +31718,56 @@ static void winMutexFree(sqlite3_mutex *p){
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- DWORD tid = GetCurrentThreadId();
-#endif
-#ifdef SQLITE_DEBUG
- assert( p );
- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
-#else
assert( p );
+#ifdef SQLITE_DEBUG
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
#endif
assert( winMutex_isInit==1 );
- EnterCriticalSection(&p->mutex);
+ if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ EnterCriticalSection(&p->u.cs);
+ }else{
+ AcquireSRWLockExclusive(&p->u.srwl);
+ }
#ifdef SQLITE_DEBUG
assert( p->nRef>0 || p->owner==0 );
- p->owner = tid;
+ p->owner = GetCurrentThreadId();
p->nRef++;
if( p->trace ){
OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
- tid, p->id, p, p->trace, p->nRef));
+ GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
}
#endif
}
static int winMutexTry(sqlite3_mutex *p){
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- DWORD tid = GetCurrentThreadId();
-#endif
int rc = SQLITE_BUSY;
assert( p );
- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
/*
- ** The sqlite3_mutex_try() routine is very rarely used, and when it
- ** is used it is merely an optimization. So it is OK for it to always
+ ** The sqlite3_mutex_try() routine is seldom used, and when it is
+ ** used it is merely an optimization. So it is OK for it to always
** fail.
- **
- ** The TryEnterCriticalSection() interface is only available on WinNT.
- ** And some windows compilers complain if you try to use it without
- ** first doing some #defines that prevent SQLite from building on Win98.
- ** For that reason, we will omit this optimization for now. See
- ** ticket #2685.
*/
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
- assert( winMutex_isInit==1 );
- assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
- if( winMutex_isNt<0 ){
- winMutex_isNt = sqlite3_win32_is_nt();
+ if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ rc = TryEnterCriticalSection(&p->u.cs);
+ }else{
+ rc = TryAcquireSRWLockExclusive(&p->u.srwl);
}
- assert( winMutex_isNt==0 || winMutex_isNt==1 );
- if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
+ if( rc ){
#ifdef SQLITE_DEBUG
- p->owner = tid;
+ p->owner = GetCurrentThreadId();
p->nRef++;
#endif
rc = SQLITE_OK;
+ }else{
+ rc = SQLITE_BUSY;
}
-#else
- UNUSED_PARAMETER(p);
-#endif
#ifdef SQLITE_DEBUG
if( p->trace ){
- OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
- tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
+ OSTRACE((
+ "TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
+ GetCurrentThreadId(), p->id, p, p->trace, p->owner, p->nRef,
+ sqlite3ErrName(rc)));
}
#endif
return rc;
@@ -30976,23 +31780,24 @@ static int winMutexTry(sqlite3_mutex *p){
** is not currently allocated. SQLite will never do either.
*/
static void winMutexLeave(sqlite3_mutex *p){
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- DWORD tid = GetCurrentThreadId();
-#endif
assert( p );
#ifdef SQLITE_DEBUG
assert( p->nRef>0 );
- assert( p->owner==tid );
+ assert( p->owner==GetCurrentThreadId() );
p->nRef--;
if( p->nRef==0 ) p->owner = 0;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
assert( winMutex_isInit==1 );
- LeaveCriticalSection(&p->mutex);
+ if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ LeaveCriticalSection(&p->u.cs);
+ }else{
+ ReleaseSRWLockExclusive(&p->u.srwl);
+ }
#ifdef SQLITE_DEBUG
if( p->trace ){
OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
- tid, p->id, p, p->trace, p->nRef));
+ GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
}
#endif
}
@@ -31312,27 +32117,6 @@ static void mallocWithAlarm(int n, void **pp){
*pp = p;
}
-/*
-** Maximum size of any single memory allocation.
-**
-** This is not a limit on the total amount of memory used. This is
-** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
-**
-** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
-** This provides a 256-byte safety margin for defense against 32-bit
-** signed integer overflow bugs when computing memory allocation sizes.
-** Paranoid applications might want to reduce the maximum allocation size
-** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
-** or even smaller would be reasonable upper bounds on the size of a memory
-** allocations for most applications.
-*/
-#ifndef SQLITE_MAX_ALLOCATION_SIZE
-# define SQLITE_MAX_ALLOCATION_SIZE 2147483391
-#endif
-#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
-# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
-#endif
-
/*
** Allocate memory. This routine is like sqlite3_malloc() except that it
** assumes the memory subsystem has already been initialized.
@@ -31556,8 +32340,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
sqlite3_free(pOld); /* IMP: R-26507-47431 */
return 0;
}
- if( nBytes>=0x7fffff00 ){
- /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
+ if( nBytes>SQLITE_MAX_ALLOCATION_SIZE ){
return 0;
}
nOld = sqlite3MallocSize(pOld);
@@ -31980,8 +32763,10 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
#define etDECIMAL 16 /* %d or %u, but not %x, %o */
+#define etESCAPE_j 17 /* %j -> JSON string literal w/o "..." */
+#define etESCAPE_J 18 /* %J -> JSON string literal with "..." */
-#define etINVALID 17 /* Any unrecognized conversion type */
+#define etINVALID 19 /* Any unrecognized conversion type */
/*
@@ -32011,20 +32796,20 @@ typedef struct et_info { /* Information about each format field */
/*
** The table is searched by hash. In the case of %C where C is the character
-** and that character has ASCII value j, then the hash is j%23.
+** and that character has ASCII value j, then the hash is j%25.
**
** The order of the entries in fmtinfo[] and the hash chain was entered
** manually, but based on the output of the following TCL script:
*/
#if 0 /***** Beginning of script ******/
-foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} {
+foreach c {d s g z q Q w c o u x X f e E G i n % p T S r J j} {
scan $c %c x
set n($c) $x
}
set mx [llength [array names n]]
puts "count: $mx"
-set mx 27
+set mx 25
puts "*********** mx=$mx ************"
for {set r 0} {$r<$mx} {incr r} {
puts -nonewline [format %2d: $r]
@@ -32036,31 +32821,34 @@ for {set r 0} {$r<$mx} {incr r} {
#endif /***** End of script ********/
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
+static const char aHex[] = "0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
-static const et_info fmtinfo[23] = {
- /* 0 */ { 's', 0, 4, etSTRING, 0, 0, 1 },
- /* 1 */ { 'E', 0, 1, etEXP, 14, 0, 0 }, /* Hash: 0 */
- /* 2 */ { 'u', 10, 0, etDECIMAL, 0, 0, 3 },
- /* 3 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 }, /* Hash: 2 */
- /* 4 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 },
- /* 5 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
- /* 6 */ { 'c', 0, 0, etCHARX, 0, 0, 0 }, /* Hash: 7 */
- /* 7 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 6 },
- /* 8 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
- /* 9 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
- /* 10 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
- /* 11 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
- /* 12 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 0 },
- /* 13 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
- /* 14 */ { '%', 0, 0, etPERCENT, 0, 0, 16 },
- /* 15 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
- /* 16 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 }, /* Hash: 14 */
- /* 17 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 19 */
- /* 18 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
- /* 19 */ { 'o', 8, 0, etRADIX, 0, 2, 17 },
- /* 20 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 },
- /* 21 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 0 },
- /* 22 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 }
+static const et_info fmtinfo[25] = {
+ /* 0 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
+ /* 1 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
+ /* 2 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
+ /* 3 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
+ /* 4 */ { 'j', 0, 0, etESCAPE_j, 0, 0, 0 }, /* Hash: 6 */
+ /* 5 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
+ /* 6 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 4 },
+ /* 7 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 }, /* Hash: 12 */
+ /* 8 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 },
+ /* 9 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
+ /* 10 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
+ /* 11 */ { 'o', 8, 0, etRADIX, 0, 2, 0 },
+ /* 12 */ { '%', 0, 0, etPERCENT, 0, 0, 7 },
+ /* 13 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 16 },
+ /* 14 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 },
+ /* 15 */ { 's', 0, 4, etSTRING, 0, 0, 0 },
+ /* 16 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 13 */
+ /* 17 */ { 'u', 10, 0, etDECIMAL, 0, 0, 0 },
+ /* 18 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 }, /* Hash: 19 */
+ /* 19 */ { 'E', 0, 1, etEXP, 14, 0, 18 },
+ /* 20 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
+ /* 21 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 },
+ /* 22 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 0 },
+ /* 23 */ { 'J', 0, 0, etESCAPE_J, 0, 0, 0 }, /* Hash: 24 */
+ /* 24 */ { 'c', 0, 0, etCHARX, 0, 0, 23 }
};
/* Additional Notes:
@@ -32111,7 +32899,7 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
return 0;
}
- z = sqlite3DbMallocRaw(pAccum->db, n);
+ z = sqlite3_malloc(n);
if( z==0 ){
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
}
@@ -32128,12 +32916,23 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
/*
-** Hard limit on the precision of floating-point conversions.
+** Hard limit on the precision of floating-point conversions to
+** the minimum of SQLITE_PRINTF_PRECISION_LIMIT and 100 million.
*/
-#ifndef SQLITE_PRINTF_PRECISION_LIMIT
+#ifdef SQLITE_PRINTF_PRECISION_LIMIT
+# if SQLITE_PRINTF_PRECISION_LIMIT<100000000
+# define SQLITE_FP_PRECISION_LIMIT SQLITE_PRINTF_PRECISION_LIMIT
+# else
+# define SQLITE_FP_PRECISION_LIMIT 100000000
+# endif
+#else
# define SQLITE_FP_PRECISION_LIMIT 100000000
#endif
+/* Forward reference */
+static void sqlite3StrAppend64(sqlite3_str *p, const char *z, i64 N);
+static void sqlite3StrAppendchar64(sqlite3_str *p, i64 N, char c);
+
/*
** Render a string given by "fmt" into the StrAccum object.
*/
@@ -32144,10 +32943,10 @@ SQLITE_API void sqlite3_str_vappendf(
){
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
- int precision; /* Precision of the current field */
- int length; /* Length of the field */
+ i64 precision; /* Precision of the current field */
+ i64 length; /* Length of the field */
int idx; /* A general purpose loop counter */
- int width; /* Width of the current field */
+ i64 width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */
etByte flag_prefix; /* '+' or ' ' or 0 for prefix */
etByte flag_alternateform; /* True if "#" flag is present */
@@ -32195,7 +32994,7 @@ SQLITE_API void sqlite3_str_vappendf(
fmt = bufpt + strlen(bufpt);
}
#endif
- sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));
+ sqlite3StrAppend64(pAccum, bufpt, fmt - bufpt);
if( *fmt==0 ) break;
}
if( (c=(*++fmt))==0 ){
@@ -32321,8 +33120,8 @@ SQLITE_API void sqlite3_str_vappendf(
}
#else
/* Fast hash-table lookup */
- assert( ArraySize(fmtinfo)==23 );
- idx = ((unsigned)c) % 23;
+ assert( ArraySize(fmtinfo)==25 );
+ idx = ((unsigned)c) % 25;
if( fmtinfo[idx].fmttype==c
|| fmtinfo[idx = fmtinfo[idx].iNxt].fmttype==c
){
@@ -32441,20 +33240,23 @@ SQLITE_API void sqlite3_str_vappendf(
longvalue = longvalue/base;
}while( longvalue>0 );
}
- length = (int)(&zOut[nOut-1]-bufpt);
- while( precision>length ){
- *(--bufpt) = '0'; /* Zero pad */
- length++;
+ length = &zOut[nOut-1] - bufpt;
+ if( precision>length ){ /* zero pad */
+ i64 nn = precision-length;
+ bufpt -= nn;
+ memset(bufpt,'0',nn);
+ length = precision;
}
if( cThousand ){
- int nn = (length - 1)/3; /* Number of "," to insert */
- int ix = (length - 1)%3 + 1;
+ i64 nn = (length - 1)/3; /* Number of "," to insert */
+ i64 ix = (length - 1)%3 + 1;
+ int ii;
bufpt -= nn;
- for(idx=0; nn>0; idx++){
- bufpt[idx] = bufpt[idx+nn];
+ for(ii=0; nn>0; ii++){
+ bufpt[ii] = bufpt[ii+nn];
ix--;
if( ix==0 ){
- bufpt[++idx] = cThousand;
+ bufpt[++ii] = cThousand;
nn--;
ix = 3;
}
@@ -32467,7 +33269,7 @@ SQLITE_API void sqlite3_str_vappendf(
pre = &aPrefix[infop->prefix];
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
}
- length = (int)(&zOut[nOut-1]-bufpt);
+ length = &zOut[nOut-1] - bufpt;
break;
case etFLOAT:
case etEXP:
@@ -32475,6 +33277,7 @@ SQLITE_API void sqlite3_str_vappendf(
FpDecode s;
int iRound;
int j;
+ i64 szBufNeeded; /* Size needed to hold the output */
if( bArgList ){
realvalue = getDoubleArg(pArgList);
@@ -32482,11 +33285,9 @@ SQLITE_API void sqlite3_str_vappendf(
realvalue = va_arg(ap,double);
}
if( precision<0 ) precision = 6; /* Set default precision */
-#ifdef SQLITE_FP_PRECISION_LIMIT
if( precision>SQLITE_FP_PRECISION_LIMIT ){
precision = SQLITE_FP_PRECISION_LIMIT;
}
-#endif
if( xtype==etFLOAT ){
iRound = -precision;
}else if( xtype==etGENERIC ){
@@ -32495,11 +33296,16 @@ SQLITE_API void sqlite3_str_vappendf(
}else{
iRound = precision+1;
}
- sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
+ sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16);
if( s.isSpecial ){
if( s.isSpecial==2 ){
- bufpt = flag_zeropad ? "null" : "NaN";
- length = sqlite3Strlen30(bufpt);
+ if( flag_zeropad ){
+ bufpt = "null";
+ length = 4;
+ }else{
+ bufpt = "NaN";
+ length = 3;
+ }
break;
}else if( flag_zeropad ){
s.z[0] = '9';
@@ -32515,7 +33321,7 @@ SQLITE_API void sqlite3_str_vappendf(
}else{
bufpt++;
}
- length = sqlite3Strlen30(bufpt);
+ length = strlen(bufpt);
break;
}
}
@@ -32563,17 +33369,31 @@ SQLITE_API void sqlite3_str_vappendf(
}else{
e2 = s.iDP - 1;
}
- bufpt = buf;
- {
- i64 szBufNeeded; /* Size of a temporary buffer needed */
- szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;
- if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
- if( szBufNeeded > etBUFSIZE ){
- bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);
- if( bufpt==0 ) return;
+
+ szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+10;
+ if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
+ if( szBufNeeded + pAccum->nChar >= pAccum->nAlloc ){
+ if( pAccum->mxAlloc==0 && pAccum->accError==0 ){
+ /* Unable to allocate space in pAccum, perhaps because it
+ ** is coming from sqlite3_snprintf() or similar. We'll have
+ ** to render into temporary space and the memcpy() it over. */
+ bufpt = sqlite3_malloc64(szBufNeeded);
+ if( bufpt==0 ){
+ sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
+ return;
+ }
+ zExtra = bufpt;
+ }else if( sqlite3StrAccumEnlarge(pAccum, szBufNeeded)zText + pAccum->nChar;
}
+ }else{
+ bufpt = pAccum->zText + pAccum->nChar;
}
zOut = bufpt;
+
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if( prefix ){
@@ -32581,12 +33401,24 @@ SQLITE_API void sqlite3_str_vappendf(
}
/* Digits prior to the decimal point */
j = 0;
+ assert( s.n>0 );
if( e2<0 ){
*(bufpt++) = '0';
- }else{
+ }else if( cThousand ){
for(; e2>=0; e2--){
*(bufpt++) = j1 ) *(bufpt++) = ',';
+ if( (e2%3)==0 && e2>1 ) *(bufpt++) = ',';
+ }
+ }else{
+ j = e2+1;
+ if( j>s.n ) j = s.n;
+ memcpy(bufpt, s.z, j);
+ bufpt += j;
+ e2 -= j;
+ if( e2>=0 ){
+ memset(bufpt, '0', e2+1);
+ bufpt += e2+1;
+ e2 = -1;
}
}
/* The decimal point */
@@ -32595,12 +33427,26 @@ SQLITE_API void sqlite3_str_vappendf(
}
/* "0" digits after the decimal point but before the first
** significant digit of the number */
- for(e2++; e2<0 && precision>0; precision--, e2++){
- *(bufpt++) = '0';
+ if( e2<(-1) && precision>0 ){
+ int nn = -1-e2;
+ if( nn>precision ) nn = precision;
+ memset(bufpt, '0', nn);
+ bufpt += nn;
+ precision -= nn;
}
/* Significant digits after the decimal point */
- while( (precision--)>0 ){
- *(bufpt++) = j0 ){
+ int nn = s.n - j;
+ if( NEVER(nn>precision) ) nn = precision;
+ if( nn>0 ){
+ memcpy(bufpt, s.z+j, nn);
+ bufpt += nn;
+ precision -= nn;
+ }
+ if( precision>0 && !flag_rtz ){
+ memset(bufpt, '0', precision);
+ bufpt += precision;
+ }
}
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
@@ -32630,27 +33476,40 @@ SQLITE_API void sqlite3_str_vappendf(
*(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
*(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
}
- *bufpt = 0;
- /* The converted number is in buf[] and zero terminated. Output it.
- ** Note that the number is in the usual order, not reversed as with
- ** integer conversions. */
- length = (int)(bufpt-zOut);
- bufpt = zOut;
-
- /* Special case: Add leading zeros if the flag_zeropad flag is
- ** set and we are not left justified */
- if( flag_zeropad && !flag_leftjustify && length < width){
- int i;
- int nPad = width - length;
- for(i=width; i>=nPad; i--){
- bufpt[i] = bufpt[i-nPad];
+ length = bufpt - zOut;
+ assert( length <= szBufNeeded );
+ if( lengthnChar + length < SMXV(pAccum->nChar) );
+ pAccum->nChar += length;
+ zOut[length] = 0;
+ continue;
+ }else{
+ /* We were unable to render directly into pAccum because we
+ ** couldn't allocate sufficient memory. We need to memcpy()
+ ** the rendering (or some prefix thereof) into the output
+ ** buffer. */
+ bufpt[0] = 0;
+ bufpt = zExtra;
+ break;
+ }
}
case etSIZE:
if( !bArgList ){
@@ -32685,19 +33544,18 @@ SQLITE_API void sqlite3_str_vappendf(
i64 nPrior = 1;
width -= precision-1;
if( width>1 && !flag_leftjustify ){
- sqlite3_str_appendchar(pAccum, width-1, ' ');
+ sqlite3StrAppendchar64(pAccum, width-1, ' ');
width = 0;
}
- sqlite3_str_append(pAccum, buf, length);
+ sqlite3StrAppend64(pAccum, buf, length);
precision--;
while( precision > 1 ){
i64 nCopyBytes;
if( nPrior > precision-1 ) nPrior = precision - 1;
nCopyBytes = length*nPrior;
- if( nCopyBytes + pAccum->nChar >= pAccum->nAlloc ){
- sqlite3StrAccumEnlarge(pAccum, nCopyBytes);
+ if( sqlite3StrAccumEnlargeIfNeeded(pAccum, nCopyBytes) ){
+ break;
}
- if( pAccum->accError ) break;
sqlite3_str_append(pAccum,
&pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);
precision -= nPrior;
@@ -32745,20 +33603,97 @@ SQLITE_API void sqlite3_str_vappendf(
while( precision-- > 0 && z[0] ){
SQLITE_SKIP_UTF8(z);
}
- length = (int)(z - (unsigned char*)bufpt);
+ length = z - (unsigned char*)bufpt;
}else{
for(length=0; length0 ){
/* Adjust width to account for extra bytes in UTF-8 characters */
- int ii = length - 1;
+ i64 ii = length - 1;
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
}
break;
+ case etESCAPE_j: /* %j: JSON string literal w/o "..." */
+ case etESCAPE_J: { /* %J: Generate a JSON string literal */
+ char *escarg;
+ i64 i, j, px, iStart;
+ unsigned char ch;
+
+ if( bArgList ){
+ escarg = getTextArg(pArgList);
+ }else{
+ escarg = va_arg(ap,char*);
+ }
+ iStart = sqlite3_str_length(pAccum);
+ if( escarg==0 ){
+ if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "null", 4);
+ }else{
+ if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "\"", 1);
+ px = precision;
+ testcase( px==0 );
+ if( px<0 ){
+ px = 0x7fffffff;
+ }else if( flag_altform2 ){
+ /* Convert precision from code-points to bytes */
+ for(i=0; i0x1f ){
+ sqlite3_str_appendchar(pAccum, 1, ch);
+ }else if( ((1u<>4]);
+ sqlite3_str_appendchar(pAccum, 1, aHex[ch&0xf]);
+ }
+ }
+ }
+ if( j0 && sqlite3_str_errcode(pAccum)==SQLITE_OK ){
+ sqlite3_int64 n = sqlite3_str_length(pAccum) - iStart;
+ sqlite3_int64 len = n;
+ char *zz;
+ if( flag_altform2 && n>0 ){
+ zz = sqlite3_str_value(pAccum);
+ for(i=iStart; zz[i]; i++){
+ if( (zz[i]&0xc0)==0x80 ) len--;
+ }
+ }
+ if( width>len ){
+ sqlite3_int64 sp = width-len;
+ assert( sp>0 && sp<0x7fffffff );
+ sqlite3StrAppendchar64(pAccum, (int)sp, ' ');
+ if( !flag_leftjustify
+ && n>0
+ && sqlite3_str_errcode(pAccum)==0
+ ){
+ zz = sqlite3_str_value(pAccum);
+ zz += iStart;
+ memmove(zz+sp, zz, n);
+ memset(zz, ' ', sp);
+ }
+ }
+ }
+ continue;
+ }
case etESCAPE_q: /* %q: Escape ' characters */
case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */
case etESCAPE_w: { /* %w: Escape " characters */
@@ -32801,8 +33736,8 @@ SQLITE_API void sqlite3_str_vappendf(
** all control characters, and for backslash itself.
** For %#Q, do the same but only if there is at least
** one control character. */
- u32 nBack = 0;
- u32 nCtrl = 0;
+ i64 nBack = 0;
+ i64 nCtrl = 0;
for(k=0; k=0x10 ? '1' : '0';
- bufpt[j++] = "0123456789abcdef"[ch&0xf];
+ bufpt[j++] = aHex[ch&0xf];
}
}
}else{
@@ -32937,11 +33872,11 @@ SQLITE_API void sqlite3_str_vappendf(
*/
width -= length;
if( width>0 ){
- if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
- sqlite3_str_append(pAccum, bufpt, length);
- if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
+ if( !flag_leftjustify ) sqlite3StrAppendchar64(pAccum, width, ' ');
+ sqlite3StrAppend64(pAccum, bufpt, length);
+ if( flag_leftjustify ) sqlite3StrAppendchar64(pAccum, width, ' ');
}else{
- sqlite3_str_append(pAccum, bufpt, length);
+ sqlite3StrAppend64(pAccum, bufpt, length);
}
if( zExtra ){
@@ -32980,10 +33915,13 @@ SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){
** as the error offset.
*/
SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
- while( pExpr
- && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
- ){
- pExpr = pExpr->pLeft;
+ while( pExpr ){
+ if( ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) ) return;
+ if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0 ){
+ pExpr = pExpr->pLeft;
+ }else{
+ break;
+ }
}
if( pExpr==0 ) return;
if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
@@ -33044,6 +33982,13 @@ SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){
return (int)N;
}
+SQLITE_PRIVATE int sqlite3StrAccumEnlargeIfNeeded(StrAccum *p, i64 N){
+ if( N + p->nChar >= p->nAlloc ){
+ sqlite3StrAccumEnlarge(p, N);
+ }
+ return p->accError;
+}
+
/*
** Append N copies of character c to the given string buffer.
*/
@@ -33054,6 +33999,13 @@ SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){
}
while( (N--)>0 ) p->zText[p->nChar++] = c;
}
+static void sqlite3StrAppendchar64(sqlite3_str *p, i64 N, char c){
+ testcase( p->nChar + N > 0x7fffffff );
+ if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
+ return;
+ }
+ while( (N--)>0 ) p->zText[p->nChar++] = c;
+}
/*
** The StrAccum "p" is not large enough to accept N new bytes of z[].
@@ -33065,6 +34017,7 @@ SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){
*/
static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
N = sqlite3StrAccumEnlarge(p, N);
+ assert( z!=0 || N==0 );
if( N>0 ){
memcpy(&p->zText[p->nChar], z, N);
p->nChar += N;
@@ -33088,6 +34041,20 @@ SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
memcpy(&p->zText[p->nChar-N], z, N);
}
}
+static void sqlite3StrAppend64(sqlite3_str *p, const char *z, i64 N){
+ assert( z!=0 || N==0 );
+ assert( p->zText!=0 || p->nChar==0 || p->accError );
+ assert( N>=0 );
+ assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 );
+ if( p->nChar+N >= (i64)p->nAlloc ){
+ enlargeAndAppend(p,z,N);
+ }else if( N ){
+ assert( p->zText );
+ p->nChar += N;
+ memcpy(&p->zText[p->nChar-N], z, N);
+ }
+}
+
/*
** Append the complete text of zero-terminated string z[] to the p string.
@@ -33125,37 +34092,11 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
return p->zText;
}
-/*
-** Use the content of the StrAccum passed as the second argument
-** as the result of an SQL function.
-*/
-SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
- if( p->accError ){
- sqlite3_result_error_code(pCtx, p->accError);
- sqlite3_str_reset(p);
- }else if( isMalloced(p) ){
- sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
- }else{
- sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
- sqlite3_str_reset(p);
- }
-}
-
-/*
-** This singleton is an sqlite3_str object that is returned if
-** sqlite3_malloc() fails to provide space for a real one. This
-** sqlite3_str object accepts no new text and always returns
-** an SQLITE_NOMEM error.
-*/
-static sqlite3_str sqlite3OomStr = {
- 0, 0, 0, 0, 0, SQLITE_NOMEM, 0
-};
-
/* Finalize a string created using sqlite3_str_new().
*/
SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){
char *z;
- if( p!=0 && p!=&sqlite3OomStr ){
+ if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){
z = sqlite3StrAccumFinish(p);
sqlite3_free(p);
}else{
@@ -33174,6 +34115,14 @@ SQLITE_API int sqlite3_str_length(sqlite3_str *p){
return p ? p->nChar : 0;
}
+/* Truncate the text of the string to be no more than N bytes. */
+SQLITE_API void sqlite3_str_truncate(sqlite3_str *p, int N){
+ if( p!=0 && N>=0 && (u32)NnChar ){
+ p->nChar = N;
+ p->zText[p->nChar] = 0;
+ }
+}
+
/* Return the current value for p */
SQLITE_API char *sqlite3_str_value(sqlite3_str *p){
if( p==0 || p->nChar==0 ) return 0;
@@ -33188,12 +34137,25 @@ SQLITE_API void sqlite3_str_reset(StrAccum *p){
if( isMalloced(p) ){
sqlite3DbFree(p->db, p->zText);
p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
+ }else if( p==(sqlite3_str*)&sqlite3OomStr ){
+ return;
}
p->nAlloc = 0;
p->nChar = 0;
p->zText = 0;
}
+/*
+** Destroy a dynamically allocate sqlite3_str object and all
+** of its content, all in one call.
+*/
+SQLITE_API void sqlite3_str_free(sqlite3_str *p){
+ if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){
+ sqlite3_str_reset(p);
+ sqlite3_free(p);
+ }
+}
+
/*
** Initialize a string accumulator.
**
@@ -33225,7 +34187,7 @@ SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3 *db){
sqlite3StrAccumInit(p, 0, 0, 0,
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
}else{
- p = &sqlite3OomStr;
+ p = (sqlite3_str*)&sqlite3OomStr;
}
return p;
}
@@ -34118,6 +35080,10 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
+ case TK_ASTERISK: {
+ sqlite3TreeViewLine(pView,"ASKTERISK");
+ break;
+ }
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
@@ -34807,7 +35773,13 @@ SQLITE_PRIVATE void sqlite3TreeViewTrigger(
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
-SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
+SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){
+ TreeView *pView = 0;
+ sqlite3TreeViewPush(&pView, 0);
+ sqlite3TreeViewLine(pView, "SRCLIST");
+ sqlite3TreeViewSrcList(pView,p);
+ sqlite3TreeViewPop(&pView);
+}
SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); }
@@ -35188,6 +36160,7 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
rc = sqlite3Win32Wait((HANDLE)p->tid);
assert( rc!=WAIT_IO_COMPLETION );
bRc = CloseHandle((HANDLE)p->tid);
+ (void)bRc; /* Prevent warning when assert() is a no-op */
assert( bRc );
}
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
@@ -35437,9 +36410,7 @@ SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
while( zIn=0xD800 && i<=0xDFFF ) t = 0xFFFD;
- if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
assert( c==t );
assert( (z-zBuf)==n );
}
@@ -35888,8 +36856,15 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
/* #include */
#ifndef SQLITE_OMIT_FLOATING_POINT
#include
+
+/* Work around a bug in older Microsoft compilers
+** Forum post 2026-04-10T06:33:11z */
+#if !defined(INFINITY) && defined(_MSC_VER)
+# define INFINITY HUGE_VAL
#endif
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+
/*
** Calls to sqlite3FaultSim() are used to simulate a failure during testing,
** or to bypass normal error detection during testing in order to let
@@ -36327,266 +37302,618 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){
return h;
}
-/* Double-Double multiplication. (x[0],x[1]) *= (y,yy)
-**
-** Reference:
-** T. J. Dekker, "A Floating-Point Technique for Extending the
-** Available Precision". 1971-07-26.
+#if !defined(SQLITE_DISABLE_INTRINSIC) \
+ && (defined(__GNUC__) || defined(__clang__)) \
+ && (defined(__x86_64__) || defined(__aarch64__) || \
+ (defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32)))
+#define SQLITE_USE_UINT128
+#endif
+
+/*
+** Two inputs are multiplied to get a 128-bit result. Write the
+** lower 64-bits of the result into *pLo, and return the high-order
+** 64 bits.
*/
-static void dekkerMul2(volatile double *x, double y, double yy){
- /*
- ** The "volatile" keywords on parameter x[] and on local variables
- ** below are needed force intermediate results to be truncated to
- ** binary64 rather than be carried around in an extended-precision
- ** format. The truncation is necessary for the Dekker algorithm to
- ** work. Intel x86 floating point might omit the truncation without
- ** the use of volatile.
- */
- volatile double tx, ty, p, q, c, cc;
- double hx, hy;
- u64 m;
- memcpy(&m, (void*)&x[0], 8);
- m &= 0xfffffffffc000000LL;
- memcpy(&hx, &m, 8);
- tx = x[0] - hx;
- memcpy(&m, &y, 8);
- m &= 0xfffffffffc000000LL;
- memcpy(&hy, &m, 8);
- ty = y - hy;
- p = hx*hy;
- q = hx*ty + tx*hy;
- c = p+q;
- cc = p - c + q + tx*ty;
- cc = x[0]*yy + x[1]*y + cc;
- x[0] = c + cc;
- x[1] = c - x[0];
- x[1] += cc;
+static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
+#if defined(SQLITE_USE_UINT128)
+ __uint128_t r = (__uint128_t)a * b;
+ *pLo = (u64)r;
+ return (u64)(r>>64);
+#elif defined(_WIN64) && !defined(SQLITE_DISABLE_INTRINSIC)
+ *pLo = a*b;
+ return __umulh(a, b);
+#else
+ u64 a0 = (u32)a;
+ u64 a1 = a >> 32;
+ u64 b0 = (u32)b;
+ u64 b1 = b >> 32;
+ u64 a0b0 = a0 * b0;
+ u64 a1b1 = a1 * b1;
+ u64 a0b1 = a0 * b1;
+ u64 a1b0 = a1 * b0;
+ u64 t = (a0b0 >> 32) + (u32)a0b1 + (u32)a1b0;
+ *pLo = (a0b0 & UINT64_C(0xffffffff)) | (t << 32);
+ return a1b1 + (a0b1>>32) + (a1b0>>32) + (t>>32);
+#endif
+}
+
+/*
+** A is an unsigned 96-bit integer formed by (a<<32)+aLo.
+** B is an unsigned 64-bit integer.
+**
+** Compute the upper 96 bits of 160-bit result of A*B.
+**
+** Write ((A*B)>>64 & 0xffffffff) (the middle 32 bits of A*B)
+** into *pLo. Return the upper 64 bits of A*B.
+**
+** The lower 64 bits of A*B are discarded.
+*/
+static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
+#if defined(SQLITE_USE_UINT128)
+ __uint128_t r = (__uint128_t)a * b;
+ r += ((__uint128_t)aLo * b) >> 32;
+ *pLo = (r>>32)&0xffffffff;
+ return r>>64;
+#elif defined(_WIN64) && !defined(SQLITE_DISABLE_INTRINSIC)
+ u64 r1_hi = __umulh(a,b);
+ u64 r1_lo = a*b;
+ u64 r2 = (__umulh((u64)aLo,b)<<32) + ((aLo*b)>>32);
+ u64 t = r1_lo + r2;
+ if( t>32;
+ return r1_hi;
+#else
+ u64 x2 = a>>32;
+ u64 x1 = a&0xffffffff;
+ u64 x0 = aLo;
+ u64 y1 = b>>32;
+ u64 y0 = b&0xffffffff;
+ u64 x2y1 = x2*y1;
+ u64 r4 = x2y1>>32;
+ u64 x2y0 = x2*y0;
+ u64 x1y1 = x1*y1;
+ u64 r3 = (x2y1 & 0xffffffff) + (x2y0 >>32) + (x1y1 >>32);
+ u64 x1y0 = x1*y0;
+ u64 x0y1 = x0*y1;
+ u64 r2 = (x2y0 & 0xffffffff) + (x1y1 & 0xffffffff) +
+ (x1y0 >>32) + (x0y1>>32);
+ u64 x0y0 = x0*y0;
+ u64 r1 = (x1y0 & 0xffffffff) + (x0y1 & 0xffffffff) +
+ (x0y0 >>32);
+ r2 += r1>>32;
+ r3 += r2>>32;
+ *pLo = r2&0xffffffff;
+ return (r4<<32) + r3;
+#endif
}
+#undef SQLITE_USE_UINT128
+
/*
-** The string z[] is an text representation of a real number.
-** Convert this string to a double and write it into *pResult.
+** Return a u64 with the N-th bit set.
+*/
+#define U64_BIT(N) (((u64)1)<<(N))
+
+/*
+** Range of powers of 10 that we need to deal with when converting
+** IEEE754 doubles to and from decimal.
+*/
+#define POWERSOF10_FIRST (-348)
+#define POWERSOF10_LAST (+347)
+
+/*
+** For any p between -348 and +347, return the integer part of
**
-** The string z[] is length bytes in length (bytes, not characters) and
-** uses the encoding enc. The string is not necessarily zero-terminated.
+** pow(10,p) * pow(2,63-pow10to2(p))
**
-** Return TRUE if the result is a valid real number (or integer) and FALSE
-** if the string is empty or contains extraneous text. More specifically
-** return
-** 1 => The input string is a pure integer
-** 2 or more => The input has a decimal point or eNNN clause
-** 0 or less => The input string is not a valid number
-** -1 => Not a valid number, but has a valid prefix which
-** includes a decimal point and/or an eNNN clause
+** Or, in other words, for any p in range, return the most significant
+** 64 bits of pow(10,p). The pow(10,p) value is shifted left or right,
+** as appropriate so the most significant 64 bits fit exactly into a
+** 64-bit unsigned integer.
**
-** Valid numbers are in one of these formats:
+** Write into *pLo the next 32 significant bits of the answer after
+** the first 64.
**
-** [+-]digits[E[+-]digits]
-** [+-]digits.[digits][E[+-]digits]
-** [+-].digits[E[+-]digits]
+** Algorithm:
**
-** Leading and trailing whitespace is ignored for the purpose of determining
-** validity.
+** (1) For p between 0 and 26, return the value directly from the aBase[]
+** lookup table.
+**
+** (2) For p outside the range 0 to 26, use aScale[] for the initial value
+** then refine that result (if necessary) by a single multiplication
+** against aBase[].
+**
+** The constant tables aBase[], aScale[], and aScaleLo[] are generated
+** by the C program at ../tool/mkfptab.c run with the --round option.
+*/
+static u64 powerOfTen(int p, u32 *pLo){
+ static const u64 aBase[] = {
+ UINT64_C(0x8000000000000000), /* 0: 1.0e+0 << 63 */
+ UINT64_C(0xa000000000000000), /* 1: 1.0e+1 << 60 */
+ UINT64_C(0xc800000000000000), /* 2: 1.0e+2 << 57 */
+ UINT64_C(0xfa00000000000000), /* 3: 1.0e+3 << 54 */
+ UINT64_C(0x9c40000000000000), /* 4: 1.0e+4 << 50 */
+ UINT64_C(0xc350000000000000), /* 5: 1.0e+5 << 47 */
+ UINT64_C(0xf424000000000000), /* 6: 1.0e+6 << 44 */
+ UINT64_C(0x9896800000000000), /* 7: 1.0e+7 << 40 */
+ UINT64_C(0xbebc200000000000), /* 8: 1.0e+8 << 37 */
+ UINT64_C(0xee6b280000000000), /* 9: 1.0e+9 << 34 */
+ UINT64_C(0x9502f90000000000), /* 10: 1.0e+10 << 30 */
+ UINT64_C(0xba43b74000000000), /* 11: 1.0e+11 << 27 */
+ UINT64_C(0xe8d4a51000000000), /* 12: 1.0e+12 << 24 */
+ UINT64_C(0x9184e72a00000000), /* 13: 1.0e+13 << 20 */
+ UINT64_C(0xb5e620f480000000), /* 14: 1.0e+14 << 17 */
+ UINT64_C(0xe35fa931a0000000), /* 15: 1.0e+15 << 14 */
+ UINT64_C(0x8e1bc9bf04000000), /* 16: 1.0e+16 << 10 */
+ UINT64_C(0xb1a2bc2ec5000000), /* 17: 1.0e+17 << 7 */
+ UINT64_C(0xde0b6b3a76400000), /* 18: 1.0e+18 << 4 */
+ UINT64_C(0x8ac7230489e80000), /* 19: 1.0e+19 >> 0 */
+ UINT64_C(0xad78ebc5ac620000), /* 20: 1.0e+20 >> 3 */
+ UINT64_C(0xd8d726b7177a8000), /* 21: 1.0e+21 >> 6 */
+ UINT64_C(0x878678326eac9000), /* 22: 1.0e+22 >> 10 */
+ UINT64_C(0xa968163f0a57b400), /* 23: 1.0e+23 >> 13 */
+ UINT64_C(0xd3c21bcecceda100), /* 24: 1.0e+24 >> 16 */
+ UINT64_C(0x84595161401484a0), /* 25: 1.0e+25 >> 20 */
+ UINT64_C(0xa56fa5b99019a5c8), /* 26: 1.0e+26 >> 23 */
+ };
+ static const u64 aScale[] = {
+ UINT64_C(0x8049a4ac0c5811ae), /* 0: 1.0e-351 << 1229 */
+ UINT64_C(0xcf42894a5dce35ea), /* 1: 1.0e-324 << 1140 */
+ UINT64_C(0xa76c582338ed2621), /* 2: 1.0e-297 << 1050 */
+ UINT64_C(0x873e4f75e2224e68), /* 3: 1.0e-270 << 960 */
+ UINT64_C(0xda7f5bf590966848), /* 4: 1.0e-243 << 871 */
+ UINT64_C(0xb080392cc4349dec), /* 5: 1.0e-216 << 781 */
+ UINT64_C(0x8e938662882af53e), /* 6: 1.0e-189 << 691 */
+ UINT64_C(0xe65829b3046b0afa), /* 7: 1.0e-162 << 602 */
+ UINT64_C(0xba121a4650e4ddeb), /* 8: 1.0e-135 << 512 */
+ UINT64_C(0x964e858c91ba2655), /* 9: 1.0e-108 << 422 */
+ UINT64_C(0xf2d56790ab41c2a2), /* 10: 1.0e-81 << 333 */
+ UINT64_C(0xc428d05aa4751e4c), /* 11: 1.0e-54 << 243 */
+ UINT64_C(0x9e74d1b791e07e48), /* 12: 1.0e-27 << 153 */
+ UINT64_C(0xcccccccccccccccc), /* 13: 1.0e-1 << 67 (special case) */
+ UINT64_C(0xcecb8f27f4200f3a), /* 14: 1.0e+27 >> 26 */
+ UINT64_C(0xa70c3c40a64e6c51), /* 15: 1.0e+54 >> 116 */
+ UINT64_C(0x86f0ac99b4e8dafd), /* 16: 1.0e+81 >> 206 */
+ UINT64_C(0xda01ee641a708de9), /* 17: 1.0e+108 >> 295 */
+ UINT64_C(0xb01ae745b101e9e4), /* 18: 1.0e+135 >> 385 */
+ UINT64_C(0x8e41ade9fbebc27d), /* 19: 1.0e+162 >> 475 */
+ UINT64_C(0xe5d3ef282a242e81), /* 20: 1.0e+189 >> 564 */
+ UINT64_C(0xb9a74a0637ce2ee1), /* 21: 1.0e+216 >> 654 */
+ UINT64_C(0x95f83d0a1fb69cd9), /* 22: 1.0e+243 >> 744 */
+ UINT64_C(0xf24a01a73cf2dccf), /* 23: 1.0e+270 >> 833 */
+ UINT64_C(0xc3b8358109e84f07), /* 24: 1.0e+297 >> 923 */
+ UINT64_C(0x9e19db92b4e31ba9), /* 25: 1.0e+324 >> 1013 */
+ };
+ static const unsigned int aScaleLo[] = {
+ 0x205b896d, /* 0: 1.0e-351 << 1229 */
+ 0x52064cad, /* 1: 1.0e-324 << 1140 */
+ 0xaf2af2b8, /* 2: 1.0e-297 << 1050 */
+ 0x5a7744a7, /* 3: 1.0e-270 << 960 */
+ 0xaf39a475, /* 4: 1.0e-243 << 871 */
+ 0xbd8d794e, /* 5: 1.0e-216 << 781 */
+ 0x547eb47b, /* 6: 1.0e-189 << 691 */
+ 0x0cb4a5a3, /* 7: 1.0e-162 << 602 */
+ 0x92f34d62, /* 8: 1.0e-135 << 512 */
+ 0x3a6a07f9, /* 9: 1.0e-108 << 422 */
+ 0xfae27299, /* 10: 1.0e-81 << 333 */
+ 0xaa97e14c, /* 11: 1.0e-54 << 243 */
+ 0x775ea265, /* 12: 1.0e-27 << 153 */
+ 0xcccccccc, /* 13: 1.0e-1 << 67 (special case) */
+ 0x00000000, /* 14: 1.0e+27 >> 26 */
+ 0x999090b6, /* 15: 1.0e+54 >> 116 */
+ 0x69a028bb, /* 16: 1.0e+81 >> 206 */
+ 0xe80e6f48, /* 17: 1.0e+108 >> 295 */
+ 0x5ec05dd0, /* 18: 1.0e+135 >> 385 */
+ 0x14588f14, /* 19: 1.0e+162 >> 475 */
+ 0x8f1668c9, /* 20: 1.0e+189 >> 564 */
+ 0x6d953e2c, /* 21: 1.0e+216 >> 654 */
+ 0x4abdaf10, /* 22: 1.0e+243 >> 744 */
+ 0xbc633b39, /* 23: 1.0e+270 >> 833 */
+ 0x0a862f81, /* 24: 1.0e+297 >> 923 */
+ 0x6c07a2c2, /* 25: 1.0e+324 >> 1013 */
+ };
+ int g, n;
+ u64 s, x;
+ u32 lo;
+
+ assert( p>=POWERSOF10_FIRST && p<=POWERSOF10_LAST );
+ if( p<0 ){
+ if( p==(-1) ){
+ *pLo = aScaleLo[13];
+ return aScale[13];
+ }
+ g = p/27;
+ n = p%27;
+ if( n ){
+ g--;
+ n += 27;
+ }
+ }else if( p<27 ){
+ *pLo = 0;
+ return aBase[p];
+ }else{
+ g = p/27;
+ n = p%27;
+ }
+ s = aScale[g+13];
+ if( n==0 ){
+ *pLo = aScaleLo[g+13];
+ return s;
+ }
+ x = sqlite3Multiply160(s,aScaleLo[g+13],aBase[n],&lo);
+ if( (U64_BIT(63) & x)==0 ){
+ x = x<<1 | ((lo>>31)&1);
+ lo = (lo<<1) | 1;
+ }
+ *pLo = lo;
+ return x;
+}
+
+/*
+** pow10to2(x) computes floor(log2(pow(10,x))).
+** pow2to10(y) computes floor(log10(pow(2,y))).
**
-** If some prefix of the input string is a valid number, this routine
-** returns FALSE but it still converts the prefix and writes the result
-** into *pResult.
+** Conceptually, pow10to2(p) converts a base-10 exponent p into
+** a corresponding base-2 exponent, and pow2to10(e) converts a base-2
+** exponent into a base-10 exponent.
+**
+** The conversions are based on the observation that:
+**
+** ln(10.0)/ln(2.0) == 108853/32768 (approximately)
+** ln(2.0)/ln(10.0) == 78913/262144 (approximately)
+**
+** These ratios are approximate, but they are accurate to 5 digits,
+** which is close enough for the usage here. Right-shift is used
+** for division so that rounding of negative numbers happens in the
+** right direction.
*/
-#if defined(_MSC_VER)
-#pragma warning(disable : 4756)
-#endif
-SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int incr;
- const char *zEnd;
- /* sign * significand * (10 ^ (esign * exponent)) */
- int sign = 1; /* sign of significand */
- u64 s = 0; /* significand */
- int d = 0; /* adjust exponent for shifting decimal point */
- int esign = 1; /* sign of exponent */
- int e = 0; /* exponent */
- int eValid = 1; /* True exponent is either not used or is well-formed */
- int nDigit = 0; /* Number of digits processed */
- int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
- u64 s2; /* round-tripped significand */
- double rr[2];
+static int pwr10to2(int p){ return (p*108853) >> 15; }
+static int pwr2to10(int p){ return (p*78913) >> 18; }
- assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
- *pResult = 0.0; /* Default return value, in case of an error */
- if( length==0 ) return 0;
+/*
+** Count leading zeros for a 64-bit unsigned integer.
+*/
+static int countLeadingZeros(u64 m){
+#if (defined(__GNUC__) || defined(__clang__)) \
+ && !defined(SQLITE_DISABLE_INTRINSIC)
+ return __builtin_clzll(m);
+#else
+ int n = 0;
+ if( m <= 0x00000000ffffffffULL) { n += 32; m <<= 32; }
+ if( m <= 0x0000ffffffffffffULL) { n += 16; m <<= 16; }
+ if( m <= 0x00ffffffffffffffULL) { n += 8; m <<= 8; }
+ if( m <= 0x0fffffffffffffffULL) { n += 4; m <<= 4; }
+ if( m <= 0x3fffffffffffffffULL) { n += 2; m <<= 2; }
+ if( m <= 0x7fffffffffffffffULL) { n += 1; }
+ return n;
+#endif
+}
- if( enc==SQLITE_UTF8 ){
- incr = 1;
- zEnd = z + length;
+/*
+** Given m and e, which represent a quantity r == m*pow(2,e),
+** return values *pD and *pP such that r == (*pD)*pow(10,*pP),
+** approximately. *pD should contain at least n significant digits.
+**
+** The input m is required to have its highest bit set. In other words,
+** m should be left-shifted, and e decremented, to maximize the value of m.
+*/
+static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){
+ int p;
+ u64 h, d1;
+ u32 d2;
+ assert( n>=1 && n<=18 );
+ p = n - 1 - pwr2to10(e+63);
+ h = sqlite3Multiply128(m, powerOfTen(p,&d2), &d1);
+ assert( -(e + pwr10to2(p) + 2) >= 0 );
+ assert( -(e + pwr10to2(p) + 1) <= 63 );
+ if( n==18 ){
+ h >>= -(e + pwr10to2(p) + 2);
+ *pD = (h + ((h<<1)&2))>>1;
}else{
- int i;
- incr = 2;
- length &= ~1;
- assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
- testcase( enc==SQLITE_UTF16LE );
- testcase( enc==SQLITE_UTF16BE );
- for(i=3-enc; i> -(e + pwr10to2(p) + 1);
}
+ *pP = -p;
+}
- /* skip leading spaces */
- while( z=zEnd ) return 0;
-
- /* get sign of significand */
- if( *z=='-' ){
- sign = -1;
- z+=incr;
- }else if( *z=='+' ){
- z+=incr;
- }
+/*
+** Return an IEEE754 floating point value that approximates d*pow(10,p).
+**
+** The (current) algorithm is adapted from the work of Ross Cox at
+** https://github.com/rsc/fpfmt
+*/
+static double sqlite3Fp10Convert2(u64 d, int p){
+ int b, lp, e, adj, s;
+ u32 pwr10l, mid1;
+ u64 pwr10h, x, hi, lo, sticky, u, m;
+ double r;
+ if( pPOWERSOF10_LAST ) return (double)INFINITY;
+ b = 64 - countLeadingZeros(d);
+ lp = pwr10to2(p);
+ e = 53 - b - lp;
+ if( e > 1074 ){
+ if( e>=1130 ) return 0.0;
+ e = 1074;
+ }
+ s = -(e-(64-b) + lp + 3);
+ pwr10h = powerOfTen(p, &pwr10l);
+ if( pwr10l!=0 ){
+ pwr10h++;
+ pwr10l = ~pwr10l;
+ }
+ x = d<<(64-b);
+ hi = sqlite3Multiply128(x,pwr10h,&lo);
+ mid1 = lo>>32;
+ sticky = 1;
+ if( (hi & (U64_BIT(s)-1))==0 ) {
+ u32 mid2 = sqlite3Multiply128(x,((u64)pwr10l)<<32,&lo)>>32;
+ sticky = (mid1-mid2 > 1);
+ hi -= mid1 < mid2;
+ }
+ u = (hi>>s) | sticky;
+ adj = (u >= U64_BIT(55)-2);
+ if( adj ){
+ u = (u>>adj) | (u&1);
+ e -= adj;
+ }
+ m = (u + 1 + ((u>>2)&1)) >> 2;
+ if( e<=(-972) ) return (double)INFINITY;
+ if((m & U64_BIT(52)) != 0){
+ m = (m & ~U64_BIT(52)) | ((u64)(1075-e)<<52);
+ }
+ memcpy(&r,&m,8);
+ return r;
+}
- /* copy max significant digits to significand */
- while( z=((LARGEST_UINT64-9)/10) ){
- /* skip non-significant significand digits
- ** (increase exponent by d to shift decimal left) */
- while( z Set if any prefix of the input is valid. Clear if
+** there is no prefix of the input that can be seen as
+** a valid floating point number.
+** bit 1 => Set if the input contains a decimal point or eNNN
+** clause. Zero if the input is an integer.
+** bit 2 => The input is exactly 0.0, not an underflow from
+** some value near zero.
+** bit 3 => Set if there are more than about 19 significant
+** digits in the input.
+**
+** If the input contains a syntax error but begins with text that might
+** be a valid number of some kind, then the result is negative. The
+** result is only zero if no prefix of the input could be interpreted as
+** a number.
+**
+** Leading and trailing whitespace is ignored. Valid numbers are in
+** one of the formats below:
+**
+** [+-]digits[E[+-]digits]
+** [+-]digits.[digits][E[+-]digits]
+** [+-].digits[E[+-]digits]
+**
+** Algorithm sketch: Compute an unsigned 64-bit integer s and a base-10
+** exponent d such that the value encoding by the input is s*pow(10,d).
+** Then invoke sqlite3Fp10Convert2() to calculated the closest possible
+** IEEE754 double. The sign is added back afterwards, if the input string
+** starts with a "-". The use of an unsigned 64-bit s mantissa means that
+** only about the first 19 significant digits of the input can contribute
+** to the result. This can result in suboptimal rounding decisions when
+** correct rounding requires more than 19 input digits. For example,
+** this routine renders "3500000000000000.2500001" as
+** 3500000000000000.0 instead of 3500000000000000.5 because the decision
+** to round up instead of using banker's rounding to round down is determined
+** by the 23rd significant digit, which this routine ignores. It is not
+** possible to do better without some kind of BigNum.
+*/
+SQLITE_PRIVATE int sqlite3AtoF(const char *zIn, double *pResult){
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ const unsigned char *z = (const unsigned char*)zIn;
+ int neg = 0; /* True for a negative value */
+ u64 s = 0; /* mantissa */
+ int d = 0; /* Value is s * pow(10,d) */
+ int mState = 0; /* 1: digit seen 2: fp 4: hard-zero */
+ unsigned v; /* Value of a single digit */
+
+ start_of_text:
+ if( (v = (unsigned)z[0] - '0')<10 ){
+ parse_integer_part:
+ mState = 1;
+ s = v;
+ z++;
+ while( (v = (unsigned)z[0] - '0')<10 ){
+ s = s*10 + v;
+ z++;
+ if( s>=(LARGEST_UINT64-9)/10 ){
+ mState = 9;
+ while( sqlite3Isdigit(z[0]) ){ z++; d++; }
+ break;
+ }
}
+ }else if( z[0]=='-' ){
+ neg = 1;
+ z++;
+ if( (v = (unsigned)z[0] - '0')<10 ) goto parse_integer_part;
+ }else if( z[0]=='+' ){
+ z++;
+ if( (v = (unsigned)z[0] - '0')<10 ) goto parse_integer_part;
+ }else if( sqlite3Isspace(z[0]) ){
+ do{ z++; }while( sqlite3Isspace(z[0]) );
+ goto start_of_text;
+ }else{
+ s = 0;
}
- if( z>=zEnd ) goto do_atof_calc;
/* if decimal point is present */
if( *z=='.' ){
- z+=incr;
- eType++;
- /* copy digits from after decimal to significand
- ** (decrease exponent by d to shift decimal right) */
- while( z=zEnd ) goto do_atof_calc;
/* if exponent is present */
if( *z=='e' || *z=='E' ){
- z+=incr;
- eValid = 0;
- eType++;
-
- /* This branch is needed to avoid a (harmless) buffer overread. The
- ** special comment alerts the mutation tester that the correct answer
- ** is obtained even if the branch is omitted */
- if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
+ int esign;
+ z++;
/* get sign of exponent */
if( *z=='-' ){
esign = -1;
- z+=incr;
- }else if( *z=='+' ){
- z+=incr;
+ z++;
+ }else{
+ esign = +1;
+ if( *z=='+' ){
+ z++;
+ }
}
/* copy digits to exponent */
- while( z0 && s<((LARGEST_UINT64-0x7ff)/10) ){
- s *= 10;
- e--;
- }
- while( e<0 && (s%10)==0 ){
- s /= 10;
- e++;
- }
-
- rr[0] = (double)s;
- assert( sizeof(s2)==sizeof(rr[0]) );
-#ifdef SQLITE_DEBUG
- rr[1] = 18446744073709549568.0;
- memcpy(&s2, &rr[1], sizeof(s2));
- assert( s2==0x43efffffffffffffLL );
-#endif
- /* Largest double that can be safely converted to u64
- ** vvvvvvvvvvvvvvvvvvvvvv */
- if( rr[0]<=18446744073709549568.0 ){
- s2 = (u64)rr[0];
- rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
+ *pResult = 0.0;
+ mState |= 4;
}else{
- rr[1] = 0.0;
+ *pResult = sqlite3Fp10Convert2(s,d);
}
- assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */
-
- if( e>0 ){
- while( e>=100 ){
- e -= 100;
- dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
- }
- while( e>=10 ){
- e -= 10;
- dekkerMul2(rr, 1.0e+10, 0.0);
- }
- while( e>=1 ){
- e -= 1;
- dekkerMul2(rr, 1.0e+01, 0.0);
- }
- }else{
- while( e<=-100 ){
- e += 100;
- dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
- }
- while( e<=-10 ){
- e += 10;
- dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
- }
- while( e<=-1 ){
- e += 1;
- dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
- }
- }
- *pResult = rr[0]+rr[1];
- if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
- if( sign<0 ) *pResult = -*pResult;
+ if( neg ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
-atof_return:
/* return true if number and no extra non-whitespace characters after */
- if( z==zEnd && nDigit>0 && eValid && eType>0 ){
- return eType;
- }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
- return -1;
- }else{
- return 0;
+ if( z[0]==0 ){
+ return mState;
}
+ if( sqlite3Isspace(z[0]) ){
+ do{ z++; }while( sqlite3Isspace(*z) );
+ if( z[0]==0 ){
+ return mState;
+ }
+ }
+ return 0xfffffff0 | mState;
#else
- return !sqlite3Atoi64(z, pResult, length, enc);
+ return sqlite3Atoi64(zIn, pResult, strlen(zIn), SQLITE_UTF8)==0;
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
-#if defined(_MSC_VER)
-#pragma warning(default : 4756)
+
+/*
+** Digit pairs used to convert a U64 or I64 into text, two digits
+** at a time.
+*/
+static const union {
+ char a[201];
+ short int forceAlignment;
+} sqlite3DigitPairs = {
+ "00010203040506070809"
+ "10111213141516171819"
+ "20212223242526272829"
+ "30313233343536373839"
+ "40414243444546474849"
+ "50515253545556575859"
+ "60616263646566676869"
+ "70717273747576777879"
+ "80818283848586878889"
+ "90919293949596979899"
+};
+
+/*
+** ARMv6, ARMv7, PPC32 are known to not support hardware u64 division.
+*/
+#if (defined(__arm__) && !defined(__aarch64__)) || \
+ (defined(__ppc__) && !defined(__ppc64__))
+# define SQLITE_AVOID_U64_DIVIDE 1
#endif
+#ifdef SQLITE_AVOID_U64_DIVIDE
+/*
+** Render an unsigned 64-bit integer as text onto the end of a 2-byte
+** aligned buffer that is SQLITE_U64_DIGIT+1 bytes long. The last byte
+** of the buffer will be filled with a \000 byte.
+**
+** Return the index into the buffer of the first byte.
+**
+** This routine is used on platforms where u64-division is slow because
+** it is not available in hardware and has to be emulated in software.
+** It seeks to minimize the number of u64 divisions and use u32 divisions
+** instead. It is slower on platforms that have hardware u64 division,
+** but much faster on platforms that do not.
+*/
+static int sqlite3UInt64ToText(u64 v, char *zOut){
+ u32 x32, kk;
+ int i;
+ zOut[SQLITE_U64_DIGITS] = 0;
+ i = SQLITE_U64_DIGITS;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[0]) );
+ assert( TWO_BYTE_ALIGNMENT(zOut) );
+ while( (v>>32)!=0 ){
+ u32 y, x0, x1, y0, y1;
+ x32 = v % 100000000;
+ v = v / 100000000;
+ y = x32 % 10000;
+ x32 /= 10000;
+ x1 = x32 / 100;
+ x0 = x32 % 100;
+ y1 = y / 100;
+ y0 = y % 100;
+ assert( i>=8 );
+ i -= 8;
+ *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[x1*2];
+ *(u16*)(&zOut[i+2]) = *(u16*)&sqlite3DigitPairs.a[x0*2];
+ *(u16*)(&zOut[i+4]) = *(u16*)&sqlite3DigitPairs.a[y1*2];
+ *(u16*)(&zOut[i+6]) = *(u16*)&sqlite3DigitPairs.a[y0*2];
+ }
+ x32 = v;
+ while( x32>=10 ){
+ kk = x32 % 100;
+ x32 = x32 / 100;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk*2]) );
+ assert( i>=2 );
+ i -= 2;
+ assert( TWO_BYTE_ALIGNMENT(&zOut[i]) );
+ *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[kk*2];
+ }
+ if( x32 ){
+ assert( i>0 );
+ zOut[--i] = x32 + '0';
+ }
+ return i;
+}
+#endif /* defined(SQLITE_AVOID_U64_DIVIDE) */
+
/*
** Render an signed 64-bit integer as text. Store the result in zOut[] and
** return the length of the string that was stored, in bytes. The value
@@ -36598,23 +37925,39 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){
int i;
u64 x;
- char zTemp[22];
- if( v<0 ){
- x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
- }else{
+ union {
+ char a[SQLITE_U64_DIGITS+1];
+ u16 forceAlignment;
+ } u;
+ if( v>0 ){
x = v;
+ }else if( v==0 ){
+ zOut[0] = '0';
+ zOut[1] = 0;
+ return 1;
+ }else{
+ x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}
- i = sizeof(zTemp)-2;
- zTemp[sizeof(zTemp)-1] = 0;
- while( 1 /*exit-by-break*/ ){
- zTemp[i] = (x%10) + '0';
- x = x/10;
- if( x==0 ) break;
- i--;
- };
- if( v<0 ) zTemp[--i] = '-';
- memcpy(zOut, &zTemp[i], sizeof(zTemp)-i);
- return sizeof(zTemp)-1-i;
+#ifdef SQLITE_AVOID_U64_DIVIDE
+ i = sqlite3UInt64ToText(x, u.a);
+#else
+ i = sizeof(u.a)-1;
+ u.a[i] = 0;
+ while( x>=10 ){
+ int kk = (x%100)*2;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
+ assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) );
+ *(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
+ i -= 2;
+ x /= 100;
+ }
+ if( x ){
+ u.a[--i] = x + '0';
+ }
+#endif /* SQLITE_AVOID_U64_DIVIDE */
+ if( v<0 ) u.a[--i] = '-';
+ memcpy(zOut, &u.a[i], sizeof(u.a)-i);
+ return sizeof(u.a)-1-i;
}
/*
@@ -36668,8 +38011,8 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
int incr;
u64 u = 0;
int neg = 0; /* assume positive */
- int i;
- int c = 0;
+ int i, j;
+ unsigned int c = 0;
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
int rc; /* Baseline return code */
const char *zStart;
@@ -36697,8 +38040,8 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
}
zStart = zNum;
while( zNum='0' && c<='9'; i+=incr){
- u = u*10 + c - '0';
+ for(i=0; &zNum[i]19*incr ? 1 : compare2pow63(zNum, incr);
- if( c<0 ){
+ j = i>19*incr ? 1 : compare2pow63(zNum, incr);
+ if( j<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
return rc;
}else{
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
- if( c>0 ){
+ if( j>0 ){
/* zNum is greater than 9223372036854775808 so it overflows */
return 2;
}else{
@@ -36871,7 +38214,7 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){
** representation.
**
** If iRound<=0 then round to -iRound significant digits to the
-** the left of the decimal point, or to a maximum of mxRound total
+** the right of the decimal point, or to a maximum of mxRound total
** significant digits.
**
** If iRound>0 round to min(iRound,mxRound) significant digits total.
@@ -36884,13 +38227,14 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){
** The p->z[] array is *not* zero-terminated.
*/
SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
- int i;
- u64 v;
- int e, exp = 0;
- double rr[2];
+ int i; /* Index into zBuf[] where to put next character */
+ int n; /* Number of digits */
+ u64 v; /* mantissa */
+ int e, exp = 0; /* Base-2 and base-10 exponent */
+ char *zBuf; /* Local alias for p->zBuf */
+ char *z; /* Local alias for p->z */
p->isSpecial = 0;
- p->z = p->zBuf;
assert( mxRound>0 );
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
@@ -36908,78 +38252,100 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
p->sign = '+';
}
memcpy(&v,&r,8);
- e = v>>52;
- if( (e&0x7ff)==0x7ff ){
+ e = (v>>52)&0x7ff;
+ if( e==0x7ff ){
p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
p->n = 0;
p->iDP = 0;
+ p->z = p->zBuf;
return;
}
-
- /* Multiply r by powers of ten until it lands somewhere in between
- ** 1.0e+19 and 1.0e+17.
- **
- ** Use Dekker-style double-double computation to increase the
- ** precision.
- **
- ** The error terms on constants like 1.0e+100 computed using the
- ** decimal extension, for example as follows:
- **
- ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
- */
- rr[0] = r;
- rr[1] = 0.0;
- if( rr[0]>9.223372036854774784e+18 ){
- while( rr[0]>9.223372036854774784e+118 ){
- exp += 100;
- dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
- }
- while( rr[0]>9.223372036854774784e+28 ){
- exp += 10;
- dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
- }
- while( rr[0]>9.223372036854774784e+18 ){
- exp += 1;
- dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
- }
+ v &= 0x000fffffffffffffULL;
+ if( e==0 ){
+ int nn = countLeadingZeros(v);
+ v <<= nn;
+ e = -1074 - nn;
}else{
- while( rr[0]<9.223372036854774784e-83 ){
- exp -= 100;
- dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
- }
- while( rr[0]<9.223372036854774784e+07 ){
- exp -= 10;
- dekkerMul2(rr, 1.0e+10, 0.0);
- }
- while( rr[0]<9.22337203685477478e+17 ){
- exp -= 1;
- dekkerMul2(rr, 1.0e+01, 0.0);
- }
+ v = (v<<11) | U64_BIT(63);
+ e -= 1086;
}
- v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
+ sqlite3Fp2Convert10(v, e, (iRound<=0||iRound>=18)?18:iRound+1, &v, &exp);
- /* Extract significant digits. */
- i = sizeof(p->zBuf)-1;
+ /* Extract significant digits, start at the right-most slot in p->zBuf
+ ** and working back to the right. "i" keeps track of the next slot in
+ ** which to store a digit. */
+ assert( sizeof(p->zBuf)==SQLITE_U64_DIGITS+1 );
assert( v>0 );
- while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; }
- assert( i>=0 && izBuf)-1 );
- p->n = sizeof(p->zBuf) - 1 - i;
- assert( p->n>0 );
- assert( p->nzBuf) );
- p->iDP = p->n + exp;
+ zBuf = p->zBuf;
+#ifdef SQLITE_AVOID_U64_DIVIDE
+ i = sqlite3UInt64ToText(v, zBuf);
+#else
+ i = SQLITE_U64_DIGITS;
+ while( v>=10 ){
+ int kk = (v%100)*2;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
+ assert( TWO_BYTE_ALIGNMENT(&zBuf[i]) );
+ assert( i-2>=0 );
+ *(u16*)(&zBuf[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
+ i -= 2;
+ v /= 100;
+ }
+ if( v ){
+ assert( v<10 );
+ assert( i>0 );
+ zBuf[--i] = v + '0';
+ }
+#endif /* SQLITE_AVOID_U64_DIVIDE */
+ assert( i>=0 && i0 );
+ assert( n<=SQLITE_U64_DIGITS );
+ p->iDP = n + exp;
if( iRound<=0 ){
iRound = p->iDP - iRound;
- if( iRound==0 && p->zBuf[i+1]>='5' ){
+ if( iRound==0 && zBuf[i]>='5' ){
iRound = 1;
- p->zBuf[i--] = '0';
- p->n++;
+ zBuf[--i] = '0';
+ n++;
p->iDP++;
}
}
- if( iRound>0 && (iRoundn || p->n>mxRound) ){
- char *z = &p->zBuf[i+1];
+ z = &zBuf[i]; /* z points to the first digit */
+ if( iRound>0 && (iRoundmxRound) ){
if( iRound>mxRound ) iRound = mxRound;
- p->n = iRound;
+ if( iRound==17 ){
+ /* If the precision is exactly 17, which only happens with the "!"
+ ** flag (ex: "%!.17g") then try to reduce the precision if that
+ ** yields text that will round-trip to the original floating-point.
+ ** value. Thus, for exaple, 49.47 will render as 49.47, rather than
+ ** as 49.469999999999999. */
+ if( z[15]=='9' && z[14]=='9' ){
+ int jj, kk;
+ u64 v2;
+ for(jj=14; jj>0 && z[jj-1]=='9'; jj--){}
+ if( jj==0 ){
+ v2 = 1;
+ }else{
+ v2 = z[0] - '0';
+ for(kk=1; kkiDP>=n || (z[15]=='0' && z[14]=='0' && z[13]=='0') ){
+ int jj, kk;
+ u64 v2;
+ assert( z[0]!='0' );
+ for(jj=13; z[jj-1]=='0'; jj--){}
+ v2 = z[0] - '0';
+ for(kk=1; kk='5' ){
int j = iRound-1;
while( 1 /*exit-by-break*/ ){
@@ -36987,8 +38353,9 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
if( z[j]<='9' ) break;
z[j] = '0';
if( j==0 ){
- p->z[i--] = '1';
- p->n++;
+ z--;
+ z[0] = '1';
+ n++;
p->iDP++;
break;
}else{
@@ -36997,13 +38364,13 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
}
}
}
- p->z = &p->zBuf[i+1];
- assert( i+p->n < sizeof(p->zBuf) );
- assert( p->n>0 );
- while( p->z[p->n-1]=='0' ){
- p->n--;
- assert( p->n>0 );
+ assert( n>0 );
+ while( z[n-1]=='0' ){
+ n--;
+ assert( n>0 );
}
+ p->n = n;
+ p->z = z;
}
/*
@@ -37017,7 +38384,7 @@ SQLITE_PRIVATE int sqlite3GetUInt32(const char *z, u32 *pI){
int i;
for(i=0; sqlite3Isdigit(z[i]); i++){
v = v*10 + z[i] - '0';
- if( v>4294967296LL ){ *pI = 0; return 0; }
+ if( v>4294967295LL ){ *pI = 0; return 0; }
}
if( i==0 || z[i]!=0 ){ *pI = 0; return 0; }
*pI = (u32)v;
@@ -37090,171 +38457,83 @@ SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
return putVarint64(p,v);
}
-/*
-** Bitmasks used by sqlite3GetVarint(). These precomputed constants
-** are defined here rather than simply putting the constant expressions
-** inline in order to work around bugs in the RVT compiler.
-**
-** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
-**
-** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
-*/
-#define SLOT_2_0 0x001fc07f
-#define SLOT_4_2_0 0xf01fc07f
-
-
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read. The value is stored in *v.
*/
SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
- u32 a,b,s;
-
- if( ((signed char*)p)[0]>=0 ){
- *v = *p;
- return 1;
- }
- if( ((signed char*)p)[1]>=0 ){
- *v = ((u32)(p[0]&0x7f)<<7) | p[1];
- return 2;
- }
-
- /* Verify that constants are precomputed correctly */
- assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
- assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
-
- a = ((u32)p[0])<<14;
- b = p[1];
- p += 2;
- a |= *p;
- /* a: p0<<14 | p2 (unmasked) */
- if (!(a&0x80))
- {
- a &= SLOT_2_0;
- b &= 0x7f;
- b = b<<7;
- a |= b;
- *v = a;
- return 3;
- }
-
- /* CSE1 from below */
- a &= SLOT_2_0;
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<14 | p3 (unmasked) */
- if (!(b&0x80))
- {
- b &= SLOT_2_0;
- /* moved CSE1 up */
- /* a &= (0x7f<<14)|(0x7f); */
- a = a<<7;
- a |= b;
- *v = a;
- return 4;
- }
-
- /* a: p0<<14 | p2 (masked) */
- /* b: p1<<14 | p3 (unmasked) */
- /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
- /* moved CSE1 up */
- /* a &= (0x7f<<14)|(0x7f); */
- b &= SLOT_2_0;
- s = a;
- /* s: p0<<14 | p2 (masked) */
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<28 | p2<<14 | p4 (unmasked) */
- if (!(a&0x80))
- {
- /* we can skip these cause they were (effectively) done above
- ** while calculating s */
- /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
- /* b &= (0x7f<<14)|(0x7f); */
- b = b<<7;
- a |= b;
- s = s>>18;
- *v = ((u64)s)<<32 | a;
- return 5;
- }
-
- /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
- s = s<<7;
- s |= b;
- /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<28 | p3<<14 | p5 (unmasked) */
- if (!(b&0x80))
- {
- /* we can skip this cause it was (effectively) done above in calc'ing s */
- /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
- a &= SLOT_2_0;
- a = a<<7;
- a |= b;
- s = s>>18;
- *v = ((u64)s)<<32 | a;
- return 6;
- }
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p2<<28 | p4<<14 | p6 (unmasked) */
- if (!(a&0x80))
- {
- a &= SLOT_4_2_0;
- b &= SLOT_2_0;
- b = b<<7;
- a |= b;
- s = s>>11;
- *v = ((u64)s)<<32 | a;
- return 7;
+ u64 iKey = p[0];
+ const u8 *pStart = p;
+ if( iKey>=0x80 ){
+ u8 x;
+ iKey = (iKey<<7) ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x10204000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<8) ^ 0x8000 ^ (*++p);
+ }
+ }
+ }
+ }
+ }
+ }else{
+ iKey ^= 0x204000;
+ }
+ }else{
+ iKey ^= 0x4000;
+ }
}
+ *v = iKey;
+ return (u8)(p - pStart) + 1;
+}
- /* CSE2 from below */
- a &= SLOT_2_0;
- p++;
- b = b<<14;
- b |= *p;
- /* b: p3<<28 | p5<<14 | p7 (unmasked) */
- if (!(b&0x80))
- {
- b &= SLOT_4_2_0;
- /* moved CSE2 up */
- /* a &= (0x7f<<14)|(0x7f); */
- a = a<<7;
- a |= b;
- s = s>>4;
- *v = ((u64)s)<<32 | a;
- return 8;
+/*
+** Return the value of a variable-length integer without computing
+** its length. This is an optimization on sqlite3GetVarint() for the
+** cases when the return value of sqlite3GetVarint() is not needed.
+*/
+SQLITE_PRIVATE i64 sqlite3VarintValue(const unsigned char *p){
+ u64 iKey = p[0];
+ if( iKey>=0x80 ){
+ u8 x;
+ iKey = (iKey<<7) ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x10204000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++p);
+ if( x>=0x80 ){
+ iKey = (iKey<<8) ^ 0x8000 ^ (*++p);
+ }
+ }
+ }
+ }
+ }
+ }else{
+ iKey ^= 0x204000;
+ }
+ }else{
+ iKey ^= 0x4000;
+ }
}
-
- p++;
- a = a<<15;
- a |= *p;
- /* a: p4<<29 | p6<<15 | p8 (unmasked) */
-
- /* moved CSE2 up */
- /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
- b &= SLOT_2_0;
- b = b<<8;
- a |= b;
-
- s = s<<4;
- b = p[-4];
- b &= 0x7f;
- b = b>>3;
- s |= b;
-
- *v = ((u64)s)<<32 | a;
-
- return 9;
+ return *(i64*)&iKey;
}
/*
@@ -37309,7 +38588,7 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
/*
-** Read or write a four-byte big-endian integer value.
+** Read an unsigned 32-bit integer from an unaligned big-endian array of bytes.
*/
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
#if SQLITE_BYTEORDER==4321
@@ -37325,10 +38604,14 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
memcpy(&x,p,4);
return _byteswap_ulong(x);
#else
+ /* Test this limb using -DSQLITE_BYTEORDER=0 */
testcase( p[0]&0x80 );
return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
#endif
}
+
+/* Write an unsigned 32-bit integer into an unaligned big-endian array of bytes.
+*/
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
#if SQLITE_BYTEORDER==4321
memcpy(p,&v,4);
@@ -37339,6 +38622,7 @@ SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
u32 x = _byteswap_ulong(v);
memcpy(p,&x,4);
#else
+ /* Test this limb using -DSQLITE_BYTEORDER=0 */
p[0] = (u8)(v>>24);
p[1] = (u8)(v>>16);
p[2] = (u8)(v>>8);
@@ -37346,7 +38630,58 @@ SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
#endif
}
+/*
+** Read an unsigned 64-bit integer from an unaligned big-endian byte array.
+*/
+SQLITE_PRIVATE SQLITE_OPT_INLINE u64 sqlite3Get8byte(const u8 *p){
+#if SQLITE_BYTEORDER==4321
+ u64 x;
+ memcpy(&x,p,8);
+ return x;
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
+ u64 x;
+ memcpy(&x,p,8);
+ return __builtin_bswap64(x);
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+ u64 x;
+ memcpy(&x,p,8);
+ return _byteswap_uint64(x);
+#else
+ /* Test this limb using -DSQLITE_BYTEORDER=0 */
+ testcase( p[0]&0x80 );
+ return (u64)(
+ (((u64)p[0]) << 56) +
+ (((u64)p[1]) << 48) +
+ (((u64)p[2]) << 40) +
+ (((u64)p[3]) << 32) +
+ (((u64)p[4]) << 24) +
+ (((u64)p[5]) << 16) +
+ (((u64)p[6]) << 8) +
+ (((u64)p[7]) << 0)
+ );
+#endif
+}
+#if SQLITE_BYTEORDER!=4321 /* Only used for little-endian machines */
+/*
+** Byte-swap a 64-bit unsigned integer.
+*/
+SQLITE_PRIVATE SQLITE_OPT_INLINE u64 sqlite3BSwap64(u64 x){
+#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
+ return __builtin_bswap64(x);
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+ return _byteswap_uint64(x);
+#else
+ /* Test this limb using -DSQLITE_BYTEORDER=0 */
+ x = (x << 32) | (x >> 32);
+ x = ((x & UINT64_C(0x0000ffff0000ffff)) << 16) |
+ ((x & UINT64_C(0xffff0000ffff0000)) >> 16);
+ x = ((x & UINT64_C(0x00ff00ff00ff00ff)) << 8) |
+ ((x & UINT64_C(0xff00ff00ff00ff00)) >> 8);
+ return x;
+#endif
+}
+#endif /* SQLITE_BYTEORDER!=4321 */
/*
** Translate a single byte of Hex into an integer.
@@ -38046,28 +39381,28 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 22 */ "SeekLE" OpHelp("key=r[P3@P4]"),
/* 23 */ "SeekGE" OpHelp("key=r[P3@P4]"),
/* 24 */ "SeekGT" OpHelp("key=r[P3@P4]"),
- /* 25 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
- /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
- /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 29 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
- /* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 32 */ "Last" OpHelp(""),
- /* 33 */ "IfSizeBetween" OpHelp(""),
- /* 34 */ "SorterSort" OpHelp(""),
- /* 35 */ "Sort" OpHelp(""),
- /* 36 */ "Rewind" OpHelp(""),
- /* 37 */ "IfEmpty" OpHelp("if( empty(P1) ) goto P2"),
- /* 38 */ "SorterNext" OpHelp(""),
- /* 39 */ "Prev" OpHelp(""),
- /* 40 */ "Next" OpHelp(""),
- /* 41 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 42 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 25 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
+ /* 26 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 27 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 28 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 29 */ "SeekRowid" OpHelp("intkey=r[P3]"),
+ /* 30 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 31 */ "Last" OpHelp(""),
+ /* 32 */ "IfSizeBetween" OpHelp(""),
+ /* 33 */ "SorterSort" OpHelp(""),
+ /* 34 */ "Sort" OpHelp(""),
+ /* 35 */ "Rewind" OpHelp(""),
+ /* 36 */ "IfEmpty" OpHelp("if( empty(P1) ) goto P2"),
+ /* 37 */ "SorterNext" OpHelp(""),
+ /* 38 */ "Prev" OpHelp(""),
+ /* 39 */ "Next" OpHelp(""),
+ /* 40 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 41 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "IdxLT" OpHelp("key=r[P3@P4]"),
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 45 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 46 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 46 */ "IFindKey" OpHelp(""),
/* 47 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
/* 48 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
/* 49 */ "Program" OpHelp(""),
@@ -38094,7 +39429,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 70 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
/* 71 */ "Halt" OpHelp(""),
/* 72 */ "Integer" OpHelp("r[P2]=P1"),
- /* 73 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 73 */ "Int64" OpHelp("r[P2]=PINT13"),
/* 74 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
/* 75 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
/* 76 */ "Null" OpHelp("r[P2..P3]=NULL"),
@@ -38145,7 +39480,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 121 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
/* 122 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
/* 123 */ "Close" OpHelp(""),
- /* 124 */ "ColumnsUsed" OpHelp(""),
+ /* 124 */ "ColumnsUsed" OpHelp("Cursor P1 uses columns PHEX23"),
/* 125 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
/* 126 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
/* 127 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
@@ -38162,7 +39497,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 138 */ "SeekEnd" OpHelp(""),
/* 139 */ "IdxInsert" OpHelp("key=r[P2]"),
/* 140 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 141 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 141 */ "IdxDelete" OpHelp("key=r[P2@P5]"),
/* 142 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
/* 143 */ "IdxRowid" OpHelp("r[P2]=rowid"),
/* 144 */ "FinishSeek" OpHelp(""),
@@ -38175,7 +39510,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 151 */ "LoadAnalysis" OpHelp(""),
/* 152 */ "DropTable" OpHelp(""),
/* 153 */ "DropIndex" OpHelp(""),
- /* 154 */ "Real" OpHelp("r[P2]=P4"),
+ /* 154 */ "Real" OpHelp("r[P2]=PDBL13"),
/* 155 */ "DropTrigger" OpHelp(""),
/* 156 */ "IntegrityCk" OpHelp(""),
/* 157 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
@@ -38234,6 +39569,22 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
** This file contains an experimental VFS layer that operates on a
** Key/Value storage engine where both keys and values must be pure
** text.
+**
+** DEBUG AND TEST
+**
+** For testing on Unix, compile using:
+**
+** make clean sqlite3d CFLAGS='-DSQLITE_OS_KV_OPTIONAL'
+**
+** Then start up a shell using something like:
+**
+** ./sqlite3d 'file:dbname?vfs=kvvfs'
+**
+** Each K/V entry is stored in a separate file in the working
+** directory that has a name like "kvvfs-dbname-*". Due to limitations
+** on the key size, the name of the database must be very short - just
+** a few characters. If the database name is too long, the VFS will
+** malfunction and you will get SQLITE_CORRUPT errors.
*/
/* #include */
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
@@ -38242,7 +39593,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
** Debugging logic
*/
-/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */
+/* SQLITE_KV_TRACE() is used for tracing calls to kvrecord routines. */
#if 0
#define SQLITE_KV_TRACE(X) printf X
#else
@@ -38256,7 +39607,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#define SQLITE_KV_LOG(X)
#endif
-
/*
** Forward declaration of objects used by this VFS implementation
*/
@@ -38264,6 +39614,11 @@ typedef struct KVVfsFile KVVfsFile;
/* A single open file. There are only two files represented by this
** VFS - the database and the rollback journal.
+**
+** Maintenance reminder: if this struct changes in any way, the JSON
+** rendering of its structure must be updated in
+** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
+** compatibility concerns, so it does not need an iVersion member.
*/
struct KVVfsFile {
sqlite3_file base; /* IO methods */
@@ -38313,7 +39668,7 @@ static int kvvfsCurrentTime(sqlite3_vfs*, double*);
static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static sqlite3_vfs sqlite3OsKvvfsObject = {
- 1, /* iVersion */
+ 2, /* iVersion */
sizeof(KVVfsFile), /* szOsFile */
1024, /* mxPathname */
0, /* pNext */
@@ -38389,23 +39744,37 @@ static sqlite3_io_methods kvvfs_jrnl_io_methods = {
/* Forward declarations for the low-level storage engine
*/
-static int kvstorageWrite(const char*, const char *zKey, const char *zData);
-static int kvstorageDelete(const char*, const char *zKey);
-static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
-#define KVSTORAGE_KEY_SZ 32
+#ifndef SQLITE_WASM
+/* In WASM builds these are implemented in JS. */
+static int kvrecordWrite(const char*, const char *zKey, const char *zData);
+static int kvrecordDelete(const char*, const char *zKey);
+static int kvrecordRead(const char*, const char *zKey, char *zBuf, int nBuf);
+#endif
+#ifndef KVRECORD_KEY_SZ
+#define KVRECORD_KEY_SZ 32
+#endif
/* Expand the key name with an appropriate prefix and put the result
** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
-** KVSTORAGE_KEY_SZ bytes.
+** KVRECORD_KEY_SZ bytes.
*/
-static void kvstorageMakeKey(
+static void kvrecordMakeKey(
const char *zClass,
const char *zKeyIn,
char *zKeyOut
){
- sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn);
+ assert( zKeyIn );
+ assert( zKeyOut );
+ assert( zClass );
+ sqlite3_snprintf(KVRECORD_KEY_SZ, zKeyOut, "kvvfs-%s-%s",
+ zClass, zKeyIn);
}
+#ifndef SQLITE_WASM
+/* In WASM builds do not define APIs which use fopen(), fwrite(),
+** and the like because those APIs are a portability issue for
+** WASM.
+*/
/* Write content into a key. zClass is the particular namespace of the
** underlying key/value store to use - either "local" or "session".
**
@@ -38413,14 +39782,14 @@ static void kvstorageMakeKey(
**
** Return the number of errors.
*/
-static int kvstorageWrite(
+static int kvrecordWrite(
const char *zClass,
const char *zKey,
const char *zData
){
FILE *fd;
- char zXKey[KVSTORAGE_KEY_SZ];
- kvstorageMakeKey(zClass, zKey, zXKey);
+ char zXKey[KVRECORD_KEY_SZ];
+ kvrecordMakeKey(zClass, zKey, zXKey);
fd = fopen(zXKey, "wb");
if( fd ){
SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey,
@@ -38438,9 +39807,9 @@ static int kvstorageWrite(
** namespace given by zClass. If the key does not previously exist,
** this routine is a no-op.
*/
-static int kvstorageDelete(const char *zClass, const char *zKey){
- char zXKey[KVSTORAGE_KEY_SZ];
- kvstorageMakeKey(zClass, zKey, zXKey);
+static int kvrecordDelete(const char *zClass, const char *zKey){
+ char zXKey[KVRECORD_KEY_SZ];
+ kvrecordMakeKey(zClass, zKey, zXKey);
unlink(zXKey);
SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey));
return 0;
@@ -38461,7 +39830,7 @@ static int kvstorageDelete(const char *zClass, const char *zKey){
** zero-terminates zBuf at zBuf[0] and returns the size of the data
** without reading it.
*/
-static int kvstorageRead(
+static int kvrecordRead(
const char *zClass,
const char *zKey,
char *zBuf,
@@ -38469,8 +39838,8 @@ static int kvstorageRead(
){
FILE *fd;
struct stat buf;
- char zXKey[KVSTORAGE_KEY_SZ];
- kvstorageMakeKey(zClass, zKey, zXKey);
+ char zXKey[KVRECORD_KEY_SZ];
+ kvrecordMakeKey(zClass, zKey, zXKey);
if( access(zXKey, R_OK)!=0
|| stat(zXKey, &buf)!=0
|| !S_ISREG(buf.st_mode)
@@ -38502,6 +39871,8 @@ static int kvstorageRead(
return (int)n;
}
}
+#endif /* #ifndef SQLITE_WASM */
+
/*
** An internal level of indirection which enables us to replace the
@@ -38509,17 +39880,27 @@ static int kvstorageRead(
** Maintenance reminder: if this struct changes in any way, the JSON
** rendering of its structure must be updated in
** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
-** compatibility concerns, so it does not need an iVersion
-** member.
+** compatibility concerns, so it does not need an iVersion member.
*/
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
struct sqlite3_kvvfs_methods {
- int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
- int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
- int (*xDelete)(const char *zClass, const char *zKey);
+ int (*xRcrdRead)(const char*, const char *zKey, char *zBuf, int nBuf);
+ int (*xRcrdWrite)(const char*, const char *zKey, const char *zData);
+ int (*xRcrdDelete)(const char*, const char *zKey);
const int nKeySize;
+ const int nBufferSize;
+#ifndef SQLITE_WASM
+# define MAYBE_CONST const
+#else
+# define MAYBE_CONST
+#endif
+ MAYBE_CONST sqlite3_vfs * pVfs;
+ MAYBE_CONST sqlite3_io_methods *pIoDb;
+ MAYBE_CONST sqlite3_io_methods *pIoJrnl;
+#undef MAYBE_CONST
};
+
/*
** This object holds the kvvfs I/O methods which may be swapped out
** for JavaScript-side implementations in WASM builds. In such builds
@@ -38534,10 +39915,20 @@ struct sqlite3_kvvfs_methods {
const
#endif
SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
-kvstorageRead,
-kvstorageWrite,
-kvstorageDelete,
-KVSTORAGE_KEY_SZ
+#ifndef SQLITE_WASM
+ .xRcrdRead = kvrecordRead,
+ .xRcrdWrite = kvrecordWrite,
+ .xRcrdDelete = kvrecordDelete,
+#else
+ .xRcrdRead = 0,
+ .xRcrdWrite = 0,
+ .xRcrdDelete = 0,
+#endif
+ .nKeySize = KVRECORD_KEY_SZ,
+ .nBufferSize = SQLITE_KVOS_SZ,
+ .pVfs = &sqlite3OsKvvfsObject,
+ .pIoDb = &kvvfs_db_io_methods,
+ .pIoJrnl = &kvvfs_jrnl_io_methods
};
/****** Utility subroutines ************************************************/
@@ -38564,7 +39955,10 @@ KVSTORAGE_KEY_SZ
** of hexadecimal and base-26 numbers, it is always clear where
** one stops and the next begins.
*/
-static int kvvfsEncode(const char *aData, int nData, char *aOut){
+#ifndef SQLITE_WASM
+static
+#endif
+int kvvfsEncode(const char *aData, int nData, char *aOut){
int i, j;
const unsigned char *a = (const unsigned char*)aData;
for(i=j=0; i='a' && c<='z' ){
n += (c - 'a')*mult;
+ if( n>nOut ) return -1 /* oversized/malformed input */;
mult *= 26;
c = aIn[++i];
}
- if( j+n>nOut ) return -1;
+ if( j+n>nOut ) return -1 /* oversized/malformed input */;
memset(&aOut[j], 0, n);
j += n;
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
- }else{
+ }else if( j='a' && c<='z' ){
- n += (zTxt[i] - 'a')*mult;
+ sqlite3_free(pFile->aJrnl);
+ pFile->aJrnl = 0;
+ pFile->nJrnl = 0;
+ while( (c = zTxt[i])>='a' && c<='z' ){
+ n += (c - 'a')*mult;
mult *= 26;
+ ++i;
+ }
+ if( ' '!=zTxt[i++] ){
+ /* Malformed input */
+ return;
}
- sqlite3_free(pFile->aJrnl);
pFile->aJrnl = sqlite3_malloc64( n );
if( pFile->aJrnl==0 ){
- pFile->nJrnl = 0;
return;
}
pFile->nJrnl = n;
@@ -38695,13 +40102,14 @@ static void kvvfsDecodeJournal(
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
char zData[50];
zData[0] = 0;
- sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1);
+ sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "sz", zData,
+ sizeof(zData)-1);
return strtoll(zData, 0, 0);
}
static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
char zData[50];
sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
- return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData);
+ return sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "sz", zData);
}
/****** sqlite3_io_methods methods ******************************************/
@@ -38716,6 +40124,7 @@ static int kvvfsClose(sqlite3_file *pProtoFile){
pFile->isJournal ? "journal" : "db"));
sqlite3_free(pFile->aJrnl);
sqlite3_free(pFile->aData);
+ memset(pFile, 0, sizeof(*pFile));
return SQLITE_OK;
}
@@ -38732,16 +40141,23 @@ static int kvvfsReadJrnl(
assert( pFile->isJournal );
SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
if( pFile->aJrnl==0 ){
- int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0);
+ int rc;
+ int szTxt = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl",
+ 0, 0);
char *aTxt;
if( szTxt<=4 ){
return SQLITE_IOERR;
}
aTxt = sqlite3_malloc64( szTxt+1 );
if( aTxt==0 ) return SQLITE_NOMEM;
- kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1);
- kvvfsDecodeJournal(pFile, aTxt, szTxt);
+ rc = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl",
+ aTxt, szTxt+1);
+ if( rc>=0 ){
+ kvvfsDecodeJournal(pFile, aTxt, szTxt);
+ rc = 0;
+ }
sqlite3_free(aTxt);
+ if( rc ) return rc;
if( pFile->aJrnl==0 ) return SQLITE_IOERR;
}
if( iOfst+iAmt>pFile->nJrnl ){
@@ -38781,8 +40197,8 @@ static int kvvfsReadDb(
pgno = 1;
}
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
- got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey,
- aData, SQLITE_KVOS_SZ-1);
+ got = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, zKey,
+ aData, SQLITE_KVOS_SZ-1);
if( got<0 ){
n = 0;
}else{
@@ -38850,6 +40266,7 @@ static int kvvfsWriteDb(
unsigned int pgno;
char zKey[30];
char *aData = pFile->aData;
+ int rc;
SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
assert( iAmt>=512 && iAmt<=65536 );
assert( (iAmt & (iAmt-1))==0 );
@@ -38858,13 +40275,13 @@ static int kvvfsWriteDb(
pgno = 1 + iOfst/iAmt;
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
kvvfsEncode(zBuf, iAmt, aData);
- if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){
- return SQLITE_IOERR;
- }
- if( iOfst+iAmt > pFile->szDb ){
- pFile->szDb = iOfst + iAmt;
+ rc = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, zKey, aData);
+ if( 0==rc ){
+ if( iOfst+iAmt > pFile->szDb ){
+ pFile->szDb = iOfst + iAmt;
+ }
}
- return SQLITE_OK;
+ return rc;
}
/*
@@ -38874,7 +40291,7 @@ static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size));
assert( size==0 );
- sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl");
+ sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, "jrnl");
sqlite3_free(pFile->aJrnl);
pFile->aJrnl = 0;
pFile->nJrnl = 0;
@@ -38893,7 +40310,7 @@ static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){
pgnoMax = 2 + pFile->szDb/pFile->szPage;
while( pgno<=pgnoMax ){
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
- sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey);
+ sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, zKey);
pgno++;
}
pFile->szDb = size;
@@ -38925,7 +40342,7 @@ static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){
}while( n>0 );
zOut[i++] = ' ';
kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
- i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut);
+ i = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "jrnl", zOut);
sqlite3_free(zOut);
return i ? SQLITE_IOERR : SQLITE_OK;
}
@@ -39039,33 +40456,44 @@ static int kvvfsOpen(
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
if( zName==0 ) zName = "";
SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName));
- if( strcmp(zName, "local")==0
- || strcmp(zName, "session")==0
- ){
- pFile->isJournal = 0;
- pFile->base.pMethods = &kvvfs_db_io_methods;
- }else
- if( strcmp(zName, "local-journal")==0
- || strcmp(zName, "session-journal")==0
- ){
+ assert(!pFile->zClass);
+ assert(!pFile->aData);
+ assert(!pFile->aJrnl);
+ assert(!pFile->nJrnl);
+ assert(!pFile->base.pMethods);
+ pFile->szPage = -1;
+ pFile->szDb = -1;
+ if( 0==sqlite3_strglob("*-journal", zName) ){
pFile->isJournal = 1;
pFile->base.pMethods = &kvvfs_jrnl_io_methods;
+ if( 0==strcmp("session-journal",zName) ){
+ pFile->zClass = "session";
+ }else if( 0==strcmp("local-journal",zName) ){
+ pFile->zClass = "local";
+ }
}else{
- return SQLITE_CANTOPEN;
+ pFile->isJournal = 0;
+ pFile->base.pMethods = &kvvfs_db_io_methods;
}
- if( zName[0]=='s' ){
- pFile->zClass = "session";
- }else{
- pFile->zClass = "local";
+ if( !pFile->zClass ){
+#ifdef SQLITE_WASM
+ if( strlen(zName) >= (KVRECORD_KEY_SZ
+ - 6 /* "kvvfs-" */
+ - 11 /* "-NNNNNNNNNNN" */) ){
+ return SQLITE_CANTOPEN;
+ }
+#else
+ if( 0!=strcmp(zName, "local") && 0!=strcmp(zName, "session") ){
+ /* Historical naming restriction which journaling depends on. */
+ return SQLITE_CANTOPEN;
+ }
+#endif
+ pFile->zClass = zName;
}
pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
if( pFile->aData==0 ){
return SQLITE_NOMEM;
}
- pFile->aJrnl = 0;
- pFile->nJrnl = 0;
- pFile->szPage = -1;
- pFile->szDb = -1;
return SQLITE_OK;
}
@@ -39075,13 +40503,17 @@ static int kvvfsOpen(
** returning.
*/
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+ int rc /* The JS impl can fail with OOM in argument conversion */;
if( strcmp(zPath, "local-journal")==0 ){
- sqlite3KvvfsMethods.xDelete("local", "jrnl");
+ rc = sqlite3KvvfsMethods.xRcrdDelete("local", "jrnl");
}else
if( strcmp(zPath, "session-journal")==0 ){
- sqlite3KvvfsMethods.xDelete("session", "jrnl");
+ rc = sqlite3KvvfsMethods.xRcrdDelete("session", "jrnl");
}
- return SQLITE_OK;
+ else{
+ rc = 0;
+ }
+ return rc;
}
/*
@@ -39095,21 +40527,42 @@ static int kvvfsAccess(
int *pResOut
){
SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath));
+#if 0 && defined(SQLITE_WASM)
+ /*
+ ** This is not having the desired effect in the JS bindings.
+ ** It's ostensibly the same logic as the #else block, but
+ ** it's not behaving that way.
+ **
+ ** In JS we map all zPaths to Storage objects, and -journal files
+ ** are mapped to the storage for the main db (which is is exactly
+ ** what the mapping of "local-journal" -> "local" is doing).
+ */
+ const char *zKey = (0==sqlite3_strglob("*-journal", zPath))
+ ? "jrnl" : "sz";
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead(zPath, zKey, 0, 0)>0;
+#else
if( strcmp(zPath, "local-journal")==0 ){
- *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0;
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("local", "jrnl", 0, 0)>0;
}else
if( strcmp(zPath, "session-journal")==0 ){
- *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0;
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("session", "jrnl", 0, 0)>0;
}else
if( strcmp(zPath, "local")==0 ){
- *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0;
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("local", "sz", 0, 0)>0;
}else
if( strcmp(zPath, "session")==0 ){
- *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0;
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("session", "sz", 0, 0)>0;
}else
{
*pResOut = 0;
}
+ /*all current JS tests avoid triggering: assert( *pResOut == 0 ); */
+#endif
SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut));
return SQLITE_OK;
}
@@ -44343,9 +45796,9 @@ static int unixShmMap(
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
if( pShmNode->nRegionszRegion = szRegion;
@@ -44376,7 +45829,7 @@ static int unixShmMap(
*/
else{
static const int pgsz = 4096;
- int iPg;
+ i64 iPg;
/* Write to the last byte of each newly allocated or extended page */
assert( (nByte % pgsz)==0 );
@@ -44393,7 +45846,7 @@ static int unixShmMap(
}
/* Map the requested memory region into this processes address space. */
- apNew = (char **)sqlite3_realloc(
+ apNew = (char **)sqlite3_realloc64(
pShmNode->apRegion, nReqRegion*sizeof(char *)
);
if( !apNew ){
@@ -44402,8 +45855,8 @@ static int unixShmMap(
}
pShmNode->apRegion = apNew;
while( pShmNode->nRegionhShm>=0 ){
pMem = osMmap(0, nMap,
@@ -44792,7 +46245,6 @@ static void unixRemapfile(
const char *zErr = "mmap";
int h = pFd->h; /* File descriptor open on db file */
u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */
- i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */
u8 *pNew = 0; /* Location of new mapping */
int flags = PROT_READ; /* Flags to pass to mmap() */
@@ -44808,37 +46260,35 @@ static void unixRemapfile(
#endif
if( pOrig ){
-#if HAVE_MREMAP
- i64 nReuse = pFd->mmapSize;
-#else
- const int szSyspage = osGetpagesize();
- i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
-#endif
- u8 *pReq = &pOrig[nReuse];
+ i64 nReuse = pFd->mmapSize & ~((int)osGetpagesize()-1);
- /* Unmap any pages of the existing mapping that cannot be reused. */
- if( nReuse!=nOrig ){
- osMunmap(pReq, nOrig-nReuse);
+ /* Unmap any part of the current mapping that will not be reused */
+ if( nReusemmapSizeActual ){
+ osMunmap(&pOrig[nReuse], pFd->mmapSizeActual - nReuse);
}
+ /* If nReuse is now zero, then the entire mapping was unmapped by the
+ ** call above. In this case do not attempt to extend pOrig. */
+ if( nReuse>0 ){
#if HAVE_MREMAP
- pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
- zErr = "mremap";
+ pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
+ zErr = "mremap";
#else
- pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
- if( pNew!=MAP_FAILED ){
- if( pNew!=pReq ){
- osMunmap(pNew, nNew - nReuse);
- pNew = 0;
- }else{
- pNew = pOrig;
+ pNew = osMmap(&pOrig[nReuse], nNew-nReuse, flags, MAP_SHARED, h, nReuse);
+ if( pNew!=MAP_FAILED ){
+ if( pNew!=&pOrig[nReuse] ){
+ osMunmap(pNew, nNew - nReuse);
+ pNew = 0;
+ }else{
+ pNew = pOrig;
+ }
}
- }
#endif
- /* The attempt to extend the existing mapping failed. Free it. */
- if( pNew==MAP_FAILED || pNew==0 ){
- osMunmap(pOrig, nReuse);
+ /* The attempt to extend the existing mapping failed. Free it. */
+ if( pNew==MAP_FAILED || pNew==0 ){
+ osMunmap(pOrig, nReuse);
+ }
}
}
@@ -45459,36 +46909,29 @@ static int fillInUnixFile(
return rc;
}
-/*
-** Directories to consider for temp files.
-*/
-static const char *azTempDirs[] = {
- 0,
- 0,
- "/var/tmp",
- "/usr/tmp",
- "/tmp",
- "."
-};
-
-/*
-** Initialize first two members of azTempDirs[] array.
-*/
-static void unixTempFileInit(void){
- azTempDirs[0] = getenv("SQLITE_TMPDIR");
- azTempDirs[1] = getenv("TMPDIR");
-}
-
/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
+**
+** The return value might be a string obtained from getenv() and so
+** the return value should not be used after any call to setenv() or
+** putenv() as that value might have been freed.
*/
static const char *unixTempFileDir(void){
- unsigned int i = 0;
+ unsigned int i;
struct stat buf;
- const char *zDir = sqlite3_temp_directory;
+ const char *zDir;
- while(1){
+ for(i=0; i<7; i++){
+ switch( i ){
+ case 0: zDir = sqlite3_temp_directory; break;
+ case 1: zDir = getenv("SQLITE_TMPDIR"); break;
+ case 2: zDir = getenv("TMPDIR"); break;
+ case 3: zDir = "/var/tmp"; break;
+ case 4: zDir = "/usr/tmp"; break;
+ case 5: zDir = "/tmp"; break;
+ default: zDir = "."; break;
+ }
if( zDir!=0
#if OS_VXWORKS
&& zDir[0]=='/'
@@ -45499,8 +46942,6 @@ static const char *unixTempFileDir(void){
){
return zDir;
}
- if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
- zDir = azTempDirs[i++];
}
return 0;
}
@@ -45849,7 +47290,22 @@ static int unixOpen(
}else if( !zName ){
/* If zName is NULL, the upper layer is requesting a temp file. */
- assert(isDelete && !isNewJrnl);
+ assert( isDelete );
+ assert( !isNewJrnl );
+ assert( isExclusive );
+ assert( isReadWrite );
+#if defined(__linux__) && defined(O_TMPFILE)
+ /* On systems that support O_TMPFILE, use that flag to create a more
+ ** secure temporary file that cannot be accessed by other processes
+ */
+ zName = unixTempFileDir();
+ if( zName
+ && (fd = robust_open(zName, O_RDWR|O_EXCL|O_TMPFILE, 0600))>=0
+ ){
+ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags|UNIXFILE_NOLOCK);
+ goto open_finished;
+ }
+#endif
rc = unixGetTempname(pVfs->mxPathname, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
@@ -47768,9 +49224,6 @@ SQLITE_API int sqlite3_os_init(void){
assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
#endif
- /* Initialize temp file dir array. */
- unixTempFileInit();
-
return SQLITE_OK;
}
@@ -47820,86 +49273,6 @@ SQLITE_API int sqlite3_os_end(void){
*/
/* #include "os_win.h" */
-/*
-** Compiling and using WAL mode requires several APIs that are only
-** available in Windows platforms based on the NT kernel.
-*/
-#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
-# error "WAL mode requires support from the Windows NT kernel, compile\
- with SQLITE_OMIT_WAL."
-#endif
-
-#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0
-# error "Memory mapped files require support from the Windows NT kernel,\
- compile with SQLITE_MAX_MMAP_SIZE=0."
-#endif
-
-/*
-** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
-** based on the sub-platform)?
-*/
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI)
-# define SQLITE_WIN32_HAS_ANSI
-#endif
-
-/*
-** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
-** based on the sub-platform)?
-*/
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \
- !defined(SQLITE_WIN32_NO_WIDE)
-# define SQLITE_WIN32_HAS_WIDE
-#endif
-
-/*
-** Make sure at least one set of Win32 APIs is available.
-*/
-#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE)
-# error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\
- must be defined."
-#endif
-
-/*
-** Define the required Windows SDK version constants if they are not
-** already available.
-*/
-#ifndef NTDDI_WIN8
-# define NTDDI_WIN8 0x06020000
-#endif
-
-#ifndef NTDDI_WINBLUE
-# define NTDDI_WINBLUE 0x06030000
-#endif
-
-#ifndef NTDDI_WINTHRESHOLD
-# define NTDDI_WINTHRESHOLD 0x06040000
-#endif
-
-/*
-** Check to see if the GetVersionEx[AW] functions are deprecated on the
-** target system. GetVersionEx was first deprecated in Win8.1.
-*/
-#ifndef SQLITE_WIN32_GETVERSIONEX
-# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
-# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */
-# else
-# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */
-# endif
-#endif
-
-/*
-** Check to see if the CreateFileMappingA function is supported on the
-** target system. It is unavailable when using "mincore.lib" on Win10.
-** When compiling for Windows 10, always assume "mincore.lib" is in use.
-*/
-#ifndef SQLITE_WIN32_CREATEFILEMAPPINGA
-# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD
-# define SQLITE_WIN32_CREATEFILEMAPPINGA 0
-# else
-# define SQLITE_WIN32_CREATEFILEMAPPINGA 1
-# endif
-#endif
-
/*
** This constant should already be defined (in the "WinDef.h" SDK file).
*/
@@ -47979,45 +49352,7 @@ SQLITE_API int sqlite3_os_end(void){
#endif
/*
-** Do we need to manually define the Win32 file mapping APIs for use with WAL
-** mode or memory mapped files (e.g. these APIs are available in the Windows
-** CE SDK; however, they are not present in the header file)?
-*/
-#if SQLITE_WIN32_FILEMAPPING_API && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
-/*
-** Two of the file mapping APIs are different under WinRT. Figure out which
-** set we need.
-*/
-#if SQLITE_OS_WINRT
-WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
- LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
-
-WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
-#else
-#if defined(SQLITE_WIN32_HAS_ANSI)
-WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
- DWORD, DWORD, DWORD, LPCSTR);
-#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
-WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
- DWORD, DWORD, DWORD, LPCWSTR);
-#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
-
-WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
-#endif /* SQLITE_OS_WINRT */
-
-/*
-** These file mapping APIs are common to both Win32 and WinRT.
-*/
-
-WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
-WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
-#endif /* SQLITE_WIN32_FILEMAPPING_API */
-
-/*
-** Some Microsoft compilers lack this definition.
+** Some older Microsoft compilers lack the following definition.
*/
#ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
@@ -48037,19 +49372,6 @@ typedef struct winShm winShm; /* A connection to shared-memory */
typedef struct winShmNode winShmNode; /* A region of shared-memory */
#endif
-/*
-** WinCE lacks native support for file locking so we have to fake it
-** with some code of our own.
-*/
-#if SQLITE_OS_WINCE
-typedef struct winceLock {
- int nReaders; /* Number of reader locks obtained */
- BOOL bPending; /* Indicates a pending lock has been obtained */
- BOOL bReserved; /* Indicates a reserved lock has been obtained */
- BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
-} winceLock;
-#endif
-
/*
** The winFile structure is a subclass of sqlite3_file* specific to the win32
** portability layer.
@@ -48068,13 +49390,6 @@ struct winFile {
#endif
const char *zPath; /* Full pathname of this file */
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
-#if SQLITE_OS_WINCE
- LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
- HANDLE hMutex; /* Mutex used to control access to shared lock */
- HANDLE hShared; /* Shared memory segment used for locking */
- winceLock local; /* Locks obtained by this instance of winFile */
- winceLock *shared; /* Global shared lock memory for the file */
-#endif
#if SQLITE_MAX_MMAP_SIZE>0
int nFetchOut; /* Number of outstanding xFetch references */
HANDLE hMap; /* Handle for accessing memory mapping */
@@ -48271,36 +49586,10 @@ static void winMemShutdown(void *pAppData);
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
#endif /* SQLITE_WIN32_MALLOC */
-/*
-** The following variable is (normally) set once and never changes
-** thereafter. It records whether the operating system is Win9x
-** or WinNT.
-**
-** 0: Operating system unknown.
-** 1: Operating system is Win9x.
-** 2: Operating system is WinNT.
-**
-** In order to facilitate testing on a WinNT system, the test fixture
-** can manually set this value to 1 to emulate Win98 behavior.
-*/
-#ifdef SQLITE_TEST
-SQLITE_API LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
-#else
-static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
-#endif
-
#ifndef SYSCALL
# define SYSCALL sqlite3_syscall_ptr
#endif
-/*
-** This function is not available on Windows CE or WinRT.
- */
-
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-# define osAreFileApisANSI() 1
-#endif
-
/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
@@ -48312,619 +49601,246 @@ static struct win_syscall {
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
sqlite3_syscall_ptr pDefault; /* Default value */
} aSyscall[] = {
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
{ "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
-#else
- { "AreFileApisANSI", (SYSCALL)0, 0 },
-#endif
-
-#ifndef osAreFileApisANSI
#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
-#endif
-
-#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
- { "CharLowerW", (SYSCALL)CharLowerW, 0 },
-#else
- { "CharLowerW", (SYSCALL)0, 0 },
-#endif
-
-#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
-
-#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
- { "CharUpperW", (SYSCALL)CharUpperW, 0 },
-#else
- { "CharUpperW", (SYSCALL)0, 0 },
-#endif
-
-#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
{ "CloseHandle", (SYSCALL)CloseHandle, 0 },
+#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[1].pCurrent)
-#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "CreateFileA", (SYSCALL)CreateFileA, 0 },
-#else
- { "CreateFileA", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
- LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "CreateFileW", (SYSCALL)CreateFileW, 0 },
-#else
- { "CreateFileW", (SYSCALL)0, 0 },
-#endif
-
#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
- LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
+ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[2].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \
- SQLITE_WIN32_CREATEFILEMAPPINGA
- { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
+#if defined(SQLITE_UWP)
+ { "CreateFileMappingFromApp",(SYSCALL)CreateFileMappingFromApp,0 },
#else
- { "CreateFileMappingA", (SYSCALL)0, 0 },
+ { "CreateFileMappingFromApp",(SYSCALL)0, 0 },
#endif
+#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE,\
+ PSECURITY_ATTRIBUTES, \
+ ULONG,ULONG64,PCWSTR))aSyscall[3].pCurrent)
-#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
- DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
-
-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
+#if !defined(SQLITE_UWP)
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
#else
{ "CreateFileMappingW", (SYSCALL)0, 0 },
#endif
-
#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
- DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
+ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[4].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
-#else
- { "CreateMutexW", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
- LPCWSTR))aSyscall[8].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
-#else
- { "DeleteFileA", (SYSCALL)0, 0 },
-#endif
-
-#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
{ "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
-#else
- { "DeleteFileW", (SYSCALL)0, 0 },
-#endif
-
-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
-
-#if SQLITE_OS_WINCE
- { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
-#else
- { "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
-#endif
-
-#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(const FILETIME*, \
- LPFILETIME))aSyscall[11].pCurrent)
-
-#if SQLITE_OS_WINCE
- { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
-#else
- { "FileTimeToSystemTime", (SYSCALL)0, 0 },
-#endif
-
-#define osFileTimeToSystemTime ((BOOL(WINAPI*)(const FILETIME*, \
- LPSYSTEMTIME))aSyscall[12].pCurrent)
+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[5].pCurrent)
{ "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[6].pCurrent)
-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
-#else
- { "FormatMessageA", (SYSCALL)0, 0 },
-#endif
-
-#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
- DWORD,va_list*))aSyscall[14].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
{ "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
-#else
- { "FormatMessageW", (SYSCALL)0, 0 },
-#endif
-
#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
- DWORD,va_list*))aSyscall[15].pCurrent)
+ DWORD,va_list*))aSyscall[7].pCurrent)
-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_UWP)
{ "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
#else
{ "FreeLibrary", (SYSCALL)0, 0 },
#endif
-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[8].pCurrent)
{ "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[9].pCurrent)
-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
-
-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
- { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
-#else
- { "GetDiskFreeSpaceA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
- LPDWORD))aSyscall[18].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
-#else
- { "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
- LPDWORD))aSyscall[19].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
-#else
- { "GetFileAttributesA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
-#else
- { "GetFileAttributesW", (SYSCALL)0, 0 },
-#endif
+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
-#else
- { "GetFileAttributesExW", (SYSCALL)0, 0 },
-#endif
-
#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
- LPVOID))aSyscall[22].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "GetFileSize", (SYSCALL)GetFileSize, 0 },
-#else
- { "GetFileSize", (SYSCALL)0, 0 },
-#endif
+ LPVOID))aSyscall[11].pCurrent)
-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
+ { "GetFileSizeEx", (SYSCALL)GetFileSizeEx, 0 },
+#define osGetFileSizeEx ((BOOL(WINAPI*)(HANDLE, \
+ PLARGE_INTEGER))aSyscall[12].pCurrent)
-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
- { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
-#else
- { "GetFullPathNameA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
- LPSTR*))aSyscall[24].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
-#else
- { "GetFullPathNameW", (SYSCALL)0, 0 },
-#endif
-
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
- LPWSTR*))aSyscall[25].pCurrent)
+ LPWSTR*))aSyscall[13].pCurrent)
-/*
-** For GetLastError(), MSDN says:
-**
-** Minimum supported client: Windows XP [desktop apps | UWP apps]
-** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
-*/
{ "GetLastError", (SYSCALL)GetLastError, 0 },
+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[14].pCurrent)
-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
-
-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
-#if SQLITE_OS_WINCE
- /* The GetProcAddressA() routine is only available on Windows CE. */
- { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
-#else
- /* All other Windows platforms expect GetProcAddress() to take
- ** an ANSI string regardless of the _UNICODE setting */
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_UWP)
{ "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
-#endif
#else
{ "GetProcAddressA", (SYSCALL)0, 0 },
#endif
-
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
- LPCSTR))aSyscall[27].pCurrent)
+ LPCSTR))aSyscall[15].pCurrent)
-#if !SQLITE_OS_WINRT
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
-#else
- { "GetSystemInfo", (SYSCALL)0, 0 },
-#endif
+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[16].pCurrent)
-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
-
- { "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
-
-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
-
-#if !SQLITE_OS_WINCE
{ "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
-#else
- { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 },
-#endif
-
#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
- LPFILETIME))aSyscall[30].pCurrent)
+ LPFILETIME))aSyscall[17].pCurrent)
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
-#else
- { "GetTempPathA", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
-
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
- { "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
-#else
+#ifdef SQLITE_UWP
{ "GetTempPathW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "GetTickCount", (SYSCALL)GetTickCount, 0 },
-#else
- { "GetTickCount", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX
- { "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
#else
- { "GetVersionExA", (SYSCALL)0, 0 },
+ { "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
#endif
+#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[18].pCurrent)
-#define osGetVersionExA ((BOOL(WINAPI*)( \
- LPOSVERSIONINFOA))aSyscall[34].pCurrent)
+ { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[19].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
- SQLITE_WIN32_GETVERSIONEX
- { "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
+#ifdef SQLITE_UWP
+ { "HeapAlloc", (SYSCALL)0, 0 },
#else
- { "GetVersionExW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetVersionExW ((BOOL(WINAPI*)( \
- LPOSVERSIONINFOW))aSyscall[35].pCurrent)
-
{ "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
-
+#endif
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
- SIZE_T))aSyscall[36].pCurrent)
+ SIZE_T))aSyscall[20].pCurrent)
-#if !SQLITE_OS_WINRT
- { "HeapCreate", (SYSCALL)HeapCreate, 0 },
-#else
+#ifdef SQLITE_UWP
{ "HeapCreate", (SYSCALL)0, 0 },
+#else
+ { "HeapCreate", (SYSCALL)HeapCreate, 0 },
#endif
-
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
- SIZE_T))aSyscall[37].pCurrent)
+ SIZE_T))aSyscall[21].pCurrent)
-#if !SQLITE_OS_WINRT
- { "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
-#else
+#ifdef SQLITE_UWP
{ "HeapDestroy", (SYSCALL)0, 0 },
+#else
+ { "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
#endif
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[22].pCurrent)
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
-
+#ifdef SQLITE_UWP
+ { "HeapFree", (SYSCALL)0, 0 },
+#else
{ "HeapFree", (SYSCALL)HeapFree, 0 },
+#endif
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[23].pCurrent)
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent)
-
+#ifdef SQLITE_UWP
+ { "HeapReAlloc", (SYSCALL)0, 0 },
+#else
{ "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
-
+#endif
#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
- SIZE_T))aSyscall[40].pCurrent)
+ SIZE_T))aSyscall[24].pCurrent)
+#ifdef SQLITE_UWP
+ { "HeapSize", (SYSCALL)0, 0 },
+#else
{ "HeapSize", (SYSCALL)HeapSize, 0 },
-
+#endif
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[41].pCurrent)
+ LPCVOID))aSyscall[25].pCurrent)
-#if !SQLITE_OS_WINRT
- { "HeapValidate", (SYSCALL)HeapValidate, 0 },
-#else
+#ifdef SQLITE_UWP
{ "HeapValidate", (SYSCALL)0, 0 },
+#else
+ { "HeapValidate", (SYSCALL)HeapValidate, 0 },
#endif
-
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[42].pCurrent)
+ LPCVOID))aSyscall[26].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- { "HeapCompact", (SYSCALL)HeapCompact, 0 },
-#else
+#ifdef SQLITE_UWP
{ "HeapCompact", (SYSCALL)0, 0 },
-#endif
-
-#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
- { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
#else
- { "LoadLibraryA", (SYSCALL)0, 0 },
+ { "HeapCompact", (SYSCALL)HeapCompact, 0 },
#endif
+#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[27].pCurrent)
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
- !defined(SQLITE_OMIT_LOAD_EXTENSION)
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_UWP)
{ "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
#else
{ "LoadLibraryW", (SYSCALL)0, 0 },
#endif
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[28].pCurrent)
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent)
-
-#if !SQLITE_OS_WINRT
{ "LocalFree", (SYSCALL)LocalFree, 0 },
-#else
- { "LocalFree", (SYSCALL)0, 0 },
-#endif
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[29].pCurrent)
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- { "LockFile", (SYSCALL)LockFile, 0 },
-#else
- { "LockFile", (SYSCALL)0, 0 },
-#endif
-
-#if !defined(osLockFile) && defined(SQLITE_WIN32_HAS_ANSI)
-#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[47].pCurrent)
-#endif
-
-#if !SQLITE_OS_WINCE
{ "LockFileEx", (SYSCALL)LockFileEx, 0 },
-#else
- { "LockFileEx", (SYSCALL)0, 0 },
-#endif
-
-#ifndef osLockFileEx
#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[48].pCurrent)
-#endif
+ LPOVERLAPPED))aSyscall[30].pCurrent)
-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
+#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
+ && !defined(SQLITE_UWP)
{ "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
#else
{ "MapViewOfFile", (SYSCALL)0, 0 },
#endif
-
#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- SIZE_T))aSyscall[49].pCurrent)
+ SIZE_T))aSyscall[31].pCurrent)
- { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
+#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
+ && defined(SQLITE_UWP)
+ { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
+#else
+ { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
+#endif
+#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
+ SIZE_T))aSyscall[32].pCurrent)
+ { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
- int))aSyscall[50].pCurrent)
+ int))aSyscall[33].pCurrent)
{ "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
-
#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
- LARGE_INTEGER*))aSyscall[51].pCurrent)
+ LARGE_INTEGER*))aSyscall[34].pCurrent)
{ "ReadFile", (SYSCALL)ReadFile, 0 },
-
#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[52].pCurrent)
+ LPOVERLAPPED))aSyscall[35].pCurrent)
{ "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[36].pCurrent)
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent)
-
-#if !SQLITE_OS_WINRT
- { "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
-#else
- { "SetFilePointer", (SYSCALL)0, 0 },
-#endif
-
-#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
- DWORD))aSyscall[54].pCurrent)
+ { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
+#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER,\
+ PLARGE_INTEGER,DWORD))aSyscall[37].pCurrent)
-#if !SQLITE_OS_WINRT
{ "Sleep", (SYSCALL)Sleep, 0 },
-#else
- { "Sleep", (SYSCALL)0, 0 },
-#endif
-
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent)
-
- { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[38].pCurrent)
-#define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \
- LPFILETIME))aSyscall[56].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
- { "UnlockFile", (SYSCALL)UnlockFile, 0 },
-#else
- { "UnlockFile", (SYSCALL)0, 0 },
-#endif
-
-#if !defined(osUnlockFile) && defined(SQLITE_WIN32_HAS_ANSI)
-#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[57].pCurrent)
-#endif
-
-#if !SQLITE_OS_WINCE
{ "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
-#else
- { "UnlockFileEx", (SYSCALL)0, 0 },
-#endif
-
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[58].pCurrent)
+ LPOVERLAPPED))aSyscall[39].pCurrent)
-#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
#else
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
#endif
-
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent)
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[40].pCurrent)
{ "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
-
#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
- LPCSTR,LPBOOL))aSyscall[60].pCurrent)
+ LPCSTR,LPBOOL))aSyscall[41].pCurrent)
{ "WriteFile", (SYSCALL)WriteFile, 0 },
-
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[61].pCurrent)
+ LPOVERLAPPED))aSyscall[42].pCurrent)
-#if SQLITE_OS_WINRT
- { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
-#else
- { "CreateEventExW", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
- DWORD,DWORD))aSyscall[62].pCurrent)
-
-/*
-** For WaitForSingleObject(), MSDN says:
-**
-** Minimum supported client: Windows XP [desktop apps | UWP apps]
-** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
-*/
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
-
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
- DWORD))aSyscall[63].pCurrent)
+ DWORD))aSyscall[43].pCurrent)
-#if !SQLITE_OS_WINCE
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
-#else
- { "WaitForSingleObjectEx", (SYSCALL)0, 0 },
-#endif
-
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
- BOOL))aSyscall[64].pCurrent)
+ BOOL))aSyscall[44].pCurrent)
-#if SQLITE_OS_WINRT
- { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
-#else
- { "SetFilePointerEx", (SYSCALL)0, 0 },
-#endif
-
-#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
- PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
-#else
- { "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
-#endif
-
-#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
- FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
-
-#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
- { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
-#else
- { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
-#endif
-
-#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
- SIZE_T))aSyscall[67].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "CreateFile2", (SYSCALL)CreateFile2, 0 },
-#else
- { "CreateFile2", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
- LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
-
-#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
- { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
-#else
- { "LoadPackagedLibrary", (SYSCALL)0, 0 },
-#endif
-
-#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
- DWORD))aSyscall[69].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
-#else
- { "GetTickCount64", (SYSCALL)0, 0 },
-#endif
-
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
-
-#if SQLITE_OS_WINRT
- { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
-#else
- { "GetNativeSystemInfo", (SYSCALL)0, 0 },
-#endif
-
-#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
- LPSYSTEM_INFO))aSyscall[71].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_ANSI)
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
-#else
- { "OutputDebugStringA", (SYSCALL)0, 0 },
-#endif
-
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
- { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
-#else
- { "OutputDebugStringW", (SYSCALL)0, 0 },
-#endif
-
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[45].pCurrent)
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
-
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
-
-#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
- { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
-#else
- { "CreateFileMappingFromApp", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
- LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[46].pCurrent)
/*
** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
@@ -48933,131 +49849,96 @@ static struct win_syscall {
*/
#if defined(InterlockedCompareExchange)
{ "InterlockedCompareExchange", (SYSCALL)0, 0 },
-
#define osInterlockedCompareExchange InterlockedCompareExchange
#else
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
-
-#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
- SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
+#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*,\
+ LONG,LONG))aSyscall[47].pCurrent)
#endif /* defined(InterlockedCompareExchange) */
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
+#if SQLITE_WIN32_USE_UUID
{ "UuidCreate", (SYSCALL)UuidCreate, 0 },
#else
{ "UuidCreate", (SYSCALL)0, 0 },
#endif
+#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[48].pCurrent)
-#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent)
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
+#if SQLITE_WIN32_USE_UUID
{ "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
#else
{ "UuidCreateSequential", (SYSCALL)0, 0 },
#endif
-
#define osUuidCreateSequential \
- ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
+ ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[49].pCurrent)
#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
{ "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
#else
{ "FlushViewOfFile", (SYSCALL)0, 0 },
#endif
-
#define osFlushViewOfFile \
- ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
+ ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[50].pCurrent)
-/*
-** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent()
-** to implement blocking locks with timeouts. MSDN says:
-**
-** Minimum supported client: Windows XP [desktop apps | UWP apps]
-** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
-*/
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
{ "CreateEvent", (SYSCALL)CreateEvent, 0 },
#else
{ "CreateEvent", (SYSCALL)0, 0 },
#endif
+#define osCreateEvent ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
+ BOOL,LPCSTR))aSyscall[51].pCurrent)
-#define osCreateEvent ( \
- (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
- aSyscall[80].pCurrent \
-)
-
-/*
-** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo()
-** for the case where a timeout expires and a lock request must be
-** cancelled.
-**
-** Minimum supported client: Windows XP [desktop apps | UWP apps]
-** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
-*/
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
{ "CancelIo", (SYSCALL)CancelIo, 0 },
#else
{ "CancelIo", (SYSCALL)0, 0 },
#endif
-
-#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32)
- { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 },
-#else
- { "GetModuleHandleW", (SYSCALL)0, 0 },
-#endif
-
-#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent)
+#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[52].pCurrent)
#ifndef _WIN32
{ "getenv", (SYSCALL)getenv, 0 },
#else
{ "getenv", (SYSCALL)0, 0 },
#endif
-
-#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent)
+#define osGetenv ((const char *(*)(const char *))aSyscall[53].pCurrent)
#ifndef _WIN32
{ "getcwd", (SYSCALL)getcwd, 0 },
#else
{ "getcwd", (SYSCALL)0, 0 },
#endif
-
-#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent)
+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[54].pCurrent)
#ifndef _WIN32
{ "readlink", (SYSCALL)readlink, 0 },
#else
{ "readlink", (SYSCALL)0, 0 },
#endif
-
-#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent)
+#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[55].pCurrent)
#ifndef _WIN32
{ "lstat", (SYSCALL)lstat, 0 },
#else
{ "lstat", (SYSCALL)0, 0 },
#endif
-
-#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent)
+#define osLstat ((int(*)(const char*,struct stat*))aSyscall[56].pCurrent)
#ifndef _WIN32
{ "__errno", (SYSCALL)__errno, 0 },
#else
{ "__errno", (SYSCALL)0, 0 },
#endif
-
-#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)())
+#define osErrno (*((int*(*)(void))aSyscall[57].pCurrent)())
#ifndef _WIN32
{ "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 },
#else
{ "cygwin_conv_path", (SYSCALL)0, 0 },
#endif
-
#define osCygwin_conv_path ((size_t(*)(unsigned int, \
- const void *, void *, size_t))aSyscall[88].pCurrent)
+ const void *, void *, size_t))aSyscall[58].pCurrent)
+
+ { "GetDriveTypeW", (SYSCALL)GetDriveTypeW, 0 },
+#define osGetDriveTypeW ((UINT(WINAPI*)(LPCWSTR))aSyscall[59].pCurrent)
}; /* End of the overrideable system calls */
@@ -49145,6 +50026,9 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
}
#ifdef SQLITE_WIN32_MALLOC
+#ifdef SQLITE_UWP
+# error SQLITE_WIN32_MALLOC is incompatible with SQLITE_UWP
+#endif
/*
** If a Win32 native heap has been configured, this function will attempt to
** compact it. Upon success, SQLITE_OK will be returned. Upon failure, one
@@ -49161,10 +50045,9 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){
DWORD lastErrno = osGetLastError();
if( lastErrno==NO_ERROR ){
@@ -49177,11 +50060,6 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
rc = SQLITE_ERROR;
}
}
-#else
- sqlite3_log(SQLITE_NOTFOUND, "failed to HeapCompact, heap=%p",
- (void*)hHeap);
- rc = SQLITE_NOTFOUND;
-#endif
if( pnLargest ) *pnLargest = nLargest;
return rc;
}
@@ -49235,9 +50113,8 @@ SQLITE_API int sqlite3_win32_reset_heap(){
#ifdef _WIN32
/*
** This function outputs the specified (ANSI) string to the Win32 debugger
-** (if available).
+** (if available). Undocumented. Might go away at any moment.
*/
-
SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
@@ -49249,7 +50126,6 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
return;
}
#endif
-#if defined(SQLITE_WIN32_HAS_ANSI)
if( nMin>0 ){
memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
memcpy(zDbgBuf, zBuf, nMin);
@@ -49257,49 +50133,13 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
}else{
osOutputDebugStringA(zBuf);
}
-#elif defined(SQLITE_WIN32_HAS_WIDE)
- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
- if ( osMultiByteToWideChar(
- osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
- nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
- return;
- }
- osOutputDebugStringW((LPCWSTR)zDbgBuf);
-#else
- if( nMin>0 ){
- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
- memcpy(zDbgBuf, zBuf, nMin);
- fprintf(stderr, "%s", zDbgBuf);
- }else{
- fprintf(stderr, "%s", zBuf);
- }
-#endif
}
-#endif /* _WIN32 */
-
-/*
-** The following routine suspends the current thread for at least ms
-** milliseconds. This is equivalent to the Win32 Sleep() interface.
-*/
-#if SQLITE_OS_WINRT
-static HANDLE sleepObj = NULL;
-#endif
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
-#if SQLITE_OS_WINRT
- if ( sleepObj==NULL ){
- sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
- SYNCHRONIZE);
- }
- assert( sleepObj!=NULL );
- osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
-#else
osSleep(milliseconds);
-#endif
}
-#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
- SQLITE_THREADSAFE>0
+#if SQLITE_MAX_WORKER_THREADS>0 && SQLITE_THREADSAFE>0
SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
DWORD rc;
while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
@@ -49307,69 +50147,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
return rc;
}
#endif
-
-/*
-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
-** or WinCE. Return false (zero) for Win95, Win98, or WinME.
-**
-** Here is an interesting observation: Win95, Win98, and WinME lack
-** the LockFileEx() API. But we can still statically link against that
-** API as long as we don't call it when running Win95/98/ME. A call to
-** this routine is used to determine if the host is Win95/98/ME or
-** WinNT/2K/XP so that we will know whether or not we can safely call
-** the LockFileEx() API.
-*/
-
-#if !SQLITE_WIN32_GETVERSIONEX
-# define osIsNT() (1)
-#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
-# define osIsNT() (1)
-#elif !defined(SQLITE_WIN32_HAS_WIDE)
-# define osIsNT() (0)
-#else
-# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
-#endif
-
-/*
-** This function determines if the machine is running a version of Windows
-** based on the NT kernel.
-*/
-SQLITE_API int sqlite3_win32_is_nt(void){
-#if SQLITE_OS_WINRT
- /*
- ** NOTE: The WinRT sub-platform is always assumed to be based on the NT
- ** kernel.
- */
- return 1;
-#elif SQLITE_WIN32_GETVERSIONEX
- if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
-#if defined(SQLITE_WIN32_HAS_ANSI)
- OSVERSIONINFOA sInfo;
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
- osGetVersionExA(&sInfo);
- osInterlockedCompareExchange(&sqlite3_os_type,
- (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
-#elif defined(SQLITE_WIN32_HAS_WIDE)
- OSVERSIONINFOW sInfo;
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
- osGetVersionExW(&sInfo);
- osInterlockedCompareExchange(&sqlite3_os_type,
- (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
-#endif
- }
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
-#elif SQLITE_TEST
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2
- || osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0
- ;
-#else
- /*
- ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
- ** deprecated are always assumed to be based on the NT kernel.
- */
- return 1;
-#endif
-}
+#endif /* _WIN32 */
#ifdef SQLITE_WIN32_MALLOC
/*
@@ -49383,7 +50161,7 @@ static void *winMemMalloc(int nBytes){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
assert( nBytes>=0 );
@@ -49405,7 +50183,7 @@ static void winMemFree(void *pPrior){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
@@ -49426,7 +50204,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
assert( nBytes>=0 );
@@ -49454,7 +50232,7 @@ static int winMemSize(void *p){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) );
#endif
if( !p ) return 0;
@@ -49484,7 +50262,7 @@ static int winMemInit(void *pAppData){
assert( pWinMemData->magic1==WINMEM_MAGIC1 );
assert( pWinMemData->magic2==WINMEM_MAGIC2 );
-#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
+#if SQLITE_WIN32_HEAP_CREATE
if( !pWinMemData->hHeap ){
DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE;
DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap;
@@ -49517,7 +50295,7 @@ static int winMemInit(void *pAppData){
#endif
assert( pWinMemData->hHeap!=0 );
assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
return SQLITE_OK;
@@ -49535,7 +50313,7 @@ static void winMemShutdown(void *pAppData){
if( pWinMemData->hHeap ){
assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
if( pWinMemData->bOwned ){
@@ -49630,6 +50408,7 @@ static char *winUnicodeToUtf8(LPCWSTR zWideText){
return zText;
}
+#ifdef _WIN32
/*
** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM
** code page.
@@ -49659,7 +50438,6 @@ static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){
return zMbcsText;
}
-#ifdef _WIN32
/*
** Convert a Microsoft Unicode string to a multi-byte character string,
** using the ANSI or OEM code page.
@@ -49687,7 +50465,6 @@ static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){
}
return zText;
}
-#endif /* _WIN32 */
/*
** Convert a multi-byte character string to UTF-8.
@@ -49707,7 +50484,6 @@ static char *winMbcsToUtf8(const char *zText, int useAnsi){
return zTextUtf8;
}
-#ifdef _WIN32
/*
** Convert a UTF-8 string to a multi-byte character string.
**
@@ -49757,7 +50533,6 @@ SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){
#endif
return winUnicodeToUtf8(zWideText);
}
-#endif /* _WIN32 */
/*
** This is a public wrapper for the winMbcsToUtf8() function.
@@ -49775,7 +50550,6 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){
return winMbcsToUtf8(zText, osAreFileApisANSI());
}
-#ifdef _WIN32
/*
** This is a public wrapper for the winMbcsToUtf8() function.
*/
@@ -49914,63 +50688,24 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
*/
DWORD dwLen = 0;
char *zOut = 0;
-
- if( osIsNT() ){
-#if SQLITE_OS_WINRT
- WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1];
- dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErrno,
- 0,
- zTempWide,
- SQLITE_WIN32_MAX_ERRMSG_CHARS,
- 0);
-#else
- LPWSTR zTempWide = NULL;
- dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErrno,
- 0,
- (LPWSTR) &zTempWide,
- 0,
- 0);
-#endif
- if( dwLen > 0 ){
- /* allocate a buffer and convert to UTF8 */
- sqlite3BeginBenignMalloc();
- zOut = winUnicodeToUtf8(zTempWide);
- sqlite3EndBenignMalloc();
-#if !SQLITE_OS_WINRT
- /* free the system buffer allocated by FormatMessage */
- osLocalFree(zTempWide);
-#endif
- }
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- char *zTemp = NULL;
- dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErrno,
- 0,
- (LPSTR) &zTemp,
- 0,
- 0);
- if( dwLen > 0 ){
- /* allocate a buffer and convert to UTF8 */
- sqlite3BeginBenignMalloc();
- zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
- sqlite3EndBenignMalloc();
- /* free the system buffer allocated by FormatMessage */
- osLocalFree(zTemp);
- }
+ LPWSTR zTempWide = NULL;
+ dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ lastErrno,
+ 0,
+ (LPWSTR) &zTempWide,
+ 0,
+ 0);
+ if( dwLen > 0 ){
+ /* allocate a buffer and convert to UTF8 */
+ sqlite3BeginBenignMalloc();
+ zOut = winUnicodeToUtf8(zTempWide);
+ sqlite3EndBenignMalloc();
+ /* free the system buffer allocated by FormatMessage */
+ osLocalFree(zTempWide);
}
-#endif
if( 0 == dwLen ){
sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
}else{
@@ -50077,13 +50812,13 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
return 0;
}
if( winIoerrCanRetry1(e) ){
- sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
+ osSleep(winIoerrRetryDelay*(1+*pnRetry));
++*pnRetry;
return 1;
}
#if defined(winIoerrCanRetry2)
else if( winIoerrCanRetry2(e) ){
- sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
+ osSleep(winIoerrRetryDelay*(1+*pnRetry));
++*pnRetry;
return 1;
}
@@ -50106,323 +50841,6 @@ static void winLogIoerr(int nRetry, int lineno){
}
}
-/*
-** This #if does not rely on the SQLITE_OS_WINCE define because the
-** corresponding section in "date.c" cannot use it.
-*/
-#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \
- (!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API)
-/*
-** The MSVC CRT on Windows CE may not have a localtime() function.
-** So define a substitute.
-*/
-/* # include */
-struct tm *__cdecl localtime(const time_t *t)
-{
- static struct tm y;
- FILETIME uTm, lTm;
- SYSTEMTIME pTm;
- sqlite3_int64 t64;
- t64 = *t;
- t64 = (t64 + 11644473600)*10000000;
- uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
- uTm.dwHighDateTime= (DWORD)(t64 >> 32);
- osFileTimeToLocalFileTime(&uTm,&lTm);
- osFileTimeToSystemTime(&lTm,&pTm);
- y.tm_year = pTm.wYear - 1900;
- y.tm_mon = pTm.wMonth - 1;
- y.tm_wday = pTm.wDayOfWeek;
- y.tm_mday = pTm.wDay;
- y.tm_hour = pTm.wHour;
- y.tm_min = pTm.wMinute;
- y.tm_sec = pTm.wSecond;
- return &y;
-}
-#endif
-
-#if SQLITE_OS_WINCE
-/*************************************************************************
-** This section contains code for WinCE only.
-*/
-#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
-
-/*
-** Acquire a lock on the handle h
-*/
-static void winceMutexAcquire(HANDLE h){
- DWORD dwErr;
- do {
- dwErr = osWaitForSingleObject(h, INFINITE);
- } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
-}
-/*
-** Release a lock acquired by winceMutexAcquire()
-*/
-#define winceMutexRelease(h) ReleaseMutex(h)
-
-/*
-** Create the mutex and shared memory used for locking in the file
-** descriptor pFile
-*/
-static int winceCreateLock(const char *zFilename, winFile *pFile){
- LPWSTR zTok;
- LPWSTR zName;
- DWORD lastErrno;
- BOOL bLogged = FALSE;
- BOOL bInit = TRUE;
-
- zName = winUtf8ToUnicode(zFilename);
- if( zName==0 ){
- /* out of memory */
- return SQLITE_IOERR_NOMEM_BKPT;
- }
-
- /* Initialize the local lockdata */
- memset(&pFile->local, 0, sizeof(pFile->local));
-
- /* Replace the backslashes from the filename and lowercase it
- ** to derive a mutex name. */
- zTok = osCharLowerW(zName);
- for (;*zTok;zTok++){
- if (*zTok == '\\') *zTok = '_';
- }
-
- /* Create/open the named mutex */
- pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
- if (!pFile->hMutex){
- pFile->lastErrno = osGetLastError();
- sqlite3_free(zName);
- return winLogError(SQLITE_IOERR, pFile->lastErrno,
- "winceCreateLock1", zFilename);
- }
-
- /* Acquire the mutex before continuing */
- winceMutexAcquire(pFile->hMutex);
-
- /* Since the names of named mutexes, semaphores, file mappings etc are
- ** case-sensitive, take advantage of that by uppercasing the mutex name
- ** and using that as the shared filemapping name.
- */
- osCharUpperW(zName);
- pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
- PAGE_READWRITE, 0, sizeof(winceLock),
- zName);
-
- /* Set a flag that indicates we're the first to create the memory so it
- ** must be zero-initialized */
- lastErrno = osGetLastError();
- if (lastErrno == ERROR_ALREADY_EXISTS){
- bInit = FALSE;
- }
-
- sqlite3_free(zName);
-
- /* If we succeeded in making the shared memory handle, map it. */
- if( pFile->hShared ){
- pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
- FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
- /* If mapping failed, close the shared memory handle and erase it */
- if( !pFile->shared ){
- pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR, pFile->lastErrno,
- "winceCreateLock2", zFilename);
- bLogged = TRUE;
- osCloseHandle(pFile->hShared);
- pFile->hShared = NULL;
- }
- }
-
- /* If shared memory could not be created, then close the mutex and fail */
- if( pFile->hShared==NULL ){
- if( !bLogged ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR, pFile->lastErrno,
- "winceCreateLock3", zFilename);
- bLogged = TRUE;
- }
- winceMutexRelease(pFile->hMutex);
- osCloseHandle(pFile->hMutex);
- pFile->hMutex = NULL;
- return SQLITE_IOERR;
- }
-
- /* Initialize the shared memory if we're supposed to */
- if( bInit ){
- memset(pFile->shared, 0, sizeof(winceLock));
- }
-
- winceMutexRelease(pFile->hMutex);
- return SQLITE_OK;
-}
-
-/*
-** Destroy the part of winFile that deals with wince locks
-*/
-static void winceDestroyLock(winFile *pFile){
- if (pFile->hMutex){
- /* Acquire the mutex */
- winceMutexAcquire(pFile->hMutex);
-
- /* The following blocks should probably assert in debug mode, but they
- are to cleanup in case any locks remained open */
- if (pFile->local.nReaders){
- pFile->shared->nReaders --;
- }
- if (pFile->local.bReserved){
- pFile->shared->bReserved = FALSE;
- }
- if (pFile->local.bPending){
- pFile->shared->bPending = FALSE;
- }
- if (pFile->local.bExclusive){
- pFile->shared->bExclusive = FALSE;
- }
-
- /* De-reference and close our copy of the shared memory handle */
- osUnmapViewOfFile(pFile->shared);
- osCloseHandle(pFile->hShared);
-
- /* Done with the mutex */
- winceMutexRelease(pFile->hMutex);
- osCloseHandle(pFile->hMutex);
- pFile->hMutex = NULL;
- }
-}
-
-/*
-** An implementation of the LockFile() API of Windows for CE
-*/
-static BOOL winceLockFile(
- LPHANDLE phFile,
- DWORD dwFileOffsetLow,
- DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToLockLow,
- DWORD nNumberOfBytesToLockHigh
-){
- winFile *pFile = HANDLE_TO_WINFILE(phFile);
- BOOL bReturn = FALSE;
-
- UNUSED_PARAMETER(dwFileOffsetHigh);
- UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
-
- if (!pFile->hMutex) return TRUE;
- winceMutexAcquire(pFile->hMutex);
-
- /* Wanting an exclusive lock? */
- if (dwFileOffsetLow == (DWORD)SHARED_FIRST
- && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
- if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
- pFile->shared->bExclusive = TRUE;
- pFile->local.bExclusive = TRUE;
- bReturn = TRUE;
- }
- }
-
- /* Want a read-only lock? */
- else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
- nNumberOfBytesToLockLow == 1){
- if (pFile->shared->bExclusive == 0){
- pFile->local.nReaders ++;
- if (pFile->local.nReaders == 1){
- pFile->shared->nReaders ++;
- }
- bReturn = TRUE;
- }
- }
-
- /* Want a pending lock? */
- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
- && nNumberOfBytesToLockLow == 1){
- /* If no pending lock has been acquired, then acquire it */
- if (pFile->shared->bPending == 0) {
- pFile->shared->bPending = TRUE;
- pFile->local.bPending = TRUE;
- bReturn = TRUE;
- }
- }
-
- /* Want a reserved lock? */
- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
- && nNumberOfBytesToLockLow == 1){
- if (pFile->shared->bReserved == 0) {
- pFile->shared->bReserved = TRUE;
- pFile->local.bReserved = TRUE;
- bReturn = TRUE;
- }
- }
-
- winceMutexRelease(pFile->hMutex);
- return bReturn;
-}
-
-/*
-** An implementation of the UnlockFile API of Windows for CE
-*/
-static BOOL winceUnlockFile(
- LPHANDLE phFile,
- DWORD dwFileOffsetLow,
- DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToUnlockLow,
- DWORD nNumberOfBytesToUnlockHigh
-){
- winFile *pFile = HANDLE_TO_WINFILE(phFile);
- BOOL bReturn = FALSE;
-
- UNUSED_PARAMETER(dwFileOffsetHigh);
- UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
-
- if (!pFile->hMutex) return TRUE;
- winceMutexAcquire(pFile->hMutex);
-
- /* Releasing a reader lock or an exclusive lock */
- if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
- /* Did we have an exclusive lock? */
- if (pFile->local.bExclusive){
- assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
- pFile->local.bExclusive = FALSE;
- pFile->shared->bExclusive = FALSE;
- bReturn = TRUE;
- }
-
- /* Did we just have a reader lock? */
- else if (pFile->local.nReaders){
- assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
- || nNumberOfBytesToUnlockLow == 1);
- pFile->local.nReaders --;
- if (pFile->local.nReaders == 0)
- {
- pFile->shared->nReaders --;
- }
- bReturn = TRUE;
- }
- }
-
- /* Releasing a pending lock */
- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
- && nNumberOfBytesToUnlockLow == 1){
- if (pFile->local.bPending){
- pFile->local.bPending = FALSE;
- pFile->shared->bPending = FALSE;
- bReturn = TRUE;
- }
- }
- /* Releasing a reserved lock */
- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
- && nNumberOfBytesToUnlockLow == 1){
- if (pFile->local.bReserved) {
- pFile->local.bReserved = FALSE;
- pFile->shared->bReserved = FALSE;
- bReturn = TRUE;
- }
- }
-
- winceMutexRelease(pFile->hMutex);
- return bReturn;
-}
-/*
-** End of the special code for wince
-*****************************************************************************/
-#endif /* SQLITE_OS_WINCE */
/*
** Lock a file region.
@@ -50435,27 +50853,11 @@ static BOOL winLockFile(
DWORD numBytesLow,
DWORD numBytesHigh
){
-#if SQLITE_OS_WINCE
- /*
- ** NOTE: Windows CE is handled differently here due its lack of the Win32
- ** API LockFile.
- */
- return winceLockFile(phFile, offsetLow, offsetHigh,
- numBytesLow, numBytesHigh);
-#else
- if( osIsNT() ){
- OVERLAPPED ovlp;
- memset(&ovlp, 0, sizeof(OVERLAPPED));
- ovlp.Offset = offsetLow;
- ovlp.OffsetHigh = offsetHigh;
- return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
-#ifdef SQLITE_WIN32_HAS_ANSI
- }else{
- return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
- numBytesHigh);
-#endif
- }
-#endif
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offsetLow;
+ ovlp.OffsetHigh = offsetHigh;
+ return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
}
#ifndef SQLITE_OMIT_WAL
@@ -50479,63 +50881,56 @@ static int winHandleLockTimeout(
DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0);
int rc = SQLITE_OK;
BOOL ret;
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offset;
- if( !osIsNT() ){
- ret = winLockFile(&hFile, flags, offset, 0, nByte, 0);
- }else{
- OVERLAPPED ovlp;
- memset(&ovlp, 0, sizeof(OVERLAPPED));
- ovlp.Offset = offset;
-
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- if( nMs!=0 ){
- flags &= ~LOCKFILE_FAIL_IMMEDIATELY;
- }
- ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL);
- if( ovlp.hEvent==NULL ){
- return SQLITE_IOERR_LOCK;
- }
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ if( nMs!=0 ){
+ flags &= ~LOCKFILE_FAIL_IMMEDIATELY;
+ }
+ ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL);
+ if( ovlp.hEvent==NULL ){
+ return SQLITE_IOERR_LOCK;
+ }
#endif
-
- ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp);
-
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was
- ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to
- ** LockFileEx() may fail because the request is still pending. This can
- ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified.
- **
- ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags
- ** passed to LockFileEx(). In this case, if the operation is pending,
- ** block indefinitely until it is finished.
- **
- ** Otherwise, wait for up to nMs ms for the operation to finish. nMs
- ** may be set to INFINITE.
- */
- if( !ret && GetLastError()==ERROR_IO_PENDING ){
- DWORD nDelay = (nMs==0 ? INFINITE : nMs);
- DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay);
- if( res==WAIT_OBJECT_0 ){
- ret = TRUE;
- }else if( res==WAIT_TIMEOUT ){
+ ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp);
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was
+ ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to
+ ** LockFileEx() may fail because the request is still pending. This can
+ ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified.
+ **
+ ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags
+ ** passed to LockFileEx(). In this case, if the operation is pending,
+ ** block indefinitely until it is finished.
+ **
+ ** Otherwise, wait for up to nMs ms for the operation to finish. nMs
+ ** may be set to INFINITE.
+ */
+ if( !ret && GetLastError()==ERROR_IO_PENDING ){
+ DWORD nDelay = (nMs==0 ? INFINITE : nMs);
+ DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay);
+ if( res==WAIT_OBJECT_0 ){
+ ret = TRUE;
+ }else if( res==WAIT_TIMEOUT ){
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
- rc = SQLITE_BUSY_TIMEOUT;
+ rc = SQLITE_BUSY_TIMEOUT;
#else
- rc = SQLITE_BUSY;
+ rc = SQLITE_BUSY;
#endif
- }else{
- /* Some other error has occurred */
- rc = SQLITE_IOERR_LOCK;
- }
-
- /* If it is still pending, cancel the LockFileEx() call. */
- osCancelIo(hFile);
+ }else{
+ /* Some other error has occurred */
+ rc = SQLITE_IOERR_LOCK;
}
- osCloseHandle(ovlp.hEvent);
-#endif
+ /* If it is still pending, cancel the LockFileEx() call. */
+ osCancelIo(hFile);
}
+ osCloseHandle(ovlp.hEvent);
+#endif /* defined(SQLITE_ENABLE_SETLK_TIMEOUT) */
+
if( rc==SQLITE_OK && !ret ){
rc = SQLITE_BUSY;
}
@@ -50553,27 +50948,11 @@ static BOOL winUnlockFile(
DWORD numBytesLow,
DWORD numBytesHigh
){
-#if SQLITE_OS_WINCE
- /*
- ** NOTE: Windows CE is handled differently here due its lack of the Win32
- ** API UnlockFile.
- */
- return winceUnlockFile(phFile, offsetLow, offsetHigh,
- numBytesLow, numBytesHigh);
-#else
- if( osIsNT() ){
- OVERLAPPED ovlp;
- memset(&ovlp, 0, sizeof(OVERLAPPED));
- ovlp.Offset = offsetLow;
- ovlp.OffsetHigh = offsetHigh;
- return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
-#ifdef SQLITE_WIN32_HAS_ANSI
- }else{
- return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
- numBytesHigh);
-#endif
- }
-#endif
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offsetLow;
+ ovlp.OffsetHigh = offsetHigh;
+ return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
}
#ifndef SQLITE_OMIT_WAL
@@ -50606,43 +50985,13 @@ static int winHandleUnlock(HANDLE h, int iOff, int nByte){
*/
static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){
int rc = SQLITE_OK; /* Return value */
-
-#if !SQLITE_OS_WINRT
- LONG upperBits; /* Most sig. 32 bits of new offset */
- LONG lowerBits; /* Least sig. 32 bits of new offset */
- DWORD dwRet; /* Value returned by SetFilePointer() */
-
- upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
- lowerBits = (LONG)(iOffset & 0xffffffff);
-
- dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN);
-
- /* API oddity: If successful, SetFilePointer() returns a dword
- ** containing the lower 32-bits of the new file-offset. Or, if it fails,
- ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
- ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
- ** whether an error has actually occurred, it is also necessary to call
- ** GetLastError(). */
- if( dwRet==INVALID_SET_FILE_POINTER ){
- DWORD lastErrno = osGetLastError();
- if( lastErrno!=NO_ERROR ){
- rc = SQLITE_IOERR_SEEK;
- }
- }
-#else
- /* This implementation works for WinRT. */
- LARGE_INTEGER x; /* The new offset */
- BOOL bRet; /* Value returned by SetFilePointerEx() */
+ LARGE_INTEGER x; /* The offset */
x.QuadPart = iOffset;
- bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN);
-
- if(!bRet){
+ if( osSetFilePointerEx(h, x, 0, FILE_BEGIN)==0 ){
rc = SQLITE_IOERR_SEEK;
}
-#endif
-
- OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc)));
+ OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset,sqlite3ErrName(rc)));
return rc;
}
@@ -50699,27 +51048,7 @@ static int winClose(sqlite3_file *id){
do{
rc = osCloseHandle(pFile->h);
/* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
- }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
-#if SQLITE_OS_WINCE
-#define WINCE_DELETION_ATTEMPTS 3
- {
- winVfsAppData *pAppData = (winVfsAppData*)pFile->pVfs->pAppData;
- if( pAppData==NULL || !pAppData->bNoLock ){
- winceDestroyLock(pFile);
- }
- }
- if( pFile->zDeleteOnClose ){
- int cnt = 0;
- while(
- osDeleteFileW(pFile->zDeleteOnClose)==0
- && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
- && cnt++ < WINCE_DELETION_ATTEMPTS
- ){
- sqlite3_win32_sleep(100); /* Wait a little before trying again */
- }
- sqlite3_free(pFile->zDeleteOnClose);
- }
-#endif
+ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (osSleep(100), 1) );
if( rc ){
pFile->h = NULL;
}
@@ -50742,7 +51071,7 @@ static int winRead(
int amt, /* Number of bytes to read */
sqlite3_int64 offset /* Begin reading at this offset */
){
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
+#if !defined(SQLITE_WIN32_NO_OVERLAPPED)
OVERLAPPED overlapped; /* The offset for ReadFile. */
#endif
winFile *pFile = (winFile*)id; /* file handle */
@@ -50776,7 +51105,7 @@ static int winRead(
}
#endif
-#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
+#if defined(SQLITE_WIN32_NO_OVERLAPPED)
if( winSeekFile(pFile, offset) ){
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
osGetCurrentProcessId(), pFile, pFile->h));
@@ -50854,13 +51183,13 @@ static int winWrite(
}
#endif
-#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
+#if defined(SQLITE_WIN32_NO_OVERLAPPED)
rc = winSeekFile(pFile, offset);
if( rc==0 ){
#else
{
#endif
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
+#if !defined(SQLITE_WIN32_NO_OVERLAPPED)
OVERLAPPED overlapped; /* The offset for WriteFile. */
#endif
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
@@ -50868,14 +51197,14 @@ static int winWrite(
DWORD nWrite; /* Bytes written by each WriteFile() call */
DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
+#if !defined(SQLITE_WIN32_NO_OVERLAPPED)
memset(&overlapped, 0, sizeof(OVERLAPPED));
overlapped.Offset = (LONG)(offset & 0xffffffff);
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
#endif
while( nRem>0 ){
-#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
+#if defined(SQLITE_WIN32_NO_OVERLAPPED)
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
#else
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
@@ -50888,7 +51217,7 @@ static int winWrite(
lastErrno = osGetLastError();
break;
}
-#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
+#if !defined(SQLITE_WIN32_NO_OVERLAPPED)
offset += nWrite;
overlapped.Offset = (LONG)(offset & 0xffffffff);
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
@@ -50943,28 +51272,14 @@ static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){
*/
static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){
int rc = SQLITE_OK;
-
-#if SQLITE_OS_WINRT
- FILE_STANDARD_INFO info;
- BOOL b;
- b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info));
- if( b ){
- *pnByte = info.EndOfFile.QuadPart;
- }else{
- rc = SQLITE_IOERR_FSTAT;
- }
-#else
- DWORD upperBits = 0;
- DWORD lowerBits = 0;
-
+ LARGE_INTEGER x;
assert( pnByte );
- lowerBits = osGetFileSize(h, &upperBits);
- *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits;
- if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){
+ if( osGetFileSizeEx(h, &x)==0 ){
rc = SQLITE_IOERR_FSTAT;
+ *pnByte = 0;
+ }else{
+ *pnByte = x.QuadPart;
}
-#endif
-
return rc;
}
@@ -51163,35 +51478,17 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
assert( pSize!=0 );
SimulateIOError(return SQLITE_IOERR_FSTAT);
OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
-
-#if SQLITE_OS_WINRT
{
- FILE_STANDARD_INFO info;
- if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
- &info, sizeof(info)) ){
- *pSize = info.EndOfFile.QuadPart;
- }else{
+ LARGE_INTEGER x;
+ if( osGetFileSizeEx(pFile->h, &x)==0 ){
+ *pSize = 0;
pFile->lastErrno = osGetLastError();
rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
"winFileSize", pFile->zPath);
+ }else{
+ *pSize = x.QuadPart;
}
}
-#else
- {
- DWORD upperBits;
- DWORD lowerBits;
- DWORD lastErrno;
-
- lowerBits = osGetFileSize(pFile->h, &upperBits);
- *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
- if( (lowerBits == INVALID_FILE_SIZE)
- && ((lastErrno = osGetLastError())!=NO_ERROR) ){
- pFile->lastErrno = lastErrno;
- rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
- "winFileSize", pFile->zPath);
- }
- }
-#endif
OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
return rc;
@@ -51237,27 +51534,8 @@ static int winGetReadLock(winFile *pFile, int bBlock){
int res;
DWORD mask = ~(bBlock ? LOCKFILE_FAIL_IMMEDIATELY : 0);
OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
- if( osIsNT() ){
-#if SQLITE_OS_WINCE
- /*
- ** NOTE: Windows CE is handled differently here due its lack of the Win32
- ** API LockFileEx.
- */
- res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
-#else
- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0,
- SHARED_SIZE, 0);
-#endif
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- int lk;
- sqlite3_randomness(sizeof(lk), &lk);
- pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask,
- SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
- }
-#endif
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0,
+ SHARED_SIZE, 0);
if( res == 0 ){
pFile->lastErrno = osGetLastError();
/* No need to log a failure to lock */
@@ -51273,14 +51551,7 @@ static int winUnlockReadLock(winFile *pFile){
int res;
DWORD lastErrno;
OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
- if( osIsNT() ){
- res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
- }
-#endif
+ res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
pFile->lastErrno = lastErrno;
winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
@@ -51391,7 +51662,7 @@ static int winLock(sqlite3_file *id, int locktype){
}
cnt--;
- if( cnt>0 ) sqlite3_win32_sleep(1);
+ if( cnt>0 ) osSleep(1);
}
gotPendingLock = res;
}
@@ -51600,7 +51871,7 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
/* Forward references to VFS helper methods used for temporary files */
static int winGetTempname(sqlite3_vfs *, char **);
-static int winIsDir(const void *);
+static int winIsDir(LPCWSTR);
static BOOL winIsLongPathPrefix(const char *);
static BOOL winIsDriveLetterAndColon(const char *);
@@ -51832,80 +52103,70 @@ static SYSTEM_INFO winSysInfo;
** happen when the file path >32k, in which case winUtf8ToUnicode()
** will fail too.
*/
-static void *winConvertFromUtf8Filename(const char *zFilename){
- void *zConverted = 0;
- if( osIsNT() ){
+static LPWSTR winConvertFromUtf8Filename(const char *zFilename){
+ LPWSTR zConverted = 0;
#ifdef __CYGWIN__
- int nChar;
- LPWSTR zWideFilename;
-
- if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename)
- && winIsDirSep(zFilename[2])) ){
- i64 nByte;
- int convertflag = CCP_POSIX_TO_WIN_W;
- if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE;
- nByte = (i64)osCygwin_conv_path(convertflag,
- zFilename, 0, 0);
- if( nByte>0 ){
- zConverted = sqlite3MallocZero(12+(u64)nByte);
- if ( zConverted==0 ){
- return zConverted;
- }
- zWideFilename = zConverted;
- /* Filenames should be prefixed, except when converted
- * full path already starts with "\\?\". */
- if( osCygwin_conv_path(convertflag, zFilename,
- zWideFilename+4, nByte)==0 ){
- if( (convertflag&CCP_RELATIVE) ){
- memmove(zWideFilename, zWideFilename+4, nByte);
- }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){
- memcpy(zWideFilename, L"\\\\?\\", 8);
- }else if( zWideFilename[6]!='?' ){
- memmove(zWideFilename+6, zWideFilename+4, nByte);
- memcpy(zWideFilename, L"\\\\?\\UNC", 14);
- }else{
- memmove(zWideFilename, zWideFilename+4, nByte);
- }
- return zConverted;
+ int nChar;
+
+ if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename)
+ && winIsDirSep(zFilename[2])) ){
+ i64 nByte;
+ int convertflag = CCP_POSIX_TO_WIN_W;
+ if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE;
+ nByte = (i64)osCygwin_conv_path(convertflag,
+ zFilename, 0, 0);
+ if( nByte>0 ){
+ zConverted = sqlite3MallocZero(12+(u64)nByte);
+ if ( zConverted==0 ){
+ return zConverted;
+ }
+ /* Filenames should be prefixed, except when converted
+ * full path already starts with "\\?\". */
+ if( osCygwin_conv_path(convertflag, zFilename,
+ zConverted+4, nByte)==0 ){
+ if( (convertflag&CCP_RELATIVE) ){
+ memmove(zConverted, zConverted+4, nByte);
+ }else if( memcmp(zConverted+4, L"\\\\", 4) ){
+ memcpy(zConverted, L"\\\\?\\", 8);
+ }else if( zConverted[6]!='?' ){
+ memmove(zConverted+6, zConverted+4, nByte);
+ memcpy(zConverted, L"\\\\?\\UNC", 14);
+ }else{
+ memmove(zConverted, zConverted+4, nByte);
}
- sqlite3_free(zConverted);
+ return zConverted;
}
+ sqlite3_free(zConverted);
}
- nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
- if( nChar==0 ){
- return 0;
- }
- zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 );
- if( zWideFilename==0 ){
- return 0;
- }
- nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
- zWideFilename, nChar);
- if( nChar==0 ){
- sqlite3_free(zWideFilename);
- zWideFilename = 0;
- }else if( nChar>MAX_PATH
- && winIsDriveLetterAndColon(zFilename)
- && winIsDirSep(zFilename[2]) ){
- memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR));
- zWideFilename[2] = '\\';
- memcpy(zWideFilename, L"\\\\?\\", 8);
- }else if( nChar>MAX_PATH
- && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1])
- && zFilename[2] != '?' ){
- memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR));
- memcpy(zWideFilename, L"\\\\?\\UNC", 14);
- }
- zConverted = zWideFilename;
-#else
- zConverted = winUtf8ToUnicode(zFilename);
-#endif /* __CYGWIN__ */
}
-#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32)
- else{
- zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
+ if( nChar==0 ){
+ return 0;
}
-#endif
+ zConverted = sqlite3MallocZero( ((u64)nChar+6)*sizeof(WCHAR) );
+ if( zConverted==0 ){
+ return 0;
+ }
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
+ zConverted, nChar);
+ if( nChar==0 ){
+ sqlite3_free(zConverted);
+ zConverted = 0;
+ }else if( nChar>MAX_PATH
+ && winIsDriveLetterAndColon(zFilename)
+ && winIsDirSep(zFilename[2]) ){
+ memmove(zConverted+4, zConverted, nChar*sizeof(WCHAR));
+ zConverted[2] = '\\';
+ memcpy(zConverted, L"\\\\?\\", 8);
+ }else if( nChar>MAX_PATH
+ && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1])
+ && zFilename[2] != '?' ){
+ memmove(zConverted+6, zConverted, nChar*sizeof(WCHAR));
+ memcpy(zConverted, L"\\\\?\\UNC", 14);
+ }
+#else /* if !defined(__CYGWIN__) */
+ zConverted = winUtf8ToUnicode(zFilename);
+#endif /* __CYGWIN__ */
/* caller will handle out of memory */
return zConverted;
}
@@ -52073,6 +52334,28 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
}
}
+/*
+** Handle h is open on the *-shm file. This function zeroes the first
+** 8 bytes of the file. If SQLITE_ENABLE_SETLK_TIMEOUT is defined, h may
+** have been opened with FILE_FLAG_OVERLAPPED.
+*/
+static int winZeroSharedMemory(HANDLE h){
+ u8 aZero[8] = {0,0,0,0,0,0,0,0};
+ DWORD nWrite = 0;
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ if( !osWriteFile(h, aZero, sizeof(aZero), &nWrite, &ovlp) ){
+ /* If the file was opened with FILE_FLAG_OVERLAPPED, the write may still
+ ** be pending. Wait for it with GetOverlappedResult(). */
+ if( osGetLastError()!=ERROR_IO_PENDING
+ || !GetOverlappedResult(h, &ovlp, &nWrite, TRUE)
+ ){
+ nWrite = 0;
+ }
+ }
+ return (nWrite==sizeof(aZero) ? SQLITE_OK : SQLITE_IOERR_WRITE);
+}
+
/*
** The DMS lock has not yet been taken on the shm file associated with
** pShmNode. Take the lock. Truncate the *-shm file if required.
@@ -52091,7 +52374,12 @@ static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){
if( pShmNode->isReadonly ){
rc = SQLITE_READONLY_CANTINIT;
}else{
- rc = winHandleTruncate(h, 0);
+ if( SQLITE_OK!=winHandleTruncate(h, 0) ){
+ /* Sometimes the truncate operation may fail because some other
+ ** process is still holding an open mapping. So try to write
+ ** zeroes into the start of the file instead. */
+ rc = winZeroSharedMemory(h);
+ }
}
/* Release the EXCLUSIVE lock acquired above. */
@@ -52124,7 +52412,7 @@ static int winHandleOpen(
HANDLE *ph /* OUT: New HANDLE for file */
){
int rc = SQLITE_OK;
- void *zConverted = 0;
+ LPWSTR zConverted = 0;
int bReadonly = *pbReadonly;
HANDLE h = INVALID_HANDLE_VALUE;
@@ -52152,44 +52440,14 @@ static int winHandleOpen(
/* TODO: platforms.
** TODO: retry-on-ioerr.
*/
- if( osIsNT() ){
-#if SQLITE_OS_WINRT
- CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
- memset(&extendedParameters, 0, sizeof(extendedParameters));
- extendedParameters.dwSize = sizeof(extendedParameters);
- extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
- extendedParameters.dwFileFlags = flag_overlapped;
- extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
- h = osCreateFile2((LPCWSTR)zConverted,
- (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */
- FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
- OPEN_ALWAYS, /* dwCreationDisposition */
- &extendedParameters
- );
-#else
- h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */
- (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
- FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
- NULL, /* lpSecurityAttributes */
- OPEN_ALWAYS, /* dwCreationDisposition */
- FILE_ATTRIBUTE_NORMAL|flag_overlapped,
- NULL
- );
-#endif
- }else{
- /* Due to pre-processor directives earlier in this file,
- ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */
-#ifdef SQLITE_WIN32_HAS_ANSI
- h = osCreateFileA((LPCSTR)zConverted,
- (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
- FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
- NULL, /* lpSecurityAttributes */
- OPEN_ALWAYS, /* dwCreationDisposition */
- FILE_ATTRIBUTE_NORMAL|flag_overlapped,
- NULL
- );
-#endif
- }
+ h = osCreateFileW(zConverted, /* lpFileName */
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL|flag_overlapped,
+ NULL
+ );
if( h==INVALID_HANDLE_VALUE ){
if( bReadonly==0 ){
@@ -52253,15 +52511,50 @@ SQLITE_API int sqlite3_win_test_unc_locking = 0;
/*
** Return true if the string passed as the only argument is likely
-** to be a UNC path. In other words, if it starts with "\\".
+** to be a UNC path. Return false if not.
+**
+** Return true if:
+**
+** (1) The name begins with "\\"
+** (2) But does not begin with "\\?\C:\" where C can be any alphabetic
+** character.
+**
+** For testing, also return true in all cases if the global variable
+** sqlite3_win_test_unc_locking is true.
*/
static int winIsUNCPath(const char *zFile){
if( zFile[0]=='\\' && zFile[1]=='\\' ){
- return 1;
+ if( zFile[2]=='?'
+ && zFile[3]=='\\'
+ && sqlite3Isalpha(zFile[4])
+ && zFile[5]==':'
+ && winIsDirSep(zFile[6])
+ ){
+ return sqlite3_win_test_unc_locking;
+ }else{
+ return 1;
+ }
}
return sqlite3_win_test_unc_locking;
}
+/*
+** Return true if the string passed in is the name of a file on a
+** remote (network-mounted) volume.
+*/
+static int winIsRemoteVolume(const char *zFile){
+ WCHAR zRoot[4];
+ if( strncmp(zFile, "\\\\?\\",4)==0 ) zFile += 4;
+ if( !sqlite3Isalpha(zFile[0]) ) return 0;
+ if( zFile[1]!=':' ) return 0;
+ if( !winIsDirSep(zFile[2]) ) return 0;
+ zRoot[0] = (WCHAR)zFile[0];
+ zRoot[1] = ':';
+ zRoot[2] = '\\';
+ zRoot[3] = 0;
+ return osGetDriveTypeW(zRoot)==DRIVE_REMOTE;
+}
+
/*
** Open the shared-memory area associated with database file pDbFd.
*/
@@ -52287,7 +52580,11 @@ static int winOpenSharedMemory(winFile *pDbFd){
pNew->zFilename = (char*)&pNew[1];
pNew->hSharedShm = INVALID_HANDLE_VALUE;
pNew->isUnlocked = 1;
- pNew->bUseSharedLockHandle = winIsUNCPath(pDbFd->zPath);
+ if( winIsUNCPath(pDbFd->zPath) || winIsRemoteVolume(pDbFd->zPath) ){
+ pNew->bUseSharedLockHandle = 1;
+ }else{
+ pNew->bUseSharedLockHandle = 0;
+ }
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
@@ -52595,7 +52892,7 @@ static int winShmMap(
if( pShmNode->nRegion<=iRegion ){
HANDLE hShared = pShmNode->hSharedShm;
struct ShmRegion *apNew; /* New aRegion[] array */
- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
+ i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
sqlite3_int64 sz; /* Current size of wal-index file */
pShmNode->szRegion = szRegion;
@@ -52626,7 +52923,7 @@ static int winShmMap(
/* Map the requested memory region into this processes address space. */
apNew = (struct ShmRegion*)sqlite3_realloc64(
- pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
+ pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
rc = SQLITE_IOERR_NOMEM_BKPT;
@@ -52643,27 +52940,24 @@ static int winShmMap(
HANDLE hMap = NULL; /* file-mapping handle */
void *pMap = 0; /* Mapped memory region */
-#if SQLITE_OS_WINRT
+#ifdef SQLITE_UWP
hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL);
-#elif defined(SQLITE_WIN32_HAS_WIDE)
+#else
hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL);
-#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
#endif
-
- OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
+ OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
hMap ? "ok" : "failed"));
if( hMap ){
- int iOffset = pShmNode->nRegion*szRegion;
+ i64 iOffset = pShmNode->nRegion*szRegion;
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
-#if SQLITE_OS_WINRT
+#ifdef SQLITE_UWP
pMap = osMapViewOfFileFromApp(hMap, flags,
- iOffset - iOffsetShift, szRegion + iOffsetShift
+ iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
);
#else
pMap = osMapViewOfFile(hMap, flags,
- 0, iOffset - iOffsetShift, szRegion + iOffsetShift
+ 0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
);
#endif
OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
@@ -52686,7 +52980,7 @@ static int winShmMap(
shmpage_out:
if( pShmNode->nRegion>iRegion ){
- int iOffset = iRegion*szRegion;
+ i64 iOffset = (i64)iRegion*(i64)szRegion;
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
char *p = (char *)pShmNode->aRegion[iRegion].pMap;
*pp = (void *)&p[iOffsetShift];
@@ -52798,16 +53092,12 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
flags |= FILE_MAP_WRITE;
}
#endif
-#if SQLITE_OS_WINRT
+#ifdef SQLITE_UWP
pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
-#elif defined(SQLITE_WIN32_HAS_WIDE)
+#else
pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
(DWORD)((nMap>>32) & 0xffffffff),
(DWORD)(nMap & 0xffffffff), NULL);
-#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
- (DWORD)((nMap>>32) & 0xffffffff),
- (DWORD)(nMap & 0xffffffff), NULL);
#endif
if( pFd->hMap==NULL ){
pFd->lastErrno = osGetLastError();
@@ -52820,7 +53110,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
}
assert( (nMap % winSysInfo.dwPageSize)==0 );
assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
-#if SQLITE_OS_WINRT
+#ifdef SQLITE_UWP
pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
#else
pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
@@ -53134,7 +53424,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
if( !azDirs[3] ) azDirs[3] = osGetenv("TEMP");
if( !azDirs[4] ) azDirs[4] = osGetenv("USERPROFILE");
for(i=0; ih = INVALID_HANDLE_VALUE;
-#if SQLITE_OS_WINRT
- if( !zUtf8Name && !sqlite3_temp_directory ){
- sqlite3_log(SQLITE_ERROR,
- "sqlite3_temp_directory variable should be set for WinRT");
- }
-#endif
-
/* If the second argument to this function is NULL, generate a
** temporary file name to use
*/
@@ -53459,87 +53703,28 @@ static int winOpen(
}
if( isDelete ){
-#if SQLITE_OS_WINCE
- dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
- isTemp = 1;
-#else
dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
| FILE_ATTRIBUTE_HIDDEN
| FILE_FLAG_DELETE_ON_CLOSE;
-#endif
}else{
dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
}
- /* Reports from the internet are that performance is always
- ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
-#if SQLITE_OS_WINCE
- dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
-#endif
-
- if( osIsNT() ){
-#if SQLITE_OS_WINRT
- CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
- extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
- extendedParameters.dwFileAttributes =
- dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
- extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
- extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
- extendedParameters.lpSecurityAttributes = NULL;
- extendedParameters.hTemplateFile = NULL;
- do{
- h = osCreateFile2((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode,
- dwCreationDisposition,
- &extendedParameters);
- if( h!=INVALID_HANDLE_VALUE ) break;
- if( isReadWrite ){
- int rc2;
- sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
- sqlite3EndBenignMalloc();
- if( rc2==SQLITE_OK && isRO ) break;
- }
- }while( winRetryIoerr(&cnt, &lastErrno) );
-#else
- do{
- h = osCreateFileW((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL);
- if( h!=INVALID_HANDLE_VALUE ) break;
- if( isReadWrite ){
- int rc2;
- sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
- sqlite3EndBenignMalloc();
- if( rc2==SQLITE_OK && isRO ) break;
- }
- }while( winRetryIoerr(&cnt, &lastErrno) );
-#endif
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- do{
- h = osCreateFileA((LPCSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL);
- if( h!=INVALID_HANDLE_VALUE ) break;
- if( isReadWrite ){
- int rc2;
- sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
- sqlite3EndBenignMalloc();
- if( rc2==SQLITE_OK && isRO ) break;
- }
- }while( winRetryIoerr(&cnt, &lastErrno) );
- }
-#endif
+ do{
+ h = osCreateFileW(zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL);
+ if( h!=INVALID_HANDLE_VALUE ) break;
+ if( isReadWrite ){
+ int rc2;
+ sqlite3BeginBenignMalloc();
+ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
+ sqlite3EndBenignMalloc();
+ if( rc2==SQLITE_OK && isRO ) break;
+ }
+ }while( winRetryIoerr(&cnt, &lastErrno) );
winLogIoerr(cnt, __LINE__);
OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
@@ -53574,27 +53759,7 @@ static int winOpen(
pAppData = (winVfsAppData*)pVfs->pAppData;
-#if SQLITE_OS_WINCE
- {
- if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
- && ((pAppData==NULL) || !pAppData->bNoLock)
- && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
- ){
- osCloseHandle(h);
- sqlite3_free(zConverted);
- sqlite3_free(zTmpname);
- OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
- return rc;
- }
- }
- if( isTemp ){
- pFile->zDeleteOnClose = zConverted;
- }else
-#endif
- {
- sqlite3_free(zConverted);
- }
-
+ sqlite3_free(zConverted);
sqlite3_free(zTmpname);
id->pMethods = pAppData ? pAppData->pMethod : &winIoMethod;
pFile->pVfs = pVfs;
@@ -53641,7 +53806,7 @@ static int winDelete(
int rc;
DWORD attr;
DWORD lastErrno = 0;
- void *zConverted;
+ LPWSTR zConverted;
UNUSED_PARAMETER(pVfs);
UNUSED_PARAMETER(syncDir);
@@ -53653,80 +53818,31 @@ static int winDelete(
OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
return SQLITE_IOERR_NOMEM_BKPT;
}
- if( osIsNT() ){
- do {
-#if SQLITE_OS_WINRT
- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
- memset(&sAttrData, 0, sizeof(sAttrData));
- if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
- &sAttrData) ){
- attr = sAttrData.dwFileAttributes;
+ do {
+ attr = osGetFileAttributesW(zConverted);
+ if ( attr==INVALID_FILE_ATTRIBUTES ){
+ lastErrno = osGetLastError();
+ if( lastErrno==ERROR_FILE_NOT_FOUND
+ || lastErrno==ERROR_PATH_NOT_FOUND ){
+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
}else{
- lastErrno = osGetLastError();
- if( lastErrno==ERROR_FILE_NOT_FOUND
- || lastErrno==ERROR_PATH_NOT_FOUND ){
- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
- }else{
- rc = SQLITE_ERROR;
- }
- break;
- }
-#else
- attr = osGetFileAttributesW(zConverted);
-#endif
- if ( attr==INVALID_FILE_ATTRIBUTES ){
- lastErrno = osGetLastError();
- if( lastErrno==ERROR_FILE_NOT_FOUND
- || lastErrno==ERROR_PATH_NOT_FOUND ){
- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
- }else{
- rc = SQLITE_ERROR;
- }
- break;
- }
- if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
- rc = SQLITE_ERROR; /* Files only. */
- break;
- }
- if ( osDeleteFileW(zConverted) ){
- rc = SQLITE_OK; /* Deleted OK. */
- break;
- }
- if ( !winRetryIoerr(&cnt, &lastErrno) ){
- rc = SQLITE_ERROR; /* No more retries. */
- break;
- }
- } while(1);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- do {
- attr = osGetFileAttributesA(zConverted);
- if ( attr==INVALID_FILE_ATTRIBUTES ){
- lastErrno = osGetLastError();
- if( lastErrno==ERROR_FILE_NOT_FOUND
- || lastErrno==ERROR_PATH_NOT_FOUND ){
- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
- }else{
- rc = SQLITE_ERROR;
- }
- break;
- }
- if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
- rc = SQLITE_ERROR; /* Files only. */
- break;
- }
- if ( osDeleteFileA(zConverted) ){
- rc = SQLITE_OK; /* Deleted OK. */
- break;
- }
- if ( !winRetryIoerr(&cnt, &lastErrno) ){
- rc = SQLITE_ERROR; /* No more retries. */
- break;
+ rc = SQLITE_ERROR;
}
- } while(1);
- }
-#endif
+ break;
+ }
+ if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
+ rc = SQLITE_ERROR; /* Files only. */
+ break;
+ }
+ if ( osDeleteFileW(zConverted) ){
+ rc = SQLITE_OK; /* Deleted OK. */
+ break;
+ }
+ if ( !winRetryIoerr(&cnt, &lastErrno) ){
+ rc = SQLITE_ERROR; /* No more retries. */
+ break;
+ }
+ } while(1);
if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
}else{
@@ -53748,9 +53864,11 @@ static int winAccess(
){
DWORD attr;
int rc = 0;
+ int cnt = 0;
DWORD lastErrno = 0;
- void *zConverted;
+ LPWSTR zConverted;
int noRetry = 0; /* Do not use winRetryIoerr() */
+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
UNUSED_PARAMETER(pVfs);
if( (flags & NORETRY)!=0 ){
@@ -53774,43 +53892,35 @@ static int winAccess(
OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
return SQLITE_IOERR_NOMEM_BKPT;
}
- if( osIsNT() ){
- int cnt = 0;
- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
- memset(&sAttrData, 0, sizeof(sAttrData));
- while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
- GetFileExInfoStandard,
- &sAttrData))
- && !noRetry
- && winRetryIoerr(&cnt, &lastErrno)
- ){ /* Loop until true */}
- if( rc ){
- /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
- ** as if it does not exist.
- */
- if( flags==SQLITE_ACCESS_EXISTS
- && sAttrData.nFileSizeHigh==0
- && sAttrData.nFileSizeLow==0 ){
- attr = INVALID_FILE_ATTRIBUTES;
- }else{
- attr = sAttrData.dwFileAttributes;
- }
+ memset(&sAttrData, 0, sizeof(sAttrData));
+ while( !(rc = osGetFileAttributesExW(zConverted,
+ GetFileExInfoStandard,
+ &sAttrData))
+ && !noRetry
+ && winRetryIoerr(&cnt, &lastErrno)
+ ){ /* Loop until true */}
+ if( rc ){
+ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
+ ** as if it does not exist.
+ */
+ if( flags==SQLITE_ACCESS_EXISTS
+ && sAttrData.nFileSizeHigh==0
+ && sAttrData.nFileSizeLow==0 ){
+ attr = INVALID_FILE_ATTRIBUTES;
}else{
- winLogIoerr(cnt, __LINE__);
- if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
- sqlite3_free(zConverted);
- return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
- zFilename);
- }else{
- attr = INVALID_FILE_ATTRIBUTES;
- }
+ attr = sAttrData.dwFileAttributes;
+ }
+ }else{
+ if( noRetry ) lastErrno = osGetLastError();
+ winLogIoerr(cnt, __LINE__);
+ if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
+ sqlite3_free(zConverted);
+ return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
+ zFilename);
+ }else{
+ attr = INVALID_FILE_ATTRIBUTES;
}
}
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- attr = osGetFileAttributesA((char*)zConverted);
- }
-#endif
sqlite3_free(zConverted);
switch( flags ){
case SQLITE_ACCESS_READ:
@@ -53964,11 +54074,9 @@ static int winFullPathnameNoMutex(
int nFull, /* Size of output buffer in bytes */
char *zFull /* Output buffer */
){
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
int nByte;
- void *zConverted;
+ LPWSTR zConverted;
char *zOut;
-#endif
/* If this path name begins with "/X:" or "\\?\", where "X" is any
** alphabetic character, discard the initial "/" from the pathname.
@@ -53985,22 +54093,23 @@ static int winFullPathnameNoMutex(
zFull[nFull-1] = '\0';
if( !winIsDriveLetterAndColon(zRelative) || !winIsDirSep(zRelative[2]) ){
int rc = SQLITE_OK;
- int nLink = 1; /* Number of symbolic links followed so far */
- const char *zIn = zRelative; /* Input path for each iteration of loop */
+ int nLink = 1; /* Number of symbolic links followed so far */
+ const char *zIn = zRelative; /* Input path for each iteration of loop */
char *zDel = 0;
struct stat buf;
UNUSED_PARAMETER(pVfs);
do {
- /* Call lstat() on path zIn. Set bLink to true if the path is a symbolic
- ** link, or false otherwise. */
+ /* Call lstat() on path zIn. Set bLink to true if the path
+ ** is a symbolic link, or false otherwise. */
int bLink = 0;
if( osLstat && osReadlink ) {
if( osLstat(zIn, &buf)!=0 ){
int myErrno = osErrno;
if( myErrno!=ENOENT ){
- rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)myErrno, "lstat", zIn);
+ rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)myErrno,
+ "lstat", zIn);
}
}else{
bLink = ((buf.st_mode & 0170000) == 0120000);
@@ -54017,7 +54126,8 @@ static int winFullPathnameNoMutex(
if( rc==SQLITE_OK ){
nByte = osReadlink(zIn, zDel, nFull-1);
if( nByte ==(DWORD)-1 ){
- rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "readlink", zIn);
+ rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno,
+ "readlink", zIn);
}else{
if( zDel[0]!='/' ){
int n;
@@ -54053,26 +54163,6 @@ static int winFullPathnameNoMutex(
}
#endif /* __CYGWIN__ */
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32)
- SimulateIOError( return SQLITE_ERROR );
- /* WinCE has no concept of a relative pathname, or so I am told. */
- /* WinRT has no way to convert a relative path to an absolute one. */
- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
- /*
- ** NOTE: We are dealing with a relative path name and the data
- ** directory has been set. Therefore, use it as the basis
- ** for converting the relative path name to an absolute
- ** one by prepending the data directory and a backslash.
- */
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
- sqlite3_data_directory, winGetDirSep(), zRelative);
- }else{
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
- }
- return SQLITE_OK;
-#endif
-
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
#if defined(_WIN32)
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
@@ -54096,21 +54186,21 @@ static int winFullPathnameNoMutex(
if( zConverted==0 ){
return SQLITE_IOERR_NOMEM_BKPT;
}
- if( osIsNT() ){
+ {
LPWSTR zTemp;
- nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
+ nByte = osGetFullPathNameW(zConverted, 0, 0, 0);
if( nByte==0 ){
sqlite3_free(zConverted);
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
"winFullPathname1", zRelative);
}
nByte += 3;
- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+ zTemp = sqlite3MallocZero( (u64)nByte*sizeof(WCHAR) );
if( zTemp==0 ){
sqlite3_free(zConverted);
return SQLITE_IOERR_NOMEM_BKPT;
}
- nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+ nByte = osGetFullPathNameW(zConverted, nByte, zTemp, 0);
if( nByte==0 ){
sqlite3_free(zConverted);
sqlite3_free(zTemp);
@@ -54121,32 +54211,6 @@ static int winFullPathnameNoMutex(
zOut = winUnicodeToUtf8(zTemp);
sqlite3_free(zTemp);
}
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- char *zTemp;
- nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
- if( nByte==0 ){
- sqlite3_free(zConverted);
- return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
- "winFullPathname3", zRelative);
- }
- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) + 3*sizeof(zTemp[0]) );
- if( zTemp==0 ){
- sqlite3_free(zConverted);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- nByte = osGetFullPathNameA((char*)zConverted, nByte+3, zTemp, 0);
- if( nByte==0 ){
- sqlite3_free(zConverted);
- sqlite3_free(zTemp);
- return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
- "winFullPathname4", zRelative);
- }
- sqlite3_free(zConverted);
- zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
- sqlite3_free(zTemp);
- }
-#endif
if( zOut ){
#ifdef __CYGWIN__
if( memcmp(zOut, "\\\\?\\", 4) ){
@@ -54173,7 +54237,6 @@ static int winFullPathnameNoMutex(
}else{
return SQLITE_IOERR_NOMEM_BKPT;
}
-#endif
}
static int winFullPathname(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
@@ -54196,25 +54259,14 @@ static int winFullPathname(
** within the shared library, and closing the shared library.
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
- HANDLE h;
- void *zConverted = winConvertFromUtf8Filename(zFilename);
+ HANDLE h = 0;
+ LPWSTR zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
if( zConverted==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
}
- if( osIsNT() ){
-#if SQLITE_OS_WINRT
- h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
-#else
- h = osLoadLibraryW((LPCWSTR)zConverted);
-#endif
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- h = osLoadLibraryA((char*)zConverted);
- }
-#endif
+ h = osLoadLibraryW ? osLoadLibraryW(zConverted) : 0;
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h));
sqlite3_free(zConverted);
return (void*)h;
@@ -54224,16 +54276,16 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
}
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
- FARPROC proc;
+ FARPROC proc = 0;
UNUSED_PARAMETER(pVfs);
- proc = osGetProcAddressA((HANDLE)pH, zSym);
+ proc = osGetProcAddressA ? osGetProcAddressA((HANDLE)pH, zSym) : 0;
OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n",
(void*)pH, zSym, (void*)proc));
return (void(*)(void))proc;
}
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
UNUSED_PARAMETER(pVfs);
- osFreeLibrary((HANDLE)pHandle);
+ if( osFreeLibrary!=0 ) osFreeLibrary((HANDLE)pHandle);
OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle));
}
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
@@ -54282,41 +54334,37 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
e.nXor = 0;
e.i = 0;
{
- SYSTEMTIME x;
- osGetSystemTime(&x);
- xorMemory(&e, (unsigned char*)&x, sizeof(SYSTEMTIME));
+ FILETIME x;
+ osGetSystemTimeAsFileTime(&x);
+ xorMemory(&e, (unsigned char*)&x, sizeof(x));
}
{
DWORD pid = osGetCurrentProcessId();
- xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD));
+ xorMemory(&e, (unsigned char*)&pid, sizeof(pid));
}
-#if SQLITE_OS_WINRT
{
ULONGLONG cnt = osGetTickCount64();
- xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG));
- }
-#else
- {
- DWORD cnt = osGetTickCount();
- xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD));
+ xorMemory(&e, (unsigned char*)&cnt, sizeof(cnt));
}
-#endif /* SQLITE_OS_WINRT */
{
LARGE_INTEGER i;
osQueryPerformanceCounter(&i);
- xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER));
+ xorMemory(&e, (unsigned char*)&i, sizeof(i));
}
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
+#if SQLITE_WIN32_USE_UUID
+#ifdef SQLITE_UWP
+# error SQLITE_WIN32_USE_UUID is incompatible with SQLITE_UWP
+#endif
{
UUID id;
- memset(&id, 0, sizeof(UUID));
+ memset(&id, 0, sizeof(id));
osUuidCreate(&id);
- xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
+ xorMemory(&e, (unsigned char*)&id, sizeof(id));
memset(&id, 0, sizeof(UUID));
osUuidCreateSequential(&id);
- xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
+ xorMemory(&e, (unsigned char*)&id, sizeof(id));
}
-#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */
+#endif /* SQLITE_WIN32_USE_UUID */
return e.nXor>nBuf ? nBuf : e.nXor;
#endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */
}
@@ -54326,7 +54374,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
** Sleep for a little while. Return the amount of time slept.
*/
static int winSleep(sqlite3_vfs *pVfs, int microsec){
- sqlite3_win32_sleep((microsec+999)/1000);
+ osSleep((microsec+999)/1000);
UNUSED_PARAMETER(pVfs);
return ((microsec+999)/1000)*1000;
}
@@ -54364,17 +54412,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
(sqlite3_int64)294967296;
-#if SQLITE_OS_WINCE
- SYSTEMTIME time;
- osGetSystemTime(&time);
- /* if SystemTimeToFileTime() fails, it returns zero. */
- if (!osSystemTimeToFileTime(&time,&ft)){
- return SQLITE_ERROR;
- }
-#else
osGetSystemTimeAsFileTime( &ft );
-#endif
-
*piNow = winFiletimeEpoch +
((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
(sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
@@ -54468,7 +54506,6 @@ SQLITE_API int sqlite3_os_init(void){
winGetSystemCall, /* xGetSystemCall */
winNextSystemCall, /* xNextSystemCall */
};
-#if defined(SQLITE_WIN32_HAS_WIDE)
static sqlite3_vfs winLongPathVfs = {
3, /* iVersion */
sizeof(winFile), /* szOsFile */
@@ -54493,7 +54530,6 @@ SQLITE_API int sqlite3_os_init(void){
winGetSystemCall, /* xGetSystemCall */
winNextSystemCall, /* xNextSystemCall */
};
-#endif
static sqlite3_vfs winNolockVfs = {
3, /* iVersion */
sizeof(winFile), /* szOsFile */
@@ -54518,7 +54554,6 @@ SQLITE_API int sqlite3_os_init(void){
winGetSystemCall, /* xGetSystemCall */
winNextSystemCall, /* xNextSystemCall */
};
-#if defined(SQLITE_WIN32_HAS_WIDE)
static sqlite3_vfs winLongPathNolockVfs = {
3, /* iVersion */
sizeof(winFile), /* szOsFile */
@@ -54543,34 +54578,29 @@ SQLITE_API int sqlite3_os_init(void){
winGetSystemCall, /* xGetSystemCall */
winNextSystemCall, /* xNextSystemCall */
};
-#endif
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==89 );
+ assert( ArraySize(aSyscall)==60 );
+ assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 );
+ assert( strcmp(aSyscall[8].zName,"FreeLibrary")==0 );
+ assert( strcmp(aSyscall[16].zName,"GetSystemInfo")==0 );
+ assert( strcmp(aSyscall[24].zName,"HeapReAlloc")==0 );
+ assert( strcmp(aSyscall[32].zName,"MapViewOfFileFromApp")==0 );
+ assert( strcmp(aSyscall[40].zName,"UnmapViewOfFile")==0 );
+ assert( strcmp(aSyscall[48].zName,"UuidCreate")==0 );
+ assert( strcmp(aSyscall[56].zName,"lstat")==0 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
-#if SQLITE_OS_WINRT
- osGetNativeSystemInfo(&winSysInfo);
-#else
osGetSystemInfo(&winSysInfo);
-#endif
assert( winSysInfo.dwAllocationGranularity>0 );
assert( winSysInfo.dwPageSize>0 );
sqlite3_vfs_register(&winVfs, 1);
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
sqlite3_vfs_register(&winLongPathVfs, 0);
-#endif
-
sqlite3_vfs_register(&winNolockVfs, 0);
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
sqlite3_vfs_register(&winLongPathNolockVfs, 0);
-#endif
-
#ifndef SQLITE_OMIT_WAL
winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
@@ -54579,17 +54609,9 @@ SQLITE_API int sqlite3_os_init(void){
}
SQLITE_API int sqlite3_os_end(void){
-#if SQLITE_OS_WINRT
- if( sleepObj!=NULL ){
- osCloseHandle(sleepObj);
- sleepObj = NULL;
- }
-#endif
-
#ifndef SQLITE_OMIT_WAL
winBigLock = 0;
#endif
-
return SQLITE_OK;
}
@@ -55358,7 +55380,7 @@ SQLITE_API unsigned char *sqlite3_serialize(
sqlite3_int64 sz;
int szPage = 0;
sqlite3_stmt *pStmt = 0;
- unsigned char *pOut;
+ unsigned char *pOut = 0;
char *zSql;
int rc;
@@ -55368,12 +55390,13 @@ SQLITE_API unsigned char *sqlite3_serialize(
return 0;
}
#endif
+ sqlite3_mutex_enter(db->mutex);
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
p = memdbFromDbSchema(db, zSchema);
iDb = sqlite3FindDbName(db, zSchema);
if( piSize ) *piSize = -1;
- if( iDb<0 ) return 0;
+ if( iDb<0 ) goto serialize_out;
if( p ){
MemStore *pStore = p->pStore;
assert( pStore->pMutex==0 );
@@ -55384,19 +55407,17 @@ SQLITE_API unsigned char *sqlite3_serialize(
pOut = sqlite3_malloc64( pStore->sz );
if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
- return pOut;
+ goto serialize_out;
}
pBt = db->aDb[iDb].pBt;
- if( pBt==0 ) return 0;
+ if( pBt==0 ) goto serialize_out;
szPage = sqlite3BtreeGetPageSize(pBt);
zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
sqlite3_free(zSql);
- if( rc ) return 0;
+ if( rc ) goto serialize_out;
rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW ){
- pOut = 0;
- }else{
+ if( rc==SQLITE_ROW ){
sz = sqlite3_column_int64(pStmt, 0)*szPage;
if( sz==0 ){
sqlite3_reset(pStmt);
@@ -55430,6 +55451,9 @@ SQLITE_API unsigned char *sqlite3_serialize(
}
}
sqlite3_finalize(pStmt);
+
+ serialize_out:
+ sqlite3_mutex_leave(db->mutex);
return pOut;
}
@@ -55475,10 +55499,10 @@ SQLITE_API int sqlite3_deserialize(
if( rc ) goto end_deserialize;
db->init.iDb = (u8)iDb;
db->init.reopenMemdb = 1;
- rc = sqlite3_step(pStmt);
+ sqlite3_step(pStmt);
db->init.reopenMemdb = 0;
- if( rc!=SQLITE_DONE ){
- rc = SQLITE_ERROR;
+ rc = sqlite3_finalize(pStmt);
+ if( rc!=SQLITE_OK ){
goto end_deserialize;
}
p = memdbFromDbSchema(db, zSchema);
@@ -55499,7 +55523,6 @@ SQLITE_API int sqlite3_deserialize(
}
end_deserialize:
- sqlite3_finalize(pStmt);
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
sqlite3_free(pData);
}
@@ -57284,22 +57307,24 @@ static int pcache1InitBulk(PCache1 *pCache){
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
szBulk = pCache->szAlloc*(i64)pCache->nMax;
}
- zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
- sqlite3EndBenignMalloc();
- if( zBulk ){
- int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
- do{
- PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
- pX->page.pBuf = zBulk;
- pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
- assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
- pX->isBulkLocal = 1;
- pX->isAnchor = 0;
- pX->pNext = pCache->pFree;
- pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
- pCache->pFree = pX;
- zBulk += pCache->szAlloc;
- }while( --nBulk );
+ if( szBulk>=pCache->szAlloc ){
+ zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
+ sqlite3EndBenignMalloc();
+ if( zBulk ){
+ int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
+ do{
+ PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
+ pX->page.pBuf = zBulk;
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
+ pX->isBulkLocal = 1;
+ pX->isAnchor = 0;
+ pX->pNext = pCache->pFree;
+ pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
+ pCache->pFree = pX;
+ zBulk += pCache->szAlloc;
+ }while( --nBulk );
+ }
}
return pCache->pFree!=0;
}
@@ -57518,6 +57543,7 @@ static void pcache1ResizeHash(PCache1 *p){
if( nNew<256 ){
nNew = 256;
}
+ assert( (nNew & (nNew-1))==0 ); /* nNew is always a power of two */
pcache1LeaveMutex(p->pGroup);
if( p->nHash ){ sqlite3BeginBenignMalloc(); }
@@ -57529,7 +57555,7 @@ static void pcache1ResizeHash(PCache1 *p){
PgHdr1 *pPage;
PgHdr1 *pNext = p->apHash[i];
while( (pPage = pNext)!=0 ){
- unsigned int h = pPage->iKey % nNew;
+ unsigned int h = (unsigned int)(pPage->iKey & (nNew-1));
pNext = pPage->pNext;
pPage->pNext = apNew[h];
apNew[h] = pPage;
@@ -57579,7 +57605,8 @@ static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){
PgHdr1 **pp;
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
- h = pPage->iKey % pCache->nHash;
+ assert( pCache->nHash>0 && (pCache->nHash & (pCache->nHash-1))==0 );
+ h = pPage->iKey & (pCache->nHash-1);
for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
*pp = (*pp)->pNext;
@@ -57624,14 +57651,14 @@ static void pcache1TruncateUnsafe(
unsigned int h, iStop;
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
assert( pCache->iMaxKey >= iLimit );
- assert( pCache->nHash > 0 );
+ assert( pCache->nHash>0 && (pCache->nHash & (pCache->nHash-1))==0 );
if( pCache->iMaxKey - iLimit < pCache->nHash ){
/* If we are just shaving the last few pages off the end of the
** cache, then there is no point in scanning the entire hash table.
** Only scan those hash slots that might contain pages that need to
** be removed. */
- h = iLimit % pCache->nHash;
- iStop = pCache->iMaxKey % pCache->nHash;
+ h = iLimit & (pCache->nHash-1);
+ iStop = pCache->iMaxKey & (pCache->nHash-1);
TESTONLY( nPage = -10; ) /* Disable the pCache->nPage validity check */
}else{
/* This is the general case where many pages are being removed.
@@ -57656,7 +57683,7 @@ static void pcache1TruncateUnsafe(
}
}
if( h==iStop ) break;
- h = (h+1) % pCache->nHash;
+ h = (h+1) & (pCache->nHash-1);
}
assert( nPage<0 || pCache->nPage==(unsigned)nPage );
}
@@ -57868,6 +57895,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache);
assert( pCache->nHash>0 && pCache->apHash );
+ assert( (pCache->nHash & (pCache->nHash-1))==0 );
/* Step 4. Try to recycle a page. */
if( pCache->bPurgeable
@@ -57896,7 +57924,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
}
if( pPage ){
- unsigned int h = iKey % pCache->nHash;
+ unsigned int h = iKey & (pCache->nHash-1);
pCache->nPage++;
pPage->iKey = iKey;
pPage->pNext = pCache->apHash[h];
@@ -57980,8 +58008,11 @@ static PgHdr1 *pcache1FetchNoMutex(
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = 0;
- /* Step 1: Search the hash table for an existing entry. */
- pPage = pCache->apHash[iKey % pCache->nHash];
+ /* Step 1: Search the hash table for an existing entry. nHash is always
+ ** a power of two when the cache is in use (see pcache1ResizeHash()), so
+ ** the modulo reduces to a mask, avoiding a hardware divide. */
+ assert( pCache->nHash>0 && (pCache->nHash & (pCache->nHash-1))==0 );
+ pPage = pCache->apHash[iKey & (pCache->nHash-1u)];
while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
/* Step 2: If the page was found in the hash table, then return it.
@@ -58100,7 +58131,8 @@ static void pcache1Rekey(
pcache1EnterMutex(pCache->pGroup);
assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
- hOld = iOld%pCache->nHash;
+ assert( pCache->nHash>0 && (pCache->nHash & (pCache->nHash-1))==0 );
+ hOld = iOld & (pCache->nHash-1);
pp = &pCache->apHash[hOld];
while( (*pp)!=pPage ){
pp = &(*pp)->pNext;
@@ -58108,7 +58140,7 @@ static void pcache1Rekey(
*pp = pPage->pNext;
assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
- hNew = iNew%pCache->nHash;
+ hNew = iNew & (pCache->nHash-1);
pPage->iKey = iNew;
pPage->pNext = pCache->apHash[hNew];
pCache->apHash[hNew] = pPage;
@@ -58941,6 +58973,10 @@ SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*);
#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_WALSTAT)
+SQLITE_PRIVATE void sqlite3WalStat(Wal*,sqlite3_str*);
+#endif
+
#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* SQLITE_WAL_H */
@@ -59738,6 +59774,8 @@ SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
if( iRead ) return 0; /* Case (4) */
}
+#else
+ UNUSED_PARAMETER(pgno);
#endif
assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
@@ -60158,17 +60196,17 @@ static int jrnlBufferSize(Pager *pPager){
*/
#ifdef SQLITE_CHECK_PAGES
/*
-** Return a 32-bit hash of the page data for pPage.
+** Return a 64-bit hash of the page data for pPage.
*/
-static u32 pager_datahash(int nByte, unsigned char *pData){
- u32 hash = 0;
+static u64 pager_datahash(int nByte, unsigned char *pData){
+ u64 hash = 0;
int i;
for(i=0; ipPager->pageSize, (unsigned char *)pPage->pData);
}
static void pager_set_pagehash(PgHdr *pPage){
@@ -60195,39 +60233,78 @@ static void checkPage(PgHdr *pPg){
#endif /* SQLITE_CHECK_PAGES */
/*
-** When this is called the journal file for pager pPager must be open.
-** This function attempts to read a super-journal file name from the
-** end of the file and, if successful, copies it into memory supplied
-** by the caller. See comments above writeSuperJournal() for the format
-** used to store a super-journal file name at the end of a journal file.
+** Free a buffer allocated by the readSuperJournal() function.
+*/
+static void freeSuperJournal(char *zSuper){
+ if( zSuper ){
+ sqlite3_free(&zSuper[-4]);
+ }
+}
+
+/*
+** Check if zSuper is a valid super-journal name. There are two valid
+** formats:
**
-** zSuper must point to a buffer of at least nSuper bytes allocated by
-** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
-** enough space to write the super-journal name). If the super-journal
-** name in the journal is longer than nSuper bytes (including a
-** nul-terminator), then this is handled as if no super-journal name
-** were present in the journal.
+** + The 3rd and 4th last bytes of the filename are ".9", and the
+** following 2 bytes are hex digits. This is a file created in 8.3
+** filenames mode.
**
-** If a super-journal file name is present at the end of the journal
-** file, then it is copied into the buffer pointed to by zSuper. A
-** nul-terminator byte is appended to the buffer following the
-** super-journal file name.
+** + The 3rd last byte of the filename is "9" and the filename
+** contains the string "-mj" starting at the 12th last byte.
+** All bytes following the "-mj" are hex digits.
**
-** If it is determined that no super-journal file name is present
-** zSuper[0] is set to 0 and SQLITE_OK returned.
+** If the filename matches either of these patterns, return non-zero.
+** Otherwise, return zero.
+*/
+static int pagerIsSuperJrnlName(const char *zSuper){
+ const int nSuper = sqlite3Strlen30(zSuper);
+ int ii;
+
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ if( nSuper<4 ) return 0;
+ if( zSuper[nSuper-3]!='9' ) return 0;
+ if( sqlite3Isxdigit(zSuper[nSuper-2])==0 ) return 0;
+ if( sqlite3Isxdigit(zSuper[nSuper-1])==0 ) return 0;
+ if( zSuper[nSuper-4]=='.' ) return 1;
+#endif
+ if( nSuper<12 ) return 0;
+ if( memcmp(&zSuper[nSuper-12], "-mj", 3) ) return 0;
+ if( zSuper[nSuper-3]!='9' ) return 0;
+ for(ii=nSuper-9; iisetSuper==0 );
assert( !pagerUseWal(pPager) );
+ assert( zSuper==0 || pagerIsSuperJrnlName(zSuper) );
if( !zSuper
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
@@ -60916,7 +61003,7 @@ static int pagerFlushOnCommit(Pager *pPager, int bCommit){
** database transaction.
**
** This routine is never called in PAGER_ERROR state. If it is called
-** in PAGER_NONE or PAGER_SHARED state and the lock held is less
+** in PAGER_OPEN or PAGER_READER state and the lock held is less
** exclusive than a RESERVED lock, it is a no-op.
**
** Otherwise, any active savepoints are released.
@@ -61462,9 +61549,20 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
char *zSuperJournal = 0; /* Contents of super-journal file */
i64 nSuperJournal; /* Size of super-journal file */
char *zJournal; /* Pointer to one journal within MJ file */
- char *zSuperPtr; /* Space to hold super-journal filename */
char *zFree = 0; /* Free this buffer */
- i64 nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
+ int bSeen = 0; /* If super-journal contains pPager->zJournal */
+
+ /* Check if this looks like a real super-journal name. If it does not,
+ ** return SQLITE_OK without attempting to delete it. This is to limit
+ ** the degree to which a crafted journal file can be used to cause
+ ** SQLite to delete arbitrary files.
+ **
+ ** This test never fails, becaue the super journal name is checked
+ ** by readSuperJournal().
+ */
+ if( NEVER(pagerIsSuperJrnlName(zSuper)==0) ){
+ return SQLITE_OK;
+ }
/* Allocate space for both the pJournal and pSuper file descriptors.
** If successful, open the super-journal file for reading.
@@ -61487,9 +61585,8 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
*/
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
- nSuperPtr = 1 + (i64)pVfs->mxPathname;
- assert( nSuperJournal>=0 && nSuperPtr>0 );
- zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
+ assert( nSuperJournal>=0 );
+ zFree = sqlite3Malloc(4 + nSuperJournal + 2);
if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
@@ -61498,7 +61595,6 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
}
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
zSuperJournal = &zFree[4];
- zSuperPtr = &zSuperJournal[nSuperJournal+2];
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
if( rc!=SQLITE_OK ) goto delsuper_out;
zSuperJournal[nSuperJournal] = 0;
@@ -61506,43 +61602,56 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
zJournal = zSuperJournal;
while( (zJournal-zSuperJournal)zJournal)==0 ){
+ bSeen = 1;
+ }else{
+ int exists;
+ rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
if( rc!=SQLITE_OK ){
goto delsuper_out;
}
+ if( exists ){
+ char *zSuperPtr = 0;
- rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
- sqlite3OsClose(pJournal);
- if( rc!=SQLITE_OK ){
- goto delsuper_out;
- }
+ /* One of the journals pointed to by the super-journal exists.
+ ** Open it and check if it points at the super-journal. If
+ ** so, return without deleting the super-journal file.
+ ** NB: zJournal is really a MAIN_JOURNAL. But call it a
+ ** SUPER_JOURNAL here so that the VFS will not send the zJournal
+ ** name into sqlite3_database_file_object().
+ */
+ int c;
+ int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
+ rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
+ if( rc!=SQLITE_OK ){
+ goto delsuper_out;
+ }
- c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
- if( c ){
- /* We have a match. Do not delete the super-journal file. */
- goto delsuper_out;
+ rc = readSuperJournal(pJournal, 1+(u64)pVfs->mxPathname, &zSuperPtr);
+ sqlite3OsClose(pJournal);
+ if( rc!=SQLITE_OK ){
+ assert( zSuperPtr==0 );
+ goto delsuper_out;
+ }
+
+ c = zSuperPtr!=0 && strcmp(zSuperPtr, zSuper)==0;
+ freeSuperJournal(zSuperPtr);
+ if( c ){
+ /* We have a match. Do not delete the super-journal file. */
+ goto delsuper_out;
+ }
}
}
zJournal += (sqlite3Strlen30(zJournal)+1);
}
sqlite3OsClose(pSuper);
- rc = sqlite3OsDelete(pVfs, zSuper, 0);
+ if( bSeen ){
+ /* Only delete the super-journal if bSeen is true - indicating that
+ ** the super-journal contained a pointer to this database's journal
+ ** file. */
+ rc = sqlite3OsDelete(pVfs, zSuper, 0);
+ }
delsuper_out:
sqlite3_free(zFree);
@@ -61747,19 +61856,11 @@ static int pager_playback(Pager *pPager, int isHot){
** If a super-journal file name is specified, but the file is not
** present on disk, then the journal is not hot and does not need to be
** played back.
- **
- ** TODO: Technically the following is an error because it assumes that
- ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
- ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
- ** mxPathname is 512, which is the same as the minimum allowable value
- ** for pageSize.
*/
- zSuper = pPager->pTmpSpace;
- rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
- if( rc==SQLITE_OK && zSuper[0] ){
+ rc = readSuperJournal(pPager->jfd, 1+(i64)pPager->pVfs->mxPathname, &zSuper);
+ if( rc==SQLITE_OK && zSuper ){
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}
- zSuper = 0;
if( rc!=SQLITE_OK || !res ){
goto end_playback;
}
@@ -61888,30 +61989,20 @@ static int pager_playback(Pager *pPager, int isHot){
*/
pPager->changeCountDone = pPager->tempFile;
- if( rc==SQLITE_OK ){
- /* Leave 4 bytes of space before the super-journal filename in memory.
- ** This is because it may end up being passed to sqlite3OsOpen(), in
- ** which case it requires 4 0x00 bytes in memory immediately before
- ** the filename. */
- zSuper = &pPager->pTmpSpace[4];
- rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
- testcase( rc!=SQLITE_OK );
- }
if( rc==SQLITE_OK
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
rc = sqlite3PagerSync(pPager, 0);
}
if( rc==SQLITE_OK ){
- rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
+ rc = pager_end_transaction(pPager, zSuper!=0, 0);
testcase( rc!=SQLITE_OK );
}
- if( rc==SQLITE_OK && zSuper[0] && res ){
+ if( rc==SQLITE_OK && zSuper && res ){
/* If there was a super-journal and this routine will return success,
** see if it is possible to delete the super-journal.
*/
- assert( zSuper==&pPager->pTmpSpace[4] );
- memset(pPager->pTmpSpace, 0, 4);
+ assert( memcmp(&zSuper[-4], "\0\0\0\0", 4)==0 );
rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
@@ -61924,6 +62015,7 @@ static int pager_playback(Pager *pPager, int isHot){
** back a journal created by a process with a different sector size
** value. Reset it to the correct value for this process.
*/
+ freeSuperJournal(zSuper);
setSectorSize(pPager);
return rc;
}
@@ -62677,7 +62769,7 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(
**
** then the pager object page size is set to *pPageSize.
**
-** If the page size is changed, then this function uses sqlite3PagerMalloc()
+** If the page size is changed, then this function uses sqlite3PageMalloc()
** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
** In all other cases, SQLITE_OK is returned.
@@ -63117,6 +63209,8 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
pPager->pWal = 0;
}
+#else
+ UNUSED_PARAMETER(db);
#endif
pager_reset(pPager);
if( MEMDB ){
@@ -63866,7 +63960,15 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
*/
if( zFilename && zFilename[0] ){
int fout = 0; /* VFS flags returned by xOpen() */
+ int bImmutable = sqlite3_uri_boolean(pPager->zFilename, "immutable", 0);
+ if( bImmutable ){
+ vfsFlags |= SQLITE_OPEN_READONLY;
+ vfsFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
+ }
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
+ if( bImmutable ){
+ goto act_like_temp_file;
+ }
assert( !memDb );
pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
@@ -63906,10 +64008,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
#endif
}
pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0);
- if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
- || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){
- vfsFlags |= SQLITE_OPEN_READONLY;
- goto act_like_temp_file;
+ if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0 ){
+ vfsFlags |= SQLITE_OPEN_READONLY;
+ goto act_like_temp_file;
}
}
}else{
@@ -63929,6 +64030,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE mode */
pPager->noLock = 1; /* Do no locking */
readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
+ assert( readOnly==0 || readOnly==1 );
}
/* The following call to PagerSetPagesize() serves to set the value of
@@ -64022,8 +64124,8 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){
/*
-** This function is called after transitioning from PAGER_UNLOCK to
-** PAGER_SHARED state. It tests if there is a hot journal present in
+** This function is called while transitioning from PAGER_OPEN to a
+** higher state. It tests if there is a hot journal present in
** the file-system for the given pager. A hot journal is one that
** needs to be played back. According to this function, a hot-journal
** file exists if the following criteria are met:
@@ -65749,6 +65851,20 @@ SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
}
#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_WALSTAT)
+/*
+** Append JSON structure elements describing the current state of
+** the write-ahead log to pStr.
+*/
+SQLITE_PRIVATE void sqlite3PagerWalStat(Pager *pPager, sqlite3_str *pStr){
+#ifndef SQLITE_OMIT_WAL
+ if( pPager->pWal ){
+ sqlite3WalStat(pPager->pWal, pStr);
+ }
+#endif
+}
+#endif
+
/*
** Return the approximate number of bytes of memory currently
** used by the pager and its associated cache.
@@ -67345,10 +67461,41 @@ typedef u16 ht_slot;
** walIteratorFree() - Free an iterator.
**
** This functionality is used by the checkpoint code (see walCheckpoint()).
+**
+** There are two possible algorithms:
+**
+** WALITER-1 Load all pages mentioned in the WAL file and sort them,
+** then hand them back out in sorted order as requested by
+** walIteratorNext(). nPagemap==0 for this algorithm.
+**
+** WALITER-2 Create a map of all database file pages and record the
+** last WAL file frame that updates that page. Then walk
+** through the map in acsending order and return all
+** non-zero entries. nPagemap is positive for this algorithm.
+**
+** Either algorithm should work for any database and WAL file, however
+** algorithm WALITER-1 is faster and uses less memory when the database is
+** larger than the WAL file and algorithm WALITER-2 is faster and uses
+** less memory when the WAL file is larger than the database, modulo a
+** constant of proportionality. The walIteratorInit() routine selects
+** the best algorithm for each situation. WALITER-2 was added for
+** SQLite 3.54.0. Prior to that, WALITER-1 was used always.
+**
+** For algorithm WALITER-2, nPagemap stores the number of pages in the
+** database file, nSegment==1, and aSegment[0].aPgno[] is the page map array
+** that is nPagemap+1 entries in length. The value of aSegment[0].aPgno[PGNO]
+** is the frame number of the last (newest) entry for page PGNO in the WAL
+** file, or 0 if PGNO is not in the WAL file. (Aside: There is no page
+** number 0 in a well-formed database, so the memory allocation is arranged
+** such that aSegment[0].aPgno[0] and aSegment[0].iZero are aliases for the
+** same four bits of memory. This saves us from having to use -1 and +1
+** offsets to translate between 1-based SQLite page numbers and 0-based
+** C-language index numbers. tag-20260903-1)
*/
struct WalIterator {
u32 iPrior; /* Last result returned from the iterator */
int nSegment; /* Number of entries in aSegment[] */
+ u32 nPagemap; /* Non-zero in "page-map" mode */
struct WalSegment {
int iNext; /* Next slot in aIndex[] not yet returned */
ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
@@ -67362,6 +67509,7 @@ struct WalIterator {
#define SZ_WALITERATOR(N) \
(offsetof(WalIterator,aSegment)+(N)*sizeof(struct WalSegment))
+
/*
** Define the parameters of the hash tables in the wal-index file. There
** is a hash-table following every HASHTABLE_NPAGE page numbers in the
@@ -67781,6 +67929,12 @@ static int walDecodeFrame(
return 0;
}
+ /* Need a valid page size
+ */
+ if( !pWal->szPage ){
+ return 0;
+ }
+
/* A frame is only valid if a checksum of the WAL header,
** all prior frames, the first 16 bytes of this frame-header,
** and the frame-data matches the checksum in the last 8
@@ -67884,7 +68038,7 @@ static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
/*
** Compute a hash on a page number. The resulting hash value must land
-** between 0 and (HASHTABLE_NSLOT-1). The walHashNext() function advances
+** between 0 and (HASHTABLE_NSLOT-1). The walNextHash() function advances
** the hash to the next value in the event of a collision.
*/
static int walHash(u32 iPage){
@@ -68092,7 +68246,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
}
- sLoc.aPgno[idx-1] = iPage;
+ sLoc.aPgno[(idx-1)&(HASHTABLE_NPAGE-1)] = iPage;
AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -68518,24 +68672,38 @@ static int walIteratorNext(
u32 *piPage, /* OUT: The page number of the next page */
u32 *piFrame /* OUT: Wal frame index of next page */
){
- u32 iMin; /* Result pgno must be greater than iMin */
u32 iRet = 0xFFFFFFFF; /* 0xffffffff is never a valid page number */
- int i; /* For looping through segments */
-
- iMin = p->iPrior;
- assert( iMin<0xffffffff );
- for(i=p->nSegment-1; i>=0; i--){
- struct WalSegment *pSegment = &p->aSegment[i];
- while( pSegment->iNextnEntry ){
- u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
- if( iPg>iMin ){
- if( iPgiZero + pSegment->aIndex[pSegment->iNext];
- }
+
+ if( p->nPagemap ){
+ /* Algorithm WALITER-2 */
+ while( p->iPriornPagemap ){
+ p->iPrior++;
+ if( p->aSegment[0].aPgno[p->iPrior] ){
+ iRet = p->iPrior;
+ *piFrame = p->aSegment[0].aPgno[p->iPrior];
break;
}
- pSegment->iNext++;
+ }
+ }else{
+ /* Algorithm WALITER-1 */
+ u32 iMin; /* Result pgno must be greater than iMin */
+ int i; /* For looping through segments */
+
+ iMin = p->iPrior;
+ assert( iMin<0xffffffff );
+ for(i=p->nSegment-1; i>=0; i--){
+ struct WalSegment *pSegment = &p->aSegment[i];
+ while( pSegment->iNextnEntry ){
+ u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
+ if( iPg>iMin ){
+ if( iPgiZero + pSegment->aIndex[pSegment->iNext];
+ }
+ break;
+ }
+ pSegment->iNext++;
+ }
}
}
@@ -68704,35 +68872,59 @@ static void walIteratorFree(WalIterator *p){
** WalIterator object when it has finished with it.
*/
static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
+ int iFirstPage; /* First 32KB *-shm page to visit */
+ int iLastPage; /* Last 32KB *-shm page to visit */
+ u32 iZero; /* Frame before first frame to visit */
WalIterator *p; /* Return value */
int nSegment; /* Number of segments to merge */
u32 iLast; /* Last frame in log */
sqlite3_int64 nByte; /* Number of bytes to allocate */
+ sqlite3_int64 nExtra; /* Number of bytes to allocate */
int i; /* Iterator variable */
- ht_slot *aTmp; /* Temp space used by merge-sort */
+ ht_slot *aTmp = 0; /* Temp space used by merge-sort */
int rc = SQLITE_OK; /* Return Code */
+ int eAlg; /* Which algorithm to use. 1 or 2 */
/* This routine only runs while holding the checkpoint lock. And
- ** it only runs if there is actually content in the log (mxFrame>0).
- */
+ ** it only runs if there is actually content in the log (mxFrame>0). */
assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
+
iLast = pWal->hdr.mxFrame;
+ iFirstPage = walFramePage(nBackfill+1);
+ iLastPage = walFramePage(iLast);
+ iZero = iFirstPage ? (HASHTABLE_NPAGE_ONE+(iFirstPage-1)*HASHTABLE_NPAGE) : 0;
+
+ if( (iLast-iZero)*sizeof(ht_slot)>pWal->hdr.nPage*sizeof(u32) ){
+ /* Algorithm WALITER-2 */
+ nSegment = 1;
+ eAlg = 2;
+ nByte = SZ_WALITERATOR(nSegment) + pWal->hdr.nPage * sizeof(u32);
+ nExtra = 0;
+ }else{
+ /* Algorithm WALITER-1 */
+ nSegment = iLastPage - iFirstPage + 1;
+ eAlg = 1;
+ nByte = SZ_WALITERATOR(nSegment) + (iLast-iZero)*sizeof(ht_slot);
+ nExtra = sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast);
+ }
/* Allocate space for the WalIterator object. */
- nSegment = walFramePage(iLast) + 1;
- nByte = SZ_WALITERATOR(nSegment)
- + iLast*sizeof(ht_slot);
- p = (WalIterator *)sqlite3_malloc64(nByte
- + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
- );
+ p = (WalIterator *)sqlite3_malloc64(nByte + nExtra);
if( !p ){
return SQLITE_NOMEM_BKPT;
}
memset(p, 0, nByte);
p->nSegment = nSegment;
- aTmp = (ht_slot*)&(((u8*)p)[nByte]);
+ if( eAlg==2 ){
+ p->nPagemap = pWal->hdr.nPage;
+ p->aSegment[0].aPgno = ((u32*)&p->aSegment[1]) - 1;
+ assert( (u8*)&(p->aSegment[0].aPgno[0]) == (u8*)&(p->aSegment[0].iZero) );
+ /* ^-- verifies tag-20260903-1 */
+ }else{
+ aTmp = (ht_slot*)&(((u8*)p)[nByte]);
+ }
SEH_FREE_ON_ERROR(0, p);
- for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && iaSegment[p->nSegment])[sLoc.iZero];
- sLoc.iZero++;
- for(j=0; jaSegment[0].aPgno;
+ for(j=0; jnPagemap ){
+ aPagemap[pgno] = sLoc.iZero + j + 1;
+ }
+ }
+ }else{
+ assert( i!=iFirstPage || iZero==sLoc.iZero );
+ aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[sLoc.iZero - iZero];
+ sLoc.iZero++;
+
+ for(j=0; jaSegment[i-iFirstPage].iZero = sLoc.iZero;
+ p->aSegment[i-iFirstPage].nEntry = nEntry;
+ p->aSegment[i-iFirstPage].aIndex = aIndex;
+ p->aSegment[i-iFirstPage].aPgno = (u32 *)sLoc.aPgno;
}
- walMergesort((u32 *)sLoc.aPgno, aTmp, aIndex, &nEntry);
- p->aSegment[i].iZero = sLoc.iZero;
- p->aSegment[i].nEntry = nEntry;
- p->aSegment[i].aIndex = aIndex;
- p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
}
}
if( rc!=SQLITE_OK ){
@@ -69012,68 +69216,82 @@ static int walCheckpoint(
&& (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
){
u32 nBackfill = pInfo->nBackfill;
- pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
-
- /* Sync the WAL to disk */
- rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
-
- /* If the database may grow as a result of this checkpoint, hint
- ** about the eventual size of the db file to the VFS layer.
- */
- if( rc==SQLITE_OK ){
- i64 nReq = ((i64)mxPage * szPage);
- i64 nSize; /* Current size of database file */
- sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
- rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
- if( rc==SQLITE_OK && nSizehdr.mxFrame*szPage)pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq);
+ WalIndexHdr *pLive = (WalIndexHdr*)walIndexHdr(pWal);
+
+ /* Now that read-lock slot 0 is locked, check that the wal has not been
+ ** wrapped since the header was read for this checkpoint. If it was, then
+ ** there was no work to do anyway. In this case the
+ ** (pInfo->nBackfillhdr.mxFrame) test above only passed because
+ ** pInfo->nBackfill had already been set to 0 by the writer that wrapped
+ ** the wal file. It would also be dangerous to proceed, as there may be
+ ** fewer than pWal->hdr.mxFrame valid frames in the wal file. */
+ int bChg = memcmp(pLive->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt));
+ if( 0==bChg ){
+ pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
+
+ /* Sync the WAL to disk */
+ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
+
+ /* If the database may grow as a result of this checkpoint, hint
+ ** about the eventual size of the db file to the VFS layer.
+ */
+ if( rc==SQLITE_OK ){
+ i64 nReq = ((i64)mxPage * szPage);
+ i64 nSize; /* Current size of database file */
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
+ rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
+ if( rc==SQLITE_OK && nSizehdr.mxFrame*szPage)pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
+ }
}
- }
-
- }
- /* Iterate through the contents of the WAL, copying data to the db file */
- while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
- i64 iOffset;
- assert( walFramePgno(pWal, iFrame)==iDbpage );
- SEH_INJECT_FAULT;
- if( AtomicLoad(&db->u1.isInterrupted) ){
- rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
- break;
- }
- if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
- continue;
}
- iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
- /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
- rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
- if( rc!=SQLITE_OK ) break;
- iOffset = (iDbpage-1)*(i64)szPage;
- testcase( IS_BIG_INT(iOffset) );
- rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
- if( rc!=SQLITE_OK ) break;
- }
- sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
- /* If work was actually accomplished... */
- if( rc==SQLITE_OK ){
- if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
- i64 szDb = pWal->hdr.nPage*(i64)szPage;
- testcase( IS_BIG_INT(szDb) );
- rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
+ /* Iterate through the contents of the WAL, copying data to the
+ ** db file */
+ while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
+ i64 iOffset;
+ assert( walFramePgno(pWal, iFrame)==iDbpage );
+ SEH_INJECT_FAULT;
+ if( AtomicLoad(&db->u1.isInterrupted) ){
+ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
+ break;
+ }
+ if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
+ continue;
}
+ iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
+ rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
+ if( rc!=SQLITE_OK ) break;
+ iOffset = (iDbpage-1)*(i64)szPage;
+ testcase( IS_BIG_INT(iOffset) );
+ rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
+ if( rc!=SQLITE_OK ) break;
}
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
+
+ /* If work was actually accomplished... */
if( rc==SQLITE_OK ){
- AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
+ if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
+ i64 szDb = pWal->hdr.nPage*(i64)szPage;
+ testcase( IS_BIG_INT(szDb) );
+ rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
+ }
+ }
+ if( rc==SQLITE_OK ){
+ AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
+ }
}
}
@@ -69621,7 +69839,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
/* Allocate a buffer to read frames into */
assert( (pWal->szPage & (pWal->szPage-1))==0 );
- assert( pWal->szPage>=512 && pWal->szPage<=65536 );
+ assert( (pWal->szPage>=512 && pWal->szPage<=65536) || pWal->szPage==0 );
szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
aFrame = (u8 *)sqlite3_malloc64(szFrame);
if( aFrame==0 ){
@@ -70326,7 +70544,10 @@ static int walFindFrame(
SEH_INJECT_FAULT;
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
u32 iFrame = iH + sLoc.iZero;
- if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){
+ if( iFrame<=iLast
+ && iFrame>=pWal->minFrame
+ && sLoc.aPgno[(iH-1)&(HASHTABLE_NPAGE-1)]==pgno
+ ){
assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame;
}
@@ -70400,11 +70621,15 @@ SQLITE_PRIVATE int sqlite3WalReadFrame(
i64 iOffset;
sz = pWal->hdr.szPage;
sz = (sz&0xfe00) + ((sz&0x0001)<<16);
+ if( nOut>sz ){
+ memset(pOut+sz, 0, nOut-sz);
+ nOut = sz;
+ }
testcase( sz<=32768 );
testcase( sz>=65536 );
iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
- return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
+ return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
}
/*
@@ -71123,6 +71348,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
/* Copy data from the log to the database file. */
if( rc==SQLITE_OK ){
+ sqlite3FaultSim(660);
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
}else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){
@@ -71376,6 +71602,64 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
return pWal->pWalFd;
}
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_WALSTAT)
+/*
+** Helper function to sqlite3WalStat().
+**
+** Append JSON-5 structure elements onto describing the current state
+** of pWal onto the end of pStr. This function is for debugging and
+** analysis only and is not included in production builds.
+*/
+static void walIndexHdrStat(volatile WalIndexHdr *pHdr, sqlite3_str *pStr){
+ sqlite3_str_appendf(pStr, "iVersion:%u",pHdr->iVersion);
+ sqlite3_str_appendf(pStr, ",iChange:%u",pHdr->iChange);
+ sqlite3_str_appendf(pStr, ",isInit:%u",pHdr->isInit);
+ sqlite3_str_appendf(pStr, ",bigEndCksum:%u",pHdr->bigEndCksum);
+ sqlite3_str_appendf(pStr, ",szPage:%u",pHdr->szPage);
+ sqlite3_str_appendf(pStr, ",mxFrame:%u",pHdr->mxFrame);
+ sqlite3_str_appendf(pStr, ",nPage:%u",pHdr->nPage);
+#if 0 /* Not often needed. Declutter. */
+ sqlite3_str_appendf(pStr, ",aFrameCksum:[0x%08x,0x%08x]",
+ pHdr->aFrameCksum[0], pHdr->aFrameCksum[1]);
+ sqlite3_str_appendf(pStr, ",aSalt:[0x%08x,0x%08x]",
+ pHdr->aSalt[0], pHdr->aSalt[1]);
+ sqlite3_str_appendf(pStr, ",aCksum:[0x%08x,0x%08x]",
+ pHdr->aCksum[0], pHdr->aCksum[1]);
+#endif
+}
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_WALSTAT */
+
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_WALSTAT)
+/*
+** Append JSON-5 structure elements onto describing the current state
+** of pWal onto the end of pStr. This function is for debugging and
+** analysis only and is not included in production builds.
+*/
+SQLITE_PRIVATE void sqlite3WalStat(Wal *pWal, sqlite3_str *pStr){
+ SEH_TRY {
+ int i;
+ volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+ volatile WalIndexHdr *pHdr = walIndexHdr(pWal);
+ sqlite3_str_appendf(pStr, "hdr0:{");
+ walIndexHdrStat(pHdr,pStr);
+ sqlite3_str_appendf(pStr, "},ckpt:{");
+ sqlite3_str_appendf(pStr, "nBackfill:%u",pInfo->nBackfill);
+ sqlite3_str_appendf(pStr, ",aReadMark:[%u", pInfo->aReadMark[0]);
+ for(i=1; iaReadMark[i]);
+ }
+ sqlite3_str_appendf(pStr, "],nBackfillAttempted:%u}",
+ pInfo->nBackfillAttempted);
+
+ sqlite3_str_appendf(pStr, ",nWiData:%d", pWal->nWiData);
+ sqlite3_str_appendf(pStr, ",readLock:%d", pWal->readLock);
+ sqlite3_str_appendf(pStr, ",minFrame:%u", pWal->minFrame);
+ }
+ SEH_EXCEPT( ; )
+}
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_WALSTAT */
+
#endif /* #ifndef SQLITE_OMIT_WAL */
/************** End of wal.c *************************************************/
@@ -71939,6 +72223,9 @@ struct BtCursor {
Btree *pBtree; /* The Btree to which this cursor belongs */
Pgno *aOverflow; /* Cache of overflow page locations */
void *pKey; /* Saved key that was cursor last known position */
+#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
+ BtCursor *pCursorHintTableCursor;
+#endif
/* All fields above are zeroed when the cursor is allocated. See
** sqlite3BtreeCursorZero(). Fields that follow must be manually
** initialized. */
@@ -72107,6 +72394,7 @@ struct IntegrityCk {
int nErr; /* Number of messages written to zErrMsg so far */
int rc; /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */
u32 nStep; /* Number of steps into the integrity_check process */
+ u8 nAbove; /* Current btree recursion depth */
const char *zPfx; /* Error message prefix */
Pgno v0; /* Value for first %u substitution in zPfx (root page) */
Pgno v1; /* Value for second %u substitution in zPfx (current pg) */
@@ -72115,6 +72403,9 @@ struct IntegrityCk {
u32 *heap; /* Min-heap used for analyzing cell coverage */
sqlite3 *db; /* Database connection running the check */
i64 nRow; /* Number of rows visited in current tree */
+#ifdef SQLITE_DEBUG
+ u32 mxHeap; /* Maximum number of entries in the Min-heap */
+#endif
};
/*
@@ -72453,6 +72744,16 @@ SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
*/
/* #include "btreeInt.h" */
+/*
+** Suppress false-positive compiler warnings from GCC. Warnings are
+** re-enabled at the bottom of this source file.
+*/
+#if defined(__GNUC__) && __GNUC__>=11
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstringop-overread"
+# pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
+
/*
** The header string that appears at the beginning of every
** SQLite database.
@@ -73433,24 +73734,41 @@ SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow)
SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
/* Used only by system that substitute their own storage engine */
#ifdef SQLITE_DEBUG
- if( ALWAYS(eHintType==BTREE_HINT_RANGE) ){
- va_list ap;
+ va_list ap;
+ va_start(ap, eHintType);
+ if( eHintType==BTREE_HINT_RANGE ){
Expr *pExpr;
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3CursorRangeHintExprCheck;
- va_start(ap, eHintType);
pExpr = va_arg(ap, Expr*);
w.u.aMem = va_arg(ap, Mem*);
- va_end(ap);
assert( pExpr!=0 );
assert( w.u.aMem!=0 );
sqlite3WalkExpr(&w, pExpr);
+ }else if( ALWAYS(eHintType==BTREE_HINT_TABLECURSOR) ){
+ BtCursor *pCsr = va_arg(ap, BtCursor*);
+ assert( pCur->pCursorHintTableCursor==0
+ || pCur->pCursorHintTableCursor==pCsr
+ );
+ assert( pCsr->pKeyInfo==0 || CORRUPT_DB );
+ pCur->pCursorHintTableCursor = pCsr;
}
+ va_end(ap);
#endif /* SQLITE_DEBUG */
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
+#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
+/*
+** Return the pointer configured via the BTREE_HINT_TABLECURSOR hint on
+** cursor pCsr. This is used from OP_DeferredSeek to assert() that the
+** index cursor has been correctly configured with the table cursor.
+*/
+SQLITE_PRIVATE BtCursor *sqlite3BtreeCursorHintTblCsr(BtCursor *pCsr){
+ return pCsr->pCursorHintTableCursor;
+}
+#endif
/*
** Provide flag hints to the cursor.
@@ -73688,7 +74006,7 @@ static void btreeParseCellPtrNoPayload(
#ifndef SQLITE_DEBUG
UNUSED_PARAMETER(pPage);
#endif
- pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
+ pInfo->nSize = 4 + sqlite3GetVarint(&pCell[4], (u64*)&pInfo->nKey);
pInfo->nPayload = 0;
pInfo->nLocal = 0;
pInfo->pPayload = 0;
@@ -73700,7 +74018,7 @@ static void btreeParseCellPtr(
CellInfo *pInfo /* Fill in this structure */
){
u8 *pIter; /* For scanning through pCell */
- u32 nPayload; /* Number of bytes of cell payload */
+ u64 nPayload; /* Number of bytes of cell payload */
u64 iKey; /* Extracted Key value */
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
@@ -73722,12 +74040,13 @@ static void btreeParseCellPtr(
do{
nPayload = (nPayload<<7) | (*++pIter & 0x7f);
}while( (*pIter)>=0x80 && pIternKey);
+ ** pIter += sqlite3GetVarint(pIter, (u64*)&pInfo->nKey);
**
** The code is inlined and the loop is unrolled for performance.
** This routine is a high-runner.
@@ -73765,11 +74084,10 @@ static void btreeParseCellPtr(
pIter++;
pInfo->nKey = *(i64*)&iKey;
- pInfo->nPayload = nPayload;
+ pInfo->nPayload = (u32)nPayload;
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==(u32)pPage->maxLocal+1 );
- assert( nPayload>=0 );
assert( pPage->maxLocal <= BT_MAX_LOCAL );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
@@ -74576,8 +74894,15 @@ static int btreeComputeFreeSpace(MemPage *pPage){
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
+ if( size<4 && sqlite3FaultSim(422)==SQLITE_OK ){
+ /* Minimum freeblock size is 4. Enable fault-sim 422 to disable this
+ ** check to reach interesting error states. However, disabling this
+ ** check can cause assertion faults due to min-heap overflow. All
+ ** fault-sims are for testing use only, but this one especially so. */
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
nFree = nFree + size;
- if( next<=pc+size+3 ) break;
+ if( next0 ){
@@ -76111,6 +76436,30 @@ static SQLITE_NOINLINE int btreeBeginTrans(
}
#endif
+#ifdef SQLITE_EXPERIMENTAL_PRAGMA_20251114
+ /* If both a read and write transaction will be opened by this call,
+ ** then issue a file-control as if the following pragma command had
+ ** been evaluated:
+ **
+ ** PRAGMA experimental_pragma_20251114 = 1|2
+ **
+ ** where the RHS is "1" if wrflag is 1 (RESERVED lock), or "2" if wrflag
+ ** is 2 (EXCLUSIVE lock). Ignore any result or error returned by the VFS.
+ **
+ ** WARNING: This code will likely remain part of SQLite only temporarily -
+ ** it exists to allow users to experiment with certain types of blocking
+ ** locks in custom VFS implementations. It MAY BE REMOVED AT ANY TIME. */
+ if( pBt->pPage1==0 && wrflag ){
+ sqlite3_file *fd = sqlite3PagerFile(pPager);
+ char *aFcntl[3] = {0,0,0};
+ aFcntl[1] = "experimental_pragma_20251114";
+ assert( wrflag==1 || wrflag==2 );
+ aFcntl[2] = (wrflag==1 ? "1" : "2");
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
+ sqlite3_free(aFcntl[0]);
+ }
+#endif
+
/* Call lockBtree() until either pBt->pPage1 is populated or
** lockBtree() returns something other than SQLITE_OK. lockBtree()
** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
@@ -77558,7 +77907,7 @@ static int accessPayload(
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
- assert( offset+amt <= pCur->info.nPayload );
+ assert( (u64)offset+(u64)amt <= (u64)pCur->info.nPayload );
assert( aPayload > pPage->aData );
if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
@@ -77599,7 +77948,9 @@ static int accessPayload(
** means "not yet known" (the cache is lazily populated).
*/
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
- int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
+ i64 nOvfl = pCur->info.nPayload;
+ testcase( nOvfl - pCur->info.nLocal + ovflSize - 1 > 0xffffffffU );
+ nOvfl = (nOvfl - pCur->info.nLocal + ovflSize-1)/ovflSize;
if( pCur->aOverflow==0
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
){
@@ -77704,6 +78055,14 @@ static int accessPayload(
(eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
+ if( eOp!=0
+ && (sqlite3PagerPageRefcount(pDbPage)!=1
+ || NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit))
+ && sqlite3FaultSim(411)==SQLITE_OK
+ ){
+ sqlite3PagerUnref(pDbPage);
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
@@ -78115,7 +78474,7 @@ SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
- if( pCur->eState==CURSOR_VALID ){
+ if( NEVER(pCur->eState==CURSOR_VALID) ){
*pRes = 0;
return SQLITE_OK;
}
@@ -78298,7 +78657,7 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
}
}
}
- getVarint(pCell, (u64*)&nCellKey);
+ nCellKey = sqlite3VarintValue(pCell);
if( nCellKeyupr ){ c = -1; break; }
@@ -78353,12 +78712,12 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
** zero if the cell is less than or equal pIdxKey. Return positive
** if unknown.
**
-** Return value negative: Cell at pCur[idx] less than pIdxKey
+** Return value negative: Cell at pPage[idx] less than pIdxKey
**
-** Return value is zero: Cell at pCur[idx] equals pIdxKey
+** Return value is zero: Cell at pPage[idx] equals pIdxKey
**
** Return value positive: Nothing is known about the relationship
-** of the cell at pCur[idx] and pIdxKey.
+** of the cell at pPage[idx] and pIdxKey.
**
** This routine is part of an optimization. It is always safe to return
** a positive value as that will cause the optimization to be skipped.
@@ -78378,14 +78737,14 @@ static int indexCellCompare(
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
- testcase( pCell+nCell+1==pPage->aDataEnd );
+ if( pCell + nCell >= pPage->aDataEnd ) return 99;
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}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
** fits entirely on the main b-tree page. */
- testcase( pCell+nCell+2==pPage->aDataEnd );
+ if( pCell + nCell >= pPage->aDataEnd ) return 99;
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* If the record extends into overflow pages, do not attempt
@@ -78547,14 +78906,17 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
- testcase( pCell+nCell+1==pPage->aDataEnd );
+ if( pCell + nCell >= pPage->aDataEnd ){
+ rc = SQLITE_CORRUPT_PAGE(pPage);
+ goto moveto_index_finish;
+ }
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
+ && pCell + nCell < pPage->aDataEnd
){
/* 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);
}else{
/* The record flows over onto one or more overflow pages. In
@@ -79502,7 +79864,7 @@ static int fillInCell(
nSrc = pX->nData;
assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */
nHeader += putVarint32(&pCell[nHeader], nPayload);
- nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey);
+ nHeader += sqlite3PutVarint(&pCell[nHeader], *(u64*)&pX->nKey);
}else{
assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
nSrc = nPayload = (int)pX->nKey;
@@ -81251,7 +81613,7 @@ static int balance_nonroot(
j--;
pNew->xParseCell(pNew, b.apCell[j], &info);
pCell = pTemp;
- sz = 4 + putVarint(&pCell[4], info.nKey);
+ sz = 4 + sqlite3PutVarint(&pCell[4], info.nKey);
pTemp = 0;
}else{
pCell -= 4;
@@ -82136,7 +82498,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
}else{
aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
}
- if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
+ if( pDest->pKeyInfo==0 ) aOut += sqlite3PutVarint(aOut, iKey);
nIn = pSrc->info.nLocal;
aIn = pSrc->info.pPayload;
if( aIn+nIn>pSrc->pPage->aDataEnd ){
@@ -82196,7 +82558,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
}while( rc==SQLITE_OK && nOut>0 );
if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){
- Pgno pgnoNew;
+ Pgno pgnoNew = 0; /* Prevent harmless static-analyzer warning */
MemPage *pNew = 0;
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
put4byte(pPgnoOut, pgnoNew);
@@ -82375,7 +82737,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pTmp!=0 );
rc = sqlite3PagerWrite(pLeaf->pDbPage);
if( rc==SQLITE_OK ){
- rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n);
+ rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4-(pCell[0]==2), pTmp, n);
}
dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
if( rc ) return rc;
@@ -82606,11 +82968,20 @@ SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, Pgno *piTable, int flags){
/*
** Erase the given database page and all its children. Return
** the page to the freelist.
+**
+** The freePageFlag parameter serves a double role:
+**
+** * Bit 0 (freePageFlag&1) means that the page should be freed
+** after it is cleared.
+**
+** * Bits 1-31 (freePageFlag>>1) is the depth of recursion. Use this
+** to prevent a corrupt database file from recursing too deeply and
+** overflowing the CPU stack.
*/
static int clearDatabasePage(
BtShared *pBt, /* The BTree that contains the table */
Pgno pgno, /* Page number to clear */
- int freePageFlag, /* Deallocate page if true */
+ int freePageFlag, /* bit 0: Deallocate page. Bits 1-31: depth */
i64 *pnChange /* Add number of Cells freed to this counter */
){
MemPage *pPage;
@@ -82624,6 +82995,9 @@ static int clearDatabasePage(
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_PGNO(pgno);
}
+ if( (freePageFlag>>1) > BTCURSOR_MAX_DEPTH ){
+ return SQLITE_CORRUPT_PGNO(pgno);
+ }
rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
if( (pBt->openFlags & BTREE_SINGLE)==0
@@ -82636,14 +83010,16 @@ static int clearDatabasePage(
for(i=0; inCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
+ rc = clearDatabasePage(pBt, get4byte(pCell),
+ (freePageFlag+2)|1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
+ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]),
+ (freePageFlag+2)|1, pnChange);
if( rc ) goto cleardatabasepage_out;
if( pPage->intKey ) pnChange = 0;
}
@@ -82651,7 +83027,7 @@ static int clearDatabasePage(
testcase( !pPage->intKey );
*pnChange += pPage->nCell;
}
- if( freePageFlag ){
+ if( (freePageFlag&1)!=0 ){
freePage(pPage, &rc);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
@@ -82781,6 +83157,9 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
}
pMove = 0;
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pMove->pDbPage);
+ }
freePage(pMove, &rc);
releasePage(pMove);
if( rc!=SQLITE_OK ){
@@ -83286,19 +83665,24 @@ static int checkTreePage(
/* Check that the page exists
*/
checkProgress(pCheck);
- if( pCheck->mxErr==0 ) goto end_of_check;
+ if( pCheck->mxErr==0 ) return 0;
pBt = pCheck->pBt;
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage) ) return 0;
pCheck->zPfx = "Tree %u page %u: ";
pCheck->v1 = iPage;
+ pCheck->nAbove++;
if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck,
"unable to get the page. error code=%d", rc);
if( rc==SQLITE_IOERR_NOMEM ) pCheck->rc = SQLITE_NOMEM;
goto end_of_check;
}
+ if( pCheck->nAbove > BTCURSOR_MAX_DEPTH ){
+ checkAppendMsg(pCheck,"btree depth exceeds %d",BTCURSOR_MAX_DEPTH);
+ goto end_of_check;
+ }
/* Clear MemPage.isInit to make sure the corruption detection code in
** btreeInitPage() is executed. */
@@ -83378,6 +83762,11 @@ static int checkTreePage(
doCoverageCheck = 0;
continue;
}
+ if( info.nPayload && info.pPayload[0]<2 ){
+ checkAppendMsg(pCheck, "Bad cell header size");
+ doCoverageCheck = 0;
+ continue;
+ }
/* Check for integer primary key out of range */
if( pPage->intKey ){
@@ -83419,6 +83808,7 @@ static int checkTreePage(
}
}else{
/* Populate the coverage-checking heap for leaf pages */
+ assert( heap!=0 && heap[0] < pCheck->mxHeap );
btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1));
}
}
@@ -83438,6 +83828,7 @@ static int checkTreePage(
u32 size;
pc = get2byteAligned(&data[cellStart+i*2]);
size = pPage->xCellSize(pPage, &data[pc]);
+ assert( heap!=0 && heap[0] < pCheck->mxHeap );
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
}
}
@@ -83454,6 +83845,7 @@ static int checkTreePage(
assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
size = get2byte(&data[i+2]);
assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */
+ assert( heap!=0 && heap[0] < pCheck->mxHeap );
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
@@ -83510,6 +83902,7 @@ static int checkTreePage(
pCheck->zPfx = saved_zPfx;
pCheck->v1 = saved_v1;
pCheck->v2 = saved_v2;
+ pCheck->nAbove--;
return depth+1;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -83587,7 +83980,10 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
checkOom(&sCheck);
goto integrity_ck_cleanup;
}
- sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
+ sCheck.heap = (u32*)sqlite3Malloc( pBt->pageSize*2 );
+#ifdef SQLITE_DEBUG
+ sCheck.mxHeap = pBt->pageSize/2 - 1;
+#endif
if( sCheck.heap==0 ){
checkOom(&sCheck);
goto integrity_ck_cleanup;
@@ -83639,7 +84035,9 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
}
#endif
sCheck.v0 = aRoot[i];
+ assert( sCheck.nAbove==0 );
checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64);
+ assert( sCheck.nAbove==0 );
}
sqlite3MemSetArrayInt64(aCnt, i, sCheck.nRow);
}
@@ -83672,7 +84070,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
/* Clean up and report errors.
*/
integrity_ck_cleanup:
- sqlite3PageFree(sCheck.heap);
+ sqlite3_free(sCheck.heap);
sqlite3_free(sCheck.aPgRef);
*pnErr = sCheck.nErr;
if( sCheck.nErr==0 ){
@@ -83981,6 +84379,13 @@ SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){
}
#endif
+/* Re-enable GCC compiler warnings that were suppressed at the top
+** of this source file to prevent annoying false-positives.
+*/
+#if defined(__GNUC__) && __GNUC__>=11
+# pragma GCC diagnostic pop
+#endif
+
/************** End of btree.c ***********************************************/
/************** Begin file backup.c ******************************************/
/*
@@ -84005,6 +84410,7 @@ SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){
*/
struct sqlite3_backup {
sqlite3* pDestDb; /* Destination database handle */
+ char *zDestDb;
Btree *pDest; /* Destination b-tree file */
u32 iDestSchema; /* Original schema cookie in destination */
int bDestLocked; /* True once a write-transaction is open on pDest */
@@ -84065,8 +84471,10 @@ struct sqlite3_backup {
** error message to pErrorDb.
*/
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
- int i = sqlite3FindDbName(pDb, zDb);
+ int i;
+ assert( pDb!=0 );
+ i = sqlite3FindDbName(pDb, zDb);
if( i==1 ){
Parse sParse;
int rc = 0;
@@ -84094,10 +84502,8 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
** Attempt to set the page size of the destination to match the page size
** of the source.
*/
-static int setDestPgsz(sqlite3_backup *p){
- int rc;
- rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
- return rc;
+static int setDestPgsz(Btree *pDest, Btree *pSrc){
+ return sqlite3BtreeSetPageSize(pDest, sqlite3BtreeGetPageSize(pSrc), 0, 0);
}
/*
@@ -84154,27 +84560,37 @@ SQLITE_API sqlite3_backup *sqlite3_backup_init(
);
p = 0;
}else {
+ int nDest = sqlite3Strlen30(zDestDb);
+
/* Allocate space for a new sqlite3_backup object...
** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
** call to sqlite3_backup_init() and is destroyed by a call to
** sqlite3_backup_finish(). */
- p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
+ p = (sqlite3_backup*)sqlite3MallocZero(sizeof(sqlite3_backup)+nDest+1);
if( !p ){
sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT);
+ }else{
+ p->zDestDb = (char*)&p[1];
+ memcpy(p->zDestDb, zDestDb, nDest);
}
}
/* If the allocation succeeded, populate the new object. */
if( p ){
+ /* Do not store the pointer to the destination b-tree at this point.
+ ** This is because there is nothing preventing it from being detached
+ ** or otherwise freed before the first call to sqlite3_backup_step()
+ ** on this object. The source b-tree does not have this problem, as
+ ** incrementing Btree.nBackup (see below) effectively locks the object. */
+ Btree *pDest = findBtree(pDestDb, pDestDb, zDestDb);
p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
- p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
p->pDestDb = pDestDb;
p->pSrcDb = pSrcDb;
p->iNext = 1;
p->isAttached = 0;
- if( 0==p->pSrc || 0==p->pDest
- || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
+ if( 0==p->pSrc || 0==pDest
+ || checkReadTransaction(pDestDb, pDest)!=SQLITE_OK
){
/* One (or both) of the named databases did not exist or an OOM
** error was hit. Or there is a transaction open on the destination
@@ -84298,7 +84714,7 @@ static void attachBackupObject(sqlite3_backup *p){
*/
SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
int rc;
- int destMode; /* Destination journal mode */
+ int destMode = 0; /* Destination journal mode */
int pgszSrc = 0; /* Source page size */
int pgszDest = 0; /* Destination page size */
@@ -84314,7 +84730,8 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
rc = p->rc;
if( !isFatalError(rc) ){
Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
- Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
+ Btree * pDest = 0; /* Dest btree */
+ Pager * pDestPager = 0; /* Dest pager */
int ii; /* Iterator variable */
int nSrcPage = -1; /* Size of source db in pages */
int bCloseTrans = 0; /* True if src db requires unlocking */
@@ -84328,6 +84745,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
rc = SQLITE_OK;
}
+
/* If there is no open read-transaction on the source database, open
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
@@ -84337,34 +84755,48 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
bCloseTrans = 1;
}
+ /* Locate the destination btree and pager. */
+ if( (pDest = p->pDest)==0 ){
+ pDest = findBtree(p->pDestDb, p->pDestDb, p->zDestDb);
+ }
+ if( pDest==0 ){
+ rc = SQLITE_ERROR;
+ }else{
+ pDestPager = sqlite3BtreePager(pDest);
+ }
+
/* If the destination database has not yet been locked (i.e. if this
** is the first call to backup_step() for the current backup operation),
** try to set its page size to the same as the source database. This
** is especially important on ZipVFS systems, as in that case it is
** not possible to create a database file that uses one page size by
** writing to it with another. */
- if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
+ if( p->bDestLocked==0 && rc==SQLITE_OK
+ && setDestPgsz(pDest, p->pSrc)==SQLITE_NOMEM
+ ){
rc = SQLITE_NOMEM;
}
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
+ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(pDest, 2,
(int*)&p->iDestSchema))
){
p->bDestLocked = 1;
+ p->pDest = pDest;
}
/* Do not allow backup if the destination database is in WAL mode
** and the page sizes are different between source and destination */
- pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
- pgszDest = sqlite3BtreeGetPageSize(p->pDest);
- destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
- if( SQLITE_OK==rc
- && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
- && pgszSrc!=pgszDest
- ){
- rc = SQLITE_READONLY;
+ if( rc==SQLITE_OK ){
+ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
+ pgszDest = sqlite3BtreeGetPageSize(p->pDest);
+ destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
+ if( (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
+ && pgszSrc!=pgszDest
+ ){
+ rc = SQLITE_READONLY;
+ }
}
/* Now that there is a read-lock on the source database, query the
@@ -84582,7 +85014,9 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
}
/* If a transaction is still open on the Btree, roll it back. */
- sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
+ if( p->pDest ){
+ sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
+ }
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
@@ -84862,21 +85296,27 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
StrAccum acc;
assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) );
assert( sz>22 );
- if( p->flags & MEM_Int ){
-#if GCC_VERSION>=7000000
- /* Work-around for GCC bug
- ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */
+ if( p->flags & (MEM_Int|MEM_IntReal) ){
+#if GCC_VERSION>=7000000 && GCC_VERSION<15000000 && defined(__i386__)
+ /* Work-around for GCC bug or bugs:
+ ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270
+ ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659
+ ** The problem appears to be fixed in GCC 15 */
i64 x;
- assert( (p->flags&MEM_Int)*2==sizeof(x) );
- memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
+ assert( (sqlite3Config.bSmallMalloc!=0xee)*8==sizeof(x) );
+ memcpy(&x, (char*)&p->u.i, (sqlite3Config.bSmallMalloc!=0xee)*8);
p->n = sqlite3Int64ToText(x, zBuf);
#else
p->n = sqlite3Int64ToText(p->u.i, zBuf);
#endif
+ if( p->flags & MEM_IntReal ){
+ memcpy(zBuf+p->n,".0", 3);
+ p->n += 2;
+ }
}else{
sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
- sqlite3_str_appendf(&acc, "%!.15g",
- (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
+ sqlite3_str_appendf(&acc, "%!.*g",
+ (p->db ? p->db->nFpDigit : 17), p->u.r);
assert( acc.zText==zBuf && acc.mxAlloc<=0 );
zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
p->n = acc.nChar;
@@ -84925,6 +85365,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){
assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 );
}
if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1;
+ if( p->db==0 ){
+ return 1; /* db->nFpDigit required to validate p->z[] */
+ }
memcpy(&tmp, p, sizeof(tmp));
vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp);
z = p->z;
@@ -85075,13 +85518,16 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
**
** This is an optimization. Correct operation continues even if
** this routine is a no-op.
+**
+** Return true if the strig is zero-terminated after this routine is
+** called and false if it is not.
*/
-SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
+SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){
/* pMem must be a string, and it cannot be an ephemeral or static string */
- return;
+ return 0;
}
- if( pMem->enc!=SQLITE_UTF8 ) return;
+ if( pMem->enc!=SQLITE_UTF8 ) return 0;
assert( pMem->z!=0 );
if( pMem->flags & MEM_Dyn ){
if( pMem->xDel==sqlite3_free
@@ -85089,18 +85535,19 @@ SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
){
pMem->z[pMem->n] = 0;
pMem->flags |= MEM_Term;
- return;
+ return 1;
}
if( pMem->xDel==sqlite3RCStrUnref ){
/* Blindly assume that all RCStr objects are zero-terminated */
pMem->flags |= MEM_Term;
- return;
+ return 1;
}
}else if( pMem->szMalloc >= pMem->n+1 ){
pMem->z[pMem->n] = 0;
pMem->flags |= MEM_Term;
- return;
+ return 1;
}
+ return 0;
}
/*
@@ -85398,18 +85845,117 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){
}
}
+/*
+** This routine implements the uncommon and slower path for
+** sqlite3MemRealValueRC() that has to deal with input strings
+** that are not UTF8 or that are not zero-terminated. It is
+** broken out into a separate no-inline routine so that the
+** main sqlite3MemRealValueRC() routine can avoid unnecessary
+** stack pushes.
+**
+** A text->float translation of pMem->z is written into *pValue.
+**
+** Result code invariants:
+**
+** rc==0 => ERROR: Input string not well-formed, or OOM
+** rc<0 => Some prefix of the input is well-formed
+** rc>0 => All of the input is well-formed
+** (rc&2)==0 => The number is expressed as an integer, with no
+** decimal point or eNNN suffix.
+*/
+static SQLITE_NOINLINE int sqlite3MemRealValueRCSlowPath(
+ Mem *pMem,
+ double *pValue
+){
+ int rc = SQLITE_OK;
+ *pValue = 0.0;
+ if( pMem->enc==SQLITE_UTF8 ){
+ char *zCopy = sqlite3DbStrNDup(pMem->db, pMem->z, pMem->n);
+ if( zCopy ){
+ rc = sqlite3AtoF(zCopy, pValue);
+ sqlite3DbFree(pMem->db, zCopy);
+ }
+ return rc;
+ }else{
+ int n, i, j;
+ char *zCopy;
+ const char *z;
+
+ n = pMem->n & ~1;
+ zCopy = sqlite3DbMallocRaw(pMem->db, n/2 + 2);
+ if( zCopy ){
+ z = pMem->z;
+ if( pMem->enc==SQLITE_UTF16LE ){
+ for(i=j=0; idb, zCopy);
+ }
+ return rc;
+ }
+}
+
+/*
+** Invoke sqlite3AtoF() on the text value of pMem. Write the
+** translation of the text input into *pValue.
+**
+** The caller must ensure that pMem->db!=0 and that pMem is in
+** mode MEM_Str or MEM_Blob.
+**
+** Result code invariants:
+**
+** rc==0 => ERROR: Input string not well-formed, or OOM
+** rc<0 => Some prefix of the input is well-formed
+** rc>0 => All of the input is well-formed
+** (rc&2)==0 => The number is expressed as an integer, with no
+** decimal point or eNNN suffix.
+*/
+SQLITE_PRIVATE int sqlite3MemRealValueRC(Mem *pMem, double *pValue){
+ testcase( pMem->db==0 );
+ assert( pMem->flags & (MEM_Str|MEM_Blob) );
+ if( pMem->z==0 ){
+ *pValue = 0.0;
+ return 0;
+ }else if( pMem->enc==SQLITE_UTF8
+ && ((pMem->flags & MEM_Term)!=0 || sqlite3VdbeMemZeroTerminateIfAble(pMem))
+ ){
+ return sqlite3AtoF(pMem->z, pValue);
+ }else if( pMem->n==0 ){
+ *pValue = 0.0;
+ return 0;
+ }else{
+ return sqlite3MemRealValueRCSlowPath(pMem, pValue);
+ }
+}
+
+/*
+** This routine acts as a bridge from sqlite3VdbeRealValue() to
+** sqlite3VdbeRealValueRC, allowing sqlite3VdbeRealValue() to avoid
+** stuffing values onto the stack.
+*/
+static SQLITE_NOINLINE double sqlite3MemRealValueNoRC(Mem *pMem){
+ double r;
+ (void)sqlite3MemRealValueRC(pMem, &r);
+ return r;
+}
+
/*
** Return the best representation of pMem that we can get into a
** double. If pMem is already a double or an integer, return its
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
-static SQLITE_NOINLINE double memRealValue(Mem *pMem){
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- double val = (double)0;
- sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
- return val;
-}
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -85420,7 +85966,7 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
testcase( pMem->flags & MEM_IntReal );
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
- return memRealValue(pMem);
+ return sqlite3MemRealValueNoRC(pMem);
}else{
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return (double)0;
@@ -85544,8 +86090,8 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
- if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
+ rc = sqlite3MemRealValueRC(pMem, &pMem->u.r);
+ if( ((rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<2)
|| sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
){
pMem->u.i = ix;
@@ -86009,6 +86555,84 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
return SQLITE_OK;
}
+/* Like sqlite3VdbeMemSetStr() except:
+**
+** enc is always SQLITE_UTF8
+** pMem->db is always non-NULL
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemSetText(
+ Mem *pMem, /* Memory cell to set to string value */
+ const char *z, /* String pointer */
+ i64 n, /* Bytes in string, or negative */
+ void (*xDel)(void*) /* Destructor function */
+){
+ i64 nByte = n; /* New value for pMem->n */
+ u16 flags;
+
+ assert( pMem!=0 );
+ assert( pMem->db!=0 );
+ assert( sqlite3_mutex_held(pMem->db->mutex) );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
+
+ /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
+ if( !z ){
+ sqlite3VdbeMemSetNull(pMem);
+ return SQLITE_OK;
+ }
+
+ if( nByte<0 ){
+ nByte = strlen(z);
+ flags = MEM_Str|MEM_Term;
+ }else{
+ flags = MEM_Str;
+ }
+ if( nByte>(i64)pMem->db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( xDel && xDel!=SQLITE_TRANSIENT ){
+ if( xDel==SQLITE_DYNAMIC ){
+ sqlite3DbFree(pMem->db, (void*)z);
+ }else{
+ xDel((void*)z);
+ }
+ }
+ sqlite3VdbeMemSetNull(pMem);
+ return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
+ }
+
+ /* The following block sets the new values of Mem.z and Mem.xDel. It
+ ** also sets a flag in local variable "flags" to indicate the memory
+ ** management (one of MEM_Dyn or MEM_Static).
+ */
+ if( xDel==SQLITE_TRANSIENT ){
+ i64 nAlloc = nByte + 1;
+ testcase( nAlloc==31 );
+ testcase( nAlloc==32 );
+ if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
+ return SQLITE_NOMEM_BKPT;
+ }
+ assert( pMem->z!=0 );
+ memcpy(pMem->z, z, nByte);
+ pMem->z[nByte] = 0;
+ }else{
+ sqlite3VdbeMemRelease(pMem);
+ pMem->z = (char *)z;
+ if( xDel==SQLITE_DYNAMIC ){
+ pMem->zMalloc = pMem->z;
+ pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
+ pMem->xDel = 0;
+ }else if( xDel==SQLITE_STATIC ){
+ pMem->xDel = xDel;
+ flags |= MEM_Static;
+ }else{
+ pMem->xDel = xDel;
+ flags |= MEM_Dyn;
+ }
+ }
+ pMem->flags = flags;
+ pMem->n = (int)(nByte & 0x7fffffff);
+ pMem->enc = SQLITE_UTF8;
+ return SQLITE_OK;
+}
+
/*
** Move data out of a btree key or data field and into a Mem structure.
** The data is payload from the entry that pCur is currently pointing
@@ -86032,7 +86656,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
){
int rc;
pMem->flags = MEM_Null;
- if( sqlite3BtreeMaxRecordSize(pCur)=SQLITE_MAX_ALLOCATION_SIZE ){
+ return SQLITE_NOMEM_BKPT;
+ }
+ if( (u64)amt + (u64)offset > (u64)sqlite3BtreeMaxRecordSize(pCur) ){
return SQLITE_CORRUPT_BKPT;
}
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
@@ -86432,7 +87061,7 @@ static int valueFromExpr(
if( affinity==SQLITE_AFF_BLOB ){
if( op==TK_FLOAT ){
assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) );
- sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8);
+ sqlite3AtoF(pVal->z, &pVal->u.r);
pVal->flags = MEM_Real;
}else if( op==TK_INTEGER ){
/* This case is required by -9223372036854775808 and other strings
@@ -86542,7 +87171,30 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
u8 affinity, /* Affinity to use */
sqlite3_value **ppVal /* Write the new value here */
){
- return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
+ int rc = SQLITE_OK;
+ sqlite3_value *pVal = 0;
+ if( pExpr ){
+ rc = valueFromExpr(db, pExpr, enc, affinity, &pVal, 0);
+ if( rc==SQLITE_OK && pVal
+ && affinity==SQLITE_AFF_REAL
+ && (pVal->flags & MEM_Int)
+ && (pVal->u.i<-140737488355328LL || pVal->u.i>140737488355327LL)
+ ){
+ /* If the integer value is too large to fit in a 6-byte integer and
+ ** the affinity is REAL, convert it to a real value now. In most
+ ** cases an OP_RealAffinity opcode will be used to convert the
+ ** value to an actual real, but this opcode is omitted if the values
+ ** are being read directly from a table in order to create an index
+ ** key. It is important to get a "real" real value for the larger
+ ** magnitude integer values so that comparisons work correctly -
+ ** SQLite by default will convert real values to integers before
+ ** doing the comparison, which is different from converting to real
+ ** first. */
+ sqlite3VdbeMemRealify(pVal);
+ }
+ }
+ *ppVal = pVal;
+ return rc;
}
#ifdef SQLITE_ENABLE_STAT4
@@ -86587,7 +87239,7 @@ static int stat4ValueFromExpr(
}else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *v;
int iBindVar = pExpr->iColumn;
- sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
+ sqlite3VdbeReprepareOnBind(pParse->pVdbe, iBindVar, 0);
if( (v = pParse->pReprepare)!=0 ){
pVal = valueNew(db, pAlloc);
if( pVal ){
@@ -86700,6 +87352,11 @@ SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(
**
** If *ppVal is initially NULL then the caller is responsible for
** ensuring that the value written into *ppVal is eventually freed.
+**
+** If the buffer does not contain a well-formed record, this routine may
+** read several bytes past the end of the buffer. Callers must therefore
+** ensure that any buffer which may contain a corrupt record is padded
+** with at least 8 bytes of addressable memory.
*/
SQLITE_PRIVATE int sqlite3Stat4Column(
sqlite3 *db, /* Database handle */
@@ -86887,6 +87544,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlag
p->prepFlags = prepFlags;
if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){
p->expmask = 0;
+ p->smimask = 0;
}
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
@@ -86960,7 +87618,8 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
pA->zNormSql = pB->zNormSql;
pB->zNormSql = zTmp;
#endif
- pB->expmask = pA->expmask;
+ pB->expmask |= pA->expmask;
+ pB->smimask |= pA->smimask;
pB->prepFlags = pA->prepFlags;
memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++;
@@ -87179,6 +87838,20 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
return i;
}
+/* Generate an opcode that loads a 64-bit integer into register iDest
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddInt64(Vdbe *p, int iDest, i64 iVal){
+ return sqlite3VdbeAddOp3(p, OP_Int64, LOWER32(iVal), iDest, UPPER32(iVal));
+}
+
+/* Generate an opcode that loads a 64-floating point value into register iDest.
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddDouble(Vdbe *p, int iDest, double rVal){
+ i64 iVal;
+ memcpy(&iVal,&rVal,8);
+ return sqlite3VdbeAddOp3(p, OP_Real, LOWER32(iVal), iDest, UPPER32(iVal));
+}
+
/* Generate code for an unconditional jump to instruction iDest
*/
SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe *p, int iDest){
@@ -87282,24 +87955,6 @@ SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(
return addr;
}
-/*
-** Add an opcode that includes the p4 value with a P4_INT64 or
-** P4_REAL type.
-*/
-SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(
- Vdbe *p, /* Add the opcode to this VM */
- int op, /* The new opcode */
- int p1, /* The P1 operand */
- int p2, /* The P2 operand */
- int p3, /* The P3 operand */
- const u8 *zP4, /* The P4 operand */
- int p4type /* P4 operand type */
-){
- char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8);
- if( p4copy ) memcpy(p4copy, zP4, 8);
- return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
-}
-
#ifndef SQLITE_OMIT_EXPLAIN
/*
** Return the address of the current EXPLAIN QUERY PLAN baseline.
@@ -87371,11 +88026,21 @@ SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){
** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
** as having been used.
**
-** The zWhere string must have been obtained from sqlite3_malloc().
+** zWhere is a WHERE clause that defines which entries of the schema
+** to reparse. If zWhere==0, that means all entries. p5 is a mask
+** of INITFLAG_* values for the parse.
+**
+** In the current usage, the following are always true:
+**
+** ALTER TABLE: zWhere==0, p5!=0
+** Otherwise: zWhere!=0, p5==0
+**
+** The zWhere string must have been obtained from sqlite3DbMalloc().
** This routine will take ownership of the allocated memory.
*/
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
int j;
+ assert( p5==0 || zWhere==0 );
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
sqlite3VdbeChangeP5(p, p5);
for(j=0; jdb->nDb; j++) sqlite3VdbeUsesBtree(p, j);
@@ -87432,7 +88097,7 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse *pParse){
** a prior call to sqlite3VdbeMakeLabel().
*/
static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
- int nNewSize = 10 - p->nLabel;
+ int nNewSize = 25 - p->nLabel;
p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
nNewSize*sizeof(p->aLabel[0]));
if( p->aLabel==0 ){
@@ -87603,6 +88268,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|| opcode==OP_Function || opcode==OP_PureFunc
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
+ || (opcode==OP_MustBeInt && pOp->p2==0)
){
hasAbort = 1;
break;
@@ -88196,8 +88862,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
freeP4FuncCtx(db, (sqlite3_context*)p4);
break;
}
- case P4_REAL:
- case P4_INT64:
case P4_DYNAMIC:
case P4_INTARRAY: {
if( p4 ) sqlite3DbNNFreeNN(db, p4);
@@ -88551,6 +89215,9 @@ static int translateP(char c, const Op *pOp){
** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
+** "PINT13" -> int(P1|P3<<32)
+** "PDBL13" -> real(P1|P3<<32)
+** "PHEX23" -> hex(P2|P3<<32)
*/
SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
sqlite3 *db, /* Optional - Oom error reporting only */
@@ -88586,6 +89253,20 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
seenCom = 1;
break;
}
+ }else if( strncmp(&zSynopsis[ii],"INT13",5)==0 ){
+ sqlite3_str_appendf(&x,"%lld",INT32_TO_64(pOp->p1,pOp->p3));
+ ii += 4;
+#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
+ }else if( strncmp(&zSynopsis[ii],"HEX23",5)==0 ){
+ sqlite3_str_appendf(&x,"0x%llx",INT32_TO_64(pOp->p2,pOp->p3));
+ ii += 4;
+#endif
+ }else if( strncmp(&zSynopsis[ii],"DBL13",5)==0 ){
+ i64 iVal = INT32_TO_64(pOp->p1,pOp->p3);
+ double r;
+ memcpy(&r, &iVal, 8);
+ sqlite3_str_appendf(&x,"%.17g",r);
+ ii += 4;
}else{
int v1 = translateP(c, pOp);
int v2;
@@ -88715,7 +89396,6 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
#if VDBE_DISPLAY_P4
/*
** Compute a string that describes the P4 parameter for an opcode.
-** Use zTemp for any required temporary buffer space.
*/
SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
char *zP4 = 0;
@@ -88764,18 +89444,10 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
- case P4_INT64: {
- sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
- break;
- }
case P4_INT32: {
sqlite3_str_appendf(&x, "%d", pOp->p4.i);
break;
}
- case P4_REAL: {
- sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal);
- break;
- }
case P4_MEM: {
Mem *pMem = pOp->p4.pMem;
if( pMem->flags & MEM_Str ){
@@ -88818,6 +89490,10 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
zP4 = pOp->p4.pTab->zName;
break;
}
+ case P4_INDEX: {
+ zP4 = pOp->p4.pIdx->zName;
+ break;
+ }
case P4_SUBRTNSIG: {
SubrtnSig *pSig = pOp->p4.pSubrtnSig;
sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff);
@@ -89497,7 +90173,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
- x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
+ x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes unused memory */
assert( x.nFree>=0 );
assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
@@ -89716,7 +90392,7 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName(
}
assert( p->aColName!=0 );
pColName = &(p->aColName[idx+var*p->nResAlloc]);
- rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel);
+ rc = sqlite3VdbeMemSetText(pColName, zName, -1, xDel);
assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
return rc;
}
@@ -90860,67 +91536,16 @@ SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in){
}
#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */
-
-/* Input "x" is a sequence of unsigned characters that represent a
-** big-endian integer. Return the equivalent native integer
-*/
-#define ONE_BYTE_INT(x) ((i8)(x)[0])
-#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
-#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
-#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
-#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
-
/*
-** Deserialize the data blob pointed to by buf as serial type serial_type
-** and store the result in pMem.
-**
-** This function is implemented as two separate routines for performance.
-** The few cases that require local variables are broken out into a separate
-** routine so that in most cases the overhead of moving the stack pointer
-** is avoided.
+** Deserialize the REAL number pointed to by buf and store it in pMem.
*/
-static void serialGet(
+static int sqlite3VdbeSerialGet7(
const unsigned char *buf, /* Buffer to deserialize from */
- u32 serial_type, /* Serial type to deserialize */
Mem *pMem /* Memory cell to write value into */
){
- u64 x = FOUR_BYTE_UINT(buf);
- u32 y = FOUR_BYTE_UINT(buf+4);
- x = (x<<32) + y;
- if( serial_type==6 ){
- /* EVIDENCE-OF: R-29851-52272 Value is a big-endian 64-bit
- ** twos-complement integer. */
- pMem->u.i = *(i64*)&x;
- pMem->flags = MEM_Int;
- testcase( pMem->u.i<0 );
- }else{
- /* EVIDENCE-OF: R-57343-49114 Value is a big-endian IEEE 754-2008 64-bit
- ** floating point number. */
-#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
- /* Verify that integers and floating point values use the same
- ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
- ** defined that 64-bit floating point values really are mixed
- ** endian.
- */
- static const u64 t1 = ((u64)0x3ff00000)<<32;
- static const double r1 = 1.0;
- u64 t2 = t1;
- swapMixedEndianFloat(t2);
- assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
-#endif
- assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
- swapMixedEndianFloat(x);
- memcpy(&pMem->u.r, &x, sizeof(x));
- pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
- }
-}
-static int serialGet7(
- const unsigned char *buf, /* Buffer to deserialize from */
- Mem *pMem /* Memory cell to write value into */
-){
- u64 x = FOUR_BYTE_UINT(buf);
- u32 y = FOUR_BYTE_UINT(buf+4);
- x = (x<<32) + y;
+ /* EVIDENCE-OF: R-57343-49114 Value is a big-endian IEEE 754-2008 64-bit
+ ** floating point number. */
+ u64 x = sqlite3Get8byte(buf);
assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
swapMixedEndianFloat(x);
memcpy(&pMem->u.r, &x, sizeof(x));
@@ -90931,6 +91556,13 @@ static int serialGet7(
pMem->flags = MEM_Real;
return 0;
}
+
+/*
+** Deserialize the data blob pointed to by buf as serial type serial_type
+** and store the result in pMem.
+**
+** Similar code is found in the implementation of the OP_Column opcode.
+*/
SQLITE_PRIVATE void sqlite3VdbeSerialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
@@ -90989,16 +91621,21 @@ SQLITE_PRIVATE void sqlite3VdbeSerialGet(
case 5: { /* 6-byte signed integer */
/* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit
** twos-complement integer. */
- pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
+ pMem->u.i = SIX_BYTE_INT(buf);
+ pMem->flags = MEM_Int;
+ testcase( pMem->u.i<0 );
+ return;
+ }
+ case 6: { /* 8-byte signed integer */
+ /* EVIDENCE-OF: R-29851-52272 Value is a big-endian 64-bit
+ ** twos-complement integer. */
+ pMem->u.i = (i64)sqlite3Get8byte(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
return;
}
- case 6: /* 8-byte signed integer */
case 7: { /* IEEE floating point */
- /* These use local variables, so do them in a separate routine
- ** to avoid having to move the frame pointer in the common case */
- serialGet(buf,serial_type,pMem);
+ sqlite3VdbeSerialGet7(buf, pMem);
return;
}
case 8: /* Integer 0 */
@@ -91604,7 +92241,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else if( serial_type==7 ){
- serialGet7(&aKey1[d1], &mem1);
+ sqlite3VdbeSerialGet7(&aKey1[d1], &mem1);
rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
}else{
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
@@ -91630,7 +92267,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
rc = -1;
}else{
if( serial_type==7 ){
- if( serialGet7(&aKey1[d1], &mem1) ){
+ if( sqlite3VdbeSerialGet7(&aKey1[d1], &mem1) ){
rc = -1; /* mem1 is a NaN */
}else if( mem1.u.ru.r ){
rc = -1;
@@ -91712,7 +92349,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
serial_type = aKey1[idx1];
if( serial_type==0
|| serial_type==10
- || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0)
+ || (serial_type==7 && sqlite3VdbeSerialGet7(&aKey1[d1], &mem1)!=0)
){
assert( rc==0 );
}else{
@@ -91786,65 +92423,42 @@ static int vdbeRecordCompareInt(
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
int serial_type = ((const u8*)pKey1)[1];
int res;
- u32 y;
- u64 x;
i64 v;
i64 lhs;
vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
- switch( serial_type ){
- case 1: { /* 1-byte signed integer */
- lhs = ONE_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 2: { /* 2-byte signed integer */
- lhs = TWO_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 3: { /* 3-byte signed integer */
- lhs = THREE_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 4: { /* 4-byte signed integer */
- y = FOUR_BYTE_UINT(aKey);
- lhs = (i64)*(int*)&y;
- testcase( lhs<0 );
- break;
- }
- case 5: { /* 6-byte signed integer */
- lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
- testcase( lhs<0 );
- break;
- }
- case 6: { /* 8-byte signed integer */
- x = FOUR_BYTE_UINT(aKey);
- x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
- lhs = *(i64*)&x;
- testcase( lhs<0 );
- break;
- }
- case 8:
- lhs = 0;
- break;
- case 9:
- lhs = 1;
- break;
-
- /* This case could be removed without changing the results of running
- ** this code. Including it causes gcc to generate a faster switch
- ** statement (since the range of switch targets now starts at zero and
- ** is contiguous) but does not cause any duplicate code to be generated
- ** (as gcc is clever enough to combine the two like cases). Other
- ** compilers might be similar. */
- case 0: case 7:
- return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
- default:
- return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
+ /* Serial types 1 through 6 are big-endian integers of 1, 2, 3, 4,
+ ** 6, or 8 bytes. Rather than handle each width in its own switch
+ ** case, read 8 bytes and use an arithmetic right shift to drop the
+ ** unwanted low-order bytes and sign-extend the value. This helps
+ ** because the switch tends to mispredict when a key column contains
+ ** integers of varying sizes. The first entry of aShift[] is a
+ ** placeholder so that the table can be indexed by serial_type
+ ** directly. Reading 8 bytes is always safe, because a buffer passed
+ ** to this routine has at least 74 bytes of padding after it, as
+ ** explained in sqlite3VdbeFindCompare() below.
+ */
+ if( (u32)(serial_type-1)<=5 ){
+ static const u8 aShift[] = { 0, 56, 48, 40, 32, 16, 0 };
+ lhs = ((i64)sqlite3Get8byte(aKey)) >> aShift[serial_type];
+ /* ^^--- This shift operator
+ ** needs to be an arithmetic right-shift, which means that
+ ** if the left-hand operand (LHS) is negative, it will be sign-extended
+ ** so that the final results is also negative. All modern C
+ ** compilers work this way as long as the LHS is a signed integer
+ ** (which is why the unsigned result from sqlite3Get8byte() is cast
+ ** into i64), but it is not defined by the C standards, or so Claude
+ ** tells me. That the correct result is obtained is verified by the
+ ** following assert() and testcase() macros:
+ */
+ assert( 0<=(i64)sqlite3Get8byte(aKey) || lhs<0 );
+ testcase( lhs<0 );
+ }else if( serial_type==8 || serial_type==9 ){
+ lhs = serial_type - 8;
+ }else{
+ return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
}
assert( pPKey2->u.i == pPKey2->aMem[0].u.i );
@@ -91979,7 +92593,7 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
testcase( flags & MEM_Null );
testcase( flags & MEM_Blob );
if( (flags & (MEM_Real|MEM_IntReal|MEM_Null|MEM_Blob))==0
- && p->pKeyInfo->aColl[0]==0
+ && sqlite3IsBinary(p->pKeyInfo->aColl[0])
){
assert( flags & MEM_Str );
p->u.z = p->aMem[0].z;
@@ -92195,17 +92809,247 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
/*
** Configure SQL variable iVar so that binding a new value to it signals
** to sqlite3_reoptimize() that re-preparing the statement may result
-** in a better query plan.
+** in a better query plan. If parameter bSmallint is true, then the
+** statement is only re-prepared if the new value is integer value 0 or 1.
+**
+** The v->expmask bit is always set. expmask means that a reprepare is
+** possible. The v->smimask bit is only set if we want to restrict
+** reprepare when the value changes from (0,1) to something else, or from
+** something else to (0,1).
*/
-SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
+SQLITE_PRIVATE void sqlite3VdbeReprepareOnBind(Vdbe *v, int iVar, int bSmallint){
+ u32 m;
assert( iVar>0 );
assert( (v->db->flags & SQLITE_EnableQPSG)==0
|| (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
- if( iVar>=32 ){
- v->expmask |= 0x80000000;
+
+ m = (iVar>=32) ? 0x80000000 : ((u32)1 << (iVar-1));
+ if( bSmallint ){
+ if( (v->expmask & m)==0 ) v->smimask |= m;
}else{
- v->expmask |= ((u32)1 << (iVar-1));
+ v->smimask &= ~m;
}
+ v->expmask |= m;
+
+ /* smimask is always a subset of expmask */
+ assert( (v->smimask & v->expmask) == v->smimask );
+}
+
+/*
+** Helper function for vdbeIsMatchingIndexKey(). Return true if column
+** iCol should be ignored when comparing a record with a record from
+** an index on disk. The field should be ignored if:
+**
+** * the corresponding bit in mask is set, and
+** * either:
+** - bIntegrity is false, or
+** - the two Mem values are both real values that differ by
+** BTREE_ULPDISTORTION or fewer ULPs.
+*/
+static int vdbeSkipField(
+ Bitmask mask, /* Mask of indexed expression fields */
+ int iCol, /* Column of index being considered */
+ Mem *pMem1, /* Expected index value */
+ Mem *pMem2, /* Actual indexed value */
+ int bIntegrity /* True if running PRAGMA integrity_check */
+){
+#define BTREE_ULPDISTORTION 2
+ if( iCol>=BMS || (mask & MASKBIT(iCol))==0 ) return 0;
+ if( bIntegrity==0 ) return 1;
+ if( (pMem1->flags & MEM_Real) && (pMem2->flags & MEM_Real) ){
+ u64 m1, m2;
+ memcpy(&m1,&pMem1->u.r,8);
+ memcpy(&m2,&pMem2->u.r,8);
+ if( (m1pKeyInfo->enc;
+ m.db = p->pKeyInfo->db;
+ nRec = sqlite3BtreePayloadSize(pCur);
+ if( nRec>0x7fffffff ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ /* Allocate 5 extra bytes at the end of the buffer. This allows the
+ ** getVarint32() call below to read slightly past the end of the buffer
+ ** if the record is corrupt. */
+ aRec = sqlite3MallocZero(nRec+5);
+ if( aRec==0 ){
+ rc = SQLITE_NOMEM_BKPT;
+ }else{
+ rc = sqlite3BtreePayload(pCur, 0, nRec, aRec);
+ }
+
+ if( rc==SQLITE_OK ){
+ u32 szHdr = 0; /* Size of record header in bytes */
+ u32 idxHdr = 0; /* Current index in header */
+
+ idxHdr = getVarint32(aRec, szHdr);
+ if( szHdr>98307 ){
+ rc = SQLITE_CORRUPT;
+ }else{
+ int res = 0; /* Result of this function call */
+ u32 idxRec = szHdr; /* Index of next field in record body */
+ int ii = 0; /* Iterator variable */
+
+ int nCol = p->pKeyInfo->nAllField;
+ for(ii=0; ii=szHdr ){
+ rc = SQLITE_CORRUPT_BKPT;
+ break;
+ }
+ idxHdr += getVarint32(&aRec[idxHdr], iSerial);
+ nSerial = sqlite3VdbeSerialTypeLen(iSerial);
+ if( (idxRec+nSerial)>nRec ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ sqlite3VdbeSerialGet(&aRec[idxRec], iSerial, &m);
+ if( vdbeSkipField(mask, ii, &p->aMem[ii], &m, bInt)==0 ){
+ res = sqlite3MemCompare(&m, &p->aMem[ii], p->pKeyInfo->aColl[ii]);
+ if( res!=0 ) break;
+ }
+ }
+ idxRec += sqlite3VdbeSerialTypeLen(iSerial);
+ }
+
+ *piRes = res;
+ }
+ }
+
+ sqlite3_free(aRec);
+ return rc;
+}
+
+/*
+** This is called when the record in (*p) should be found in the index
+** opened by cursor pCur, but was not. This may happen as part of a DELETE
+** operation or an integrity check.
+**
+** One reason that an exact match was not found may be the EIIB bug - that
+** a text-to-float conversion may have caused a real value in record (*p)
+** to be slightly different from its counterpart on disk. This function
+** attempts to find the right index record. If it does find the right
+** record, it leaves *pCur pointing to it and sets (*pRes) to 0 before
+** returning. Otherwise, (*pRes) is set to non-zero and an SQLite error
+** code returned.
+**
+** The algorithm used to find the correct record is:
+**
+** * Scan up to BTREE_FDK_RANGE entries either side of the current entry.
+** If parameter bIntegrity is false, then all fields that are indexed
+** expressions or virtual table columns are omitted from the comparison.
+** If bIntegrity is true, then small differences in real values in
+** such fields are overlooked, but they are not omitted from the comparison
+** altogether.
+**
+** * If the above fails to find an entry and bIntegrity is false, search
+** the entire index.
+*/
+SQLITE_PRIVATE int sqlite3VdbeFindIndexKey(
+ BtCursor *pCur,
+ Index *pIdx,
+ UnpackedRecord *p,
+ int *pRes,
+ int bIntegrity
+){
+#define BTREE_FDK_RANGE 10
+ int nStep = 0;
+ int res = 1;
+ int rc = SQLITE_OK;
+ int ii = 0;
+
+ /* Calculate a mask based on the first 64 columns of the index. The mask
+ ** bit is set if the corresponding index field is either an expression
+ ** or a virtual column of the table. */
+ Bitmask mask = 0;
+ for(ii=0; iinColumn, BMS); ii++){
+ int iCol = pIdx->aiColumn[ii];
+ if( (iCol==XN_EXPR)
+ || (iCol>=0 && (pIdx->pTable->aCol[iCol].colFlags & COLFLAG_VIRTUAL))
+ ){
+ mask |= MASKBIT(ii);
+ }
+ }
+
+ /* If the mask is 0 at this point, then the index contains no expressions
+ ** or virtual columns. So do not search for a match - return so that the
+ ** caller may declare the db corrupt immediately. Or, if mask is non-zero,
+ ** proceed. */
+ if( mask!=0 ){
+
+ /* Move the cursor back BTREE_FDK_RANGE entries. If this hits an EOF,
+ ** position the cursor at the first entry in the index and set nStep
+ ** to -1 so that the first loop below scans the entire index. Otherwise,
+ ** set nStep to BTREE_FDK_RANGE*2 so that the first loop below scans
+ ** just that many entries. */
+ for(ii=0; sqlite3BtreeEof(pCur)==0 && ii=0), or the entire index if (nStep<0). */
+ while( sqlite3BtreeCursorIsValidNN(pCur) ){
+ for(ii=0; rc==SQLITE_OK && (iiexpired;
+ int iRet = 1;
+ if( pStmt ){
+ Vdbe *p = (Vdbe*)pStmt;
+ sqlite3_mutex_enter(p->db->mutex);
+ iRet = p->expired;
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return iRet;
}
#endif
@@ -92776,15 +93626,18 @@ SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){
/**************************** sqlite3_result_ *******************************
-** The following routines are used by user-defined functions to specify
-** the function result.
+** The following routines are used by application-defined SQL functions to
+** specify the function return value. There are many variations on
+** sqlite3_result_xxxx() for different types of return values.
**
-** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
-** result as a string or blob. Appropriate errors are set if the string/blob
-** is too big or if an OOM occurs.
+** The setStrOrError() function is a helper function that invokes
+** sqlite3VdbeMemSetStr() to store the result as a string or blob.
+** Appropriate errors are set if the string/blob is too big or if
+** an OOM occurs.
**
-** The invokeValueDestructor(P,X) routine invokes destructor function X()
-** on value P if P is not going to be used and need to be destroyed.
+** The invokeValueDestructor(P,X) helper function invokes the destructor
+** function X() on value P if P is not going to be used and need to
+** be destroyed.
*/
static void setResultStrOrError(
sqlite3_context *pCtx, /* Function context */
@@ -92794,7 +93647,23 @@ static void setResultStrOrError(
void (*xDel)(void*) /* Destructor function */
){
Mem *pOut = pCtx->pOut;
- int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
+ int rc;
+ if( enc==SQLITE_UTF8 ){
+ rc = sqlite3VdbeMemSetText(pOut, z, n, xDel);
+ }else if( enc==SQLITE_UTF8_ZT ){
+ /* It is usually considered improper to assert() on an input. However,
+ ** the following assert() is checking for inputs that are documented
+ ** to result in undefined behavior. */
+ assert( z==0
+ || n<0
+ || n>pOut->db->aLimit[SQLITE_LIMIT_LENGTH]
+ || z[n]==0
+ );
+ rc = sqlite3VdbeMemSetText(pOut, z, n, xDel);
+ pOut->flags |= MEM_Term;
+ }else{
+ rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
+ }
if( rc ){
if( rc==SQLITE_TOOBIG ){
sqlite3_result_error_toobig(pCtx);
@@ -92987,7 +93856,7 @@ SQLITE_API void sqlite3_result_text64(
#endif
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
- if( enc!=SQLITE_UTF8 ){
+ if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
n &= ~(u64)1;
}
@@ -93081,7 +93950,7 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
}
}
-/* Force an SQLITE_TOOBIG error. */
+/* Cause the SQL function to raise an SQLITE_TOOBIG error. */
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
#ifdef SQLITE_ENABLE_API_ARMOR
if( pCtx==0 ) return;
@@ -93092,7 +93961,7 @@ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
SQLITE_UTF8, SQLITE_STATIC);
}
-/* An SQLITE_NOMEM error. */
+/* Cause the SQL function to raise an SQLITE_NOMEM error. */
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
#ifdef SQLITE_ENABLE_API_ARMOR
if( pCtx==0 ) return;
@@ -93103,6 +93972,64 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
sqlite3OomFault(pCtx->pOut->db);
}
+/* Make the return value of the SQL function or virtual table pCtx
+** be the content of the sqlite3_str object pStr. The eOwn flag
+** determines ownership of the sqlite3_str object and its content.
+**
+** eOwn Ownership transfer
+** ------------- ------------------------------------------------
+**
+** SQLITE_COPY The SQL function returns a copy the sqlite3_str
+** content and leaves the sqlite3_str object itself
+** unchanged.
+**
+** SQLITE_XFER The content of the sqlite3_str is transferred to
+** the SQL function and the SQL function takes
+** responsibility for freeing that content when it is
+** no longer needed. The sqlite3_str object is reset
+** to an empty string.
+**
+** SQLITE_FINISH Like SQLITE_XFER except that the pStr is also
+** freed using sqlite3_str_free().
+*/
+SQLITE_API void sqlite3_result_str(sqlite3_context *pCtx, sqlite3_str *pStr, int eOwn){
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( pCtx==0 ) return;
+ if( pStr==0 ) return;
+#endif
+ testcase( pStr==(sqlite3_str*)&sqlite3OomStr );
+ if( pStr->accError==0 ){
+ if( pStr->nChar==0 ){
+ setResultStrOrError(pCtx, "", 0, SQLITE_UTF8_ZT, SQLITE_STATIC);
+ sqlite3_str_reset(pStr);
+ }else{
+ const char *zText = sqlite3_str_value(pStr);
+ /* Only internal code has the ability to capture a pointer to
+ ** an sqlite3_str object that uses static buffer. And none of
+ ** those internal use cases every invoke the sqlite3_result_str()
+ ** interface on a static-buffer sqlite3_str. Should this change
+ ** in the future, the following assert() will let us know. */
+ assert( isMalloced(pStr) );
+ if( eOwn==SQLITE_COPY ){
+ setResultStrOrError(pCtx, zText, pStr->nChar,
+ SQLITE_UTF8, SQLITE_TRANSIENT);
+ }else{
+ setResultStrOrError(pCtx, zText, pStr->nChar,
+ SQLITE_UTF8_ZT, SQLITE_DYNAMIC);
+ sqlite3StrAccumInit(pStr, pStr->db, 0, 0, pStr->mxAlloc);
+ }
+ }
+ }else if( pStr->accError==SQLITE_NOMEM ){
+ sqlite3_result_error_nomem(pCtx);
+ }else{
+ assert( pStr->accError==SQLITE_TOOBIG );
+ sqlite3_result_error_toobig(pCtx);
+ }
+ if( eOwn==SQLITE_FINISH ){
+ sqlite3_str_free(pStr);
+ }
+}
+
#ifndef SQLITE_UNTESTABLE
/* Force the INT64 value currently stored as the result to be
** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL
@@ -93138,6 +94065,8 @@ static int doWalCallbacks(sqlite3 *db){
}
}
}
+#else
+ UNUSED_PARAMETER(db);
#endif
return rc;
}
@@ -93445,7 +94374,7 @@ static int valueFromValueList(
Mem sMem; /* Raw content of current row */
memset(&sMem, 0, sizeof(sMem));
sz = sqlite3BtreePayloadSize(pRhs->pCsr);
- rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem);
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,sz,&sMem);
if( rc==SQLITE_OK ){
u8 *zBuf = (u8*)sMem.z;
u32 iSerial;
@@ -94053,10 +94982,8 @@ static int vdbeUnbind(Vdbe *p, unsigned int i){
sqlite3_mutex_leave(p->db->mutex);
return SQLITE_RANGE;
}
+
pVar = &p->aVar[i];
- sqlite3VdbeMemRelease(pVar);
- pVar->flags = MEM_Null;
- p->db->errCode = SQLITE_OK;
/* If the bit corresponding to this variable in Vdbe.expmask is set, then
** binding a new value to this variable invalidates the current query plan.
@@ -94068,9 +94995,22 @@ static int vdbeUnbind(Vdbe *p, unsigned int i){
** following any change to the bindings of that parameter.
*/
assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
+ assert( (p->expmask & p->smimask)==p->smimask );
if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<expired = 1;
+ /* If the p->smimask bit is also set, then only expire the statement if
+ ** the value being clobbered was integer value 0 or 1. */
+ if( (p->smimask==0)
+ || (p->smimask & (i>=31 ? 0x80000000 : (u32)1<flags & MEM_Int)!=0 && pVar->u.i>=0 && pVar->u.i<=1)
+ ){
+ p->expired = 1;
+ }
}
+
+ sqlite3VdbeMemRelease(pVar);
+ pVar->flags = MEM_Null;
+ p->db->errCode = SQLITE_OK;
+
return SQLITE_OK;
}
@@ -94094,13 +95034,25 @@ static int bindText(
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
if( zData!=0 ){
pVar = &p->aVar[i-1];
- rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
- if( rc==SQLITE_OK ){
- if( encoding==0 ){
- pVar->enc = ENC(p->db);
- }else{
- rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
- }
+ if( encoding==SQLITE_UTF8 ){
+ rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel);
+ }else if( encoding==SQLITE_UTF8_ZT ){
+ /* It is usually consider improper to assert() on an input.
+ ** However, the following assert() is checking for inputs
+ ** that are documented to result in undefined behavior. */
+ assert( zData==0
+ || nData<0
+ || nData>pVar->db->aLimit[SQLITE_LIMIT_LENGTH]
+ || ((u8*)zData)[nData]==0
+ );
+ rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel);
+ pVar->flags |= MEM_Term;
+ }else{
+ rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
+ if( encoding==0 ) pVar->enc = ENC(p->db);
+ }
+ if( rc==SQLITE_OK && encoding!=0 ){
+ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
if( rc ){
sqlite3Error(p->db, rc);
@@ -94155,15 +95107,46 @@ SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
return sqlite3_bind_int64(p, i, (i64)iValue);
}
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
- int rc;
- Vdbe *p = (Vdbe *)pStmt;
- rc = vdbeUnbind(p, (u32)(i-1));
- if( rc==SQLITE_OK ){
- assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
- sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
+ Mem *pVar;
+ Vdbe *p = (Vdbe*)pStmt;
+ if( vdbeSafetyNotNull(p) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ sqlite3_mutex_enter(p->db->mutex);
+ if( p->eVdbeState!=VDBE_READY_STATE ){
+ sqlite3Error(p->db, SQLITE_MISUSE_BKPT);
+ sqlite3_mutex_leave(p->db->mutex);
+ sqlite3_log(SQLITE_MISUSE,
+ "bind on a busy prepared statement: [%s]", p->zSql);
+ return SQLITE_MISUSE_BKPT;
+ }
+ if( i<=0 || (--i)>=p->nVar ){
+ sqlite3Error(p->db, SQLITE_RANGE);
sqlite3_mutex_leave(p->db->mutex);
+ return SQLITE_RANGE;
}
- return rc;
+ pVar = &p->aVar[i];
+ if( p->expmask!=0 ){
+ u32 expireMask = i>=32 ? 0x80000000 : (u32)1 << i;
+ assert( (p->expmask & p->smimask)==p->smimask );
+ if( (p->expmask & expireMask)!=0 ){
+ if( (p->smimask & expireMask)!=0 ){
+ /* If the smimask bit is set, only expire the prepared statement
+ ** if the value is changing to or from (0,1) and something else */
+ int sm1 = (pVar->flags & MEM_Int)!=0 && pVar->u.i>=0 && pVar->u.i<=1;
+ int sm2 = iValue>=0 && iValue<=1;
+ if( sm1!=sm2 ){
+ p->expired = 1;
+ }
+ }else if( (pVar->flags & MEM_Int)==0 || iValue!=pVar->u.i ){
+ /* Always expire if the smimask bit is clear */
+ p->expired = 1;
+ }
+ }
+ }
+ sqlite3VdbeMemSetInt64(pVar, iValue);
+ sqlite3_mutex_leave(p->db->mutex);
+ return SQLITE_OK;
}
SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
int rc;
@@ -94212,7 +95195,7 @@ SQLITE_API int sqlite3_bind_text64(
unsigned char enc
){
assert( xDel!=SQLITE_DYNAMIC );
- if( enc!=SQLITE_UTF8 ){
+ if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
nData &= ~(u64)1;
}
@@ -94787,6 +95770,11 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}else if( iStore>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
+ }else if( (p->pTab->aCol)
+ && (p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL)
+ && (pMem->flags & (MEM_Int|MEM_IntReal))
+ ){
+ sqlite3VdbeMemRealify(pMem);
}
}else{
/* For an UPDATE, memory cell (p->iNewReg+1+iStore) contains the required
@@ -95249,17 +96237,19 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
-/*
-** The following routine only works on Pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if !defined(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if defined(_MSC_VER) && defined(_WIN32)
+
+/* #include "windows.h" */
+ #include
- #if defined(__GNUC__)
+ __inline sqlite3_uint64 sqlite3Hwtime(void){
+ LARGE_INTEGER tm;
+ QueryPerformanceCounter(&tm);
+ return (sqlite3_uint64)tm.QuadPart;
+ }
+
+#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \
+ (defined(i586) || defined(__i586__) || defined(_M_IX86))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned int lo, hi;
@@ -95267,17 +96257,6 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
return (sqlite_uint64)hi << 32 | lo;
}
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
@@ -95286,6 +96265,14 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
return (sqlite_uint64)hi << 32 | lo;
}
+#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__aarch64__)
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ sqlite3_uint64 cnt;
+ __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (cnt));
+ return cnt;
+ }
+
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
@@ -95644,12 +96631,11 @@ static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
*/
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
double rValue;
- u8 enc = pRec->enc;
int rc;
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
- rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
+ rc = sqlite3MemRealValueRC(pRec, &rValue);
if( rc<=0 ) return;
- if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
+ if( (rc&2)==0 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
pRec->flags |= MEM_Int;
}else{
pRec->u.r = rValue;
@@ -95729,7 +96715,12 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
int eType = sqlite3_value_type(pVal);
if( eType==SQLITE_TEXT ){
Mem *pMem = (Mem*)pVal;
+#if SQLITE_THREADSAFE>0
+ sqlite3_mutex *pMutex = pMem->db ? pMem->db->mutex : 0;
+#endif
+ sqlite3_mutex_enter(pMutex);
applyNumericAffinity(pMem, 0);
+ sqlite3_mutex_leave(pMutex);
eType = sqlite3_value_type(pVal);
}
return eType;
@@ -95762,15 +96753,15 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
pMem->u.i = 0;
return MEM_Int;
}
- rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
+ rc = sqlite3MemRealValueRC(pMem, &pMem->u.r);
if( rc<=0 ){
- if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
+ if( (rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
pMem->u.i = ix;
return MEM_Int;
}else{
return MEM_Real;
}
- }else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){
+ }else if( (rc&2)==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){
pMem->u.i = ix;
return MEM_Int;
}
@@ -95975,6 +96966,10 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
/*
** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning
** with pOp->p3. Return the hash.
+**
+** IMPORTANT RESTRICTION (tag-202607231411): This hash is only valid if the
+** collating sequence for TEXT is BINARY. Hence, Bloom filters that use this
+** hash will not work for look-ups that use any other collating sequence.
*/
static u64 filterHash(const Mem *aMem, const Op *pOp){
int i, mx;
@@ -95987,17 +96982,33 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){
h += p->u.i;
}else if( p->flags & MEM_Real ){
h += sqlite3VdbeIntValue(p);
- }else if( p->flags & (MEM_Str|MEM_Blob) ){
- /* All strings have the same hash and all blobs have the same hash,
- ** though, at least, those hashes are different from each other and
- ** from NULL. */
- h += 4093 + (p->flags & (MEM_Str|MEM_Blob));
+ }else if( p->flags & MEM_Str ){
+ u64 x;
+ h += p->n;
+ if( p->n >= (int)sizeof(x) ){
+ memcpy(&x, p->z, sizeof(x));
+ h += x;
+ memcpy(&x, p->z + p->n - sizeof(x), sizeof(x));
+ h += x;
+ }else{
+ x = 0;
+ memcpy(&x, p->z, p->n);
+ h += x;
+ }
+ }else if( p->flags & MEM_Blob ){
+ int n = p->n;
+ u64 x = 0;
+ if( n ){
+ memcpy(&x, p->z, MIN(n, (int)sizeof(x)));
+ h += x;
+ }
+ h += n;
+ if( p->flags & MEM_Zero ) h += p->u.nZero;
}
}
return h;
}
-
/*
** For OP_Column, factor out the case where content is loaded from
** overflow pages, so that the code to implement this case is separate
@@ -96069,6 +97080,7 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow(
}else{
rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, 0,
sqlite3RCStrUnref);
+ pDest->enc = encoding;
}
}else{
rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, iOffset, len, pDest);
@@ -96083,6 +97095,40 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow(
return rc;
}
+/*
+** Memory cell pMem may contain a blob or a NULL value. Cursor pCsr is
+** open on an index. If the current index entry matches the blob value in
+** pMem byte-for-byte, set pMem to NULL and return 1. Otherwise, return 0.
+**
+** If an error occurs, set (*pRc) to an SQLite error code. Return 1 in this
+** case as well.
+*/
+static SQLITE_NOINLINE int vdbeIndexKeyCompare(
+ BtCursor *pCsr, /* Cursor to compare key to */
+ Mem *pMem,
+ int *pRc
+){
+ int ret = 0;
+ u32 nKey = 0;
+
+ assert( pMem->flags & (MEM_Blob|MEM_Null) );
+ nKey = sqlite3BtreePayloadSize(pCsr);
+ if( nKey==(u32)pMem->n && ALWAYS((pMem->flags & MEM_Blob)!=0) ){
+ /* This code could just use sqlite3BtreePayloadFetch(). But calling that
+ ** function here apparently prevents compilers from inlining it in other,
+ ** more performance critical, places. So this code uses
+ ** MemFromBtreeZeroOffset(), which is just as fast in most cases, but also
+ ** handles the case where the index record uses overflow pages. */
+ Mem m;
+ memset(&m, 0, sizeof(m));
+ *pRc = sqlite3VdbeMemFromBtreeZeroOffset(pCsr, nKey, &m);
+ ret = (*pRc!=SQLITE_OK || 0==memcmp(pMem->z, m.z, nKey));
+ sqlite3VdbeMemReleaseMalloc(&m);
+ }
+
+ return ret;
+}
+
/*
** Send a "statement aborts" message to the error log.
*/
@@ -96663,31 +97709,35 @@ case OP_Integer: { /* out2 */
break;
}
-/* Opcode: Int64 * P2 * P4 *
-** Synopsis: r[P2]=P4
+/* Opcode: Int64 P1 P2 P3 * *
+** Synopsis: r[P2]=PINT13
**
-** P4 is a pointer to a 64-bit integer value.
-** Write that value into register P2.
+** Combine P1 and P3 into a signed 64-bit integer. P1 is the least
+** significant 32 bits and P3 is the most significant. Store the
+** result in register P2.
*/
case OP_Int64: { /* out2 */
pOut = out2Prerelease(p, pOp);
- assert( pOp->p4.pI64!=0 );
- pOut->u.i = *pOp->p4.pI64;
+ pOut->u.i = INT32_TO_64(pOp->p1,pOp->p3);
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
-/* Opcode: Real * P2 * P4 *
-** Synopsis: r[P2]=P4
+/* Opcode: Real P1 P2 P3 * *
+** Synopsis: r[P2]=PDBL13
**
-** P4 is a pointer to a 64-bit floating point value.
-** Write that value into register P2.
+** P1 and P3 are combined to 64 bits with P1 being the lower the P3
+** the upper. The result is interpreted as a 64-bit floating-point
+** and stored in register P2.
*/
case OP_Real: { /* same as TK_FLOAT, out2 */
+ u64 ii;
pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Real;
- assert( !sqlite3IsNaN(*pOp->p4.pReal) );
- pOut->u.r = *pOp->p4.pReal;
+ ii = (u64)INT32_TO_64(pOp->p1,pOp->p3);
+ swapMixedEndianFloat(ii);
+ memcpy(&pOut->u.r, &ii, 8);
+ assert( !sqlite3IsNaN(pOut->u.r) );
break;
}
#endif
@@ -97394,7 +98444,18 @@ case OP_AddImm: { /* in1 */
case OP_MustBeInt: { /* jump0, in1 */
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Int)==0 ){
- applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
+ if( (pIn1->flags & MEM_Real)!=0 ){
+ sqlite3_int64 ix;
+ if( pIn1->u.r>=-9223372036854775808.0
+ && pIn1->u.r<+9223372036854775808.0
+ && (double)(ix = sqlite3RealToI64(pIn1->u.r))==pIn1->u.r
+ ){
+ pIn1->u.i = ix;
+ MemSetTypeFlag(pIn1, MEM_Int);
+ }
+ }else{
+ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
+ }
if( (pIn1->flags & MEM_Int)==0 ){
VdbeBranchTaken(1, 2);
if( pOp->p2==0 ){
@@ -98480,30 +99541,91 @@ case OP_Column: { /* ncycle */
assert( t==pC->aType[p2] );
if( pC->szRow>=aOffset[p2+1] ){
/* This is the common case where the desired content fits on the original
- ** page - where the content is not on an overflow page */
+ ** page - where the content is not on an overflow page.
+ **
+ ** The big switch() is an in-line variant of sqlite3VdbeSerialGet() that
+ ** has been optimized for the OP_Column opcode.
+ */
zData = pC->aRow + aOffset[p2];
- if( t<12 ){
- sqlite3VdbeSerialGet(zData, t, pDest);
- }else{
- /* If the column value is a string, we need a persistent value, not
- ** a MEM_Ephem value. This branch is a fast short-cut that is equivalent
- ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize().
- */
- static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
- pDest->n = len = (t-12)/2;
- pDest->enc = encoding;
- if( pDest->szMalloc < len+2 ){
- if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big;
+ switch( t ){
+ case 0:
+ case 11:
pDest->flags = MEM_Null;
- if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
- }else{
- pDest->z = pDest->zMalloc;
+ break;
+ case 1:
+ pDest->u.i = ONE_BYTE_INT(zData);
+ pDest->flags = MEM_Int;
+ testcase( pDest->u.i<0 );
+ break;
+ case 2:
+ pDest->u.i = TWO_BYTE_INT(zData);
+ pDest->flags = MEM_Int;
+ testcase( pDest->u.i<0 );
+ break;
+ case 3:
+ pDest->u.i = THREE_BYTE_INT(zData);
+ pDest->flags = MEM_Int;
+ testcase( pDest->u.i<0 );
+ break;
+ case 4:
+ pDest->u.i = FOUR_BYTE_INT(zData);
+ pDest->flags = MEM_Int;
+ testcase( pDest->u.i<0 );
+ break;
+ case 5:
+ pDest->u.i = SIX_BYTE_INT(zData);
+ pDest->flags = MEM_Int;
+ testcase( pDest->u.i<0 );
+ break;
+ case 6: {
+ pDest->u.i = (i64)sqlite3Get8byte(zData);
+ pDest->flags = MEM_Int;
+ testcase( pDest->u.i<0 );
+ break;
}
- memcpy(pDest->z, zData, len);
- pDest->z[len] = 0;
- pDest->z[len+1] = 0;
- pDest->flags = aFlag[t&1];
- }
+ case 7: {
+ u64 x = sqlite3Get8byte(zData);
+ swapMixedEndianFloat(x);
+ pDest->flags = IsNaN(x) ? MEM_Null : MEM_Real;
+ memcpy(&pDest->u.r, &x, sizeof(x));
+ testcase( pDest->u.r<0 );
+ break;
+ }
+ case 8:
+ case 9: {
+ pDest->u.i = t-8;
+ pDest->flags = MEM_Int;
+ break;
+ }
+ case 10:
+ /* Internal use only: NULL with virtual table
+ ** UPDATE no-change flag set */
+ pDest->flags = MEM_Null|MEM_Zero;
+ pDest->u.nZero = 0;
+ pDest->n = 0;
+ break;
+ default: {
+ /* If the column value is a string or blob, we need a persistent
+ ** value, not a MEM_Ephem value. This case is a fast short-cut
+ ** that is equivalent to calling sqlite3VdbeSerialGet() and
+ ** sqlite3VdbeDeephemeralize().
+ */
+ static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
+ pDest->n = len = (t-12)/2;
+ pDest->enc = encoding;
+ if( pDest->szMalloc < len+2 ){
+ if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big;
+ pDest->flags = MEM_Null;
+ if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
+ }else{
+ pDest->z = pDest->zMalloc;
+ }
+ memcpy(pDest->z, zData, len);
+ pDest->z[len] = 0;
+ pDest->z[len+1] = 0;
+ pDest->flags = aFlag[t&1];
+ }
+ } /* End of switch */
}else{
u8 p5;
pDest->enc = encoding;
@@ -98703,22 +99825,9 @@ case OP_Affinity: {
assert( zAffinity[0]==SQLITE_AFF_NONE || memIsValid(pIn1) );
applyAffinity(pIn1, zAffinity[0], encoding);
if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){
- /* When applying REAL affinity, if the result is still an MEM_Int
- ** that will fit in 6 bytes, then change the type to MEM_IntReal
- ** so that we keep the high-resolution integer value but know that
- ** the type really wants to be REAL. */
- testcase( pIn1->u.i==140737488355328LL );
- testcase( pIn1->u.i==140737488355327LL );
- testcase( pIn1->u.i==-140737488355328LL );
- testcase( pIn1->u.i==-140737488355329LL );
- if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){
- pIn1->flags |= MEM_IntReal;
- pIn1->flags &= ~MEM_Int;
- }else{
- pIn1->u.r = (double)pIn1->u.i;
- pIn1->flags |= MEM_Real;
- pIn1->flags &= ~(MEM_Int|MEM_Str);
- }
+ pIn1->u.r = (double)pIn1->u.i;
+ pIn1->flags |= MEM_Real;
+ pIn1->flags &= ~(MEM_Int|MEM_Str);
}
REGISTER_TRACE((int)(pIn1-aMem), pIn1);
zAffinity++;
@@ -98971,12 +100080,24 @@ case OP_MakeRecord: {
}
nByte = nHdr+nData;
+ /* If we are able to put an over-run area of 7 bytes on the end of the
+ ** memory allocation into which the record is being constructed, then
+ ** the encoding of integer values can go faster. This is only possible
+ ** if SQLITE_MAX_LENGTH is no with 7 of INT32_MAX and if the host CPU
+ ** byte-order is known at compile-time.
+ */
+#if SQLITE_MAX_LENGTH<=2147483640 && SQLITE_BYTEORDER>0
+# define OVERRUN 7 /* We are able to allocate an overrun of 7 bytes */
+#else
+# define OVERRUN 0 /* No overrun will be available */
+#endif
+
/* Make sure the output register has a buffer large enough to store
** the new record. The output register (pOp->p3) is not allowed to
** be one of the input registers (because the following call to
** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
*/
- if( nByte+nZero<=pOut->szMalloc ){
+ if( nByte+nZero<=pOut->szMalloc-OVERRUN ){
/* The output register is already large enough to hold the record.
** No error checks or buffer enlargement is required */
pOut->z = pOut->zMalloc;
@@ -98986,7 +100107,7 @@ case OP_MakeRecord: {
if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
+ if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte+OVERRUN) ){
goto no_mem;
}
}
@@ -99029,6 +100150,27 @@ case OP_MakeRecord: {
}
len = sqlite3SmallTypeSizes[serial_type];
assert( len>=1 && len<=8 && len!=5 && len!=7 );
+#if SQLITE_BYTEORDER==1234
+ v = sqlite3BSwap64(v);
+ if( OVERRUN ){
+ static const u8 aShift[] = { 0, 56, 48, 40, 32, 16, 0, 0 };
+ v >>= aShift[serial_type];
+ memcpy(zPayload, &v, 8);
+ }else{
+ /* Test this limb by compiling with -DSQLITE_MAX_LENGTH=2147483647 */
+ memcpy(zPayload, (u8*)&v + 8 - len, len);
+ }
+#elif SQLITE_BYTEORDER==4321
+ if( OVERRUN ){
+ static const u8 aShift[] = { 0, 56, 48, 40, 32, 16, 0, 0 };
+ v <<= aShift[serial_type];
+ memcpy(zPayload, &v, 8);
+ }else{
+ /* Test this limb by compiling with -DSQLITE_MAX_LENGTH=2147483647 */
+ memcpy(zPayload, (u8*)&v + 8 - len, len);
+ }
+#else
+ /* Test this limb by compiling with -DSQLITE_BYTEORDER=0 */
switch( len ){
default: zPayload[7] = (u8)(v&0xff); v >>= 8;
zPayload[6] = (u8)(v&0xff); v >>= 8;
@@ -99044,6 +100186,8 @@ case OP_MakeRecord: {
/* no break */ deliberate_fall_through
case 1: zPayload[0] = (u8)(v&0xff);
}
+#endif
+#undef OVERRUN /* We are done with the OVERRUN macro now */
zPayload += len;
}
}else if( serial_type<0x80 ){
@@ -100001,21 +101145,21 @@ case OP_Close: { /* ncycle */
}
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
-/* Opcode: ColumnsUsed P1 * * P4 *
+/* Opcode: ColumnsUsed P1 P2 P3 * *
+** Synopsis: Cursor P1 uses columns PHEX23
**
** This opcode (which only exists if SQLite was compiled with
** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the
-** table or index for cursor P1 are used. P4 is a 64-bit integer
-** (P4_INT64) in which the first 63 bits are one for each of the
-** first 63 columns of the table or index that are actually used
-** by the cursor. The high-order bit is set if any column after
-** the 64th is used.
+** table or index for cursor P1 are used. P2 and P3 combine to give
+** a 64-bit unsigned integer mask. P2 stores the lower 32 bits and
+** P3 stores the upper 32 bits. If the high-order bit of P3 is set
+** that means that and 64-th or some later column is used.
*/
case OP_ColumnsUsed: {
VdbeCursor *pC;
pC = p->apCsr[pOp->p1];
assert( pC->eCurType==CURTYPE_BTREE );
- pC->maskUsed = *(u64*)pOp->p4.pI64;
+ pC->maskUsed = INT32_TO_64(pOp->p2,pOp->p3);
break;
}
#endif
@@ -100526,24 +101670,6 @@ case OP_SeekHit: { /* ncycle */
break;
}
-/* Opcode: IfNotOpen P1 P2 * * *
-** Synopsis: if( !csr[P1] ) goto P2
-**
-** If cursor P1 is not open or if P1 is set to a NULL row using the
-** OP_NullRow opcode, then jump to instruction P2. Otherwise, fall through.
-*/
-case OP_IfNotOpen: { /* jump */
- VdbeCursor *pCur;
-
- assert( pOp->p1>=0 && pOp->p1nCursor );
- pCur = p->apCsr[pOp->p1];
- VdbeBranchTaken(pCur==0 || pCur->nullRow, 2);
- if( pCur==0 || pCur->nullRow ){
- goto jump_to_p2_and_check_for_interrupt;
- }
- break;
-}
-
/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
@@ -100785,7 +101911,7 @@ case OP_SeekRowid: { /* jump0, in3, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
- u64 iKey;
+ i64 iKey;
pIn3 = &aMem[pOp->p3];
testcase( pIn3->flags & MEM_Int );
@@ -100799,9 +101925,21 @@ case OP_SeekRowid: { /* jump0, in3, ncycle */
** changing the datatype of pIn3, however, as it is used by other
** parts of the prepared statement. */
Mem x = pIn3[0];
- applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding);
- if( (x.flags & MEM_Int)==0 ) goto jump_to_p2;
- iKey = x.u.i;
+ if( x.flags & MEM_Str ){
+ applyNumericAffinity(&x, 1);
+ }
+ if( x.flags & MEM_Int ){
+ iKey = x.u.i;
+ }else
+ if( (x.flags & MEM_Real)==0
+ || x.u.r < -9223372036854775808.0
+ || x.u.r > 9223372036854774784.0
+ /* ^^^^^^^^^^^^^^^^^^^^^-- same value as every other double
+ ** between 9223372036854774263.0 and 923372036854775295.0 */
+ || (double)(iKey = sqlite3RealToI64(x.u.r))!=x.u.r
+ ){
+ goto jump_to_p2;
+ }
goto notExistsWithKey;
}
/* Fall through into OP_NotExists */
@@ -101481,14 +102619,17 @@ case OP_Rowid: { /* out2, ncycle */
break;
}
-/* Opcode: NullRow P1 * * * *
+/* Opcode: NullRow P1 P2 * * *
**
-** Move the cursor P1 to a null row. Any OP_Column operations
+** Move the cursor P1 to a null row if P2 is 0. Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
**
** If cursor P1 is not previously opened, open it now to a special
** pseudo-cursor that always returns NULL for every column.
+**
+** If P2 is not 0, then the nullRow flag on the pseudo-cursor is
+** turned off.
*/
case OP_NullRow: {
VdbeCursor *pC;
@@ -101505,7 +102646,7 @@ case OP_NullRow: {
pC->noReuse = 1;
pC->uc.pCursor = sqlite3BtreeFakeValidCursor();
}
- pC->nullRow = 1;
+ pC->nullRow = (pOp->p2==0);
pC->cacheStatus = CACHE_STALE;
if( pC->eCurType==CURTYPE_BTREE ){
assert( pC->uc.pCursor!=0 );
@@ -101911,20 +103052,22 @@ case OP_SorterInsert: { /* in2 */
break;
}
-/* Opcode: IdxDelete P1 P2 P3 * P5
-** Synopsis: key=r[P2@P3]
+/* Opcode: IdxDelete P1 P2 P3 P4 P5
+** Synopsis: key=r[P2@P5]
**
-** The content of P3 registers starting at register P2 form
+** The content of P5 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
**
-** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
-** if no matching index entry is found. This happens when running
-** an UPDATE or DELETE statement and the index entry to be updated
-** or deleted is not found. For some uses of IdxDelete
-** (example: the EXCEPT operator) it does not matter that no matching
-** entry is found. For those cases, P5 is zero. Also, do not raise
-** this (self-correcting and non-critical) error if in writable_schema mode.
+** P4 is a pointer to an Index structure.
+**
+** If P3 is non-zero, it is the register number of a register holding
+** a record that will be inserted into this index. If that record is
+** identical to the one that would be deleted by this instruction,
+** skip the delete and set register P3 to NULL.
+**
+** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
+** and not in writable_schema mode.
*/
case OP_IdxDelete: {
VdbeCursor *pC;
@@ -101932,8 +103075,8 @@ case OP_IdxDelete: {
int res;
UnpackedRecord r;
- assert( pOp->p3>0 );
- assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
+ assert( pOp->p5>0 );
+ assert( pOp->p2>0 && pOp->p2+pOp->p5<=(p->nMem+1 - p->nCursor)+1 );
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
@@ -101942,18 +103085,34 @@ case OP_IdxDelete: {
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
r.pKeyInfo = pC->pKeyInfo;
- r.nField = (u16)pOp->p3;
+ r.nField = pOp->p5;
r.default_rc = 0;
r.aMem = &aMem[pOp->p2];
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
if( rc ) goto abort_due_to_error;
- if( res==0 ){
- rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
+ if( res!=0 ){
+ rc = sqlite3VdbeFindIndexKey(pCrsr, pOp->p4.pIdx, &r, &res, 0);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ if( res!=0 ){
+ if( !sqlite3WritableSchema(db) ){
+ rc = sqlite3ReportError(
+ SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
+ goto abort_due_to_error;
+ }
+ pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = 0;
+ break;
+ }
+ }
+
+ if( pOp->p3 && vdbeIndexKeyCompare(pCrsr, &aMem[pOp->p3], &rc) ){
if( rc ) goto abort_due_to_error;
- }else if( pOp->p5 && !sqlite3WritableSchema(db) ){
- rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
- goto abort_due_to_error;
+ sqlite3VdbeMemSetNull(&aMem[pOp->p3]);
+ break;
}
+
+ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
+ if( rc ) goto abort_due_to_error;
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
pC->seekResult = 0;
@@ -102025,6 +103184,11 @@ case OP_IdxRowid: { /* out2, ncycle */
assert( pTabCur->eCurType==CURTYPE_BTREE );
assert( pTabCur->uc.pCursor!=0 );
assert( pTabCur->isTable );
+#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
+ assert(
+ sqlite3BtreeCursorHintTblCsr(pC->uc.pCursor)==pTabCur->uc.pCursor
+ );
+#endif
pTabCur->nullRow = 0;
pTabCur->movetoTarget = rowid;
pTabCur->deferredMoveto = 1;
@@ -102385,12 +103549,19 @@ case OP_SqlExec: {
break;
}
-/* Opcode: ParseSchema P1 * * P4 *
+/* Opcode: ParseSchema P1 * * P4 P5
**
** Read and parse all entries from the schema table of database P1
** that match the WHERE clause P4. If P4 is a NULL pointer, then the
** entire schema for P1 is reparsed.
**
+** When P4 is NULL, the P5 value is used as the mFlags argument
+** to sqlite3InitOne(). In other words, P5 should be a mask composed
+** of INITFLAG_* values.
+**
+** The P4==0 case is only used by ALTER TABLE and P5!=0 for all such
+** cases. For uses other than ALTER TABLE, P4<>0 and P5==0.
+**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine. It is thus a re-entrant opcode.
*/
@@ -102418,6 +103589,7 @@ case OP_ParseSchema: {
#ifndef SQLITE_OMIT_ALTERTABLE
if( pOp->p4.z==0 ){
+ assert( pOp->p5!=0 );
sqlite3SchemaClear(db->aDb[iDb].pSchema);
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
@@ -102426,6 +103598,7 @@ case OP_ParseSchema: {
}else
#endif
{
+ assert( pOp->p5==0 );
zSchema = LEGACY_SCHEMA_TABLE;
initData.db = db;
initData.iDb = iDb;
@@ -102580,6 +103753,58 @@ case OP_IntegrityCk: {
sqlite3VdbeChangeEncoding(pIn1, encoding);
goto check_for_interrupt;
}
+
+/* Opcode: IFindKey P1 P2 P3 P4 *
+**
+** This instruction always follows an OP_Found with the same P1, P2 and P3
+** values as this instruction and a non-zero P4 value. The P4 value to
+** this opcode is of type P4_INDEX and contains a pointer to the Index
+** object of for the index being searched.
+**
+** This opcode uses sqlite3VdbeFindIndexKey() to search around the current
+** cursor location for an index key that exactly matches all fields that
+** are not indexed expressions or references to VIRTUAL generated columns,
+** and either exactly match or are real numbers that are within 2 ULPs of
+** each other if the don't match.
+**
+** To put it another way, this opcode looks for nearby index entries that
+** are very close to the search key, but which might have small differences
+** in floating-point values that come via an expression.
+**
+** If no nearby alternative entry is found in cursor P1, then jump to P2.
+** But if a close match is found, fall through.
+**
+** This opcode is used by PRAGMA integrity_check to help distinguish
+** between truely corrupt indexes and expression indexes that are holding
+** floating-point values that are off by one or two ULPs.
+*/
+case OP_IFindKey: { /* jump, in3 */
+ VdbeCursor *pC;
+ int res;
+ UnpackedRecord r;
+
+ assert( pOp[-1].opcode==OP_Found );
+ assert( pOp[-1].p1==pOp->p1 );
+ assert( pOp[-1].p3==pOp->p3 );
+ pC = p->apCsr[pOp->p1];
+ assert( pOp->p4type==P4_INDEX );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ assert( pC->uc.pCursor!=0 );
+ assert( pC->isTable==0 );
+
+ memset(&r, 0, sizeof(r));
+ r.aMem = &aMem[pOp->p3];
+ r.nField = pOp->p4.pIdx->nColumn;
+ r.pKeyInfo = pC->pKeyInfo;
+
+ rc = sqlite3VdbeFindIndexKey(pC->uc.pCursor, pOp->p4.pIdx, &r, &res, 1);
+ if( rc || res!=0 ){
+ rc = SQLITE_OK;
+ goto jump_to_p2;
+ }
+ pC->nullRow = 0;
+ break;
+};
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
/* Opcode: RowSetAdd P1 P2 * * *
@@ -102735,7 +103960,7 @@ case OP_Program: { /* jump0 */
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
rc = SQLITE_ERROR;
- sqlite3VdbeError(p, "too many levels of trigger recursion");
+ sqlite3VdbeError(p, "triggers nested too deep");
goto abort_due_to_error;
}
@@ -104346,23 +105571,37 @@ case OP_Init: { /* jump0 */
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
-/* Opcode: CursorHint P1 * * P4 *
+/* Opcode: CursorHint P1 * P3 P4 *
**
-** Provide a hint to cursor P1 that it only needs to return rows that
-** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer
-** to values currently held in registers. TK_COLUMN terms in the P4
+** Provide a hint to cursor P1.
+**
+** If P4 is of type P4_EXPR, then the hint is that the cursor need only return
+** rows that satisfy the Expr in P4. TK_REGISTER terms in the P4 expression
+** refer to values currently held in registers. TK_COLUMN terms in the P4
** expression refer to columns in the b-tree to which cursor P1 is pointing.
+** P3 is ignore in this case.
+**
+** Or, if P4 is P4_NOTUSED, then the hint is that cursor P1 is an index cursor
+** used to drive table cursor P3. In other words, that this VM may execute
+** OP_DeferredSeek instructions to lazily position P3 based on current
+** position of P1.
*/
case OP_CursorHint: {
VdbeCursor *pC;
+ pC = p->apCsr[pOp->p1];
assert( pOp->p1>=0 && pOp->p1nCursor );
- assert( pOp->p4type==P4_EXPR );
- pC = p->apCsr[pOp->p1];
+
if( pC ){
assert( pC->eCurType==CURTYPE_BTREE );
- sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE,
- pOp->p4.pExpr, aMem);
+ if( pOp->p4type==P4_EXPR ){
+ sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE,
+ pOp->p4.pExpr, aMem);
+ }else if( p->apCsr[pOp->p3] ){
+ sqlite3BtreeCursorHint(
+ pC->uc.pCursor, BTREE_HINT_TABLECURSOR, p->apCsr[pOp->p3]->uc.pCursor
+ );
+ }
}
break;
}
@@ -105494,6 +106733,7 @@ struct VdbeSorter {
#define SORTER_TYPE_INTEGER 0x01
#define SORTER_TYPE_TEXT 0x02
+#define SORTER_TYPE_REAL 0x04
/*
** An instance of the following object is used to read records out of a
@@ -106067,6 +107307,150 @@ static int vdbeSorterCompareInt(
return res;
}
+/* Helper function for vdbeSorterCompareReal().
+**
+** The first elements of both pKey1 and pKey2 have been decoded into double
+** values r1 and r2. Do the comparison between those keys and return the
+** result. If r1==r2, break the tie with a comparison of subsequent elements
+** from each key.
+*/
+static int vdbeSorterFinishRealCompare(
+ SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
+ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
+ const void *pKey1, int nKey1, /* Left side of comparison */
+ const void *pKey2, int nKey2, /* Right side of comparison */
+ double r1, /* REAL value of first element of pKey1 */
+ double r2 /* REAL value of first element of pKey2 */
+){
+ int res;
+ if( r1r2 ){
+ res = +1;
+ }else{
+ res = 0;
+ }
+ assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
+ if( res==0 ){
+ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
+ res = vdbeSorterCompareTail(
+ pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
+ );
+ }
+ }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
+ assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
+ res = res * -1;
+ }
+ return res;
+}
+
+/* Helper function for vdbeSorterCompareReal().
+**
+** Buffer p[] is a record where the first term is guaranteed to be either
+** a floating-point value, or an integer stand-in for a floating point
+** value (a MEM_IntReal). Whatever its format, extract the value and
+** return it.
+*/
+static double vdbeSorterGetReal(const u8 *p){
+ double r; /* the return value */
+
+ assert( p[0]<0x80 ); /* 1-byte headers: nAllField<13 */
+ assert( p[1]>0 && p[1]<10 ); /* first fields proven numeric */
+
+ if( p[1]==7 ){
+ u64 x = sqlite3Get8byte(p + p[0]);
+ swapMixedEndianFloat(x);
+ assert( !IsNaN(x) );
+ memcpy(&r, &x, sizeof(r));
+ }else{
+ Mem m;
+ m.u.i = 0;
+ sqlite3VdbeSerialGet(p + p[0], p[1], &m);
+ assert( m.flags==MEM_Int );
+ r = (double)m.u.i;
+ }
+ return r;
+}
+
+/* Helper function for vdbeSorterCompareReal()
+**
+** This routine handles the case of comparing two floating-point values
+** where one or both of the floating-point are represented by integers.
+** In other words, where one both is an MEM_RealInt.
+**
+** This subroutine is factored out from vdbeSorterCompareReal() for
+** efficiency. If inlined into vdbeSorterCompareReal(), this routine
+** will use extra stack space and consume CPU cycles setting up and
+** breaking down that stack space, even if in the common case where
+** this path is not used.
+*/
+static SQLITE_NOINLINE int vdbeSorterCompareRealInt(
+ SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
+ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
+ const void *pKey1, int nKey1, /* Left side of comparison */
+ const void *pKey2, int nKey2 /* Right side of comparison */
+){
+ const u8 * const p1 = (const u8 * const)pKey1;
+ const u8 * const p2 = (const u8 * const)pKey2;
+ if( p1[1]==6 || p2[1]==6 ){
+ /* 64-bit integer values cannot be represented exactly by a double so
+ ** must be handled by the generalized comparison function. */
+ return vdbeSorterCompare(pTask,
+ pbKey2Cached, pKey1,nKey1, pKey2,nKey2);
+ }else{
+ double r1 = vdbeSorterGetReal(p1);
+ double r2 = vdbeSorterGetReal(p2);
+ return vdbeSorterFinishRealCompare(pTask,pbKey2Cached,
+ pKey1,nKey1,pKey2,nKey2,r1,r2);
+ }
+}
+
+/*
+** Comparison function optimized for the case where the first term
+** of both keys are either MEM_Real or MEM_RealInt.
+**
+** See also vdbeSorterCompareInt() for MEM_Int values and
+** vdbeSorterCompareText() for MEM_Str values. The general
+** case is vdbeSorterCompare() which handles anything, but is slower.
+*/
+static int vdbeSorterCompareReal(
+ SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
+ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
+ const void *pKey1, int nKey1, /* Left side of comparison */
+ const void *pKey2, int nKey2 /* Right side of comparison */
+){
+ const u8*const p1 = (const u8*const)pKey1; /* Left key record */
+ const u8*const p2 = (const u8*const)pKey2; /* Right key record */
+ u64 x; /* A real value stored as an integer */
+ double r1; /* First element of pKey1 */
+ double r2; /* First element of pKey2 */
+
+ assert( p1[0]<0x80 && p2[0]<0x80 ); /* 1-byte headers: nAllField<13 */
+ assert( p1[1]>0 && p1[1]<10 ); /* first field guaranteed numeric */
+ assert( p2[1]>0 && p2[1]<10 ); /* first field guaranteed numeric */
+
+ if( p1[1]!=7 || p2[1]!=7 ){
+ /* One or both floating point values are stored as INTEGER. This might
+ ** be because of the MEM_RealInt encoding. Try to optimize that case. */
+ return vdbeSorterCompareRealInt(pTask,
+ pbKey2Cached, pKey1,nKey1, pKey2,nKey2
+ );
+ }
+ assert( p1[0]<=nKey1-8 && p2[0]<=nKey2-8 );
+
+ x = sqlite3Get8byte(p1 + *p1);
+ swapMixedEndianFloat(x);
+ assert( !IsNaN(x) );
+ memcpy(&r1, &x, sizeof(r1));
+ x = sqlite3Get8byte(p2 + *p2);
+ swapMixedEndianFloat(x);
+ assert( !IsNaN(x) );
+ memcpy(&r2, &x, sizeof(r2));
+ return vdbeSorterFinishRealCompare(pTask,
+ pbKey2Cached, pKey1,nKey1, pKey2,nKey2, r1, r2
+ );
+}
+
/*
** Initialize the temporary index cursor just opened as a sorter cursor.
**
@@ -106189,7 +107573,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
&& (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
&& (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0
){
- pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
+ pSorter->typeMask = SORTER_TYPE_INTEGER|SORTER_TYPE_TEXT|SORTER_TYPE_REAL;
}
}
@@ -106561,10 +107945,12 @@ static SorterRecord *vdbeSorterMerge(
** sorter object passed as the only argument.
*/
static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
- if( p->typeMask==SORTER_TYPE_INTEGER ){
+ if( p->typeMask & SORTER_TYPE_INTEGER ){
return vdbeSorterCompareInt;
- }else if( p->typeMask==SORTER_TYPE_TEXT ){
+ }else if( p->typeMask & SORTER_TYPE_TEXT ){
return vdbeSorterCompareText;
+ }else if( p->typeMask & SORTER_TYPE_REAL ){
+ return vdbeSorterCompareReal;
}
return vdbeSorterCompare;
}
@@ -106962,8 +108348,12 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
assert( pCsr->eCurType==CURTYPE_SORTER );
pSorter = pCsr->uc.pSorter;
getVarint32NR((const u8*)&pVal->z[1], t);
- if( t>0 && t<10 && t!=7 ){
- pSorter->typeMask &= SORTER_TYPE_INTEGER;
+ if( t>0 && t<10 ){
+ if( t==7 ){
+ pSorter->typeMask &= SORTER_TYPE_REAL;
+ }else{
+ pSorter->typeMask &= (SORTER_TYPE_INTEGER|SORTER_TYPE_REAL);
+ }
}else if( t>10 && (t & 0x01) ){
pSorter->typeMask &= SORTER_TYPE_TEXT;
}else{
@@ -109862,7 +111252,7 @@ static int lookupName(
** cnt>1 means there were two or more matches.
**
** cnt==0 is always an error. cnt>1 is often an error, but might
- ** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING.
+ ** be multiple matches for a NATURAL OUTER JOIN or a OUTER JOIN USING.
*/
assert( pFJMatch==0 || cnt>0 );
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
@@ -109882,6 +111272,7 @@ static int lookupName(
pExpr->op = TK_FUNCTION;
pExpr->u.zToken = "coalesce";
pExpr->x.pList = pFJMatch;
+ pExpr->affExpr = SQLITE_AFF_DEFER;
cnt = 1;
goto lookupname_end;
}else{
@@ -109944,10 +111335,19 @@ static int lookupName(
if( cnt==1 ){
assert( pNC!=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
- if( pParse->db->xAuth
- && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
- ){
- sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+ if( db->xAuth ){
+ if( pFJMatch ){
+ assert( pExpr->op==TK_FUNCTION );
+ assert( sqlite3_stricmp(pExpr->u.zToken,"coalesce")==0 );
+ assert( pExpr->x.pList==pFJMatch );
+ assert( pFJMatch->nExpr>0 );
+ for(i=0; inExpr; i++){
+ assert( pFJMatch->a[i].pExpr->op==TK_COLUMN );
+ sqlite3AuthRead(pParse,pFJMatch->a[i].pExpr,pSchema,pNC->pSrcList);
+ }
+ }else if( 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
@@ -110044,12 +111444,41 @@ static int exprProbability(Expr *p){
double r = -1.0;
if( p->op!=TK_FLOAT ) return -1;
assert( !ExprHasProperty(p, EP_IntValue) );
- sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
+ sqlite3AtoF(p->u.zToken, &r);
assert( r>=0.0 );
if( r>1.0 ) return -1;
return (int)(r*134217728.0);
}
+/*
+** Set the EP_SubtArg property on every expression inside of
+** pList. If any subexpression is actually a subquery, then
+** also set the EP_SubtArg property on the first result-set
+** column of that subquery.
+*/
+static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
+ int nn, ii;
+ nn = pList ? pList->nExpr : 0;
+ for(ii=0; iia[ii].pExpr;
+ while( 1 /*exit-by-break*/ ){
+ ExprSetProperty(pExpr, EP_SubtArg);
+ if( pExpr->op==TK_SELECT ){
+ assert( ExprUseXSelect(pExpr) );
+ assert( pExpr->x.pSelect!=0 );
+ resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
+ break;
+ }
+ if( pExpr->op==TK_UPLUS ){
+ pExpr = pExpr->pLeft;
+ assert( pExpr!=0 );
+ }else{
+ break;
+ }
+ }
+ }
+}
+
/*
** This routine is callback for sqlite3WalkExpr().
**
@@ -110294,10 +111723,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( (pDef->funcFlags & SQLITE_SUBTYPE)
|| ExprHasProperty(pExpr, EP_SubtArg)
){
- int ii;
- for(ii=0; iia[ii].pExpr, EP_SubtArg);
- }
+ resolveSetExprSubtypeArg(pList);
}
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
@@ -110327,8 +111753,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
/* Internal-use-only functions are disallowed unless the
** SQL is being compiled using sqlite3NestedParse() or
** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
- ** used to activate internal functions for testing purposes */
- no_such_func = 1;
+ ** used to activate internal functions for testing purposes.
+ **
+ ** The 2 value for no_such_func means that the function is
+ ** an internal-use-only function which should be treated as a
+ ** non-existant function for name resolution purposes.
+ */
+ no_such_func = 2;
pDef = 0;
}else
if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
@@ -110372,9 +111803,16 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
is_agg = 0;
}
#endif
- else if( no_such_func && pParse->db->init.busy==0
+ else if( no_such_func
+ && (pParse->db->init.busy==0 ||
+ (no_such_func==2 && pParse->db->init.busy==2))
+ /* Suppress "no such function" errors when reading
+ ** the sqlite_schema table. Except, do raise the error
+ ** if init.busy is 2, meaning the schema parse is due
+ ** to an ALTER TABLE ADD COLUMN statement, and the function
+ ** is an internal-use-only function (no_such_func==2). */
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- && pParse->explain==0
+ && pParse->explain==0
#endif
){
sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr);
@@ -110631,7 +112069,7 @@ static int resolveOrderByTermToExprList(
int rc; /* Return code from subprocedures */
u8 savedSuppErr; /* Saved value of db->suppressErr */
- assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
+ assert( sqlite3ExprIsInteger(pE, &i, 0, 0)==0 );
pEList = pSelect->pEList;
/* Resolve all names in the ORDER BY term expression
@@ -110730,7 +112168,7 @@ static int resolveCompoundOrderBy(
if( pItem->fg.done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
if( NEVER(pE==0) ) continue;
- if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
+ if( sqlite3ExprIsInteger(pE, &iCol, 0, 0) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
return 1;
@@ -110764,10 +112202,8 @@ static int resolveCompoundOrderBy(
/* Convert the ORDER BY term into an integer column number iCol,
** taking care to preserve the COLLATE clause if it exists. */
if( !IN_RENAME_OBJECT ){
- Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+ Expr *pNew = sqlite3ExprInt32(db, iCol);
if( pNew==0 ) return 1;
- pNew->flags |= EP_IntValue;
- pNew->u.iValue = iCol;
if( pItem->pExpr==pE ){
pItem->pExpr = pNew;
}else{
@@ -110915,7 +112351,7 @@ static int resolveOrderGroupBy(
continue;
}
}
- if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
+ if( sqlite3ExprIsInteger(pE2, &iCol, 0, 0) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
@@ -111121,10 +112557,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
#endif
- /* The ORDER BY and GROUP BY clauses may not refer to terms in
- ** outer queries
- */
- sNC.pNext = 0;
sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;
/* If this is a converted compound query, move the ORDER BY clause from
@@ -111187,6 +112619,14 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
+ /* If the SELECT statement contains ON clauses that were moved into
+ ** the WHERE clause, go through and verify that none of the terms
+ ** in the ON clauses reference tables to the right of the ON clause. */
+ if( (p->selFlags & SF_OnToWhere) ){
+ sqlite3SelectCheckOnClauses(pParse, p);
+ if( pParse->nErr ) return WRC_Abort;
+ }
+
/* Advance to the next term of the compound
*/
p = p->pPrior;
@@ -111601,23 +113041,29 @@ SQLITE_PRIVATE int sqlite3ExprDataType(const Expr *pExpr){
** and the pExpr parameter is returned unchanged.
*/
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
- const Parse *pParse, /* Parsing context */
+ Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */
){
- if( pCollName->n>0 ){
+ if( pCollName->n>0 && pParse->nErr==0 ){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
+ assert( pExpr!=0 );
if( pNew ){
pNew->pLeft = pExpr;
pNew->flags |= EP_Collate|EP_Skip;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ pNew->nHeight = pExpr->nHeight+1;
+ sqlite3ExprCheckHeight(pParse, pNew->nHeight);
+ testcase( pParse->nErr>0 );
+#endif
pExpr = pNew;
}
}
return pExpr;
}
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(
- const Parse *pParse, /* Parsing context */
+ Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
const char *zC /* The collating sequence name */
){
@@ -111759,7 +113205,9 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr){
SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
- return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
+ assert( (pColl1==pColl2) ==
+ (sqlite3_stricmp(pColl1->zName,pColl2->zName)==0) );
+ return pColl1==pColl2;
}
/*
@@ -112089,6 +113537,7 @@ static int exprVectorRegister(
Expr *pVector, /* Vector to extract element from */
int iField, /* Field to extract from pVector */
int regSelect, /* First in array of registers */
+ Expr *pTmp, /* Temporary space */
Expr **ppExpr, /* OUT: Expression element */
int *pRegFree /* OUT: Temp register to free */
){
@@ -112100,8 +113549,17 @@ static int exprVectorRegister(
}
if( op==TK_SELECT ){
assert( ExprUseXSelect(pVector) );
- *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
- return regSelect+iField;
+ /* Use the temporary expression node to wrap expression iField of the
+ ** sub-select in a TK_SELECT_COLUMN node. This causes the caller to
+ ** use the affinity of the expression in any comparison, but not the
+ ** collation sequence. */
+ memset(pTmp, 0, sizeof(Expr));
+ pTmp->op = TK_SELECT_COLUMN;
+ pTmp->pLeft = pVector;
+ pTmp->iColumn = iField;
+ pTmp->iTable = pVector->x.pSelect->pEList->nExpr;
+ *ppExpr = pTmp;
+ return regSelect+iField;
}
if( op==TK_VECTOR ){
assert( ExprUseXList(pVector) );
@@ -112168,11 +113626,12 @@ static void codeVectorCompare(
for(i=0; 1 /*Loop exits by "break"*/; i++){
int regFree1 = 0, regFree2 = 0;
Expr *pL = 0, *pR = 0;
+ Expr tmp1, tmp2;
int r1, r2;
assert( i>=0 && in+1 : 0;
assert( db!=0 );
- if( pToken ){
- if( op!=TK_INTEGER || pToken->z==0
- || sqlite3GetInt32(pToken->z, &iValue)==0 ){
- nExtra = pToken->n+1; /* tag-20240227-a */
- assert( iValue>=0 );
- }
- }
pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra);
if( pNew ){
memset(pNew, 0, sizeof(Expr));
pNew->op = (u8)op;
pNew->iAgg = -1;
- if( pToken ){
- if( nExtra==0 ){
- pNew->flags |= EP_IntValue|EP_Leaf|(iValue?EP_IsTrue:EP_IsFalse);
- pNew->u.iValue = iValue;
- }else{
- pNew->u.zToken = (char*)&pNew[1];
- assert( pToken->z!=0 || pToken->n==0 );
- if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
- pNew->u.zToken[pToken->n] = 0;
- if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){
- sqlite3DequoteExpr(pNew);
- }
+ if( nExtra ){
+ assert( pToken!=0 );
+ pNew->u.zToken = (char*)&pNew[1];
+ assert( pToken->z!=0 || pToken->n==0 );
+ if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
+ pNew->u.zToken[pToken->n] = 0;
+ if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){
+ sqlite3DequoteExpr(pNew);
}
}
#if SQLITE_MAX_EXPR_DEPTH>0
@@ -112415,6 +113862,24 @@ SQLITE_PRIVATE Expr *sqlite3Expr(
return sqlite3ExprAlloc(db, op, &x, 0);
}
+/*
+** Allocate an expression for a 32-bit signed integer literal.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3 *db, int iVal){
+ Expr *pNew = sqlite3DbMallocRawNN(db, sizeof(Expr));
+ if( pNew ){
+ memset(pNew, 0, sizeof(Expr));
+ pNew->op = TK_INTEGER;
+ pNew->iAgg = -1;
+ pNew->flags = EP_IntValue|EP_Leaf|(iVal?EP_IsTrue:EP_IsFalse);
+ pNew->u.iValue = iVal;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ pNew->nHeight = 1;
+#endif
+ }
+ return pNew;
+}
+
/*
** Attach subtrees pLeft and pRight to the Expr node pRoot.
**
@@ -112577,7 +114042,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
){
sqlite3ExprDeferredDelete(pParse, pLeft);
sqlite3ExprDeferredDelete(pParse, pRight);
- return sqlite3Expr(db, TK_INTEGER, "0");
+ return sqlite3ExprInt32(db, 0);
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
}
@@ -112702,7 +114167,9 @@ SQLITE_PRIVATE void sqlite3ExprFunctionUsable(
){
assert( !IN_RENAME_OBJECT );
assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
- if( ExprHasProperty(pExpr, EP_FromDDL) ){
+ if( ExprHasProperty(pExpr, EP_FromDDL)
+ || pParse->prepFlags & SQLITE_PREPARE_FROM_DDL
+ ){
if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
|| (pParse->db->flags & SQLITE_TrustedSchema)==0
){
@@ -112776,6 +114243,8 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n
if( x>pParse->nVar ){
pParse->nVar = (int)x;
doAdd = 1;
+ }else if( xaVnbmc[x>>6] & MASKBIT64(x&63))==0;
}else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){
doAdd = 1;
}
@@ -112792,6 +114261,9 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n
}
if( doAdd ){
pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x);
+ if( pParse->pVList!=0 && xaVnbmc[x>>6] |= MASKBIT64(x&63);
+ }
}
}
pExpr->iColumn = x;
@@ -113398,9 +114870,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
pNew->iLimit = 0;
pNew->iOffset = 0;
- pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral;
- pNew->addrOpenEphm[0] = -1;
- pNew->addrOpenEphm[1] = -1;
+ pNew->selFlags = p->selFlags;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = sqlite3WithDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -113925,7 +115395,7 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction(
if( pDef==0
|| pDef->xFinalize!=0
|| (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
- || ExprHasProperty(pExpr, EP_WinFunc)
+ || NEVER(ExprHasProperty(pExpr, EP_WinFunc))
){
pWalker->eCode = 0;
return WRC_Abort;
@@ -113946,6 +115416,7 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction(
** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
** sqlite3ExprIsTableConstant() pWalker->eCode==3
** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
+** sqlite3ExprListIsConstant() pWalker->eCode==1 or 6
**
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
** is found to not be a constant.
@@ -113972,19 +115443,25 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
}
switch( pExpr->op ){
- /* Consider functions to be constant if all their arguments are constant
- ** and either pWalker->eCode==4 or 5 or the function has the
- ** SQLITE_FUNC_CONST flag. */
case TK_FUNCTION:
- if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc))
- && !ExprHasProperty(pExpr, EP_WinFunc)
- ){
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ pWalker->eCode = 0; /* Window functions are never constant */
+ return WRC_Abort;
+ }else if( pWalker->eCode>=4 && pWalker->eCode<=5 ){
+ /* Functions used within a CREATE TABLE statement are constant as
+ ** long as all of their arguments are constant */
if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
return WRC_Continue;
+ }else if( ExprHasProperty(pExpr,EP_ConstFunc) ){
+ /* Functions marked with EP_ConstFunc are constant as long as
+ ** all their arugments are constant and they are not window functions */
+ return WRC_Continue;
}else if( pWalker->pParse ){
+ /* Functions are constant if they have SQLITE_FUNC_CONSTANT or
+ ** SQLITE_FUNC_SLOCHNG and if all arguments are constant */
return exprNodeIsConstantFunction(pWalker, pExpr);
}else{
- pWalker->eCode = 0;
+ pWalker->eCode = 0; /* Function call is not constant */
return WRC_Abort;
}
case TK_ID:
@@ -114018,6 +115495,13 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_RAISE );
pWalker->eCode = 0;
return WRC_Abort;
+ case TK_IS:
+ case TK_ISNOT:
+ if( pWalker->eCode==6 ){
+ pWalker->eCode = 0;
+ return WRC_Abort;
+ }
+ return WRC_Continue;
case TK_VARIABLE:
if( pWalker->eCode==5 ){
/* Silently convert bound parameters that appear inside of CREATE
@@ -114052,7 +115536,7 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
/*
** Walk an expression tree. Return non-zero if the expression is constant
-** and 0 if it involves variables or function calls.
+** or return zero if the expression involves variables or function calls.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
@@ -114068,11 +115552,27 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
return exprIsConst(pParse, p, 1);
}
+/*
+** Return true if all expressions in pList are constant. If parameter bNoIs
+** is true, do not consider expressions that contain "IS" operators to be
+** constant. IS operators are not always considered constant as expressions
+** like "x IS TRUE" need to be transformed to TK_TRUTH expression nodes,
+** which happens at the same time as column name resolution.
+*/
+SQLITE_PRIVATE int sqlite3ExprListIsConstant(Parse *pParse, ExprList *pList, int bNoIs){
+ const int iInit = bNoIs ? 6 : 1;
+ int ii;
+ for(ii=0; iinExpr; ii++){
+ if( 0==exprIsConst(pParse, pList->a[ii].pExpr, iInit) ) return 0;
+ }
+ return 1;
+}
+
/*
** Walk an expression tree. Return non-zero if
**
** (1) the expression is constant, and
-** (2) the expression does originate in the ON or USING clause
+** (2) the expression does not originate in the ON or USING clause
** of a LEFT JOIN, and
** (3) the expression does not contain any EP_FixedCol TK_COLUMN
** operands created by the constant propagation optimization.
@@ -114309,65 +115809,68 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
#endif
/*
-** If the expression p codes a constant integer that is small enough
-** to fit in a 32-bit integer, return 1 and put the value of the integer
-** in *pValue. If the expression is not an integer or if it is too big
-** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
+** If the expression p codes a constant integer between 0 and 0x7fffffff,
+** then return 1 and put the value of the integer in *pValue. If the
+** expression is not an integer or if it is an integer that is out side
+** the range of 0...0x7fffffff, then return 0 and leave *pValue unchanged.
**
** If the pParse pointer is provided, then allow the expression p to be
-** a parameter (TK_VARIABLE) that is bound to an integer.
-** But if pParse is NULL, then p must be a pure integer literal.
-*/
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
- int rc = 0;
- if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
-
- /* If an expression is an integer literal that fits in a signed 32-bit
- ** integer, then the EP_IntValue flag will have already been set */
- assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0
- || sqlite3GetInt32(p->u.zToken, &rc)==0 );
-
- if( p->flags & EP_IntValue ){
- *pValue = p->u.iValue;
- return 1;
- }
- switch( p->op ){
- case TK_UPLUS: {
- rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
- break;
+** a parameter (TK_VARIABLE) that is bound to an integer between 0 and
+** 0x7fffffff. Variables that hold anything other than integers, or that
+** hold integers outside the range of 0..0x7fffffff are not seen.
+** But if pParse is NULL, then p must be a pure integer literal between
+** 0 and 0x7fffffff.
+**
+** If pParse is not NULL and expression p is a variable, then the variable
+** is marked so as to cause the statement to be reprepared each time a new
+** value is bound to it. Except, if parameter bRSI is true, then the statement
+** will only be reprepared if the rebind changes the value to or from a
+** "small integer" (either 0 or 1).
+*/
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse, int bRSI){
+ int iSign = 1; /* Either +1 or -1. */
+ while( 1/*exit-by-break*/ ){
+ if( NEVER(p==0) ) return 0;
+ if( ExprUseUValue(p) ){
+ *pValue = p->u.iValue*iSign;
+ return 1;
}
- case TK_UMINUS: {
- int v = 0;
- if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
- assert( ((unsigned int)v)!=0x80000000 );
- *pValue = -v;
- rc = 1;
- }
- break;
+ if( p->op==TK_UPLUS ){
+ p = p->pLeft;
+ pParse = 0;
+ continue;
}
- case TK_VARIABLE: {
- sqlite3_value *pVal;
- if( pParse==0 ) break;
+ if( p->op==TK_UMINUS ){
+ iSign = -iSign;
+ p = p->pLeft;
+ pParse = 0;
+ continue;
+ }
+ if( p->op==TK_VARIABLE && pParse!=0 ){
+ sqlite3_value *pVal; /* The variable */
+ int rc = 0; /* 1 if successful, 0 if failed */
+ assert( iSign==1 );
if( NEVER(pParse->pVdbe==0) ) break;
if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
- sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
SQLITE_AFF_BLOB);
if( pVal ){
- if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
- sqlite3_int64 vv = sqlite3_value_int64(pVal);
- if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
- *pValue = (int)vv;
- rc = 1;
- }
+ i64 vv;
+ if( sqlite3_value_type(pVal)==SQLITE_INTEGER
+ && (vv = sqlite3_value_int64(pVal))>=0
+ && vv<=0x7fffffff
+ ){
+ *pValue = (int)vv;
+ rc = 1;
}
sqlite3ValueFree(pVal);
}
- break;
+ sqlite3VdbeReprepareOnBind(pParse->pVdbe, p->iColumn, bRSI);
+ return rc;
}
- default: break;
+ break;
}
- return rc;
+ return 0;
}
/*
@@ -114501,10 +116004,8 @@ static Select *isCandidateForInOpt(const Expr *pX){
if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */
p = pX->x.pSelect;
if( p->pPrior ) return 0; /* Not a compound SELECT */
- if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
- testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
- testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
- return 0; /* No DISTINCT keyword and no aggregate functions */
+ if( p->selFlags & SF_Aggregate ){
+ return 0; /* No GROUP BY keyword or aggregate functions */
}
assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
if( p->pLimit ) return 0; /* Has no LIMIT clause */
@@ -114536,13 +116037,24 @@ static Select *isCandidateForInOpt(const Expr *pX){
** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull
** to be set to NULL if iCur contains one or more NULL values.
*/
-static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
+static void sqlite3SetHasNullFlag(
+ Vdbe *v, /* Write new code into this statement under construction */
+ int iCur, /* Cursor for the index */
+ int regHasNull, /* Register in which to store hasNull flag */
+ int eSortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */
+){
int addr1;
+ int op;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
- addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
+ if( eSortOrder==SQLITE_SO_ASC ){
+ op = OP_Rewind;
+ }else{
+ op = OP_Last;
+ }
+ addr1 = sqlite3VdbeAddOp1(v, op, iCur); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
- VdbeComment((v, "first_entry_in(%d)", iCur));
+ VdbeComment((v, op==OP_Last?"last_entry_in(%d)":"first_entry_in(%d)", iCur));
sqlite3VdbeJumpHere(v, addr1);
}
#endif
@@ -114803,13 +116315,14 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
if( prRhsHasNull ){
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- i64 mask = (1<nMem;
if( nExpr==1 ){
- sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
+ sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull,
+ pIdx->aSortOrder[0]);
}
}
sqlite3VdbeJumpHere(v, iAddr);
@@ -114842,6 +116355,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
*/
u32 savedNQueryLoop = pParse->nQueryLoop;
int rMayHaveNull = 0;
+ int bloomOk = (inFlags & IN_INDEX_MEMBERSHIP)!=0;
eType = IN_INDEX_EPH;
if( inFlags & IN_INDEX_LOOP ){
pParse->nQueryLoop = 0;
@@ -114849,9 +116363,15 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
*prRhsHasNull = rMayHaveNull = ++pParse->nMem;
}
assert( pX->op==TK_IN );
- sqlite3CodeRhsOfIN(pParse, pX, iTab);
+ if( !bloomOk
+ && ExprUseXSelect(pX)
+ && (pX->x.pSelect->selFlags & SF_ClonedRhsIn)!=0
+ ){
+ bloomOk = 1;
+ }
+ sqlite3CodeRhsOfIN(pParse, pX, iTab, bloomOk);
if( rMayHaveNull ){
- sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
+ sqlite3SetHasNullFlag(v, iTab, rMayHaveNull, SQLITE_SO_ASC);
}
pParse->nQueryLoop = savedNQueryLoop;
}
@@ -115007,7 +116527,8 @@ static int findCompatibleInRhsSubrtn(
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The IN operator */
- int iTab /* Use this cursor number */
+ int iTab, /* Use this cursor number */
+ int allowBloom /* True to allow the use of a Bloom filter */
){
int addrOnce = 0; /* Address of the OP_Once instruction at top */
int addr; /* Address of OP_OpenEphemeral instruction */
@@ -115105,6 +116626,8 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
}
#endif
pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
+ assert( pKeyInfo!=0 || pParse->nErr );
+ if( pKeyInfo==0 ) return;
if( ExprUseXSelect(pExpr) ){
/* Case 1: expr IN (SELECT ...)
@@ -115129,14 +116652,31 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
- if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ for(i=0; iaColl[i] = pColl = sqlite3BinaryCompareCollSeq(
+ pParse, p, pEList->a[i].pExpr
+ );
+ if( !sqlite3IsBinary(pColl) ){
+ allowBloom = 0; /* tag-202607231411 */
+ }
+ }
+ if( addrOnce
+ && allowBloom
+ && OptimizationEnabled(pParse->db, SQLITE_BloomFilter)
+ ){
int regBloom = ++pParse->nMem;
addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
VdbeComment((v, "Bloom filter"));
dest.iSDParm2 = regBloom;
+ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
+ pKeyInfo = 0;
}
testcase( pSelect->selFlags & SF_Distinct );
- testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
@@ -115154,16 +116694,6 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
sqlite3KeyInfoUnref(pKeyInfo);
return;
}
- assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
- assert( pEList!=0 );
- assert( pEList->nExpr>0 );
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq(
- pParse, p, pEList->a[i].pExpr
- );
- }
}
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
@@ -115184,10 +116714,9 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
}else if( affinity==SQLITE_AFF_REAL ){
affinity = SQLITE_AFF_NUMERIC;
}
- if( pKeyInfo ){
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- }
+ assert( pKeyInfo!=0 );
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
/* Loop through each expression in . */
r1 = sqlite3GetTempReg(pParse);
@@ -115350,7 +116879,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|| (pLeft->u.iValue!=1 && pLeft->u.iValue!=0)
){
sqlite3 *db = pParse->db;
- pLimit = sqlite3Expr(db, TK_INTEGER, "0");
+ pLimit = sqlite3ExprInt32(db, 0);
if( pLimit ){
pLimit->affExpr = SQLITE_AFF_NUMERIC;
pLimit = sqlite3PExpr(pParse, TK_NE,
@@ -115361,7 +116890,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}
}else{
/* If there is no pre-existing limit add a limit of 1 */
- pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
+ pLimit = sqlite3ExprInt32(pParse->db, 1);
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
}
pSel->iLimit = 0;
@@ -115377,6 +116906,12 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}
sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1);
+ if( dest.eDest==SRT_Mem
+ && sqlite3ExprCanReturnSubtype(pParse, pSel->pEList->a[0].pExpr)
+ ){
+ sqlite3VdbeAddOp1(v, OP_ClrSubtype, rReg);
+ }
+
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
@@ -115572,16 +117107,30 @@ static void sqlite3ExprCodeIN(
** we need to reorder the LHS values to be in index order. Run Affinity
** before reordering the columns, so that the affinity is correct.
*/
- sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
+ if( nVector==1 ){
+ char aff = zAff[0];
+ if( aff>=SQLITE_AFF_TEXT && aff!=sqlite3ExprAffinity(pLeft) ){
+ /* The OP_Affinity below may change the value. In this case, create a
+ ** copy of rLhs to run OP_Affinity on, in case the original register
+ ** is used again (e.g. if it is TK_AGG_COLUMN). */
+ int rTmp = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_Copy, rLhs, rTmp, 0);
+ rLhs = rTmp;
+ sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, 1, 0, zAff, 1);
+ }
+ }else{
+ sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
+ }
+
for(i=0; ipLeft, i);
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
- sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
+ testcase( aiMap[i]!=i );
+ sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+aiMap[i], destStep2);
VdbeCoverage(v);
}
}
@@ -115622,8 +117172,9 @@ static void sqlite3ExprCodeIN(
if( ExprHasProperty(pExpr, EP_Subrtn) ){
const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
assert( pOp->opcode==OP_Once || pParse->nErr );
- if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */
- assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
+ if( pOp->p3>0 ){ /* tag-202407032019 */
+ assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter)
+ || pParse->nErr );
sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
rLhs, nVector); VdbeCoverage(v);
}
@@ -115658,7 +117209,13 @@ static void sqlite3ExprCodeIN(
** of the RHS.
*/
if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6);
- addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, destIfFalse);
+ if( eType==IN_INDEX_INDEX_DESC ){
+ addrTop = sqlite3VdbeAddOp2(v, OP_Last, iTab, destIfFalse);
+ }else{
+ testcase( eType==IN_INDEX_EPH );
+ testcase( eType==IN_INDEX_ROWID );
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, destIfFalse);
+ }
VdbeCoverage(v);
if( nVector>1 ){
destNotNull = sqlite3VdbeMakeLabel(pParse);
@@ -115672,9 +117229,19 @@ static void sqlite3ExprCodeIN(
CollSeq *pColl;
int r3 = sqlite3GetTempReg(pParse);
p = sqlite3VectorFieldSubexpr(pLeft, i);
- pColl = sqlite3ExprCollSeq(pParse, p);
- sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
+ if( ExprUseXSelect(pExpr) ){
+ Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr;
+ pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs);
+ }else{
+ /* If the RHS of the IN(...) expression are scalar expressions, do
+ ** not consider their collation sequences. The documentation says
+ ** "The collating sequence used for expressions of the form "x IN (y, z,
+ ** ...)" is the collating sequence of x.". */
+ pColl = sqlite3ExprCollSeq(pParse, p);
+ }
+ testcase( aiMap[i]!=i );
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, aiMap[i], r3);
+ sqlite3VdbeAddOp4(v, OP_Ne, rLhs+aiMap[i], destNotNull, r3,
(void*)pColl, P4_COLLSEQ);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r3);
@@ -115713,10 +117280,10 @@ static void sqlite3ExprCodeIN(
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
if( ALWAYS(z!=0) ){
double value;
- sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
+ sqlite3AtoF(z, &value);
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
if( negateFlag ) value = -value;
- sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
+ sqlite3VdbeAddDouble(v, iMem, value);
}
}
#endif
@@ -115757,7 +117324,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
#endif
}else{
if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; }
- sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
+ sqlite3VdbeAddInt64(v, iMem, value);
}
}
}
@@ -115838,12 +117405,12 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
VdbeComment((v, "%s.rowid", pTab->zName));
- }else{
- int op;
+ }else{
int x;
if( IsVirtual(pTab) ){
- op = OP_VColumn;
x = iCol;
+ sqlite3VdbeAddOp3(v, OP_VColumn, iTabCur, x, regOut);
+ return;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
Parse *pParse = sqlite3VdbeParser(v);
@@ -115863,13 +117430,11 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
}else if( !HasRowid(pTab) ){
testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) );
x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
- op = OP_Column;
}else{
x = sqlite3TableColumnToStorage(pTab,iCol);
testcase( x!=iCol );
- op = OP_Column;
}
- sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
+ sqlite3VdbeAddOp3(v, OP_Column, iTabCur, x, regOut);
sqlite3ColumnDefault(v, pTab, iCol, regOut);
}
}
@@ -116095,36 +117660,52 @@ static int exprCodeInlineFunction(
}
/*
-** Expression Node callback for sqlite3ExprCanReturnSubtype().
+** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
+** pExpr is able to return a subtype, set pWalker->eCode and abort
+** the search. If pExpr can never return a subtype, prune search.
**
-** Only a function call is able to return a subtype. So if the node
-** is not a function call, return WRC_Prune immediately.
+** The only expressions that can return a subtype are:
**
-** A function call is able to return a subtype if it has the
-** SQLITE_RESULT_SUBTYPE property.
+** 1. A function, including an aggregate function
+** 2. The no-op "+" operator
+** 3. A CASE...END expression
+** 4. A CAST() expression
+** 5. A "expr COLLATE colseq" expression.
**
-** Assume that every function is able to pass-through a subtype from
-** one of its argument (using sqlite3_result_value()). Most functions
-** are not this way, but we don't have a mechanism to distinguish those
-** that are from those that are not, so assume they all work this way.
-** That means that if one of its arguments is another function and that
-** other function is able to return a subtype, then this function is
-** able to return a subtype.
+** For any other kind of expression, prune the search.
+**
+** For case 1, the expression can yield a subtype if the function has
+** the SQLITE_RESULT_SUBTYPE property. Functions can also return
+** a subtype (via sqlite3_result_value()) if any of the arguments can
+** return a subtype.
+**
+** In all cases 1 through 5, the expression might also return a subtype
+** if any operand can return a subtype.
*/
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
int n;
FuncDef *pDef;
sqlite3 *db;
- if( pExpr->op!=TK_FUNCTION ){
+ if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
+ || pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
+ ){
+ return WRC_Continue;
+ }
+ if( pExpr->op!=TK_FUNCTION && pExpr->op!=TK_AGG_FUNCTION ){
return WRC_Prune;
}
assert( ExprUseXList(pExpr) );
db = pWalker->pParse->db;
- n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
+ n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
- if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ if( pDef==0 ) return WRC_Continue;
+#else
+ assert( pDef!=0 );
+#endif
+ if( (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
pWalker->eCode = 1;
- return WRC_Prune;
+ return WRC_Abort;
}
return WRC_Continue;
}
@@ -116137,7 +117718,7 @@ static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
** are acceptable as they only disable an optimization. False negatives,
** on the other hand, can lead to incorrect answers.
*/
-static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
+SQLITE_PRIVATE int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = pParse;
@@ -116192,10 +117773,16 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
v = pParse->pVdbe;
assert( v!=0 );
- if( p->bMaybeNullRow ){
- /* If the index is on a NULL row due to an outer join, then we
- ** cannot extract the value from the index. The value must be
- ** computed using the original expression. */
+ if( p->bMaybeNullRow || sqlite3ExprIsConstant(pParse, pExpr) ){
+ /* The value of pExpr should be computed from the original expression,
+ ** not from the index, if either:
+ **
+ ** 1. The index might be on a NULL row due to an outer join.
+ **
+ ** 2. The expression is a constant. This prevents an attempt to
+ ** use an index value outside of the loop that positions the
+ ** index. (Bug 2026-10-11T19:26:40Z).
+ */
int addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target);
VdbeCoverage(v);
@@ -116241,6 +117828,11 @@ static int exprPartidxExprLookup(Parse *pParse, Expr *pExpr, int iTarget){
ret = sqlite3ExprCodeTarget(pParse, p->pExpr, iTarget);
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Affinity, ret, 1, 0,
(const char*)&p->aff, 1);
+ if( sqlite3ExprCanReturnSubtype(pParse, p->pExpr) ){
+ /* If the expression value may have a sub-type, clear it. Values
+ ** read from columns do not have subtypes. */
+ sqlite3VdbeAddOp1(pParse->pVdbe, OP_ClrSubtype, ret);
+ }
if( addr ){
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeChangeP3(v, addr, ret);
@@ -116572,7 +118164,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
case TK_ISNOT:
op = (op==TK_IS) ? TK_EQ : TK_NE;
p5 = SQLITE_NULLEQ;
- /* fall-through */
+ /* no break */ deliberate_fall_through
case TK_LT:
case TK_LE:
case TK_GT:
@@ -116769,7 +118361,12 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
pDef = sqlite3FindFunction(db, "unknown", nFarg, enc, 0);
}
#endif
- if( pDef==0 || pDef->xFinalize!=0 ){
+ if( pDef==0
+ || pDef->xFinalize!=0
+ || ((pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 &&
+ !pParse->nested &&
+ (db->mDbFlags & DBFLAG_InternalFunc)==0)
+ ){
sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr);
break;
}
@@ -117910,7 +119507,7 @@ static SQLITE_NOINLINE int exprCompareVariable(
sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
if( pR ){
iVar = pVar->iColumn;
- sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
+ sqlite3VdbeReprepareOnBind(pParse->pVdbe, iVar, 0);
pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
if( pL ){
if( sqlite3_value_type(pL)==SQLITE_TEXT ){
@@ -118166,7 +119763,7 @@ static int sqlite3ExprIsNotTrue(Expr *pExpr){
if( pExpr->op==TK_NULL ) return 1;
if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1;
v = 1;
- if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1;
+ if( sqlite3ExprIsInteger(pExpr, &v, 0, 0) && v==0 ) return 1;
return 0;
}
@@ -118814,7 +120411,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
if( pIEpr==0 ) break;
if( NEVER(!ExprUseYTab(pExpr)) ) break;
for(i=0; inSrc; i++){
- if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break;
+ if( pSrcList->a[i].iCursor==pIEpr->iDataCur ){
+ testcase( i>0 );
+ break;
+ }
}
if( i>=pSrcList->nSrc ) break;
if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */
@@ -118909,7 +120509,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
if( pOBList->nExpr==1
&& nArg==1
&& sqlite3ExprCompare(0,pOBList->a[0].pExpr,
- pExpr->x.pList->a[0].pExpr,0)==0
+ pExpr->x.pList->a[0].pExpr,-1)==0
){
pItem->bOBPayload = 0;
pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct);
@@ -118997,6 +120597,13 @@ SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
*/
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
if( iReg ){
+#ifdef SQLITE_DEBUG
+ /* Verify that iReg is not already on the unused register list */
+ int kk;
+ for(kk=0; kknTempReg; kk++){
+ assert( pParse->aTempReg[kk]!=iReg );
+ }
+#endif
sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0);
if( pParse->nTempRegaTempReg) ){
pParse->aTempReg[pParse->nTempReg++] = iReg;
@@ -119414,6 +121021,30 @@ static void sqlite3ErrorIfNotEmpty(
);
}
+/*
+** zCol is a column name used in an ALTER TABLE DROP, ADD or RENAME COLUMN
+** operation. zOp identifies the specific operation - "drop", "add", "rename
+** to" or "rename from". pTab is the table being altered.
+**
+** If pTab has a rowid and zCol is a rowid alias, then SQLITE_ERROR is
+** returned and an error message left in pParse. Or, if zCol is not an alias
+** for "rowid" or pTab is not an intkey table, then SQLITE_OK is returned.
+*/
+static int isRowidAlias(
+ Parse *pParse,
+ Table *pTab,
+ const char *zCol,
+ const char *zOp
+){
+ if( HasRowid(pTab) && sqlite3IsRowid(zCol) ){
+ sqlite3ErrorMsg(pParse, "cannot %s rowid alias: %s", zOp, zCol);
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+
+
/*
** This function is called after an "ALTER TABLE ... ADD" statement
** has been parsed. Argument pColDef contains the text of the new
@@ -119459,9 +121090,9 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
#endif
- /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
- ** If there is a NOT NULL constraint, then the default value for the
- ** column must not be NULL.
+ /* Check that the new column is not specified as PRIMARY KEY or UNIQUE,
+ ** or a rowid alias. If there is a NOT NULL constraint, then the default
+ ** value for the column must not be NULL.
*/
if( pCol->colFlags & COLFLAG_PRIMKEY ){
sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
@@ -119472,6 +121103,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
"Cannot add a UNIQUE column");
return;
}
+ if( isRowidAlias(pParse, pTab, pCol->zCnName, "add") ) return;
if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
/* If the default value for the new column was specified with a
** literal NULL, then set pDflt to 0. This simplifies checking
@@ -119560,6 +121192,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|| (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0)
|| (pTab->tabFlags & TF_Strict)!=0
){
+ pParse->colNamesSet = 1;
sqlite3NestedParse(pParse,
"SELECT CASE WHEN quick_check GLOB 'CHECK*'"
" THEN raise(ABORT,'CHECK constraint failed')"
@@ -119603,7 +121236,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
/* Look up the table being altered. */
assert( pParse->pNewTable==0 );
assert( sqlite3BtreeHoldsAllMutexes(db) );
- if( db->mallocFailed ) goto exit_begin_add_column;
+ if( NEVER(db->mallocFailed) ) goto exit_begin_add_column;
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
if( !pTab ) goto exit_begin_add_column;
@@ -119675,7 +121308,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
** Or, if pTab is not a view or virtual table, zero is returned.
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
-static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
+static int isRealTable(Parse *pParse, Table *pTab, int iOp){
const char *zType = 0;
#ifndef SQLITE_OMIT_VIEW
if( IsView(pTab) ){
@@ -119688,9 +121321,12 @@ static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
}
#endif
if( zType ){
+ const char *azMsg[] = {
+ "rename columns of", "drop column from", "edit constraints of"
+ };
+ assert( iOp>=0 && iOpzName
+ azMsg[iOp], zType, pTab->zName
);
return 1;
}
@@ -119761,6 +121397,8 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn(
sqlite3MayAbort(pParse);
zNew = sqlite3NameFromToken(db, pNew);
if( !zNew ) goto exit_rename_column;
+ if( isRowidAlias(pParse, pTab, zOld, "rename from") ) goto exit_rename_column;
+ if( isRowidAlias(pParse, pTab, zNew, "rename to") ) goto exit_rename_column;
assert( pNew->n>0 );
bQuote = sqlite3Isquote(pNew->z[0]);
sqlite3NestedParse(pParse,
@@ -120161,6 +121799,25 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
return pBest;
}
+/*
+** Set the error message of the context passed as the first argument to
+** the result of formatting zFmt using printf() style formatting.
+*/
+static void errorMPrintf(sqlite3_context *pCtx, const char *zFmt, ...){
+ sqlite3 *db = sqlite3_context_db_handle(pCtx);
+ char *zErr = 0;
+ va_list ap;
+ va_start(ap, zFmt);
+ zErr = sqlite3VMPrintf(db, zFmt, ap);
+ va_end(ap);
+ if( zErr ){
+ sqlite3_result_error(pCtx, zErr, -1);
+ sqlite3DbFree(db, zErr);
+ }else{
+ sqlite3_result_error_nomem(pCtx);
+ }
+}
+
/*
** An error occurred while parsing or otherwise processing a database
** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an
@@ -120458,8 +122115,8 @@ static int renameResolveTrigger(Parse *pParse){
sqlite3SelectPrep(pParse, pStep->pSelect, &sNC);
if( pParse->nErr ) rc = pParse->rc;
}
- if( rc==SQLITE_OK && pStep->zTarget ){
- SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep);
+ if( rc==SQLITE_OK && pStep->pSrc ){
+ SrcList *pSrc = sqlite3SrcListDup(db, pStep->pSrc, 0);
if( pSrc ){
Select *pSel = sqlite3SelectNew(
pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0
@@ -120487,10 +122144,10 @@ static int renameResolveTrigger(Parse *pParse){
pSel->pSrc = 0;
sqlite3SelectDelete(db, pSel);
}
- if( pStep->pFrom ){
+ if( ALWAYS(pStep->pSrc) ){
int i;
- for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){
- SrcItem *p = &pStep->pFrom->a[i];
+ for(i=0; ipSrc->nSrc && rc==SQLITE_OK; i++){
+ SrcItem *p = &pStep->pSrc->a[i];
if( p->fg.isSubquery ){
assert( p->u4.pSubq!=0 );
sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0);
@@ -120559,13 +122216,13 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere);
sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere);
}
- if( pStep->pFrom ){
+ if( pStep->pSrc ){
int i;
- SrcList *pFrom = pStep->pFrom;
- for(i=0; inSrc; i++){
- if( pFrom->a[i].fg.isSubquery ){
- assert( pFrom->a[i].u4.pSubq!=0 );
- sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect);
+ SrcList *pSrc = pStep->pSrc;
+ for(i=0; inSrc; i++){
+ if( pSrc->a[i].fg.isSubquery ){
+ assert( pSrc->a[i].u4.pSubq!=0 );
+ sqlite3WalkSelect(pWalker, pSrc->a[i].u4.pSubq->pSelect);
}
}
}
@@ -120736,8 +122393,8 @@ static void renameColumnFunc(
if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){
- if( pStep->zTarget ){
- Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb);
+ if( pStep->pSrc ){
+ Table *pTarget = sqlite3LocateTableItem(&sParse, 0, &pStep->pSrc->a[0]);
if( pTarget==pTab ){
if( pStep->pUpsert ){
ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet;
@@ -120749,7 +122406,6 @@ static void renameColumnFunc(
}
}
-
/* Find tokens to edit in UPDATE OF clause */
if( sParse.pTriggerTab==pTab ){
renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld);
@@ -120951,13 +122607,10 @@ static void renameTableFunc(
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
- if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
- renameTokenFind(&sParse, &sCtx, pStep->zTarget);
- }
- if( pStep->pFrom ){
+ if( pStep->pSrc ){
int i;
- for(i=0; ipFrom->nSrc; i++){
- SrcItem *pItem = &pStep->pFrom->a[i];
+ for(i=0; ipSrc->nSrc; i++){
+ SrcItem *pItem = &pStep->pSrc->a[i];
if( 0==sqlite3_stricmp(pItem->zName, zOld) ){
renameTokenFind(&sParse, &sCtx, pItem->zName);
}
@@ -121204,6 +122857,57 @@ static void renameTableTest(
#endif
}
+
+/*
+** Return the number of bytes until the end of the next non-whitespace and
+** non-comment token. For the purpose of this function, a "(" token includes
+** all of the bytes through and including the matching ")", or until the
+** first illegal token, whichever comes first.
+**
+** Write the token type into *piToken.
+**
+** The value returned is the number of bytes in the token itself plus
+** the number of bytes of leading whitespace and comments skipped plus
+** all bytes through the next matching ")" if the token is TK_LP.
+**
+** Example: (Note: '.' used in place of '*' in the example z[] text)
+**
+** ,--------- *piToken := TK_RP
+** v
+** z[] = " /.comment./ --comment\n (two three four) five"
+** | |
+** |<-------------------------------------->|
+** |
+** `--- return value
+*/
+static int getConstraintToken(const u8 *z, int *piToken){
+ int iOff = 0;
+ int t = 0;
+ do {
+ iOff += sqlite3GetToken(&z[iOff], &t);
+ }while( t==TK_SPACE || t==TK_COMMENT );
+
+ *piToken = t;
+
+ if( t==TK_LP ){
+ int nNest = 1;
+ while( nNest>0 ){
+ iOff += sqlite3GetToken(&z[iOff], &t);
+ if( t==TK_LP ){
+ nNest++;
+ }else if( t==TK_RP ){
+ t = TK_LP;
+ nNest--;
+ }else if( t==TK_ILLEGAL ){
+ break;
+ }
+ }
+ }
+
+ *piToken = t;
+ return iOff;
+}
+
/*
** The implementation of internal UDF sqlite_drop_column().
**
@@ -121248,15 +122952,24 @@ static void dropColumnFunc(
goto drop_column_done;
}
- pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
if( iColnCol-1 ){
RenameToken *pEnd;
+ pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
zEnd = (const char*)pEnd->t.z;
}else{
+ int eTok;
assert( IsOrdinaryTable(pTab) );
+ assert( iCol!=0 );
+ /* Point pCol->t.z at the "," immediately preceding the definition of
+ ** the column being dropped. To do this, start at the name of the
+ ** previous column, and tokenize until the next ",". */
+ pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol-1].zCnName);
+ do {
+ pCol->t.z += getConstraintToken((const u8*)pCol->t.z, &eTok);
+ }while( eTok!=TK_COMMA );
+ pCol->t.z--;
zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
- while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
}
zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
@@ -121312,6 +123025,7 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName);
goto exit_drop_column;
}
+ if( isRowidAlias(pParse, pTab, zCol, "drop") ) goto exit_drop_column;
/* Do not allow the user to drop a PRIMARY KEY column or a column
** constrained by a UNIQUE constraint. */
@@ -121425,6 +123139,684 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T
sqlite3SrcListDelete(db, pSrc);
}
+/*
+** Return the number of bytes of leading whitespace/comments in string z[].
+*/
+static int getWhitespace(const u8 *z){
+ int nRet = 0;
+ while( 1 ){
+ int t = 0;
+ int n = sqlite3GetToken(&z[nRet], &t);
+ if( t!=TK_SPACE && t!=TK_COMMENT ) break;
+ nRet += n;
+ }
+ return nRet;
+}
+
+
+/*
+** Argument z points into the body of a constraint - specifically the
+** second token of the constraint definition. For a named constraint,
+** z points to the second token of the constraint definition. For an
+** unnamed NOT NULL constraint, z points to the first byte past the NOT
+** keyword.
+**
+** Argument eTok may be the token value of the first token of the constraint
+** (e.g. TK_CHECK or TK_REFERENCES) or zero. If it is either TK_REFERENCES
+** or TK_FOREIGN, special parsing is enabled to find the end of the foreign-key
+** constraint definition.
+**
+** Return the number of bytes until the end of the constraint.
+*/
+static int getConstraint(const u8 *z, int eTok){
+ int iOff = 0;
+ int t = 0;
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ if( eTok==TK_FOREIGN ){
+ /* For a FOREIGN KEY constraint, use getConstraint() to parse everything
+ ** up to the REFERENCES keyword. Then getConstraintToken() to consume
+ ** the TK_REFERENCES token itself. Then fall through to the special
+ ** handling for TK_REFERENCES below. */
+ iOff = getConstraint(z, 0);
+ iOff += getConstraintToken(&z[iOff], &eTok);
+ }
+
+ if( eTok==TK_REFERENCES ){
+ /* REFERENCES is followed by a table name. Gobble this up here in
+ ** case the table name is a fallback token like TK_GENERATED. */
+ iOff += getConstraintToken(&z[iOff], &t);
+ }
+#endif
+
+ /* Now, the current constraint proceeds until the next occurence of one
+ ** of the following tokens:
+ **
+ ** CONSTRAINT, PRIMARY, NOT, UNIQUE, CHECK, DEFAULT,
+ ** COLLATE, REFERENCES, FOREIGN, GENERATED, AS, RP, or COMMA
+ **
+ ** Also exit the loop if ILLEGAL turns up.
+ */
+ while( 1 ){
+ int n = getConstraintToken(&z[iOff], &t);
+ if( t==TK_CONSTRAINT || t==TK_PRIMARY || t==TK_NOT || t==TK_UNIQUE
+ || t==TK_CHECK || t==TK_DEFAULT || t==TK_COLLATE || t==TK_REFERENCES
+ || t==TK_FOREIGN || t==TK_RP || t==TK_COMMA || t==TK_ILLEGAL
+ || t==TK_AS || t==TK_GENERATED
+ ){
+ break;
+ }
+ iOff += n;
+ }
+
+ return iOff;
+}
+
+/*
+** Compare two constraint names.
+**
+** Summary: *pRes := zQuote != zCmp
+**
+** Details:
+** Compare the (possibly quoted) constraint name zQuote[0..nQuote-1]
+** against zCmp[]. Write zero into *pRes if they are the same and
+** non-zero if they differ. Normally return SQLITE_OK, except if there
+** is an OOM, set the OOM error condition on ctx and return SQLITE_NOMEM.
+*/
+static int quotedCompare(
+ sqlite3_context *ctx, /* Function context on which to report errors */
+ int t, /* Token type */
+ const u8 *zQuote, /* Possibly quoted text. Not zero-terminated. */
+ int nQuote, /* Length of zQuote in bytes */
+ const u8 *zCmp, /* Zero-terminated, unquoted name to compare against */
+ int *pRes /* OUT: Set to 0 if equal, non-zero if unequal */
+){
+ char *zCopy = 0; /* De-quoted, zero-terminated copy of zQuote[] */
+
+ if( t==TK_ILLEGAL ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ zCopy = sqlite3MallocZero(nQuote+1);
+ if( zCopy==0 ){
+ sqlite3_result_error_nomem(ctx);
+ return SQLITE_NOMEM_BKPT;
+ }
+ memcpy(zCopy, zQuote, nQuote);
+ sqlite3Dequote(zCopy);
+ *pRes = sqlite3_stricmp((const char*)zCopy, (const char*)zCmp);
+ sqlite3_free(zCopy);
+ return SQLITE_OK;
+}
+
+/*
+** zSql[] is a CREATE TABLE statement, supposedly. Find the offset
+** into zSql[] of the first character past the first "(" and write
+** that offset into *piOff and return SQLITE_OK. Or, if not found,
+** set the SQLITE_CORRUPT error code and return SQLITE_ERROR.
+*/
+static int skipCreateTable(sqlite3_context *ctx, const u8 *zSql, int *piOff){
+ int iOff = 0;
+
+ if( zSql==0 ) return SQLITE_ERROR;
+
+ /* Jump past the "CREATE TABLE" bit. */
+ while( 1 ){
+ int t = 0;
+ iOff += sqlite3GetToken(&zSql[iOff], &t);
+ if( t==TK_LP ) break;
+ if( t==TK_ILLEGAL ){
+ sqlite3_result_error_code(ctx, SQLITE_CORRUPT_BKPT);
+ return SQLITE_ERROR;
+ }
+ }
+
+ *piOff = iOff;
+ return SQLITE_OK;
+}
+
+/*
+** Internal SQL function sqlite3_drop_constraint(): Given an input
+** CREATE TABLE statement, return a revised CREATE TABLE statement
+** with a constraint removed. Two forms, depending on the datatype
+** of argv[2]:
+**
+** sqlite_drop_constraint(SQL, INT) -- Omit NOT NULL from the INT-th column
+** sqlite_drop_constraint(SQL, TEXT) -- OMIT constraint with name TEXT
+**
+** In the first case, the left-most column is 0.
+*/
+static void dropConstraintFunc(
+ sqlite3_context *ctx,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ const u8 *zSql = sqlite3_value_text(argv[0]);
+ const u8 *zCons = 0;
+ int iNotNull = -1;
+ int ii;
+ int iOff = 0;
+ int iStart = 0;
+ int iEnd = 0;
+ char *zNew = 0;
+ int t = 0;
+ sqlite3 *db;
+ UNUSED_PARAMETER(NotUsed);
+
+ if( zSql==0 ) return;
+
+ /* Jump past the "CREATE TABLE" bit. */
+ if( skipCreateTable(ctx, zSql, &iOff) ) return;
+
+ if( sqlite3_value_type(argv[1])==SQLITE_INTEGER ){
+ iNotNull = sqlite3_value_int(argv[1]);
+ }else{
+ zCons = sqlite3_value_text(argv[1]);
+ }
+
+ /* Search for the named constraint within column definitions. */
+ for(ii=0; iEnd==0; ii++){
+
+ /* Now parse the column or table constraint definition. Search
+ ** for the token CONSTRAINT if this is a DROP CONSTRAINT command, or
+ ** NOT in the right column if this is a DROP NOT NULL. */
+ while( 1 ){
+ iStart = iOff;
+ iOff += getConstraintToken(&zSql[iOff], &t);
+ if( t==TK_CONSTRAINT && (zCons || iNotNull==ii) ){
+ /* Check if this is the constraint we are searching for. */
+ int nTok = 0;
+ int cmp = 1;
+
+ /* Skip past any whitespace. */
+ iOff += getWhitespace(&zSql[iOff]);
+
+ /* Compare the next token - which may be quoted - with the name of
+ ** the constraint being dropped. */
+ nTok = getConstraintToken(&zSql[iOff], &t);
+ if( zCons ){
+ if( quotedCompare(ctx, t, &zSql[iOff], nTok, zCons, &cmp) ) return;
+ }
+ iOff += nTok;
+
+ /* The next token is usually the first token of the constraint
+ ** definition. This is enough to tell the type of the constraint -
+ ** TK_NOT means it is a NOT NULL, TK_CHECK a CHECK constraint etc.
+ **
+ ** There is also the chance that the next token is TK_CONSTRAINT
+ ** (or TK_DEFAULT or TK_COLLATE), for example if a table has been
+ ** created as follows:
+ **
+ ** CREATE TABLE t1(cols, CONSTRAINT one CONSTRAINT two NOT NULL);
+ **
+ ** In this case, allow the "CONSTRAINT one" bit to be dropped by
+ ** this command if that is what is requested, or to advance to
+ ** the next iteration of the loop with &zSql[iOff] still pointing
+ ** to the CONSTRAINT keyword. */
+ nTok = getConstraintToken(&zSql[iOff], &t);
+ if( t==TK_CONSTRAINT || t==TK_DEFAULT || t==TK_COLLATE
+ || t==TK_COMMA || t==TK_RP || t==TK_GENERATED || t==TK_AS
+ ){
+ t = TK_CHECK;
+ }else{
+ iOff += nTok;
+ iOff += getConstraint(&zSql[iOff], t);
+ }
+
+ if( cmp==0 || (iNotNull>=0 && t==TK_NOT) ){
+ if( t!=TK_NOT && t!=TK_CHECK && t!=TK_REFERENCES && t!=TK_FOREIGN ){
+ errorMPrintf(ctx, "constraint may not be dropped: %s", zCons);
+ return;
+ }
+ iEnd = iOff;
+ break;
+ }
+
+ }else if( t==TK_NOT && iNotNull==ii ){
+ iEnd = iOff + getConstraint(&zSql[iOff], 0);
+ break;
+ }else if( t==TK_RP || t==TK_ILLEGAL ){
+ iEnd = -1;
+ break;
+ }else if( t==TK_COMMA ){
+ break;
+ }
+ }
+ }
+
+ /* If the constraint has not been found it is an error. */
+ if( iEnd<=0 ){
+ if( zCons ){
+ errorMPrintf(ctx, "no such constraint: %s", zCons);
+ }else{
+ /* SQLite follows postgres in that a DROP NOT NULL on a column that is
+ ** not NOT NULL is not an error. So just return the original SQL here. */
+ sqlite3_result_text(ctx, (const char*)zSql, -1, SQLITE_TRANSIENT);
+ }
+ }else{
+
+ /* Figure out if an extra space should be inserted after the constraint
+ ** is removed. And if an additional comma preceding the constraint
+ ** should be removed. */
+ const char *zSpace = " ";
+ iEnd += getWhitespace(&zSql[iEnd]);
+ sqlite3GetToken(&zSql[iEnd], &t);
+ if( t==TK_RP || t==TK_COMMA ){
+ zSpace = "";
+ if( zSql[iStart-1]==',' ) iStart--;
+ }
+
+ db = sqlite3_context_db_handle(ctx);
+ zNew = sqlite3MPrintf(db, "%.*s%s%s", iStart, zSql, zSpace, &zSql[iEnd]);
+ sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC);
+ }
+}
+
+/*
+** Internal SQL function:
+**
+** sqlite_add_constraint(SQL, CONSTRAINT-TEXT, ICOL)
+**
+** SQL is a CREATE TABLE statement. Return a modified version of
+** SQL that adds CONSTRAINT-TEXT at the end of the ICOL-th column
+** definition. (The left-most column defintion is 0.)
+*/
+static void addConstraintFunc(
+ sqlite3_context *ctx,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ const u8 *zSql = sqlite3_value_text(argv[0]);
+ const char *zCons = (const char*)sqlite3_value_text(argv[1]);
+ int iCol = sqlite3_value_int(argv[2]);
+ int iOff = 0;
+ int ii;
+ sqlite3_str *pNew;
+ int t = 0;
+ UNUSED_PARAMETER(NotUsed);
+
+ if( skipCreateTable(ctx, zSql, &iOff) ) return;
+
+ for(ii=0; ii<=iCol || (iCol<0 && t!=TK_RP); ii++){
+ iOff += getConstraintToken(&zSql[iOff], &t);
+ while( 1 ){
+ int nTok = getConstraintToken(&zSql[iOff], &t);
+ if( t==TK_COMMA || t==TK_RP ) break;
+ if( t==TK_ILLEGAL ){
+ sqlite3_result_error_code(ctx, SQLITE_CORRUPT_BKPT);
+ return;
+ }
+ iOff += nTok;
+ }
+ }
+
+ iOff += getWhitespace(&zSql[iOff]);
+
+ pNew = sqlite3_str_new(sqlite3_context_db_handle(ctx));
+ sqlite3_str_append(pNew, (const char*)zSql, iOff);
+ if( iCol<0 ) sqlite3_str_append(pNew, ",", 1);
+ sqlite3_str_appendf(pNew, " %s%s", zCons, &zSql[iOff]);
+ sqlite3_result_str(ctx, pNew, SQLITE_FINISH);
+}
+
+/*
+** Find a column named pCol in table pTab. If successful, set output
+** parameter *piCol to the index of the column in the table and return
+** SQLITE_OK. Otherwise, set *piCol to -1 and return an SQLite error
+** code.
+*/
+static int alterFindCol(Parse *pParse, Table *pTab, Token *pCol, int *piCol){
+ sqlite3 *db = pParse->db;
+ char *zName = sqlite3NameFromToken(db, pCol);
+ int rc = SQLITE_NOMEM;
+ int iCol = -1;
+
+ if( zName ){
+ iCol = sqlite3ColumnIndex(pTab, zName);
+ if( iCol<0 ){
+ sqlite3ErrorMsg(pParse, "no such column: %s", zName);
+ rc = SQLITE_ERROR;
+ }else{
+ rc = SQLITE_OK;
+ }
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( rc==SQLITE_OK ){
+ const char *zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
+ const char *zCol = pTab->aCol[iCol].zCnName;
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){
+ pTab = 0;
+ }
+ }
+#endif
+
+ sqlite3DbFree(db, zName);
+ *piCol = iCol;
+ return rc;
+}
+
+
+/*
+** Find the table named by the first entry in source list pSrc. If successful,
+** return a pointer to the Table structure and set output variable (*pzDb)
+** to point to the name of the database containin the table (i.e. "main",
+** "temp" or the name of an attached database).
+**
+** If the table cannot be located, return NULL. The value of the two output
+** parameters is undefined in this case.
+*/
+static Table *alterFindTable(
+ Parse *pParse, /* Parsing context */
+ SrcList *pSrc, /* Name of the table to look for */
+ int *piDb, /* OUT: write the iDb here */
+ const char **pzDb, /* OUT: write name of schema here */
+ int bAuth /* Do ALTER TABLE authorization checks if true */
+){
+ sqlite3 *db = pParse->db;
+ Table *pTab = 0;
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
+ if( pTab ){
+ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ *pzDb = db->aDb[iDb].zDbSName;
+ *piDb = iDb;
+
+ if( SQLITE_OK!=isRealTable(pParse, pTab, 2)
+ || SQLITE_OK!=isAlterableTable(pParse, pTab)
+ ){
+ pTab = 0;
+ }
+ }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pTab && bAuth ){
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, *pzDb, pTab->zName, 0) ){
+ pTab = 0;
+ }
+ }
+#endif
+ sqlite3SrcListDelete(db, pSrc);
+ return pTab;
+}
+
+/*
+** Generate bytecode for one of:
+**
+** (1) ALTER TABLE pSrc DROP CONSTRAINT pCons
+** (2) ALTER TABLE pSrc ALTER pCol DROP NOT NULL
+**
+** One of pCons and pCol must be NULL and the other non-null.
+*/
+SQLITE_PRIVATE void sqlite3AlterDropConstraint(
+ Parse *pParse, /* Parsing context */
+ SrcList *pSrc, /* The table being altered */
+ Token *pCons, /* Name of the constraint to drop */
+ Token *pCol /* Name of the column from which to remove the NOT NULL */
+){
+ sqlite3 *db = pParse->db;
+ Table *pTab = 0;
+ int iDb = 0;
+ const char *zDb = 0;
+ char *zArg = 0;
+
+ assert( (pCol==0)!=(pCons==0) );
+ assert( pSrc->nSrc==1 );
+ pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, pCons!=0);
+ if( !pTab ) return;
+
+ if( pCons ){
+ char *z = sqlite3NameFromToken(db, pCons);
+ zArg = sqlite3MPrintf(db, "%Q", z);
+ sqlite3DbFree(db, z);
+ }else{
+ int iCol;
+ if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
+ zArg = sqlite3MPrintf(db, "%d", iCol);
+ }
+
+ /* Edit the SQL for the named table. */
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
+ "sql = sqlite_drop_constraint(sql, %s) "
+ "WHERE type='table' AND tbl_name=%Q COLLATE nocase"
+ , zDb, zArg, pTab->zName
+ );
+ sqlite3DbFree(db, zArg);
+
+ /* Finally, reload the database schema. */
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons);
+}
+
+/*
+** The implementation of SQL function sqlite_fail(MSG). This takes a single
+** argument, and returns it as an error message with the error code set to
+** SQLITE_CONSTRAINT.
+*/
+static void failConstraintFunc(
+ sqlite3_context *ctx,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ const char *zText = (const char*)sqlite3_value_text(argv[0]);
+ int err = sqlite3_value_int(argv[1]);
+ (void)NotUsed;
+ sqlite3_result_error(ctx, zText, -1);
+ sqlite3_result_error_code(ctx, err);
+}
+
+/*
+** Buffer pCons, which is nCons bytes in size, contains the text of a
+** NOT NULL or CHECK constraint that will be inserted into a CREATE TABLE
+** statement. If successful, this function returns the size of the buffer in
+** bytes not including any trailing whitespace or "--" style comments. Or,
+** if an OOM occurs, it returns 0 and sets db->mallocFailed to true.
+**
+** C-style comments at the end are preserved. "--" style comments are
+** removed because the comment terminator might be \000, and we are about
+** to insert the pCons[] text into the middle of a larger string, and that
+** will have the effect of removing the comment terminator and messing up
+** the syntax.
+*/
+static int alterRtrimConstraint(
+ sqlite3 *db, /* used to record OOM error */
+ const char *pCons, /* Buffer containing constraint */
+ int nCons /* Size of pCons in bytes */
+){
+ u8 *zTmp = (u8*)sqlite3MPrintf(db, "%.*s", nCons, pCons);
+ int iOff = 0;
+ int iEnd = 0;
+
+ if( zTmp==0 ) return 0;
+
+ while( 1 ){
+ int t = 0;
+ int nToken = sqlite3GetToken(&zTmp[iOff], &t);
+ if( t==TK_ILLEGAL ) break;
+ if( t!=TK_SPACE && (t!=TK_COMMENT || zTmp[iOff]!='-') ){
+ iEnd = iOff+nToken;
+ }
+ iOff += nToken;
+ }
+
+ sqlite3DbFree(db, zTmp);
+ return iEnd;
+}
+
+/*
+** Prepare a statement of the form:
+**
+** ALTER TABLE pSrc ALTER pCol SET NOT NULL
+*/
+SQLITE_PRIVATE void sqlite3AlterSetNotNull(
+ Parse *pParse, /* Parsing context */
+ SrcList *pSrc, /* Name of the table being altered */
+ Token *pCol, /* Name of the column to add a NOT NULL constraint to */
+ Token *pFirst /* The NOT token of the NOT NULL constraint text */
+){
+ Table *pTab = 0;
+ int iCol = 0;
+ int iDb = 0;
+ const char *zDb = 0;
+ const char *pCons = 0;
+ int nCons = 0;
+
+ /* Look up the table being altered. */
+ assert( pSrc->nSrc==1 );
+ pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 0);
+ if( !pTab ) return;
+
+ /* Find the column being altered. */
+ if( alterFindCol(pParse, pTab, pCol, &iCol) ){
+ return;
+ }
+
+ /* Find the length in bytes of the constraint definition */
+ pCons = pFirst->z;
+ nCons = alterRtrimConstraint(pParse->db, pCons, pParse->sLastToken.z - pCons);
+
+ /* Search for a constraint violation. Throw an exception if one is found. */
+ sqlite3NestedParse(pParse,
+ "SELECT sqlite_fail('constraint failed', %d) "
+ "FROM %Q.%Q AS x WHERE x.%.*s IS NULL",
+ SQLITE_CONSTRAINT, zDb, pTab->zName, (int)pCol->n, pCol->z
+ );
+
+ /* Edit the SQL for the named table. */
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
+ "sql = sqlite_add_constraint(sqlite_drop_constraint(sql, %d), %.*Q, %d) "
+ "WHERE type='table' AND tbl_name=%Q COLLATE nocase"
+ , zDb, iCol, nCons, pCons, iCol, pTab->zName
+ );
+
+ /* Finally, reload the database schema. */
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons);
+}
+
+/*
+** Implementation of internal SQL function:
+**
+** sqlite_find_constraint(SQL, CONSTRAINT-NAME)
+**
+** This function returns true if the SQL passed as the first argument is a
+** CREATE TABLE that contains a constraint with the name CONSTRAINT-NAME,
+** or false otherwise.
+*/
+static void findConstraintFunc(
+ sqlite3_context *ctx,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ const u8 *zSql = 0;
+ const u8 *zCons = 0;
+ int iOff = 0;
+ int t = 0;
+
+ (void)NotUsed;
+ zSql = sqlite3_value_text(argv[0]);
+ zCons = sqlite3_value_text(argv[1]);
+
+ if( zSql==0 || zCons==0 ) return;
+ while( t!=TK_LP && t!=TK_ILLEGAL ){
+ iOff += sqlite3GetToken(&zSql[iOff], &t);
+ }
+
+ while( 1 ){
+ iOff += getConstraintToken(&zSql[iOff], &t);
+ if( t==TK_CONSTRAINT ){
+ int nTok = 0;
+ int cmp = 0;
+ iOff += getWhitespace(&zSql[iOff]);
+ nTok = getConstraintToken(&zSql[iOff], &t);
+ if( quotedCompare(ctx, t, &zSql[iOff], nTok, zCons, &cmp) ) return;
+ if( cmp==0 ){
+ sqlite3_result_int(ctx, 1);
+ return;
+ }
+ }else if( t==TK_ILLEGAL ){
+ break;
+ }
+ }
+
+ sqlite3_result_int(ctx, 0);
+}
+
+/*
+** Generate bytecode to implement:
+**
+** ALTER TABLE pSrc ADD [CONSTRAINT pName] CHECK(pExpr)
+**
+** Any "ON CONFLICT" text that occurs after the "CHECK(...)", up
+** until pParse->sLastToken, is included as part of the new constraint.
+*/
+SQLITE_PRIVATE void sqlite3AlterAddConstraint(
+ Parse *pParse, /* Parse context */
+ SrcList *pSrc, /* Table to add constraint to */
+ Token *pFirst, /* First token of new constraint */
+ Token *pName, /* Name of new constraint. NULL if name omitted. */
+ const char *zExpr, /* Text of CHECK expression */
+ int nExpr, /* Size of pExpr in bytes */
+ Expr *pExpr /* The parsed CHECK expression */
+){
+ Table *pTab = 0; /* Table identified by pSrc */
+ int iDb = 0; /* Which schema does pTab live in */
+ const char *zDb = 0; /* Name of the schema in which pTab lives */
+ const char *pCons = 0; /* Text of the constraint */
+ int nCons; /* Bytes of text to use from pCons[] */
+ int rc; /* Result from error checking pExpr */
+
+ /* Look up the table being altered. */
+ assert( pSrc->nSrc==1 );
+ pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
+ if( !pTab ){
+ sqlite3ExprDelete(pParse->db, pExpr);
+ return;
+ }
+
+ /* Verify that the new CHECK constraint does not contain any
+ ** internal-use-only function. Forum post 2026-05-10T01:11:28Z
+ */
+ rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
+ sqlite3ExprDelete(pParse->db, pExpr);
+ if( rc ) return;
+
+ /* If this new constraint has a name, check that it is not a duplicate of
+ ** an existing constraint. It is an error if it is. */
+ if( pName ){
+ char *zName = sqlite3NameFromToken(pParse->db, pName);
+
+ sqlite3NestedParse(pParse,
+ "SELECT sqlite_fail('constraint %q already exists', %d) "
+ "FROM \"%w\"." LEGACY_SCHEMA_TABLE " "
+ "WHERE type='table' AND tbl_name=%Q COLLATE nocase "
+ "AND sqlite_find_constraint(sql, %Q)",
+ zName, SQLITE_ERROR, zDb, pTab->zName, zName
+ );
+ sqlite3DbFree(pParse->db, zName);
+ }
+
+ /* Search for a constraint violation. Throw an exception if one is found. */
+ sqlite3NestedParse(pParse,
+ "SELECT sqlite_fail('constraint failed', %d) "
+ "FROM %Q.%Q WHERE (%.*s) IS FALSE",
+ SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
+ );
+
+ /* Edit the SQL for the named table. */
+ pCons = pFirst->z;
+ nCons = alterRtrimConstraint(pParse->db, pCons, pParse->sLastToken.z - pCons);
+
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
+ "sql = sqlite_add_constraint(sql, %.*Q, -1) "
+ "WHERE type='table' AND tbl_name=%Q COLLATE nocase"
+ , zDb, nCons, pCons, pTab->zName
+ );
+
+ /* Finally, reload the database schema. */
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons);
+}
+
/*
** Register built-in functions used to help implement ALTER TABLE
*/
@@ -121435,6 +123827,10 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void){
INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
+ INTERNAL_FUNCTION(sqlite_drop_constraint,2, dropConstraintFunc),
+ INTERNAL_FUNCTION(sqlite_fail, 2, failConstraintFunc),
+ INTERNAL_FUNCTION(sqlite_add_constraint, 3, addConstraintFunc),
+ INTERNAL_FUNCTION(sqlite_find_constraint,2, findConstraintFunc),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
@@ -122320,7 +124716,7 @@ static void statGet(
assert( p->current.anEq[i] || p->nRow==0 );
#endif
}
- sqlite3ResultStrAccum(context, &sStat);
+ sqlite3_result_str(context, &sStat, SQLITE_XFER);
}
#ifdef SQLITE_ENABLE_STAT4
else if( eCall==STAT_GET_ROWID ){
@@ -122357,7 +124753,7 @@ static void statGet(
sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]);
}
if( sStat.nChar ) sStat.nChar--;
- sqlite3ResultStrAccum(context, &sStat);
+ sqlite3_result_str(context, &sStat, SQLITE_XFER);
}
#endif /* SQLITE_ENABLE_STAT4 */
#ifndef SQLITE_DEBUG
@@ -123258,9 +125654,9 @@ static int loadStatTbl(
}
pIdx->nSampleCol = nIdxCol;
pIdx->mxSample = nSample;
- nByte = ROUND8(sizeof(IndexSample) * nSample);
- nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
- nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
+ nByte = ROUND8(sizeof64(IndexSample) * nSample);
+ nByte += sizeof64(tRowcnt) * nIdxCol * 3 * nSample;
+ nByte += nIdxCol * sizeof64(tRowcnt); /* Space for Index.aAvgEq[] */
pIdx->aSample = sqlite3DbMallocZero(db, nByte);
if( pIdx->aSample==0 ){
@@ -123268,7 +125664,7 @@ static int loadStatTbl(
return SQLITE_NOMEM_BKPT;
}
pPtr = (u8*)pIdx->aSample;
- pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
+ pPtr += ROUND8(nSample*sizeof64(pIdx->aSample[0]));
pSpace = (tRowcnt*)pPtr;
assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
@@ -123515,6 +125911,23 @@ SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){
);
}
+/*
+** If any TEMP triggers reference schema pSchema, move those triggers to
+** reference the TEMP schema itself.
+*/
+static void detachTempTriggers(sqlite3 *db, Schema *pSchema){
+ HashElem *pEntry;
+ assert( db->aDb[1].pSchema );
+ pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash);
+ while( pEntry ){
+ Trigger *pTrig = (Trigger*)sqliteHashData(pEntry);
+ if( pTrig->pTabSchema==pSchema ){
+ pTrig->pTabSchema = pTrig->pSchema;
+ }
+ pEntry = sqliteHashNext(pEntry);
+ }
+}
+
/*
** An SQL user-function registered to do the work of an ATTACH statement. The
** three arguments to the function come directly from an attach statement:
@@ -123565,6 +125978,16 @@ static void attachFunc(
** from sqlite3_deserialize() to close database db->init.iDb and
** reopen it as a MemDB */
Btree *pNewBt = 0;
+
+ pNew = &db->aDb[db->init.iDb];
+ assert( pNew->pBt!=0 );
+ if( sqlite3BtreeTxnState(pNew->pBt)!=SQLITE_TXN_NONE
+ || sqlite3BtreeIsInBackup(pNew->pBt)
+ ){
+ rc = SQLITE_BUSY;
+ goto attach_error;
+ }
+
pVfs = sqlite3_vfs_find("memdb");
if( pVfs==0 ) return;
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
@@ -123574,10 +125997,16 @@ static void attachFunc(
/* Both the Btree and the new Schema were allocated successfully.
** Close the old db and update the aDb[] slot with the new memdb
** values. */
- pNew = &db->aDb[db->init.iDb];
- if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt);
+ detachTempTriggers(db, pNew->pSchema);
+ sqlite3BtreeClose(pNew->pBt);
pNew->pBt = pNewBt;
pNew->pSchema = pNewSchema;
+ if( db->init.iDb==0 ){
+ /* Clear all eponymous virtual table instances, as they are holding
+ ** pointers to the schema object just freed by sqlite3BtreeClose() */
+ sqlite3VtabEponymousTableClearAll(db);
+ }
+ sqlite3ExpirePreparedStatements(db, 1);
}else{
sqlite3BtreeClose(pNewBt);
rc = SQLITE_NOMEM;
@@ -123749,7 +126178,6 @@ static void detachFunc(
sqlite3 *db = sqlite3_context_db_handle(context);
int i;
Db *pDb = 0;
- HashElem *pEntry;
char zErr[128];
UNUSED_PARAMETER(NotUsed);
@@ -123776,18 +126204,7 @@ static void detachFunc(
goto detach_error;
}
- /* If any TEMP triggers reference the schema being detached, move those
- ** triggers to reference the TEMP schema itself. */
- assert( db->aDb[1].pSchema );
- pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash);
- while( pEntry ){
- Trigger *pTrig = (Trigger*)sqliteHashData(pEntry);
- if( pTrig->pTabSchema==pDb->pSchema ){
- pTrig->pTabSchema = pTrig->pSchema;
- }
- pEntry = sqliteHashNext(pEntry);
- }
-
+ detachTempTriggers(db, pDb->pSchema);
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
pDb->pSchema = 0;
@@ -124055,7 +126472,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(
if( sqlite3WalkSelect(&pFix->w, pStep->pSelect)
|| sqlite3WalkExpr(&pFix->w, pStep->pWhere)
|| sqlite3WalkExprList(&pFix->w, pStep->pExprList)
- || sqlite3FixSrcList(pFix, pStep->pFrom)
+ || sqlite3FixSrcList(pFix, pStep->pSrc)
){
return 1;
}
@@ -124162,7 +126579,7 @@ SQLITE_API int sqlite3_set_authorizer(
sqlite3_mutex_enter(db->mutex);
db->xAuth = (sqlite3_xauth)xAuth;
db->pAuthArg = pArg;
- if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1);
+ sqlite3ExpirePreparedStatements(db, 1);
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -124273,8 +126690,14 @@ SQLITE_PRIVATE void sqlite3AuthRead(
** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
** is returned, then the error count and error message in pParse are
** modified appropriately.
+**
+** Divided into two routines. realAuthCheck() does the work. The
+** sqlite3AuthCheck() routine is usually a fast no-op but invokes
+** realAuthCheck() (and spends time doing some stack pushes and pops
+** as a result) in the uncommon case where an authorization check is
+** actually needed.
*/
-SQLITE_PRIVATE int sqlite3AuthCheck(
+static int SQLITE_NOINLINE realAuthCheck(
Parse *pParse,
int code,
const char *zArg1,
@@ -124288,7 +126711,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->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
+ if( IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
@@ -124313,6 +126736,19 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
}
return rc;
}
+SQLITE_PRIVATE int sqlite3AuthCheck(
+ Parse *pParse,
+ int code,
+ const char *zArg1,
+ const char *zArg2,
+ const char *zArg3
+){
+ if( pParse->db->xAuth!=0 && pParse->db->init.busy==0 ){
+ return realAuthCheck(pParse,code,zArg1,zArg2,zArg3);
+ }else{
+ return SQLITE_OK;
+ }
+}
/*
** Push an authorization context. After this routine is called, the
@@ -124417,6 +126853,7 @@ static SQLITE_NOINLINE void lockTable(
assert( pToplevel->nTableLock < 0x7fff0000 );
nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
+ if( pToplevel->nTableLock==0 ) pToplevel->aTableLock = 0;
pToplevel->aTableLock =
sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
if( pToplevel->aTableLock ){
@@ -124583,7 +127020,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
/* Initialize any AUTOINCREMENT data structures required.
*/
- if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse);
+ if( pParse->usesAinc ) sqlite3AutoincrementBegin(pParse);
/* Code constant expressions that were factored out of inner loops.
*/
@@ -124616,7 +127053,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
if( pParse->nErr==0 ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
- assert( pParse->pAinc==0 || pParse->nTab>0 );
+ assert( pParse->usesAinc==0 || pParse->nTab>0 );
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
}else{
@@ -124833,6 +127270,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
const char *zDb;
if( p->fg.fixedSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
+ assert( iDb>=0 && iDbdb->nDb );
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
assert( !p->fg.isSubquery );
@@ -124984,6 +127422,7 @@ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
for(i=0; inDb; i++){
if( DbHasProperty(db, i, DB_ResetWanted) ){
sqlite3SchemaClear(db->aDb[i].pSchema);
+ db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
}
}
}
@@ -125047,10 +127486,41 @@ SQLITE_PRIVATE void sqlite3ColumnSetExpr(
}
}
+#ifndef SQLITE_OMIT_AUTHORIZATION
+/*
+** If the expression contains any TK_FUNCTION, send it to the authorizer
+** and if the authorization fails then raise an error.
+*/
+static int authFunctions(Walker *pWalker, Expr *p){
+ if( p->op==TK_FUNCTION ){
+ Parse *pParse = pWalker->pParse;
+ int rc = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, p->u.zToken, 0);
+ if( rc ){
+ sqlite3ErrorMsg(pParse, "not authorized to use function: %#T", p);
+ return WRC_Abort;
+ }
+ }
+ return WRC_Continue;
+}
+static void sqlite3FuncAuth(Parse *pParse, Expr *pExpr){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = authFunctions;
+ w.pParse = pParse;
+ sqlite3WalkExpr(&w,pExpr);
+}
+#endif /* SQLITE_OMIT_AUTHORIZATION */
+
/*
** Return the expression associated with a column. The expression might be
** the DEFAULT clause or the AS clause of a generated column.
** Return NULL if the column has no associated expression.
+**
+** There are two variants of this routine. sqlite3ColumnExpr() just
+** returns the expression with no side effects. sqlite3ColumnExprAuth()
+** takes the extra step of invoking the authorizer (if one is defined)
+** and raising an error if the returned expression uses any unauthorized
+** SQL function.
*/
SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( pCol->iDflt==0 ) return 0;
@@ -125059,6 +127529,28 @@ SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( NEVER(pTab->u.tab.pDfltList->nExpriDflt) ) return 0;
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
}
+SQLITE_PRIVATE Expr *sqlite3ColumnExprAuth(Table *pTab, Column *pCol, Parse *pParse){
+ Expr *pExpr = sqlite3ColumnExpr(pTab,pCol);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pParse->db->xAuth!=0 ){
+ sqlite3FuncAuth(pParse, pExpr);
+ }
+#endif
+ return pExpr;
+}
+
+/*
+** Suppress false-positive warning message generated with -O3 in GCC
+** on the second call to sqlite3Strlen30() in the sqlite3ColumnSetColl()
+** function below. See the forum thread beginning on 2026-05-10T01:11:22Z.
+**
+** See also the "pop" pragma to undo this warning suppression immediately
+** after the function.
+*/
+#if defined(__GNUC__) && __GNUC__>=11
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstringop-overread"
+#endif
/*
** Set the collating sequence name for a column.
@@ -125085,6 +127577,11 @@ SQLITE_PRIVATE void sqlite3ColumnSetColl(
}
}
+/* Undo the false-positive warning suppression above. */
+#if defined(__GNUC__) && __GNUC__>=11
+# pragma GCC diagnostic pop
+#endif
+
/*
** Return the collating sequence name for a column
*/
@@ -126107,6 +128604,13 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(
pDfltExpr = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
sqlite3DbFree(db, x.u.zToken);
sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Reject unauthorized functions from DEFAULT clauses */
+ if( db->init.busy==0 && db->xAuth!=0 ){
+ sqlite3FuncAuth(pParse, pExpr);
+ }
+#endif /* SQLITE_OMIT_AUTHORIZER */
+
}
}
if( IN_RENAME_OBJECT ){
@@ -126406,8 +128910,8 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){
** The estimate is conservative. It might be larger that what is
** really needed.
*/
-static int identLength(const char *z){
- int n;
+static i64 identLength(const char *z){
+ i64 n;
for(n=0; *z; n++, z++){
if( *z=='"' ){ n++; }
}
@@ -126562,6 +129066,23 @@ static int resizeIndexObject(Parse *pParse, Index *pIdx, int N){
return SQLITE_OK;
}
+/*
+** Return true if the index pIdx can support a Bloom filter on its
+** first N columns. Specifically, return true if all of the first N
+** columns have the BINARY collating sequence or no collating sequence
+** at all, and return false if there are any non-BINARY collating
+** seqeuences on any of the first N columns. tag-202607231411
+*/
+SQLITE_PRIVATE int sqlite3IndexBloomable(const Index *pIdx, int N){
+ int i;
+ assert( pIdx!=0 );
+ assert( N <= pIdx->nColumn );
+ for(i=0; iazColl[i],"BINARY")!=0 ) return 0;
+ }
+ return 1;
+}
+
/*
** Estimate the total row width for a table.
*/
@@ -126840,9 +129361,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( !hasColumn(pPk->aiColumn, j, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
){
+ const char *zColl = sqlite3ColumnColl(&pTab->aCol[i]);
assert( jnColumn );
pPk->aiColumn[j] = i;
- pPk->azColl[j] = sqlite3StrBINARY;
+ pPk->azColl[j] = zColl ? zColl : sqlite3StrBINARY;
j++;
}
}
@@ -126912,18 +129434,16 @@ SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){
/*
** Return true if zName is a shadow table name in the current database
** connection.
-**
-** zName is temporarily modified while this routine is running, but is
-** restored to its original value prior to this routine returning.
*/
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
- char *zTail; /* Pointer to the last "_" in zName */
+ const char *zTail; /* Pointer to the last "_" in zName */
Table *pTab; /* Table that zName is a shadow of */
+ char *zCopy; /* Transient copy of zName after last "_" */
zTail = strrchr(zName, '_');
if( zTail==0 ) return 0;
- *zTail = 0;
- pTab = sqlite3FindTable(db, zName, 0);
- *zTail = '_';
+ zCopy = sqlite3DbStrNDup(db, zName, (int)(zTail-zName));
+ pTab = zCopy ? sqlite3FindTable(db, zCopy, 0) : 0;
+ sqlite3DbFree(db, zCopy);
if( pTab==0 ) return 0;
if( !IsVirtual(pTab) ) return 0;
return sqlite3IsShadowTableOf(db, pTab, zName);
@@ -126957,7 +129477,6 @@ static void markExprListImmutable(ExprList *pList){
#define markExprListImmutable(X) /* no-op */
#endif /* SQLITE_DEBUG */
-
/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
@@ -127076,6 +129595,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
convertToWithoutRowidTable(pParse, p);
}
iDb = sqlite3SchemaToIndex(db, p->pSchema);
+ assert( iDb>=0 && iDb<=db->nDb );
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
@@ -127371,6 +129891,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
+ assert( iDb>=0 && iDbnDb );
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
@@ -128428,8 +130949,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
+ }else if( db->init.busy ){
+ sqlite3ErrorMsg(pParse,""); /* corruptSchema() will do the error */
}else{
- assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3ForceNotReadOnly(pParse);
}
@@ -128967,6 +131489,7 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
goto exit_drop_index;
}
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
+ assert( iDb>=0 && iDbnDb );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_INDEX;
@@ -129864,8 +132387,7 @@ SQLITE_PRIVATE void sqlite3RowidConstraint(
}
/*
-** Check to see if pIndex uses the collating sequence pColl. Return
-** true if it does and false if it does not.
+** Return true if any column of pIndex uses the zColl collation
*/
#ifndef SQLITE_OMIT_REINDEX
static int collationMatch(const char *zColl, Index *pIndex){
@@ -129873,8 +132395,8 @@ static int collationMatch(const char *zColl, Index *pIndex){
assert( zColl!=0 );
for(i=0; inColumn; i++){
const char *z = pIndex->azColl[i];
- assert( z!=0 || pIndex->aiColumn[i]<0 );
- if( pIndex->aiColumn[i]>=0 && 0==sqlite3StrICmp(z, zColl) ){
+ assert( z!=0 );
+ if( 0==sqlite3StrICmp(z, zColl) ){
return 1;
}
}
@@ -129882,73 +132404,39 @@ static int collationMatch(const char *zColl, Index *pIndex){
}
#endif
-/*
-** Recompute all indices of pTab that use the collating sequence pColl.
-** If pColl==0 then recompute all indices of pTab.
-*/
-#ifndef SQLITE_OMIT_REINDEX
-static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
- 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);
- }
- }
- }
-}
-#endif
-
-/*
-** Recompute all indices of all tables in all databases where the
-** indices use the collating sequence pColl. If pColl==0 then recompute
-** all indices everywhere.
-*/
-#ifndef SQLITE_OMIT_REINDEX
-static void reindexDatabases(Parse *pParse, char const *zColl){
- Db *pDb; /* A single database */
- int iDb; /* The database index number */
- sqlite3 *db = pParse->db; /* The database connection */
- HashElem *k; /* For looping over tables in pDb */
- Table *pTab; /* A table in the database */
-
- assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */
- for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){
- assert( pDb!=0 );
- for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
- pTab = (Table*)sqliteHashData(k);
- reindexTable(pParse, pTab, zColl);
- }
- }
-}
-#endif
-
/*
** Generate code for the REINDEX command.
**
** REINDEX -- 1
** REINDEX -- 2
-** REINDEX ?.? -- 3
-** REINDEX ?.? -- 4
+** REINDEX ?.? -- 3
+** REINDEX ?.? -- 4
+** REINDEX EXPRESSIONS -- 5
**
-** Form 1 causes all indices in all attached databases to be rebuilt.
-** Form 2 rebuilds all indices in all databases that use the named
+** Form 1 causes all indexes in all attached databases to be rebuilt.
+** Form 2 rebuilds all indexes in all databases that use the named
** collating function. Forms 3 and 4 rebuild the named index or all
-** indices associated with the named table.
+** indexes associated with the named table, respectively. Form 5
+** rebuilds all expression indexes in addition to all collations,
+** indexes, or tables named "EXPRESSIONS".
+**
+** If the name is ambiguous such that it matches two or more of
+** forms 2 through 5, then rebuild the union of all matching indexes,
+** taken care to avoid rebuilding the same index more than once.
*/
#ifndef SQLITE_OMIT_REINDEX
SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
- CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */
- char *z; /* Name of a table or index */
- const char *zDb; /* Name of the database */
- Table *pTab; /* A table in the database */
- Index *pIndex; /* An index associated with pTab */
- int iDb; /* The database index number */
+ char *z = 0; /* Name of a table or index or collation */
+ const char *zDb = 0; /* Name of the database */
+ int iReDb = -1; /* The database index number */
sqlite3 *db = pParse->db; /* The database connection */
Token *pObjName; /* Name of the table or index to be reindexed */
+ int bMatch = 0; /* At least one name match */
+ const char *zColl = 0; /* Rebuild indexes using this collation */
+ Table *pReTab = 0; /* Rebuild all indexes of this table */
+ Index *pReIndex = 0; /* Rebuild this index */
+ int isExprIdx = 0; /* Rebuild all expression indexes */
+ int bAll = 0; /* Rebuild all indexes */
/* Read the database schema. If an error occurs, leave an error message
** and code in pParse and return NULL. */
@@ -129957,41 +132445,66 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
}
if( pName1==0 ){
- reindexDatabases(pParse, 0);
- return;
+ /* rebuild all indexes */
+ bMatch = 1;
+ bAll = 1;
}else if( NEVER(pName2==0) || pName2->z==0 ){
- char *zColl;
assert( pName1->z );
- zColl = sqlite3NameFromToken(pParse->db, pName1);
- if( !zColl ) return;
- pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
- if( pColl ){
- reindexDatabases(pParse, zColl);
- sqlite3DbFree(db, zColl);
- return;
+ z = sqlite3NameFromToken(pParse->db, pName1);
+ if( z==0 ) return;
+ }else{
+ iReDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
+ if( iReDb<0 ) return;
+ z = sqlite3NameFromToken(db, pObjName);
+ if( z==0 ) return;
+ zDb = db->aDb[iReDb].zDbSName;
+ }
+ if( !bAll ){
+ if( zDb==0 && sqlite3StrICmp(z, "expressions")==0 ){
+ isExprIdx = 1;
+ bMatch = 1;
+ }
+ if( zDb==0 && sqlite3FindCollSeq(db, ENC(db), z, 0)!=0 ){
+ zColl = z;
+ bMatch = 1;
+ }
+ if( zColl==0 && (pReTab = sqlite3FindTable(db, z, zDb))!=0 ){
+ bMatch = 1;
+ }
+ if( zColl==0 && (pReIndex = sqlite3FindIndex(db, z, zDb))!=0 ){
+ bMatch = 1;
}
- sqlite3DbFree(db, zColl);
}
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
- if( iDb<0 ) return;
- z = sqlite3NameFromToken(db, pObjName);
- if( z==0 ) return;
- zDb = pName2->n ? db->aDb[iDb].zDbSName : 0;
- pTab = sqlite3FindTable(db, z, zDb);
- if( pTab ){
- reindexTable(pParse, pTab, 0);
- sqlite3DbFree(db, z);
- return;
+ if( bMatch ){
+ int iDb;
+ HashElem *k;
+ Table *pTab;
+ Index *pIdx;
+ Db *pDb;
+ for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){
+ assert( pDb!=0 );
+ if( iReDb>=0 && iReDb!=iDb ) continue;
+ for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
+ pTab = (Table*)sqliteHashData(k);
+ if( IsVirtual(pTab) ) continue;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( bAll
+ || pTab==pReTab
+ || pIdx==pReIndex
+ || (isExprIdx && pIdx->bHasExpr)
+ || (zColl!=0 && collationMatch(zColl,pIdx))
+ ){
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3RefillIndex(pParse, pIdx, -1);
+ }
+ } /* End loop over indexes of pTab */
+ } /* End loop over tables of iDb */
+ } /* End loop over databases */
+ }else{
+ sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
}
- pIndex = sqlite3FindIndex(db, z, zDb);
sqlite3DbFree(db, z);
- if( pIndex ){
- iDb = sqlite3SchemaToIndex(db, pIndex->pTable->pSchema);
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3RefillIndex(pParse, pIndex, -1);
- return;
- }
- sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
+ return;
}
#endif
@@ -130801,7 +133314,7 @@ static int vtabIsReadOnly(Parse *pParse, Table *pTab){
** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
** virtual tables if PRAGMA trusted_schema=ON.
*/
- if( pParse->pToplevel!=0
+ if( (pParse->pToplevel!=0 || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL))
&& pTab->u.vtab.p->eVtabRisk >
((pParse->db->flags & SQLITE_TrustedSchema)!=0)
){
@@ -131630,6 +134143,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
v = pParse->pVdbe;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+ int p3 = 0;
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
if( pIdx==pPk ) continue;
@@ -131637,9 +134151,12 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
&iPartIdxLabel, pPrior, r1);
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
- pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
- sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */
+ if( pIdx->bHasExpr && aRegIdx ){
+ p3 = aRegIdx[i];
+ }
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, p3);
+ sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
+ sqlite3VdbeChangeP5(v, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
pPrior = pIdx;
}
@@ -131878,13 +134395,17 @@ static void lengthFunc(
case SQLITE_TEXT: {
const unsigned char *z = sqlite3_value_text(argv[0]);
const unsigned char *z0;
- unsigned char c;
if( z==0 ) return;
z0 = z;
- while( (c = *z)!=0 ){
- z++;
- if( c>=0xc0 ){
- while( (*z & 0xc0)==0x80 ){ z++; z0++; }
+ while( 1 /*exit-by-break*/ ){
+ /* vvvvvv---- See tag-20260418-01 */
+ if( (u8)(z[0]-1)<(0x80-1) ){
+ z++;
+ }else if( z[0]==0 ){
+ break;
+ }else{
+ z++;
+ while( (z[0]&0xc0)==0x80 ){ z++; z0++; }
}
}
sqlite3_result_int(context, (int)(z-z0));
@@ -132064,7 +134585,6 @@ static void printfFunc(
PrintfArguments x;
StrAccum str;
const char *zFormat;
- int n;
sqlite3 *db = sqlite3_context_db_handle(context);
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
@@ -132074,9 +134594,7 @@ static void printfFunc(
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
str.printfFlags = SQLITE_PRINTF_SQLFUNC;
sqlite3_str_appendf(&str, zFormat, &x);
- n = str.nChar;
- sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
- SQLITE_DYNAMIC);
+ sqlite3_result_str(context, &str, SQLITE_XFER);
}
}
@@ -132125,7 +134643,7 @@ static void substrFunc(
p2 = sqlite3_value_int64(argv[2]);
if( p2==0 && sqlite3_value_type(argv[2])==SQLITE_NULL ) return;
}else{
- p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
+ p2 = LARGEST_INT64;
}
if( p1==0 ){
#ifdef SQLITE_SUBSTR_COMPATIBILITY
@@ -132163,12 +134681,25 @@ static void substrFunc(
}
assert( p1>=0 && p2>=0 );
if( p0type!=SQLITE_BLOB ){
- while( *z && p1 ){
- SQLITE_SKIP_UTF8(z);
- p1--;
+ for( ; p1>0; p1--){
+ /* vvvvvv---- See tag-20260418-01 */
+ if( (u8)(z[0]-1)<(0x80-1) ){
+ z++;
+ }else if( z[0]==0 ){
+ break;
+ }else{
+ do{ z++; }while( (z[0]&0xc0)==0x80 );
+ }
}
- for(z2=z; *z2 && p2; p2--){
- SQLITE_SKIP_UTF8(z2);
+ for(z2=z; p2>0; p2--){
+ /* vvvvvv---- See tag-20260418-01 */
+ if( (u8)(z2[0]-1)<(0x80-1) ){
+ z2++;
+ }else if( z2[0]==0 ){
+ break;
+ }else{
+ do{ z2++; }while( (z2[0]&0xc0)==0x80 );
+ }
}
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
SQLITE_UTF8);
@@ -132214,7 +134745,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_result_error_nomem(context);
return;
}
- sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
+ sqlite3AtoF(zBuf, &r);
sqlite3_free(zBuf);
}
sqlite3_result_double(context, r);
@@ -132846,18 +135377,11 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int
switch( sqlite3_value_type(pValue) ){
case SQLITE_FLOAT: {
- double r1, r2;
- const char *zVal;
- r1 = sqlite3_value_double(pValue);
- sqlite3_str_appendf(pStr, "%!0.15g", r1);
- zVal = sqlite3_str_value(pStr);
- if( zVal ){
- sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
- if( r1!=r2 ){
- sqlite3_str_reset(pStr);
- sqlite3_str_appendf(pStr, "%!0.20e", r1);
- }
- }
+ /* ,--- Show infinity as 9.0e+999
+ ** |
+ ** | ,--- 17 precision guarantees round-trip
+ ** v v */
+ sqlite3_str_appendf(pStr, "%!0.17g", sqlite3_value_double(pValue));
break;
}
case SQLITE_INTEGER: {
@@ -132949,7 +135473,7 @@ static void unistrFunc(
}
i = j = 0;
while( iaLimit[SQLITE_LIMIT_LENGTH]);
sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context)));
- sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
- SQLITE_DYNAMIC);
- if( str.accError!=SQLITE_OK ){
- sqlite3_result_null(context);
- sqlite3_result_error_code(context, str.accError);
- }
+ sqlite3_result_str(context, &str, SQLITE_XFER);
}
/*
@@ -133079,7 +135598,7 @@ static void charFunc(
} \
}
*zOut = 0;
- sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
+ sqlite3_result_text64(context, (char*)z, zOut-z,sqlite3_free,SQLITE_UTF8_ZT);
}
/*
@@ -133108,7 +135627,7 @@ static void hexFunc(
}
*z = 0;
sqlite3_result_text64(context, zHex, (u64)(z-zHex),
- sqlite3_free, SQLITE_UTF8);
+ sqlite3_free, SQLITE_UTF8_ZT);
}
}
@@ -133242,7 +135761,7 @@ static void replaceFunc(
int nRep; /* Size of zRep */
i64 nOut; /* Maximum size of zOut */
int loopLimit; /* Last zStr[] that might match zPattern[] */
- int i, j; /* Loop counters */
+ i64 i, j; /* Loop counters */
unsigned cntExpand; /* Number zOut expansions */
sqlite3 *db = sqlite3_context_db_handle(context);
@@ -133446,7 +135965,7 @@ static void concatFuncCore(
}
z[j] = 0;
assert( j<=n );
- sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8);
+ sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8_ZT);
}
/*
@@ -133563,6 +136082,21 @@ static void soundexFunc(
}
#endif /* SQLITE_SOUNDEX */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_BUILTIN_OOM_FUNCTION)
+/*
+** This SQL function just invokes sqlite3OomFault() and then returns
+** NULL. Used for testing only.
+*/
+static void oomFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ sqlite3OomFault(db);
+}
+#endif /* SQLITE_DEBUG || SQLITE_BUILTIN_OOM_FUNCTION */
+
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** A function that loads a shared-library extension then returns NULL.
@@ -133721,11 +136255,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
assert( p->cnt>0 );
p->cnt--;
if( !p->approx ){
- if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
- p->ovrfl = 1;
- p->approx = 1;
+ i64 x = p->iSum;
+ if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
+ p->iSum = x;
+ return;
}
- }else if( type==SQLITE_INTEGER ){
+ p->ovrfl = 1;
+ p->approx = 1;
+ kahanBabuskaNeumaierInit(p, p->iSum);
+ }
+ if( type==SQLITE_INTEGER ){
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal!=SMALLEST_INT64 ){
kahanBabuskaNeumaierStepInt64(p, -iVal);
@@ -134050,7 +136589,7 @@ static void groupConcatFinalize(sqlite3_context *context){
GroupConcatCtx *pGCC
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
if( pGCC ){
- sqlite3ResultStrAccum(context, &pGCC->str);
+ sqlite3_result_str(context, &pGCC->str, SQLITE_XFER);
#ifndef SQLITE_OMIT_WINDOWFUNC
sqlite3_free(pGCC->pnSepLengths);
#endif
@@ -134060,18 +136599,8 @@ static void groupConcatFinalize(sqlite3_context *context){
static void groupConcatValue(sqlite3_context *context){
GroupConcatCtx *pGCC
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
- if( pGCC ){
- StrAccum *pAccum = &pGCC->str;
- if( pAccum->accError==SQLITE_TOOBIG ){
- sqlite3_result_error_toobig(context);
- }else if( pAccum->accError==SQLITE_NOMEM ){
- sqlite3_result_error_nomem(context);
- }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
- sqlite3_result_text(context, "", 1, SQLITE_STATIC);
- }else{
- const char *zText = sqlite3_str_value(pAccum);
- sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
- }
+ if( pGCC && pGCC->nAccum>0 ){
+ sqlite3_result_str(context, &pGCC->str, SQLITE_COPY);
}
}
#else
@@ -134112,6 +136641,8 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc,
0, 0, 0, 0, 0);
pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0);
+ assert( pDef!=0 ); /* The sqlite3CreateFunc() call above cannot fail
+ ** because the "like" SQL-function already exists */
pDef->funcFlags |= flags;
pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE;
}
@@ -134689,54 +137220,105 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
** (1) To avoid a dependency on qsort()
** (2) To avoid the function call to the comparison routine for each
** comparison.
+**
+** If parameter iReq is non-negative, then the caller will only access
+** elements a[iReq] and a[iReq+1] (if it exists) of the sorted array and
+** so it is not necessary to position any other elements. Or if iReq is
+** negative, then the final array must be fully sorted.
*/
-static void percentSort(double *a, unsigned int n){
- int iLt; /* Entries before a[iLt] are less than rPivot */
- int iGt; /* Entries at or after a[iGt] are greater than rPivot */
+static void percentSort(
+ double *a, /* Array to sort */
+ unsigned int n, /* Number of elements in array a[] */
+ int iReq /* Element caller cares about (or -ve) */
+){
+ int iLt; /* Entries before a[iLt] are less than or equal to rPivot */
+ int iGt; /* Entries a[iGt] and after are greater or equal to rPivot */
int i; /* Loop counter */
double rPivot; /* The pivot value */
assert( n>=2 );
- if( a[0]>a[n-1] ){
- SWAP_DOUBLE(a[0],a[n-1])
- }
- if( n==2 ) return;
- iGt = n-1;
- i = n/2;
- if( a[0]>a[i] ){
- SWAP_DOUBLE(a[0],a[i])
- }else if( a[i]>a[iGt] ){
- SWAP_DOUBLE(a[i],a[iGt])
- }
- if( n==3 ) return;
- rPivot = a[i];
- iLt = i = 1;
do{
- if( a[i]iLt ) SWAP_DOUBLE(a[i],a[iLt])
- iLt++;
- i++;
- }else if( a[i]>rPivot ){
- do{
- iGt--;
- }while( iGt>i && a[iGt]>rPivot );
+ /* Put the first, middle, and last elements in sorted order.
+ ** After doing so, return immediately if the array contains
+ ** three or fewer elements as there is nothing more to do.
+ */
+ if( a[0]>a[n-1] ){
+ SWAP_DOUBLE(a[0],a[n-1])
+ }
+ if( n==2 ) return;
+ iGt = n-1;
+ i = n/2;
+ if( a[0]>a[i] ){
+ SWAP_DOUBLE(a[0],a[i])
+ }else if( a[i]>a[iGt] ){
SWAP_DOUBLE(a[i],a[iGt])
- }else{
- i++;
}
- }while( i=2 ) percentSort(a, iLt);
- if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
+ if( n==3 ) return;
-/* Uncomment for testing */
-#if 0
- for(i=0; iiLt ) SWAP_DOUBLE(a[i],a[iLt])
+ iLt++;
+ i++;
+ }else if( a[i]>rPivot ){
+ do{
+ iGt--;
+ }while( iGt>i && a[iGt]>rPivot );
+ SWAP_DOUBLE(a[i],a[iGt])
+ }else{
+ i++;
+ }
+ }while( i0 && iLtiLt+1 );
+ assert( a[iLt]==rPivot );
+ assert( a[iLt-1]<=rPivot );
+ assert( a[iGt]>=rPivot );
+ assert( a[iLt+1]>=rPivot );
+
+ if( iReq>=0 ){
+ /* In this case, the only elements that the caller requires sorted into
+ ** the correct positions are elements a[iReq] and a[iReq+1]. At this
+ ** point we know that element a[iLt] is in the correct position and
+ ** all elements smaller than a[iLt] are in the left-hand partition.
+ ** So if (iReq=iLt), then elements iReq and iReq+1 are either in the
+ ** right partition or the equal partition (elements for which
+ ** iLt<=iElem(int)(n/2) ){
+ if( n-iGt>=2 ) percentSort(a+iGt, n-iGt, -1);
+ n = iLt;
+ }else{
+ if( iLt>=2 ) percentSort(a, iLt, -1);
+ a += iGt;
+ n -= iGt;
+ }
+ }
+ }while( n>=2 );
}
-
/*
** The "inverse" function for percentile(Y,P) is called to remove a
** row that was previously inserted by "step".
@@ -134769,7 +137351,7 @@ static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
}
if( p->bSorted==0 ){
assert( p->nUsed>1 );
- percentSort(p->a, p->nUsed);
+ percentSort(p->a, p->nUsed, -1);
p->bSorted = 1;
}
p->bKeepSorted = 1;
@@ -134798,13 +137380,17 @@ static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
if( p==0 ) return;
if( p->a==0 ) return;
if( p->nUsed ){
+ ix = p->rPct*(p->nUsed-1);
+ i1 = (unsigned)ix;
if( p->bSorted==0 ){
+ /* In cases where bIsFinal is non-zero, setting Percentile.bSorted
+ ** after the percentSort() call here is not technically correct, as
+ ** the array is not fully sorted. But in this case the object will be
+ ** freed below anyway, so it doesn't matter. */
assert( p->nUsed>1 );
- percentSort(p->a, p->nUsed);
+ percentSort(p->a, p->nUsed, (bIsFinal ? (int)i1 : -1));
p->bSorted = 1;
}
- ix = p->rPct*(p->nUsed-1);
- i1 = (unsigned)ix;
if( settings & 1 ){
vx = p->a[i1];
}else{
@@ -134859,7 +137445,7 @@ static void filestatFunc(
assert( pPager!=0 );
fd = sqlite3PagerFile(pPager);
pStr = sqlite3_str_new(db);
- if( pStr==0 ){
+ if( sqlite3_str_errcode(pStr) ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_str_append(pStr, "{\"db\":", 6);
@@ -134872,8 +137458,7 @@ static void filestatFunc(
if( rc ) sqlite3_str_append(pStr, "null", 4);
}
sqlite3_str_append(pStr, "}", 1);
- sqlite3_result_text(context, sqlite3_str_finish(pStr), -1,
- sqlite3_free);
+ sqlite3_result_str(context, pStr, SQLITE_FINISH);
}
sqlite3BtreeLeave(pBtree);
}else{
@@ -134882,6 +137467,48 @@ static void filestatFunc(
}
#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_WALSTAT)
+/*
+** Implementation of sqlite_walstat(SCHEMA).
+**
+** Return JSON text that describes the current state of a WAL file.
+** This function is for debugging and analysis only. It is not part
+** of production builds. This function is not part of the SQLite API
+** and is likely to change or be removed in future versions of SQLite.
+*/
+static void walstatFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ const char *zDbName;
+ sqlite3_str *pStr;
+ Btree *pBtree;
+
+ zDbName = (const char*)sqlite3_value_text(argv[0]);
+ pBtree = sqlite3DbNameToBtree(db, zDbName);
+ if( pBtree ){
+ Pager *pPager;
+ sqlite3BtreeEnter(pBtree);
+ pPager = sqlite3BtreePager(pBtree);
+ assert( pPager!=0 );
+ pStr = sqlite3_str_new(db);
+ if( sqlite3_str_errcode(pStr) ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ sqlite3_str_append(pStr, "{", 1);
+ sqlite3PagerWalStat(pPager, pStr);
+ sqlite3_str_append(pStr, "}", 1);
+ sqlite3_result_str(context, pStr, SQLITE_FINISH);
+ }
+ sqlite3BtreeLeave(pBtree);
+ }else{
+ sqlite3_result_text(context, "{}", 2, SQLITE_STATIC);
+ }
+}
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_WALSTAT */
+
#ifdef SQLITE_DEBUG
/*
** Implementation of fpdecode(x,y,z) function.
@@ -134962,7 +137589,7 @@ static void parseuriFunc(
flgs = (unsigned int)sqlite3_value_int(argv[1]);
rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
pResult = sqlite3_str_new(0);
- if( pResult ){
+ if( !sqlite3_str_errcode(pResult) ){
int i;
sqlite3_str_appendf(pResult, "rc=%d", rc);
sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
@@ -134989,8 +137616,8 @@ static void parseuriFunc(
}
}
}
- sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free);
}
+ sqlite3_result_str(ctx, pResult, SQLITE_FINISH);
sqlite3_free_filename(zFile);
sqlite3_free(zErr);
}
@@ -135042,6 +137669,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
FUNCTION(sqlite_filestat, 1, 0, 0, filestatFunc ),
+ FUNCTION(sqlite_walstat, 1, 0, 0, walstatFunc ),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
@@ -135070,6 +137698,9 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ),
FUNCTION(parseuri, -1, 0, 0, parseuriFunc ),
#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_BUILTIN_OOM_FUNCTION)
+ FUNCTION(oom, -1, 0, 0, oomFunc ),
+#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
FUNCTION(round, 1, 0, 0, roundFunc ),
FUNCTION(round, 2, 0, 0, roundFunc ),
@@ -135087,7 +137718,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
- FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
+ SFUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
FUNCTION(unistr, 1, 0, 0, unistrFunc ),
FUNCTION(quote, 1, 0, 0, quoteFunc ),
FUNCTION(unistr_quote, 1, 1, 0, quoteFunc ),
@@ -135900,6 +138531,7 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){
static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
if( p ){
TriggerStep *pStep = p->step_list;
+ sqlite3SrcListDelete(dbMem, pStep->pSrc);
sqlite3ExprDelete(dbMem, pStep->pWhere);
sqlite3ExprListDelete(dbMem, pStep->pExprList);
sqlite3SelectDelete(dbMem, pStep->pSelect);
@@ -136119,6 +138751,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
if( !IsOrdinaryTable(pTab) ) return;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb>=00 && iDbnDb );
zDb = db->aDb[iDb].zDbSName;
/* Loop through all the foreign key constraints for which pTab is the
@@ -136516,7 +139149,7 @@ static Trigger *fkActionTrigger(
testcase( pCol->colFlags & COLFLAG_STORED );
pDflt = 0;
}else{
- pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol);
+ pDflt = sqlite3ColumnExprAuth(pFKey->pFrom, pCol, pParse);
}
if( pDflt ){
pNew = sqlite3ExprDup(db, pDflt, 0);
@@ -136536,7 +139169,6 @@ static Trigger *fkActionTrigger(
nFrom = sqlite3Strlen30(zFrom);
if( action==OE_Restrict ){
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
SrcList *pSrc;
Expr *pRaise;
@@ -136547,10 +139179,10 @@ static Trigger *fkActionTrigger(
}
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
- assert( pSrc->nSrc==1 );
- pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom);
- assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 );
- pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ SrcItem *pItem = &pSrc->a[0];
+ pItem->zName = sqlite3DbStrDup(db, zFrom);
+ pItem->fg.fixedSchema = 1;
+ pItem->u4.pSchema = pTab->pSchema;
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
@@ -136566,14 +139198,17 @@ static Trigger *fkActionTrigger(
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
sizeof(Trigger) + /* struct Trigger */
- sizeof(TriggerStep) + /* Single step in trigger program */
- nFrom + 1 /* Space for pStep->zTarget */
+ sizeof(TriggerStep) /* Single step in trigger program */
);
if( pTrigger ){
pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
- pStep->zTarget = (char *)&pStep[1];
- memcpy((char *)pStep->zTarget, zFrom, nFrom);
-
+ pStep->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
+ if( pStep->pSrc ){
+ SrcItem *pItem = &pStep->pSrc->a[0];
+ pItem->zName = sqlite3DbStrNDup(db, zFrom, nFrom);
+ pItem->u4.pSchema = pTab->pSchema;
+ pItem->fg.fixedSchema = 1;
+ }
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
@@ -137132,6 +139767,9 @@ static int autoIncBegin(
return 0;
}
+ if( pToplevel->usesAinc==0 ){
+ pToplevel->pAinc = 0;
+ }
pInfo = pToplevel->pAinc;
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
if( pInfo==0 ){
@@ -137141,6 +139779,7 @@ static int autoIncBegin(
if( pParse->db->mallocFailed ) return 0;
pInfo->pNext = pToplevel->pAinc;
pToplevel->pAinc = pInfo;
+ pToplevel->usesAinc = 1;
pInfo->pTab = pTab;
pInfo->iDb = iDb;
pToplevel->nMem++; /* Register to hold name of table */
@@ -137169,6 +139808,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
assert( sqlite3IsToplevel(pParse) );
assert( v ); /* We failed long ago if this is not so */
+ assert( pParse->usesAinc );
for(p = pParse->pAinc; p; p = p->pNext){
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList autoInc[] = {
@@ -137236,6 +139876,7 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
sqlite3 *db = pParse->db;
assert( v );
+ assert( pParse->usesAinc );
for(p = pParse->pAinc; p; p = p->pNext){
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList autoIncEnd[] = {
@@ -137268,7 +139909,7 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
}
}
SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
- if( pParse->pAinc ) autoIncrementEnd(pParse);
+ if( pParse->usesAinc ) autoIncrementEnd(pParse);
}
#else
/*
@@ -137295,25 +139936,13 @@ SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
}
}
-/*
-** Return true if all expressions in the expression-list passed as the
-** only argument are constant.
-*/
-static int exprListIsConstant(Parse *pParse, ExprList *pRow){
- int ii;
- for(ii=0; iinExpr; ii++){
- if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0;
- }
- return 1;
-}
-
/*
** Return true if all expressions in the expression-list passed as the
** only argument are both constant and have no affinity.
*/
static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){
int ii;
- if( exprListIsConstant(pParse,pRow)==0 ) return 0;
+ if( sqlite3ExprListIsConstant(pParse, pRow, 0)==0 ) return 0;
for(ii=0; iinExpr; ii++){
Expr *pExpr = pRow->a[ii].pExpr;
assert( pExpr->op!=TK_RAISE );
@@ -137379,7 +140008,7 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
if( pParse->bHasWith /* condition (a) above */
|| pParse->db->init.busy /* condition (b) above */
- || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */
+ || sqlite3ExprListIsConstant(pParse, pRow, 1)==0 /* condition (c) above */
|| (pLeft->pSrc->nSrc==0 &&
exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */
|| IN_SPECIAL_PARSE
@@ -138092,7 +140721,7 @@ SQLITE_PRIVATE void sqlite3Insert(
/* Hidden columns that are not explicitly named in the INSERT
** get their default value */
sqlite3ExprCodeFactorable(pParse,
- sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
+ sqlite3ColumnExprAuth(pTab, &pTab->aCol[i], pParse),
iRegStore);
continue;
}
@@ -138104,7 +140733,7 @@ SQLITE_PRIVATE void sqlite3Insert(
/* A column not named in the insert column list gets its
** default value */
sqlite3ExprCodeFactorable(pParse,
- sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
+ sqlite3ColumnExprAuth(pTab, &pTab->aCol[i], pParse),
iRegStore);
continue;
}
@@ -138112,7 +140741,7 @@ SQLITE_PRIVATE void sqlite3Insert(
}else if( nColumn==0 ){
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
sqlite3ExprCodeFactorable(pParse,
- sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
+ sqlite3ColumnExprAuth(pTab, &pTab->aCol[i], pParse),
iRegStore);
continue;
}else{
@@ -138163,6 +140792,7 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
+ sqlite3MayAbort(pParse);
}
/* Copy the new data already generated. */
@@ -138231,6 +140861,7 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, addr1+2); VdbeCoverage(v);
}
sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v);
+ sqlite3MayAbort(pParse);
}
}else if( IsVirtual(pTab) || withoutRowid ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
@@ -138710,7 +141341,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
nSeenReplace++;
sqlite3ExprCodeCopy(pParse,
- sqlite3ColumnExpr(pTab, pCol), iReg);
+ sqlite3ColumnExprAuth(pTab, pCol, pParse), iReg);
sqlite3VdbeJumpHere(v, addr1);
break;
}
@@ -138923,6 +141554,22 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
pTrigger = 0;
regTrigCnt = sqlite3FkRequired(pParse, pTab, 0, 0);
}
+ if( regTrigCnt ){
+ /* At this point regTrigCnt is non-zero if there are DELETE triggers
+ ** or FK triggers. But we only care about these things if there is
+ ** a chance that a row will be deleted by an ON CONFLICT REPLACE
+ ** constraint. So zero regTrigCnt if no such constraint can be found. */
+ if( overrideError!=OE_Replace ){
+ if( overrideError!=OE_Default ){
+ regTrigCnt = 0;
+ }else if( pkChng==0 || pPk || pTab->keyConf!=OE_Replace ){
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->onError==OE_Replace ) break;
+ }
+ if( pIdx==0 ) regTrigCnt = 0;
+ }
+ }
+ }
if( regTrigCnt ){
/* Replace triggers might exist. Allocate the counter and
** initialize it to zero. */
@@ -138974,9 +141621,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( onError==OE_Replace /* IPK rule is REPLACE */
&& onError!=overrideError /* Rules for other constraints are different */
&& pTab->pIndex /* There exist other constraints */
- && !upsertIpkDelay /* IPK check already deferred by UPSERT */
){
- ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
+ if( upsertIpkDelay ){
+ ipkTop = upsertIpkDelay + 1;
+ upsertIpkDelay = 0;
+ }else{
+ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
+ }
VdbeComment((v, "defer IPK REPLACE until last"));
}
@@ -139070,11 +141721,11 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeResolveLabel(v, addrRowidOk);
- if( pUpsert && pUpsertClause!=pUpsert ){
- upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto);
- }else if( ipkTop ){
+ if( ipkTop ){
ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, ipkTop-1);
+ }else if( pUpsert && pUpsertClause!=pUpsert ){
+ upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto);
}
}
@@ -139094,6 +141745,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int iThisCur; /* Cursor for this UNIQUE index */
int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */
int addrConflictCk; /* First opcode in the conflict check logic */
+ int nConflictCk; /* Number of opcodes in conflict check logic */
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
if( pUpsert ){
@@ -139270,6 +141922,11 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
+ nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
+ assert( nConflictCk>0 || db->mallocFailed );
+ testcase( nConflictCk<=0 );
+ testcase( nConflictCk>1 );
+
/* Generate code that executes if the new index entry is not unique */
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace || onError==OE_Update );
@@ -139295,13 +141952,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
break;
}
default: {
- int nConflictCk; /* Number of opcodes in conflict check logic */
-
assert( onError==OE_Replace );
- nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
- assert( nConflictCk>0 || db->mallocFailed );
- testcase( nConflictCk<=0 );
- testcase( nConflictCk>1 );
if( regTrigCnt ){
sqlite3MultiWrite(pParse);
nReplaceTrig++;
@@ -139315,57 +141966,57 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( pTrigger && isUpdate ){
sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur);
}
- if( regTrigCnt ){
- int addrBypass; /* Jump destination to bypass recheck logic */
+ seenReplace = 1;
+ break;
+ }
+ }
+ if( regTrigCnt ){
+ int addrBypass; /* Jump destination to bypass recheck logic */
- sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
- addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */
- VdbeComment((v, "bypass recheck"));
-
- /* Here we insert code that will be invoked after all constraint
- ** checks have run, if and only if one or more replace triggers
- ** fired. */
- sqlite3VdbeResolveLabel(v, lblRecheckOk);
- lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
- if( pIdx->pPartIdxWhere ){
- /* Bypass the recheck if this partial index is not defined
- ** for the current row */
- sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk);
- VdbeCoverage(v);
- }
- /* Copy the constraint check code from above, except change
- ** the constraint-ok jump destination to be the address of
- ** the next retest block */
- while( nConflictCk>0 ){
- VdbeOp x; /* Conflict check opcode to copy */
- /* The sqlite3VdbeAddOp4() call might reallocate the opcode array.
- ** Hence, make a complete copy of the opcode, rather than using
- ** a pointer to the opcode. */
- x = *sqlite3VdbeGetOp(v, addrConflictCk);
- if( x.opcode!=OP_IdxRowid ){
- int p2; /* New P2 value for copied conflict check opcode */
- const char *zP4;
- if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){
- p2 = lblRecheckOk;
- }else{
- p2 = x.p2;
- }
- zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z;
- sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type);
- sqlite3VdbeChangeP5(v, x.p5);
- VdbeCoverageIf(v, p2!=x.p2);
- }
- nConflictCk--;
- addrConflictCk++;
- }
- /* If the retest fails, issue an abort */
- sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);
+ sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
+ addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */
+ VdbeComment((v, "bypass recheck"));
- sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */
+ /* Here we insert code that will be invoked after all constraint
+ ** checks have run, if and only if one or more replace triggers
+ ** fired. */
+ sqlite3VdbeResolveLabel(v, lblRecheckOk);
+ lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
+ if( pIdx->pPartIdxWhere ){
+ /* Bypass the recheck if this partial index is not defined
+ ** for the current row */
+ sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk);
+ VdbeCoverage(v);
+ }
+ /* Copy the constraint check code from above, except change
+ ** the constraint-ok jump destination to be the address of
+ ** the next retest block */
+ while( nConflictCk>0 ){
+ VdbeOp x; /* Conflict check opcode to copy */
+ /* The sqlite3VdbeAddOp4() call might reallocate the opcode array.
+ ** Hence, make a complete copy of the opcode, rather than using
+ ** a pointer to the opcode. */
+ x = *sqlite3VdbeGetOp(v, addrConflictCk);
+ if( x.opcode!=OP_IdxRowid || isUpdate ){
+ int p2; /* New P2 value for copied conflict check opcode */
+ const char *zP4;
+ if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){
+ p2 = lblRecheckOk;
+ }else{
+ p2 = x.p2;
+ }
+ zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z;
+ sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type);
+ sqlite3VdbeChangeP5(v, x.p5);
+ VdbeCoverageIf(v, p2!=x.p2);
}
- seenReplace = 1;
- break;
+ nConflictCk--;
+ addrConflictCk++;
}
+ /* If the retest fails, issue an abort */
+ sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);
+
+ sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */
}
sqlite3VdbeResolveLabel(v, addrUniqueOk);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
@@ -139404,8 +142055,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}else{
sqlite3VdbeGoto(v, addrRecheck);
}
- sqlite3VdbeResolveLabel(v, lblRecheckOk);
}
+ if( regTrigCnt ) sqlite3VdbeResolveLabel(v, lblRecheckOk);
/* Generate the table record */
if( HasRowid(pTab) ){
@@ -139508,7 +142159,10 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
|| pIdx->pNext==0
|| pIdx->pNext->onError==OE_Replace );
if( aRegIdx[i]==0 ) continue;
- if( pIdx->pPartIdxWhere ){
+ if( pIdx->pPartIdxWhere || (update_flags && pIdx->bHasExpr) ){
+ /* If this is a partial index, or an UPDATE of an index on an
+ ** expression, then the record register may be set to NULL to indicate
+ ** that no record should be inserted into this index. */
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
}
@@ -139683,6 +142337,44 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
return 1;
}
+/*
+** Examine an expression node and abort if it references the ROWID.
+** This is a Walker callback used by xferCompatibleCheck()
+*/
+static int xferCheckRowid(Walker *pWalk, Expr *pExpr){
+ if( pExpr->op==TK_COLUMN && pExpr->iColumn<0 ){
+ pWalk->eCode = 1;
+ return WRC_Abort;
+ }else{
+ return WRC_Continue;
+ }
+}
+
+/*
+** Analyze CHECK constraints on the source and destination tables and
+** return true if those CHECK constraints are compatible with the
+** xfer-optimization.
+**
+** * The pDest and pSrc tables must have identical CHECK constraints.
+**
+** * If the destination table, pDest, does not have an
+** INTEGER PRIMARY KEY column, then no CHECK constraint may
+** referenced the ROWID. (See forum post 2026-05-11T13:15:57Z)
+*/
+static int xferCompatibleCheck(Table *pDest, Table *pSrc){
+ if( sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
+ return 0;
+ }
+ if( pDest->iPKey<0 ){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = xferCheckRowid;
+ sqlite3WalkExprList(&w,pDest->pCheck);
+ if( w.eCode ) return 0;
+ }
+ return 1;
+}
+
/*
** Attempt the transfer optimization on INSERTs of the form
**
@@ -139809,8 +142501,19 @@ static int xferOptimization(
if( pDest->iPKey!=pSrc->iPKey ){
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
}
- if( (pDest->tabFlags & TF_Strict)!=0 && (pSrc->tabFlags & TF_Strict)==0 ){
- return 0; /* Cannot feed from a non-strict into a strict table */
+ if( (pDest->tabFlags & TF_Strict)!=0 ){
+ if( (pSrc->tabFlags & TF_Strict)==0 ){
+ return 0; /* Cannot feed from a non-strict into a strict table */
+ }
+ for(i=0; inCol; i++){
+ unsigned eDestType = pDest->aCol[i].eCType;
+ unsigned eSrcType = pSrc->aCol[i].eCType;
+ if( eDestType==COLTYPE_ANY ) continue;
+ if( eDestType==eSrcType ) continue;
+ if( eDestType==COLTYPE_INT && eSrcType==COLTYPE_INTEGER ) continue;
+ if( eDestType==COLTYPE_INTEGER && eSrcType==COLTYPE_INT ) continue;
+ return 0; /* Incompatible types in source and destination */
+ }
}
for(i=0; inCol; i++){
Column *pDestCol = &pDest->aCol[i];
@@ -139904,7 +142607,7 @@ static int xferOptimization(
#ifndef SQLITE_OMIT_CHECK
if( pDest->pCheck
&& (db->mDbFlags & DBFLAG_Vacuum)==0
- && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
+ && !xferCompatibleCheck(pDest,pSrc)
){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
@@ -139925,6 +142628,18 @@ static int xferOptimization(
if( (db->flags & SQLITE_CountRows)!=0 ){
return 0; /* xfer opt does not play well with PRAGMA count_changes */
}
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( db->xAuth ){
+ int iDb = sqlite3SchemaToIndex(db, pSrc->pSchema);
+ if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 0;
+ for(i=0; inCol; i++){
+ Column *pSrcCol = &pSrc->aCol[i];
+ if( sqlite3AuthReadCol(pParse, pSrc->zName, pSrcCol->zCnName, iDb) ){
+ return 0;
+ }
+ }
+ }
+#endif
/* If we get this far, it means that the xfer optimization is at
** least a possibility, though it might only work if the destination
@@ -140368,7 +143083,7 @@ struct sqlite3_api_routines {
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
- char * (*mprintf)(const char*,...);
+ char *(SQLITE_CDECL*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
@@ -140389,11 +143104,11 @@ struct sqlite3_api_routines {
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
- void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
+ void *(*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
- char * (*xsnprintf)(int,char*,const char*,...);
+ char *(SQLITE_CDECL*xsnprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
@@ -140457,7 +143172,7 @@ struct sqlite3_api_routines {
int (*xthreadsafe)(void);
void (*result_zeroblob)(sqlite3_context*,int);
void (*result_error_code)(sqlite3_context*,int);
- int (*test_control)(int, ...);
+ int (SQLITE_CDECL*test_control)(int, ...);
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
@@ -140477,11 +143192,11 @@ struct sqlite3_api_routines {
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*));
- int (*db_config)(sqlite3*,int,...);
+ int (SQLITE_CDECL*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
- void (*log)(int,const char*,...);
+ void (SQLITE_CDECL*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
@@ -140491,7 +143206,7 @@ struct sqlite3_api_routines {
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
- int (*vtab_config)(sqlite3*,int op,...);
+ int (SQLITE_CDECL*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
/* Version 3.7.16 and later */
int (*close_v2)(sqlite3*);
@@ -140560,7 +143275,7 @@ struct sqlite3_api_routines {
int (*keyword_check)(const char*,int);
sqlite3_str *(*str_new)(sqlite3*);
char *(*str_finish)(sqlite3_str*);
- void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
+ void (SQLITE_CDECL*str_appendf)(sqlite3_str*, const char *zFormat, ...);
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
void (*str_append)(sqlite3_str*, const char *zIn, int N);
void (*str_appendall)(sqlite3_str*, const char *zIn);
@@ -140630,7 +143345,14 @@ struct sqlite3_api_routines {
/* Version 3.51.0 and later */
int (*set_errmsg)(sqlite3*,int,const char*);
int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
-
+ /* Version 3.52.0 and later */
+ void (*str_truncate)(sqlite3_str*,int);
+ void (*str_free)(sqlite3_str*);
+ int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
+ int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
+ /* Version 3.54.0 and later */
+ sqlite3_int64 (*incomplete)(const char*);
+ void (*result_str)(sqlite3_context*,sqlite3_str*,int);
};
/*
@@ -140969,6 +143691,14 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.51.0 and later */
#define sqlite3_set_errmsg sqlite3_api->set_errmsg
#define sqlite3_db_status64 sqlite3_api->db_status64
+/* Version 3.52.0 and later */
+#define sqlite3_str_truncate sqlite3_api->str_truncate
+#define sqlite3_str_free sqlite3_api->str_free
+#define sqlite3_carray_bind sqlite3_api->carray_bind
+#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
+/* Version 3.54.0 and later */
+#define sqlite3_incomplete sqlite3_api->incomplete
+#define sqlite3_result_str sqlite3_api->result_str
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -141495,7 +144225,20 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_setlk_timeout,
/* Version 3.51.0 and later */
sqlite3_set_errmsg,
- sqlite3_db_status64
+ sqlite3_db_status64,
+ /* Version 3.52.0 and later */
+ sqlite3_str_truncate,
+ sqlite3_str_free,
+#ifdef SQLITE_ENABLE_CARRAY
+ sqlite3_carray_bind,
+ sqlite3_carray_bind_v2,
+#else
+ 0,
+ 0,
+#endif
+ /* Version 3.54.0 and later */
+ sqlite3_incomplete,
+ sqlite3_result_str
};
/* True if x is the directory separator character
@@ -141597,33 +144340,42 @@ static int sqlite3LoadExtension(
** entry point name "sqlite3_extension_init" was not found, then
** construct an entry point name "sqlite3_X_init" where the X is
** replaced by the lowercase value of every ASCII alphabetic
- ** character in the filename after the last "/" upto the first ".",
- ** and eliding the first three characters if they are "lib".
+ ** character in the filename after the last "/" up to the first ".",
+ ** and skipping the first three characters if they are "lib".
** Examples:
**
** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init
** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init
+ **
+ ** If that still finds no entry point, repeat a second time but this
+ ** time include both alphabetic and numeric characters up to the first
+ ** ".". Example:
+ **
+ ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example5_init
*/
if( xInit==0 && zProc==0 ){
int iFile, iEntry, c;
int ncFile = sqlite3Strlen30(zFile);
+ int cnt = 0;
zAltEntry = sqlite3_malloc64(ncFile+30);
if( zAltEntry==0 ){
sqlite3OsDlClose(pVfs, handle);
return SQLITE_NOMEM_BKPT;
}
- memcpy(zAltEntry, "sqlite3_", 8);
- for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
- iFile++;
- if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
- for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
- if( sqlite3Isalpha(c) ){
- zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
+ do{
+ memcpy(zAltEntry, "sqlite3_", 8);
+ for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
+ iFile++;
+ if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
+ for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
+ if( sqlite3Isalpha(c) || (cnt && sqlite3Isdigit(c)) ){
+ zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
+ }
}
- }
- memcpy(zAltEntry+iEntry, "_init", 6);
- zEntry = zAltEntry;
- xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
+ memcpy(zAltEntry+iEntry, "_init", 6);
+ zEntry = zAltEntry;
+ xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
+ }while( xInit==0 && (++cnt)<2 );
}
if( xInit==0 ){
if( pzErrMsg ){
@@ -142168,7 +144920,7 @@ static const PragmaName aPragmaName[] = {
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_CountRows },
#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && defined(_WIN32)
{/* zName: */ "data_store_directory",
/* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
/* ePragFlg: */ PragFlg_NoColumns1,
@@ -142591,7 +145343,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
-/* Number of pragmas: 68 on by default, 78 total. */
+/* Number of pragmas: 67 on by default, 78 total. */
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
@@ -142644,7 +145396,7 @@ static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){
/* on no off false yes true extra full */
int i, n;
if( sqlite3Isdigit(*z) ){
- return (u8)sqlite3Atoi(z);
+ return sqlite3Atoi(z)!=0;
}
n = sqlite3Strlen30(z);
for(i=0; isafety_level = iLevel;
pDb->bSyncSet = 1;
@@ -144317,10 +147075,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x); /* Current table */
Index *pIdx; /* An index on pTab */
- int nIdx; /* Number of indexes on pTab */
if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
if( HasRowid(pTab) ) cnt++;
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ cnt++; }
}
if( cnt==0 ) continue;
if( pObjTab ) cnt++;
@@ -144500,8 +147257,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
if( pCol->iDflt ){
sqlite3_value *pDfltValue = 0;
- sqlite3ValueFromExpr(db, sqlite3ColumnExpr(pTab,pCol), ENC(db),
- pCol->affinity, &pDfltValue);
+ sqlite3ValueFromExpr(db, sqlite3ColumnExprAuth(pTab,pCol,pParse),
+ ENC(db), pCol->affinity, &pDfltValue);
if( pDfltValue ){
p4 = sqlite3_value_type(pDfltValue);
sqlite3ValueFree(pDfltValue);
@@ -144633,8 +147390,20 @@ SQLITE_PRIVATE void sqlite3Pragma(
pPrior = pIdx;
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
/* Verify that an index entry exists for the current table row */
- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
+ sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
pIdx->nColumn); VdbeCoverage(v);
+ jmp2 = sqlite3VdbeAddOp3(v, OP_IFindKey, iIdxCur+j, ckUniq, r1);
+ VdbeCoverage(v);
+ sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
+ sqlite3MPrintf(db, "index %s stores an imprecise floating-point "
+ "value for row ", pIdx->zName),
+ P4_DYNAMIC);
+ sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
+ integrityCheckResultRow(v);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ckUniq);
+
+ sqlite3VdbeJumpHere(v, jmp2);
sqlite3VdbeLoadString(v, 3, "row ");
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
sqlite3VdbeLoadString(v, 4, " missing from index ");
@@ -144642,7 +147411,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
jmp4 = integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, jmp2);
+ sqlite3VdbeResolveLabel(v, ckUniq);
/* The OP_IdxRowid opcode is an optimized version of OP_Column
** that extracts the rowid off the end of the index record.
@@ -145203,9 +147972,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
** disables the timeout.
*/
/*case PragTyp_BUSY_TIMEOUT*/ default: {
+ int n = 0;
assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT );
- if( zRight ){
- sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
+ if( zRight && sqlite3GetInt32(zRight,&n) ){
+ sqlite3_busy_timeout(db, n);
}
returnSingleInt(v, db->busyTimeout);
break;
@@ -145695,7 +148465,8 @@ static void corruptSchema(
static const char *azAlterType[] = {
"rename",
"drop column",
- "add column"
+ "add column",
+ "drop constraint"
};
*pData->pzErrMsg = sqlite3MPrintf(db,
"error in %s %s after %s: %s", azObj[0], azObj[1],
@@ -145771,6 +148542,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
}
assert( iDb>=0 && iDbnDb );
+ assert( db->aDb[iDb].pSchema!=0 );
if( argv[3]==0 ){
corruptSchema(pData, argv, 0);
}else if( argv[4]
@@ -145789,6 +148561,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
int rc;
u8 saved_iDb = db->init.iDb;
sqlite3_stmt *pStmt;
+ const char *zEnd;
TESTONLY(int rcp); /* Return code from sqlite3_prepare() */
assert( db->init.busy );
@@ -145803,7 +148576,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
db->init.orphanTrigger = 0;
db->init.azInit = (const char**)argv;
pStmt = 0;
- TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
+ TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, &zEnd);
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
@@ -145819,6 +148592,8 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
corruptSchema(pData, argv, sqlite3_errmsg(db));
}
}
+ }else if( zEnd[0] ){
+ corruptSchema(pData, argv, 0);
}
db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */
sqlite3_finalize(pStmt);
@@ -145846,6 +148621,16 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
}
}
}
+ if( pData->pzErrMsg[0]==0 ){
+ Schema *pX = db->aDb[iDb].pSchema;
+ if( pX->tblHash.count + pX->idxHash.count + pX->trigHash.count
+ > (u32)db->aLimit[SQLITE_LIMIT_SCHEMA]
+ ){
+ *pData->pzErrMsg = sqlite3MPrintf(db, "too many schema objects");
+ pData->rc = SQLITE_ERROR;
+ return 1;
+ }
+ }
return 0;
}
@@ -145877,7 +148662,13 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
assert( sqlite3_mutex_held(db->mutex) );
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
- db->init.busy = 1;
+ db->init.busy = 1 + ((mFlags & INITFLAG_AlterAdd)!=0);
+ /* ^--- Any non-zero value for init.busy means that we are scanning
+ ** the sqlite_schema table to build the internal schema representation,
+ ** rather than running actual CREATE statements. init.busy==2 has the
+ ** additional meaning that the scan is happening as part of
+ ** ALTER TABLE ADD COLUMN, which is stricter in its enforcement of
+ ** function name resolution. */
/* Construct the in-memory representation schema tables (sqlite_schema or
** sqlite_temp_schema) by invoking the parser directly. The appropriate
@@ -146236,7 +149027,7 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){
assert( db->pParse==pParse );
assert( pParse->nested==0 );
#ifndef SQLITE_OMIT_SHARED_CACHE
- if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
+ if( pParse->nTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
#endif
while( pParse->pCleanup ){
ParseCleanup *pCleanup = pParse->pCleanup;
@@ -146320,6 +149111,7 @@ SQLITE_PRIVATE void *sqlite3ParserAddCleanup(
** is generated by Lemon.
*/
SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){
+ assert( db!=0 );
memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ);
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
assert( db->pParse!=pParse );
@@ -146719,7 +149511,7 @@ SQLITE_API int sqlite3_prepare16(
const void **pzTail /* OUT: End of parsed string */
){
int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);
+ rc = sqlite3Prepare16(db,zSql,nBytes&~1,0,ppStmt,pzTail);
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
@@ -146731,7 +149523,7 @@ SQLITE_API int sqlite3_prepare16_v2(
const void **pzTail /* OUT: End of parsed string */
){
int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail);
+ rc = sqlite3Prepare16(db,zSql,nBytes&~1,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail);
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
@@ -146744,7 +149536,7 @@ SQLITE_API int sqlite3_prepare16_v3(
const void **pzTail /* OUT: End of parsed string */
){
int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,
+ rc = sqlite3Prepare16(db,zSql,nBytes&~1,
SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK),
ppStmt,pzTail);
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
@@ -146778,7 +149570,7 @@ SQLITE_API int sqlite3_prepare16_v3(
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
- u8 isTnct; /* 0: Not distinct. 1: DISTICT 2: DISTINCT and ORDER BY */
+ u8 isTnct; /* 0: Not distinct. 1: DISTINCT 2: DISTINCT and ORDER BY */
u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
int tabTnct; /* Ephemeral table used for DISTINCT processing */
int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
@@ -146908,8 +149700,6 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selId = ++pParse->nSelect;
- pNew->addrOpenEphm[0] = -1;
- pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
pNew->pSrc = pSrc;
@@ -147277,6 +150067,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
int i, j; /* Loop counters */
SrcItem *pLeft; /* Left table being joined */
SrcItem *pRight; /* Right table being joined */
+ int bSeenTFunc = 0; /* True if have seen table-valued function */
pSrc = p->pSrc;
pLeft = &pSrc->a[0];
@@ -147418,6 +150209,21 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
pRight->fg.isOn = 1;
p->selFlags |= SF_OnToWhere;
}
+
+ if( bSeenTFunc==0 ){
+ bSeenTFunc = (pLeft->fg.isTabFunc && pLeft->u1.pFuncArg);
+ }
+
+ /* We also need to call sqlite3SelectCheckOnClauses() to verify that
+ ** table-valued function arguments do not illegally refer to any tables to
+ ** their right. This test is required if either (a) there is a RIGHT JOIN
+ ** in the SrcList, or (b) there is a LEFT JOIN to the right of a
+ ** table-valued function. */
+ if( (pRight->fg.isTabFunc && joinType==EP_OuterON && pRight->u1.pFuncArg)
+ || (bSeenTFunc && joinType==EP_OuterON)
+ ){
+ p->selFlags |= SF_OnToWhere;
+ }
}
return 0;
}
@@ -147882,6 +150688,48 @@ static void selectExprDefer(
}
#endif
+#ifdef SQLITE_DEBUG
+/*
+** This is a byte-code validation check that only runs when SQLITE_DEBUG
+** is defined. This routine looks backwards through the bytecode
+** for the definition of cursor with index iCur. It extracts the KeyInfo from
+** that cursor (it must be an index cursor) and verifies that the cursor
+** does not use any collating seqeuences other than BINARY for its first
+** nCol columns.
+**
+** This routine is used inside of an assert(). So it should return true
+** on success and false if the invariant is not satisfied.
+**
+** tag-202607231411
+*/
+static int sqlite3CursorBloomable(Parse *pParse, int iCur, int nCol){
+ int i,k;
+ Vdbe *v = pParse->pVdbe;
+ if( pParse->nErr ) return 1;
+ assert( v );
+ for(k=sqlite3VdbeCurrentAddr(v)-1; k>0; k--){
+ const VdbeOp *pOp = sqlite3VdbeGetOp(v, k);
+ const KeyInfo *pKeyInfo;
+ if( pOp->p1!=iCur ) continue;
+ if( pOp->opcode!=OP_OpenRead
+ && pOp->opcode!=OP_OpenWrite
+ && pOp->opcode!=OP_OpenEphemeral
+ ){
+ continue;
+ }
+ assert( pOp->p4type==P4_KEYINFO );
+ pKeyInfo = (const KeyInfo*)pOp->p4.pKeyInfo;
+ assert( pKeyInfo!=0 );
+ for(i=0; iaColl[i]) );
+ }
+ return 1;
+ }
+ return 0;
+}
+#endif /* SQLITE_DEBUG */
+
+
/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
@@ -148057,29 +150905,6 @@ static void selectInnerLoop(
}
switch( eDest ){
- /* In this mode, write each query result to the key of the temporary
- ** table iParm.
- */
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
- case SRT_Union: {
- int r1;
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
- sqlite3ReleaseTempReg(pParse, r1);
- break;
- }
-
- /* Construct a record from the query result, but instead of
- ** saving that record, use it as a key to delete elements from
- ** the temporary table iParm.
- */
- case SRT_Except: {
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
- break;
- }
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */
-
/* Store the result as data using a unique key.
*/
case SRT_Fifo:
@@ -148175,6 +151000,7 @@ static void selectInnerLoop(
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
if( pDest->iSDParm2 ){
+ assert( sqlite3CursorBloomable(pParse,iParm,nResultCol) );
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
regResult, nResultCol);
ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
@@ -148504,6 +151330,9 @@ static void generateSortTail(
Table *pTab = pSort->aDefer[i].pTab;
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead);
+ sqlite3VdbeAddOp2(v, OP_Rewind, pSort->aDefer[i].iCsr,
+ sqlite3VdbeCurrentAddr(v)+1);
+ VdbeCoverage(v);
nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey);
}
#endif
@@ -149192,8 +152021,8 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(
}
}
if( zType ){
- const i64 k = sqlite3Strlen30(zType);
- n = sqlite3Strlen30(pCol->zCnName);
+ const i64 k = strlen(zType);
+ n = strlen(pCol->zCnName);
pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2);
pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
if( pCol->zCnName ){
@@ -149210,6 +152039,20 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(
pTab->szTabRow = 1; /* Any non-zero value works */
}
+/*
+** Check the current subquery nesting depth. Return true and set an
+** error if it has gone too deep.
+*/
+static int checkSubqueryNestingDepth(Parse *pParse){
+#if SQLITE_MAX_EXPR_DEPTH>0
+ if( pParse->nNestSel >= pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
+ sqlite3ErrorMsg(pParse, "VIEWs and/or subqueries nested too deep");
+ return 1;
+ }
+#endif
+ return 0;
+}
+
/*
** Given a SELECT statement, generate a Table structure that describes
** the result set of that SELECT.
@@ -149219,6 +152062,8 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, c
sqlite3 *db = pParse->db;
u64 savedFlags;
+ pParse->nNestSel++;
+ if( checkSubqueryNestingDepth(pParse) ) return 0;
savedFlags = db->flags;
db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
@@ -149240,6 +152085,8 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, c
sqlite3DeleteTable(db, pTab);
return 0;
}
+ pParse->nNestSel--;
+ assert( pParse->nNestSel>=0 );
return pTab;
}
@@ -149251,9 +152098,7 @@ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){
if( pParse->pVdbe ){
return pParse->pVdbe;
}
- if( pParse->pToplevel==0
- && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
- ){
+ if( pParse->pToplevel==0 ){
pParse->okConstFactor = 1;
}
return sqlite3VdbeCreate(pParse);
@@ -149304,7 +152149,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
p->iLimit = iLimit = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
- if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
+ if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse, 0) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
@@ -149317,6 +152162,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
sqlite3ExprCode(pParse, pLimit->pLeft, iLimit);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
VdbeComment((v, "LIMIT counter"));
+ sqlite3MayAbort(pParse);
sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
}
if( pLimit->pRight ){
@@ -149324,6 +152170,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
pParse->nMem++; /* Allocate an extra register for limit+offset */
sqlite3ExprCode(pParse, pLimit->pRight, iOffset);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
+ sqlite3MayAbort(pParse);
VdbeComment((v, "OFFSET counter"));
sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
VdbeComment((v, "LIMIT+OFFSET"));
@@ -149366,9 +152213,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
** function is responsible for ensuring that this structure is eventually
** freed.
*/
-static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
+static KeyInfo *multiSelectByMergeKeyInfo(Parse *pParse, Select *p, int nExtra){
ExprList *pOrderBy = p->pOrderBy;
- int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0;
+ int nOrderBy = (pOrderBy!=0) ? pOrderBy->nExpr : 0;
sqlite3 *db = pParse->db;
KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
if( pRet ){
@@ -149501,7 +152348,7 @@ static void generateWithRecursiveQuery(
regCurrent = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
if( pOrderBy ){
- KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
+ KeyInfo *pKeyInfo = multiSelectByMergeKeyInfo(pParse, p, 1);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
(char*)pKeyInfo, P4_KEYINFO);
destQueue.pOrderBy = pOrderBy;
@@ -149510,8 +152357,28 @@ static void generateWithRecursiveQuery(
}
VdbeComment((v, "Queue table"));
if( iDistinct ){
- p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
- p->selFlags |= SF_UsesEphemeral;
+ /* Generate an ephemeral table used to enforce distinctness on the
+ ** output of the recursive part of the CTE.
+ */
+ KeyInfo *pKeyInfo; /* Collating sequence for the result set */
+ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
+
+ assert( p->pNext==0 );
+ assert( p->pEList!=0 );
+ nCol = p->pEList->nExpr;
+ pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nCol, 1);
+ if( pKeyInfo ){
+ for(i=0, apColl=pKeyInfo->aColl; idb->pDfltColl;
+ }
+ }
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iDistinct, nCol, 0,
+ (void*)pKeyInfo, P4_KEYINFO);
+ }else{
+ assert( pParse->nErr>0 );
+ }
}
/* Detach the ORDER BY clause from the compound SELECT */
@@ -149586,7 +152453,7 @@ static void generateWithRecursiveQuery(
#endif /* SQLITE_OMIT_CTE */
/* Forward references */
-static int multiSelectOrderBy(
+static int multiSelectByMerge(
Parse *pParse, /* Parsing context */
Select *p, /* The right-most of SELECTs to be coded */
SelectDest *pDest /* What to do with query results */
@@ -149651,11 +152518,33 @@ static int hasAnchor(Select *p){
}
/*
-** This routine is called to process a compound query form from
+** Return TRUE if p is a UNION with a LIMIT of exactly 1 and no OFFSET
+** clause. This is a precondition for a couple of related optimizations.
+**
+** False negatives are harmless (apart from resulting in a slower query).
+** False positives can result in incorrect answers, however. To provoke
+** false negatives for testing purposes, disable the SQLITE_UnionLimit
+** optimization.
+*/
+static int unionWithLimitOne(sqlite3 *db, Select *p){
+ int v;
+ if( p->op!=TK_UNION ) return 0;
+ if( p->pLimit==0 ) return 0;
+ if( p->pLimit->pRight ) return 0; /* No OFFSET */
+ v = 0;
+ assert( p->pLimit->pLeft!=0 );
+ if( sqlite3ExprIsInteger(p->pLimit->pLeft, &v, 0, 0)==0 ) return 0;
+ if( v!=1 ) return 0;
+ if( OptimizationDisabled(db, SQLITE_UnionLimit) ) return 0;
+ return 1;
+}
+
+/*
+** This routine is called to process a compound query formed 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
+** "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.
**
@@ -149735,12 +152624,27 @@ static int multiSelect(
generateWithRecursiveQuery(pParse, p, &dest);
}else
#endif
-
- /* Compound SELECTs that have an ORDER BY clause are handled separately.
- */
if( p->pOrderBy ){
- return multiSelectOrderBy(pParse, p, pDest);
- }else{
+ /* If the compound has an ORDER BY clause, then always use the merge
+ ** algorithm. */
+ return multiSelectByMerge(pParse, p, pDest);
+ }else if( p->op!=TK_ALL && !unionWithLimitOne(db,p) ){
+ /* If the compound is EXCEPT, INTERSECT, or UNION (anything other than
+ ** UNION ALL) then also always use the merge algorithm. However, the
+ ** multiSelectByMerge() routine requires that the compound have an
+ ** ORDER BY clause, and it doesn't right now. So invent one first. */
+ Expr *pOne = sqlite3ExprInt32(db, 1);
+ p->pOrderBy = sqlite3ExprListAppend(pParse, 0, pOne);
+ if( pParse->nErr ) goto multi_select_end;
+ assert( p->pOrderBy!=0 );
+ p->pOrderBy->a[0].u.x.iOrderByCol = 1;
+ return multiSelectByMerge(pParse, p, pDest);
+ }else{
+ /* For a UNION ALL compound without ORDER BY, or for a UNION with a
+ ** LIMIT of exactly 1 and no OFFSET and no ORDER BY, simply run the left
+ ** query, then run the right query */
+ int addr = 0;
+ int nLimit = 0; /* Initialize to suppress harmless compiler warning */
#ifndef SQLITE_OMIT_EXPLAIN
if( pPrior->pPrior==0 ){
@@ -149748,300 +152652,49 @@ static int multiSelect(
ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY"));
}
#endif
-
- /* Generate code for the left and right SELECT statements.
- */
- switch( p->op ){
- case TK_ALL: {
- int addr = 0;
- int nLimit = 0; /* Initialize to suppress harmless compiler warning */
- assert( !pPrior->pLimit );
- pPrior->iLimit = p->iLimit;
- pPrior->iOffset = p->iOffset;
- pPrior->pLimit = p->pLimit;
- TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
- rc = sqlite3Select(pParse, pPrior, &dest);
- pPrior->pLimit = 0;
- if( rc ){
- goto multi_select_end;
- }
- p->pPrior = 0;
- p->iLimit = pPrior->iLimit;
- p->iOffset = pPrior->iOffset;
- if( p->iLimit ){
- addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
- VdbeComment((v, "Jump ahead if LIMIT reached"));
- if( p->iOffset ){
- sqlite3VdbeAddOp3(v, OP_OffsetLimit,
- p->iLimit, p->iOffset+1, p->iOffset);
- }
- }
- ExplainQueryPlan((pParse, 1, "UNION ALL"));
- TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n"));
- rc = sqlite3Select(pParse, p, &dest);
- testcase( rc!=SQLITE_OK );
- pDelete = p->pPrior;
- p->pPrior = pPrior;
- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- if( p->pLimit
- && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
- && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
- ){
- p->nSelectRow = sqlite3LogEst((u64)nLimit);
- }
- if( addr ){
- sqlite3VdbeJumpHere(v, addr);
- }
- break;
- }
- case TK_EXCEPT:
- case TK_UNION: {
- int unionTab; /* Cursor number of the temp table holding result */
- u8 op = 0; /* One of the SRT_ operations to apply to self */
- int priorOp; /* The SRT_ operation to apply to prior selects */
- Expr *pLimit; /* Saved values of p->nLimit */
- int addr;
- int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */
- SelectDest uniondest;
-
-
- testcase( p->op==TK_EXCEPT );
- testcase( p->op==TK_UNION );
- priorOp = SRT_Union;
- if( dest.eDest==priorOp ){
- /* We can reuse a temporary table generated by a SELECT to our
- ** right.
- */
- assert( p->pLimit==0 ); /* Not allowed on leftward elements */
- unionTab = dest.iSDParm;
- }else{
- /* We will need to create our own temporary table to hold the
- ** intermediate results.
- */
- unionTab = pParse->nTab++;
- assert( p->pOrderBy==0 );
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
- assert( p->addrOpenEphm[0] == -1 );
- p->addrOpenEphm[0] = addr;
- findRightmost(p)->selFlags |= SF_UsesEphemeral;
- assert( p->pEList );
- }
-
-
- /* Code the SELECT statements to our left
- */
- assert( !pPrior->pOrderBy );
- sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
- TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
- rc = sqlite3Select(pParse, pPrior, &uniondest);
- if( rc ){
- goto multi_select_end;
- }
-
- /* Code the current SELECT statement
- */
- if( p->op==TK_EXCEPT ){
- op = SRT_Except;
- emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab);
- VdbeCoverage(v);
- }else{
- assert( p->op==TK_UNION );
- op = SRT_Union;
- }
- p->pPrior = 0;
- pLimit = p->pLimit;
- p->pLimit = 0;
- uniondest.eDest = op;
- ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- sqlite3SelectOpName(p->op)));
- TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
- rc = sqlite3Select(pParse, p, &uniondest);
- testcase( rc!=SQLITE_OK );
- assert( p->pOrderBy==0 );
- pDelete = p->pPrior;
- p->pPrior = pPrior;
- p->pOrderBy = 0;
- if( p->op==TK_UNION ){
- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- }
- if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass);
- sqlite3ExprDelete(db, p->pLimit);
- p->pLimit = pLimit;
- p->iLimit = 0;
- p->iOffset = 0;
-
- /* Convert the data in the temporary table into whatever form
- ** it is that we currently need.
- */
- assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
- assert( p->pEList || db->mallocFailed );
- if( dest.eDest!=priorOp && db->mallocFailed==0 ){
- int iCont, iBreak, iStart;
- iBreak = sqlite3VdbeMakeLabel(pParse);
- iCont = sqlite3VdbeMakeLabel(pParse);
- computeLimitRegisters(pParse, p, iBreak);
- sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
- iStart = sqlite3VdbeCurrentAddr(v);
- selectInnerLoop(pParse, p, unionTab,
- 0, 0, &dest, iCont, iBreak);
- sqlite3VdbeResolveLabel(v, iCont);
- sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
- sqlite3VdbeResolveLabel(v, iBreak);
- sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
- }
- break;
- }
- default: assert( p->op==TK_INTERSECT ); {
- int tab1, tab2;
- int iCont, iBreak, iStart;
- Expr *pLimit;
- int addr, iLimit, iOffset;
- SelectDest intersectdest;
- int r1;
- int emptyBypass;
-
- /* INTERSECT is different from the others since it requires
- ** two temporary tables. Hence it has its own case. Begin
- ** by allocating the tables we will need.
- */
- tab1 = pParse->nTab++;
- tab2 = pParse->nTab++;
- assert( p->pOrderBy==0 );
-
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
- assert( p->addrOpenEphm[0] == -1 );
- p->addrOpenEphm[0] = addr;
- findRightmost(p)->selFlags |= SF_UsesEphemeral;
- assert( p->pEList );
-
- /* Code the SELECTs to our left into temporary table "tab1".
- */
- sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
- TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n"));
- rc = sqlite3Select(pParse, pPrior, &intersectdest);
- if( rc ){
- goto multi_select_end;
- }
-
- /* Initialize LIMIT counters before checking to see if the LHS
- ** is empty, in case the jump is taken */
- iBreak = sqlite3VdbeMakeLabel(pParse);
- computeLimitRegisters(pParse, p, iBreak);
- emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v);
-
- /* Code the current SELECT into temporary table "tab2"
- */
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
- assert( p->addrOpenEphm[1] == -1 );
- p->addrOpenEphm[1] = addr;
-
- /* Disable prior SELECTs and the LIMIT counters during the computation
- ** of the RHS select */
- pLimit = p->pLimit;
- iLimit = p->iLimit;
- iOffset = p->iOffset;
- p->pPrior = 0;
- p->pLimit = 0;
- p->iLimit = 0;
- p->iOffset = 0;
-
- intersectdest.iSDParm = tab2;
- ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- sqlite3SelectOpName(p->op)));
- TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n"));
- rc = sqlite3Select(pParse, p, &intersectdest);
- testcase( rc!=SQLITE_OK );
- pDelete = p->pPrior;
- p->pPrior = pPrior;
- if( p->nSelectRow>pPrior->nSelectRow ){
- p->nSelectRow = pPrior->nSelectRow;
- }
- sqlite3ExprDelete(db, p->pLimit);
-
- /* Reinstate the LIMIT counters prior to running the final intersect */
- p->pLimit = pLimit;
- p->iLimit = iLimit;
- p->iOffset = iOffset;
-
- /* Generate code to take the intersection of the two temporary
- ** tables.
- */
- if( rc ) break;
- assert( p->pEList );
- sqlite3VdbeAddOp1(v, OP_Rewind, tab1);
- r1 = sqlite3GetTempReg(pParse);
- iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
- iCont = sqlite3VdbeMakeLabel(pParse);
- sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
- VdbeCoverage(v);
- sqlite3ReleaseTempReg(pParse, r1);
- selectInnerLoop(pParse, p, tab1,
- 0, 0, &dest, iCont, iBreak);
- sqlite3VdbeResolveLabel(v, iCont);
- sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
- sqlite3VdbeResolveLabel(v, iBreak);
- sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
- sqlite3VdbeJumpHere(v, emptyBypass);
- sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
- break;
- }
- }
-
- #ifndef SQLITE_OMIT_EXPLAIN
- if( p->pNext==0 ){
- ExplainQueryPlanPop(pParse);
- }
- #endif
- }
- if( pParse->nErr ) goto multi_select_end;
-
- /* Compute collating sequences used by
- ** temporary tables needed to implement the compound select.
- ** Attach the KeyInfo structure to all temporary tables.
- **
- ** This section is run by the right-most SELECT statement only.
- ** SELECT statements to the left always skip this part. The right-most
- ** SELECT might also skip this part if it has no ORDER BY clause and
- ** no temp tables are required.
- */
- if( p->selFlags & SF_UsesEphemeral ){
- int i; /* Loop counter */
- KeyInfo *pKeyInfo; /* Collating sequence for the result set */
- Select *pLoop; /* For looping through SELECT statements */
- CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
- int nCol; /* Number of columns in result set */
-
- assert( p->pNext==0 );
- assert( p->pEList!=0 );
- nCol = p->pEList->nExpr;
- pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
- if( !pKeyInfo ){
- rc = SQLITE_NOMEM_BKPT;
+ assert( !pPrior->pLimit );
+ pPrior->iLimit = p->iLimit;
+ pPrior->iOffset = p->iOffset;
+ pPrior->pLimit = sqlite3ExprDup(db, p->pLimit, 0);
+ TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
+ rc = sqlite3Select(pParse, pPrior, &dest);
+ sqlite3ExprDelete(db, pPrior->pLimit);
+ pPrior->pLimit = 0;
+ if( rc ){
goto multi_select_end;
}
- for(i=0, apColl=pKeyInfo->aColl; ipDfltColl;
- }
+ p->pPrior = 0;
+ p->iLimit = pPrior->iLimit;
+ p->iOffset = pPrior->iOffset;
+ if( p->iLimit ){
+ addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
+ VdbeComment((v, "Jump ahead if LIMIT reached"));
+ if( p->iOffset ){
+ sqlite3VdbeAddOp3(v, OP_OffsetLimit,
+ p->iLimit, p->iOffset+1, p->iOffset);
+ }
+ }
+ ExplainQueryPlan((pParse, 1, "UNION ALL"));
+ TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n"));
+ rc = sqlite3Select(pParse, p, &dest);
+ testcase( rc!=SQLITE_OK );
+ pDelete = p->pPrior;
+ p->pPrior = pPrior;
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
+ if( p->pLimit
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse, 0)
+ && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
+ ){
+ p->nSelectRow = sqlite3LogEst((u64)nLimit);
}
-
- for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
- for(i=0; i<2; i++){
- int addr = pLoop->addrOpenEphm[i];
- if( addr<0 ){
- /* If [0] is unused then [1] is also unused. So we can
- ** always safely abort as soon as the first unused slot is found */
- assert( pLoop->addrOpenEphm[1]<0 );
- break;
- }
- sqlite3VdbeChangeP2(v, addr, nCol);
- sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo),
- P4_KEYINFO);
- pLoop->addrOpenEphm[i] = -1;
- }
+ if( addr ){
+ sqlite3VdbeJumpHere(v, addr);
}
- sqlite3KeyInfoUnref(pKeyInfo);
+#ifndef SQLITE_OMIT_EXPLAIN
+ if( p->pNext==0 ){
+ ExplainQueryPlanPop(pParse);
+ }
+#endif
}
multi_select_end:
@@ -150073,8 +152726,8 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
** Code an output subroutine for a coroutine implementation of a
** SELECT statement.
**
-** The data to be output is contained in pIn->iSdst. There are
-** pIn->nSdst columns to be output. pDest is where the output should
+** The data to be output is contained in an array of pIn->nSdst registers
+** starting at register pIn->iSdst. pDest is where the output should
** be sent.
**
** regReturn is the number of the register holding the subroutine
@@ -150103,6 +152756,8 @@ static int generateOutputSubroutine(
int iContinue;
int addr;
+ assert( pIn->eDest==SRT_Coroutine );
+
addr = sqlite3VdbeCurrentAddr(v);
iContinue = sqlite3VdbeMakeLabel(pParse);
@@ -150124,23 +152779,60 @@ static int generateOutputSubroutine(
*/
codeOffset(v, p->iOffset, iContinue);
- assert( pDest->eDest!=SRT_Exists );
- assert( pDest->eDest!=SRT_Table );
switch( pDest->eDest ){
/* Store the result as data using a unique key.
*/
+ case SRT_Fifo:
+ case SRT_DistFifo:
+ case SRT_Table:
case SRT_EphemTab: {
int r1 = sqlite3GetTempReg(pParse);
int r2 = sqlite3GetTempReg(pParse);
+ int iParm = pDest->iSDParm;
+ testcase( pDest->eDest==SRT_Table );
+ testcase( pDest->eDest==SRT_EphemTab );
+ testcase( pDest->eDest==SRT_Fifo );
+ testcase( pDest->eDest==SRT_DistFifo );
sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
- sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
- sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
+#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG)
+ /* A destination of SRT_Table and a non-zero iSDParm2 parameter means
+ ** that this is an "UPDATE ... FROM" on a virtual table or view. In this
+ ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC.
+ ** This does not affect operation in any way - it just allows MakeRecord
+ ** to process OPFLAG_NOCHANGE values without an assert() failing. */
+ if( pDest->eDest==SRT_Table && pDest->iSDParm2 ){
+ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
+ }
+#endif
+#ifndef SQLITE_OMIT_CTE
+ if( pDest->eDest==SRT_DistFifo ){
+ /* If the destination is DistFifo, then cursor (iParm+1) is open
+ ** on an ephemeral index that is used to enforce uniqueness on the
+ ** total result. At this point, we are processing the setup portion
+ ** of the recursive CTE using the merge algorithm, so the results are
+ ** guaranteed to be unique anyhow. But we still need to populate the
+ ** (iParm+1) cursor for use by the subsequent recursive phase.
+ */
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,
+ pIn->iSdst, pIn->nSdst);
+ }
+#endif
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
+ sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3ReleaseTempReg(pParse, r2);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
+ /* If any row exist in the result set, record that fact and abort.
+ */
+ case SRT_Exists: {
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
+ /* The LIMIT clause will terminate the loop for us */
+ break;
+ }
+
#ifndef SQLITE_OMIT_SUBQUERY
/* If we are creating a set for an "expr IN (SELECT ...)".
*/
@@ -150153,6 +152845,7 @@ static int generateOutputSubroutine(
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
if( pDest->iSDParm2>0 ){
+ assert( sqlite3CursorBloomable(pParse, pDest->iSDParm, pIn->nSdst) );
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
pIn->iSdst, pIn->nSdst);
ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
@@ -150187,9 +152880,51 @@ static int generateOutputSubroutine(
break;
}
+#ifndef SQLITE_OMIT_CTE
+ /* Write the results into a priority queue that is order according to
+ ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an
+ ** index with pSO->nExpr+2 columns. Build a key using pSO for the first
+ ** pSO->nExpr columns, then make sure all keys are unique by adding a
+ ** final OP_Sequence column. The last column is the record as a blob.
+ */
+ case SRT_DistQueue:
+ case SRT_Queue: {
+ int nKey;
+ int r1, r2, r3, ii;
+ ExprList *pSO;
+ int iParm = pDest->iSDParm;
+ pSO = pDest->pOrderBy;
+ assert( pSO );
+ nKey = pSO->nExpr;
+ r1 = sqlite3GetTempReg(pParse);
+ r2 = sqlite3GetTempRange(pParse, nKey+2);
+ r3 = r2+nKey+1;
+
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r3);
+ if( pDest->eDest==SRT_DistQueue ){
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
+ }
+ for(ii=0; iiiSdst + pSO->a[ii].u.x.iOrderByCol - 1,
+ r2+ii);
+ }
+ sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
+ sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ReleaseTempRange(pParse, r2, nKey+2);
+ break;
+ }
+#endif /* SQLITE_OMIT_CTE */
+
+ /* Ignore the output */
+ case SRT_Discard: {
+ break;
+ }
+
/* If none of the above, then the result destination must be
- ** SRT_Output. This routine is never called with any other
- ** destination other than the ones handled above or SRT_Output.
+ ** SRT_Output.
**
** For SRT_Output, results are stored in a sequence of registers.
** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
@@ -150217,8 +152952,9 @@ static int generateOutputSubroutine(
}
/*
-** Alternative compound select code generator for cases when there
-** is an ORDER BY clause.
+** Generate code for a compound SELECT statement using a merge
+** algorithm. The compound must have an ORDER BY clause for this
+** to work.
**
** We assume a query of the following form:
**
@@ -150235,7 +152971,7 @@ static int generateOutputSubroutine(
**
** outB: Move the output of the selectB coroutine into the output
** of the compound query. (Only generated for UNION and
-** UNION ALL. EXCEPT and INSERTSECT never output a row that
+** UNION ALL. EXCEPT and INTERSECT never output a row that
** appears only in B.)
**
** AltB: Called when there is data from both coroutines and Au.x.iOrderByCol==i ) break;
}
if( j==nOrderBy ){
- Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+ Expr *pNew = sqlite3ExprInt32(db, i);
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
- pNew->flags |= EP_IntValue;
- pNew->u.iValue = i;
p->pOrderBy = pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
}
@@ -150385,26 +153117,29 @@ static int multiSelectOrderBy(
}
/* Compute the comparison permutation and keyinfo that is used with
- ** the permutation used to determine if the next
- ** row of results comes from selectA or selectB. Also add explicit
- ** collations to the ORDER BY clause terms so that when the subqueries
- ** to the right and the left are evaluated, they use the correct
- ** collation.
+ ** the permutation to determine if the next row of results comes
+ ** from selectA or selectB. Also add literal collations to the
+ ** ORDER BY clause terms so that when selectA and selectB are
+ ** evaluated, they use the correct collation.
*/
aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
if( aPermute ){
struct ExprList_item *pItem;
+ int bKeep = 0;
aPermute[0] = nOrderBy;
for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
assert( pItem!=0 );
assert( pItem->u.x.iOrderByCol>0 );
assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
+ if( aPermute[i]!=(u32)i-1 ) bKeep = 1;
+ }
+ if( bKeep==0 ){
+ sqlite3DbFreeNN(db, aPermute);
+ aPermute = 0;
}
- pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
- }else{
- pKeyMerge = 0;
}
+ pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1);
/* Allocate a range of temporary registers and the KeyInfo needed
** for the logic that removes duplicate result rows when the
@@ -150457,7 +153192,7 @@ static int multiSelectOrderBy(
/* Compute the limit registers */
computeLimitRegisters(pParse, p, labelEnd);
- if( p->iLimit && op==TK_ALL ){
+ if( p->iLimit && (op==TK_ALL || unionWithLimitOne(db,p)) ){
regLimitA = ++pParse->nMem;
regLimitB = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit,
@@ -150483,7 +153218,7 @@ static int multiSelectOrderBy(
*/
addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
- VdbeComment((v, "left SELECT"));
+ VdbeComment((v, "SUBR: next-A"));
pPrior->iLimit = regLimitA;
ExplainQueryPlan((pParse, 1, "LEFT"));
sqlite3Select(pParse, pPrior, &destA);
@@ -150495,7 +153230,7 @@ static int multiSelectOrderBy(
*/
addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
- VdbeComment((v, "right SELECT"));
+ VdbeComment((v, "SUBR: next-B"));
savedLimit = p->iLimit;
savedOffset = p->iOffset;
p->iLimit = regLimitB;
@@ -150509,7 +153244,7 @@ static int multiSelectOrderBy(
/* Generate a subroutine that outputs the current row of the A
** select as the next output row of the compound select.
*/
- VdbeNoopComment((v, "Output routine for A"));
+ VdbeNoopComment((v, "SUBR: out-A"));
addrOutA = generateOutputSubroutine(pParse,
p, &destA, pDest, regOutA,
regPrev, pKeyDup, labelEnd);
@@ -150518,7 +153253,7 @@ static int multiSelectOrderBy(
** select as the next output row of the compound select.
*/
if( op==TK_ALL || op==TK_UNION ){
- VdbeNoopComment((v, "Output routine for B"));
+ VdbeNoopComment((v, "SUBR: out-B"));
addrOutB = generateOutputSubroutine(pParse,
p, &destB, pDest, regOutB,
regPrev, pKeyDup, labelEnd);
@@ -150531,10 +153266,12 @@ static int multiSelectOrderBy(
if( op==TK_EXCEPT || op==TK_INTERSECT ){
addrEofA_noB = addrEofA = labelEnd;
}else{
- VdbeNoopComment((v, "eof-A subroutine"));
+ VdbeNoopComment((v, "SUBR: eof-A"));
addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
+ VdbeComment((v, "out-B"));
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
VdbeCoverage(v);
+ VdbeComment((v, "next-B"));
sqlite3VdbeGoto(v, addrEofA);
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
}
@@ -150546,17 +153283,20 @@ static int multiSelectOrderBy(
addrEofB = addrEofA;
if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
}else{
- VdbeNoopComment((v, "eof-B subroutine"));
+ VdbeNoopComment((v, "SUBR: eof-B"));
addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
+ VdbeComment((v, "out-A"));
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
+ VdbeComment((v, "next-A"));
sqlite3VdbeGoto(v, addrEofB);
}
/* Generate code to handle the case of AB
*/
- VdbeNoopComment((v, "A-gt-B subroutine"));
addrAgtB = sqlite3VdbeCurrentAddr(v);
if( op==TK_ALL || op==TK_UNION ){
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
+ VdbeComment((v, "out-B"));
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
+ VdbeComment((v, "next-B"));
+ sqlite3VdbeGoto(v, labelCmpr);
+ }else{
+ addrAgtB++; /* Just do next-B. Might as well use the next-B call
+ ** in the next code block */
}
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
- sqlite3VdbeGoto(v, labelCmpr);
/* This code runs once to initialize everything.
*/
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
+ VdbeComment((v, "next-A"));
+ /* v--- Also the A>B case for EXCEPT and INTERSECT */
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
+ VdbeComment((v, "next-B"));
/* Implement the main merge loop
*/
+ if( aPermute!=0 ){
+ sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
+ }
sqlite3VdbeResolveLabel(v, labelCmpr);
- sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
(char*)pKeyMerge, P4_KEYINFO);
- sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
- sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);
+ if( aPermute!=0 ){
+ sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
+ }
+ sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
+ VdbeCoverageIf(v, op==TK_ALL);
+ VdbeCoverageIf(v, op==TK_UNION);
+ VdbeCoverageIf(v, op==TK_EXCEPT);
+ VdbeCoverageIf(v, op==TK_INTERSECT);
/* Jump to the this point in order to terminate the query.
*/
@@ -150921,7 +153673,9 @@ static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
renumberCursorDoMapping(pWalker, &pExpr->iTable);
}
- if( ExprHasProperty(pExpr, EP_OuterON) ){
+ if( ExprHasProperty(pExpr, (EP_OuterON|EP_InnerON)) ){
+ testcase( ExprHasProperty(pExpr, EP_OuterON) );
+ testcase( ExprHasProperty(pExpr, EP_InnerON) );
renumberCursorDoMapping(pWalker, &pExpr->w.iJoin);
}
return WRC_Continue;
@@ -151468,7 +154222,7 @@ static int flattenSubquery(
pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
- u8 jointype = pSubitem->fg.jointype;
+ u8 jointype = pParent->pSrc->a[iFrom].fg.jointype;
assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
@@ -151493,7 +154247,6 @@ static int flattenSubquery(
pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
if( pSrc==0 ) break;
pParent->pSrc = pSrc;
- pSubitem = &pSrc->a[iFrom];
}
/* Transfer the FROM clause terms from the subquery into the
@@ -151511,9 +154264,9 @@ static int flattenSubquery(
pItem->fg.jointype |= (jointype & JT_LTORJ);
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
- pSubitem->fg.jointype |= jointype;
+ pSrc->a[iFrom].fg.jointype |= jointype;
- /* Now begin substituting subquery result set expressions for
+ /* Begin substituting subquery result set expressions for
** references to the iParent in the outer query.
**
** Example:
@@ -151525,7 +154278,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 && (pParent->selFlags & SF_NoopOrderBy)==0 ){
+ if( pSub->pOrderBy ){
/* 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
@@ -151533,9 +154286,9 @@ static int flattenSubquery(
** zero them before transferring the ORDER BY clause.
**
** Not doing this may cause an error if a subsequent call to this
- ** function attempts to flatten a compound sub-query into pParent
- ** (the only way this can happen is if the compound sub-query is
- ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */
+ ** function attempts to flatten a compound sub-query into pParent.
+ ** See ticket [d11a6e908f].
+ */
ExprList *pOrderBy = pSub->pOrderBy;
for(i=0; inExpr; i++){
pOrderBy->a[i].u.x.iOrderByCol = 0;
@@ -151626,12 +154379,21 @@ struct WhereConst {
};
/*
-** Add a new entry to the pConst object. Except, do not add duplicate
-** pColumn entries. Also, do not add if doing so would not be appropriate.
+** Add a new entry to the pConst object, if appropriate.
+**
+** * Do not add if pValue is not constant. (This is enforced by
+** the caller)
+**
+** * Do not add duplicate pColumn entries
+**
+** * Do not add if pValue has an affinity
+**
+** * Do not add if the comparison uses a collating sequence other
+** than binary.
+**
+** * Do not add if pValue is a function that might return a subtype
**
-** 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.
+** The caller guarantees the pColumn is a column.
*/
static void constInsert(
WhereConst *pConst, /* The WhereConst into which we are inserting */
@@ -151642,12 +154404,12 @@ static void constInsert(
int i;
assert( pColumn->op==TK_COLUMN );
assert( sqlite3ExprIsConstant(pConst->pParse, pValue) );
-
if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
if( sqlite3ExprAffinity(pValue)!=0 ) return;
if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){
return;
}
+ if( sqlite3ExprCanReturnSubtype(pConst->pParse, pValue) ) return;
/* 2018-10-25 ticket [cf5ed20f]
** Make sure the same pColumn is not inserted more than once */
@@ -151793,7 +154555,7 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
**
** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
** 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
+** part of a ON clause from an OUTER JOIN, then throughout the query
** replace all other occurrences of COLUMN with CONSTANT.
**
** For example, the query:
@@ -152153,6 +154915,16 @@ static int pushDownWhereTerms(
x.pEList = pSubq->pEList;
x.pCList = findLeftmostExprlist(pSubq);
pNew = substExpr(&x, pNew);
+ assert( pNew!=0 || pParse->nErr!=0 );
+ if( pParse->nErr==0 && pNew->op==TK_IN && ExprUseXSelect(pNew) ){
+ assert( pNew->x.pSelect!=0 );
+ pNew->x.pSelect->selFlags |= SF_ClonedRhsIn;
+ assert( pWhere!=0 );
+ assert( pWhere->op==TK_IN );
+ assert( ExprUseXSelect(pWhere) );
+ assert( pWhere->x.pSelect!=0 );
+ pWhere->x.pSelect->selFlags |= SF_ClonedRhsIn;
+ }
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
/* Restriction 6c has prevented push-down in this case */
@@ -152387,14 +155159,14 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2)
** ORDER BY ... COLLATE ...
**
-** This transformation is necessary because the multiSelectOrderBy() routine
+** This transformation is necessary because the multiSelectByMerge() routine
** above that generates the code for a compound SELECT with an ORDER BY clause
** uses a merge algorithm that requires the same collating sequence on the
** result columns as on the ORDER BY clause. See ticket
** http://sqlite.org/src/info/6709574d2a
**
** This transformation is only needed for EXCEPT, INTERSECT, and UNION.
-** The UNION ALL operator works fine with multiSelectOrderBy() even when
+** The UNION ALL operator works fine with multiSelectByMerge() even when
** there are COLLATE terms in the ORDER BY.
*/
static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
@@ -152541,14 +155313,13 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
}
/*
-** This function checks if argument pFrom refers to a CTE declared by
+** This function checks to see 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.
+** pParse->pWith linked list). And if currently processing a CTE expression,
+** it also 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->pSTab
-** and other fields are populated accordingly.
+** If pFrom matches a CTE, pFrom->pSTab and other fields are populated
+** accordingly.
**
** Return 0 if no match is found.
** Return 1 if a match is found.
@@ -152677,6 +155448,18 @@ static int resolveFromTermToCte(
pRecTerm = pRecTerm->pPrior;
}
+#if SQLITE_MAX_EXPR_DEPTH>0
+ if( pParse->nTab>=db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
+ /* Bug 2026-10-04T05:35:14Z: Prevent nested CTEs from generating
+ ** an exponential number of cursors. The error message here will
+ ** be "Nested too deep", which isn't exactly correct, but it is
+ ** sufficient, and we don't want to use extra code space for more
+ ** detail on such an obscure error. */
+ pParse->nNestSel = pParse->nTab;
+ }
+ pParse->nNestSel++;
+ if( checkSubqueryNestingDepth(pParse) ) return 2;
+#endif
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
@@ -152701,6 +155484,10 @@ static int resolveFromTermToCte(
}
}
pParse->pWith = pWith;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ pParse->nNestSel--;
+ assert( pParse->nNestSel>=0 );
+#endif
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
pEList = pLeft->pEList;
@@ -152940,7 +155727,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( ALWAYS(IsVirtual(pTab))
- && pFrom->fg.fromDDL
+ && (pFrom->fg.fromDDL || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL))
&& ALWAYS(pTab->u.vtab.p!=0)
&& pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
){
@@ -153147,6 +155934,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pRight = sqlite3Expr(db, TK_ID, zName);
if( (pTabList->nSrc>1
&& ( (pFrom->fg.jointype & JT_LTORJ)==0
+ || zTName!=0
|| (selFlags & SF_NestedFrom)!=0
|| !inAnyUsingClause(zName,pFrom,pTabList->nSrc-i-1)
)
@@ -153893,7 +156681,7 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
&& pExpr->pAggInfo==0
){
sqlite3 *db = pWalker->pParse->db;
- Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
+ Expr *pNew = sqlite3ExprInt32(db, 1);
if( pNew ){
Expr *pWhere = pS->pWhere;
SWAP(Expr, *pNew, *pExpr);
@@ -154033,7 +156821,8 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
if( ExprHasProperty(pExpr, EP_WinFunc) ) return 0;/* Not a window function */
pFrom = p->pSrc->a;
- if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */
+ if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */
+ if( (p->selFlags & SF_Correlated)!=0 ) return 0; /* Not a correlated subq */
pSub = pFrom->u4.pSubq->pSelect;
if( pSub->pPrior==0 ) return 0; /* Must be a compound */
if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */
@@ -154076,6 +156865,10 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
}else{
pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr);
}
+ if( pParse->nErr ){
+ sqlite3ExprDelete(db, pExpr);
+ pExpr = 0;
+ }
pSub = pPrior;
}
p->pEList->a[0].pExpr = pExpr;
@@ -154211,6 +157004,7 @@ static SQLITE_NOINLINE void existsToJoin(
&& !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
&& ALWAYS(p->pSrc!=0)
&& p->pSrc->nSrcpLimit==0 || p->pLimit->pRight==0)
){
if( pWhere->op==TK_AND ){
Expr *pRight = pWhere->pRight;
@@ -154244,7 +157038,6 @@ static SQLITE_NOINLINE void existsToJoin(
ExprSetProperty(pWhere, EP_IntValue);
assert( p->pWhere!=0 );
pSub->pSrc->a[0].fg.fromExists = 1;
- pSub->pSrc->a[0].fg.jointype |= JT_CROSS;
p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc);
if( pSubWhere ){
p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere);
@@ -154252,6 +157045,7 @@ static SQLITE_NOINLINE void existsToJoin(
}
pSub->pSrc = 0;
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSub);
+ recomputeColumnsUsed(p, &p->pSrc->a[p->pSrc->nSrc-1]);
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x100000 ){
TREETRACE(0x100000,pParse,p,
@@ -154259,7 +157053,6 @@ static SQLITE_NOINLINE void existsToJoin(
sqlite3TreeViewSelect(0, p, 0);
}
#endif
- existsToJoin(pParse, p, pSubWhere);
}
}
}
@@ -154270,9 +157063,10 @@ static SQLITE_NOINLINE void existsToJoin(
*/
typedef struct CheckOnCtx CheckOnCtx;
struct CheckOnCtx {
- SrcList *pSrc; /* SrcList for this context */
- int iJoin; /* Cursor numbers must be =< than this */
- CheckOnCtx *pParent; /* Parent context */
+ SrcList *pSrc; /* SrcList for this context */
+ int iJoin; /* Cursors must be left of this one, if not negative */
+ int bFuncArg; /* True for table-function arg */
+ CheckOnCtx *pParent; /* Parent context */
};
/*
@@ -154303,11 +157097,11 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
** set it to the cursor number of the RHS of the join to which this
** ON expression was attached and then iterate through the entire
** expression. */
- assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin );
- if( pCtx->iJoin==0 ){
+ assert( pCtx->iJoin<0 || pCtx->iJoin==pExpr->w.iJoin );
+ if( pCtx->iJoin<0 ){
pCtx->iJoin = pExpr->w.iJoin;
sqlite3WalkExprNN(pWalker, pExpr);
- pCtx->iJoin = 0;
+ pCtx->iJoin = -1;
return WRC_Prune;
}
}
@@ -154317,14 +157111,25 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
** Then, if CheckOnCtx.iJoin indicates that this expression is part of an
** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it
** does not refer to a table to the right of CheckOnCtx.iJoin. */
+ int iTab = pExpr->iTable;
do {
SrcList *pSrc = pCtx->pSrc;
- int iTab = pExpr->iTable;
- if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
- if( pCtx->iJoin && iTab>pCtx->iJoin ){
- sqlite3ErrorMsg(pWalker->pParse,
- "ON clause references tables to its right");
- return WRC_Abort;
+ int nSrc = pSrc->nSrc;
+ int ii;
+ for(ii=0; iia[ii].iCursor!=iTab; ii++){}
+ if( iiiJoin>=0 ){
+ for(ii--; ii>=0 && pSrc->a[ii].iCursor!=pCtx->iJoin; ii--){}
+ if( ii>=0 ){
+ /* Table iJoin appears to the left of table iTab in the SrcList.
+ ** Therefore the expression refers to a table to its right. */
+ sqlite3ErrorMsg(pWalker->pParse,
+ "%s references tables to its right",
+ (pCtx->bFuncArg ? "table-function argument" : "ON clause")
+ );
+ return WRC_Abort;
+ }
}
break;
}
@@ -154346,6 +157151,7 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
memset(&sCtx, 0, sizeof(sCtx));
sCtx.pSrc = pSelect->pSrc;
sCtx.pParent = pCtx;
+ sCtx.iJoin = -1;
pWalker->u.pCheckOnCtx = &sCtx;
sqlite3WalkSelect(pWalker, pSelect);
pWalker->u.pCheckOnCtx = pCtx;
@@ -154358,9 +157164,10 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
** Check all ON clauses in pSelect to verify that they do not reference
** columns to the right.
*/
-static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
+SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect){
Walker w;
CheckOnCtx sCtx;
+ int ii;
assert( pSelect->selFlags & SF_OnToWhere );
assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 );
memset(&w, 0, sizeof(w));
@@ -154370,8 +157177,67 @@ static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
w.u.pCheckOnCtx = &sCtx;
memset(&sCtx, 0, sizeof(sCtx));
sCtx.pSrc = pSelect->pSrc;
- sqlite3WalkExprNN(&w, pSelect->pWhere);
+ sCtx.iJoin = -1;
+ sqlite3WalkExpr(&w, pSelect->pWhere);
pSelect->selFlags &= ~SF_OnToWhere;
+
+ /* Check for any table-function args that are attached to virtual tables
+ ** on the RHS of an outer join. They are subject to similar constraints
+ ** as ON clauses. Specifically:
+ **
+ ** * If the table-valued function is to the left of any RIGHT JOIN, or if
+ ** it is the RHS of a RIGHT JOIN, then the table-valued function arguments
+ ** may not refer to any tables to the right of this one.
+ **
+ ** * If the table-valued function is to the left of a LEFT JOIN, then it
+ ** may not refer to any table that occurs to the right of the LEFT JOIN.
+ */
+ sCtx.bFuncArg = 1;
+ for(ii=0; iipSrc->nSrc; ii++){
+ SrcItem *pItem = &pSelect->pSrc->a[ii];
+ if( pItem->fg.isTabFunc ){
+ sCtx.iJoin = -1;
+ if( (pItem->fg.jointype & (JT_LTORJ|JT_RIGHT)) ){
+ sCtx.iJoin = pItem->iCursor;
+ }else{
+ int jj;
+ for(jj=ii+1; jjpSrc->nSrc; jj++){
+ SrcItem *pItem2 = &pSelect->pSrc->a[jj];
+ if( pItem2->fg.jointype & JT_OUTER ){
+ sCtx.iJoin = pItem2[-1].iCursor;
+ break;
+ }
+ }
+ }
+ if( sCtx.iJoin>=0 ){
+ sqlite3WalkExprList(&w, pItem->u1.pFuncArg);
+ }
+ }
+ }
+}
+
+/*
+** If p2 exists and p1 and p2 have the same number of terms, then change
+** every term of p1 to have the same sort order as p2 and return true.
+**
+** If p2 is NULL or p1 and p2 are different lengths, then make no changes
+** and return false.
+**
+** p1 must be non-NULL.
+*/
+static int sqlite3CopySortOrder(ExprList *p1, ExprList *p2){
+ assert( p1 );
+ if( p2 && p1->nExpr==p2->nExpr ){
+ int ii;
+ for(ii=0; iinExpr; ii++){
+ u8 sortFlags;
+ sortFlags = p2->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
+ p1->a[ii].fg.sortFlags = sortFlags;
+ }
+ return 1;
+ }else{
+ return 0;
+ }
}
/*
@@ -154469,8 +157335,7 @@ SQLITE_PRIVATE int sqlite3Select(
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
if( IgnorableDistinct(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
- pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
+ assert(pDest->eDest==SRT_Exists || 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 ){
@@ -154486,7 +157351,6 @@ SQLITE_PRIVATE int sqlite3Select(
p->pOrderBy = 0;
}
p->selFlags &= ~(u32)SF_Distinct;
- p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
if( pParse->nErr ){
@@ -154501,18 +157365,6 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
- /* If the SELECT statement contains ON clauses that were moved into
- ** the WHERE clause, go through and verify that none of the terms
- ** in the ON clauses reference tables to the right of the ON clause.
- ** Do this now, after name resolution, but before query flattening
- */
- if( p->selFlags & SF_OnToWhere ){
- selectCheckOnClauses(pParse, p);
- if( pParse->nErr ){
- goto select_end;
- }
- }
-
/* If the SF_UFSrcCheck flag is set, then this function is being called
** as part of populating the temp table for an UPDATE...FROM statement.
** In this case, it is an error if the target object (pSrc->a[0]) name
@@ -155026,7 +157878,8 @@ SQLITE_PRIVATE int sqlite3Select(
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
- && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
+ && sqlite3CopySortOrder(pEList, sSort.pOrderBy)
+ && sqlite3ExprListCompare(pEList, sSort.pOrderBy, -1)==0
&& OptimizationEnabled(db, SQLITE_GroupByOrder)
#ifndef SQLITE_OMIT_WINDOWFUNC
&& p->pWin==0
@@ -155240,21 +158093,10 @@ SQLITE_PRIVATE int sqlite3Select(
** but not actually sorted. Either way, record the fact that the
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
** variable. */
- if( 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; iinExpr; ii++){
- u8 sortFlags;
- sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
- pGroupBy->a[ii].fg.sortFlags = sortFlags;
- }
- if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
- orderByGrp = 1;
- }
+ if( sqlite3CopySortOrder(pGroupBy, sSort.pOrderBy)
+ && sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0
+ ){
+ orderByGrp = 1;
}
}else{
assert( 0==sqlite3LogEst(1) );
@@ -156064,7 +158906,7 @@ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerS
sqlite3SelectDelete(db, pTmp->pSelect);
sqlite3IdListDelete(db, pTmp->pIdList);
sqlite3UpsertDelete(db, pTmp->pUpsert);
- sqlite3SrcListDelete(db, pTmp->pFrom);
+ sqlite3SrcListDelete(db, pTmp->pSrc);
sqlite3DbFree(db, pTmp->zSpan);
sqlite3DbFree(db, pTmp);
@@ -156244,8 +159086,9 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
+ }else if( db->init.busy ){
+ sqlite3ErrorMsg(pParse,""); /* Err msg generated by corruptSchema() */
}else{
- assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
VVA_ONLY( pParse->ifNotExists = 1; )
}
@@ -156253,11 +159096,16 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
}
}
+ /* NB: The SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES compile-time option is
+ ** experimental and unsupported. Do not use it unless understand the
+ ** implications and you cannot get by without this capability. */
+#if !defined(SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES) /* Experimental */
/* Do not create a trigger on a system table */
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
goto trigger_cleanup;
}
+#endif
/* INSTEAD of triggers are only for views and views only support INSTEAD
** of triggers.
@@ -156364,16 +159212,22 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
DbFixer sFix; /* Fixer object */
int iDb; /* Database containing the trigger */
Token nameToken; /* Trigger name for error reporting */
+ i64 n; /* Number of steps */
pParse->pNewTrigger = 0;
if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
zName = pTrig->zName;
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
+ assert( iDb>=00 && iDbnDb );
pTrig->step_list = pStepList;
- while( pStepList ){
+ for(n=0; pStepList; n++){
pStepList->pTrig = pTrig;
pStepList = pStepList->pNext;
}
+ if( n>pParse->db->aLimit[SQLITE_LIMIT_TRIGGER_STEPS] ){
+ sqlite3ErrorMsg(pParse, "trigger \"%w\" contains too many steps", zName);
+ goto triggerfinish_cleanup;
+ }
sqlite3TokenInit(&nameToken, pTrig->zName);
sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
@@ -156403,12 +159257,12 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
if( sqlite3ReadOnlyShadowTables(db) ){
TriggerStep *pStep;
for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){
- if( pStep->zTarget!=0
- && sqlite3ShadowTableName(db, pStep->zTarget)
+ if( pStep->pSrc!=0
+ && sqlite3ShadowTableName(db, pStep->pSrc->a[0].zName)
){
sqlite3ErrorMsg(pParse,
"trigger \"%s\" may not write to shadow table \"%s\"",
- pTrig->zName, pStep->zTarget);
+ pTrig->zName, pStep->pSrc->a[0].zName);
goto triggerfinish_cleanup;
}
}
@@ -156499,26 +159353,39 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(
static TriggerStep *triggerStepAllocate(
Parse *pParse, /* Parser context */
u8 op, /* Trigger opcode */
- Token *pName, /* The target name */
+ SrcList *pTabList, /* Target table */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
+ Trigger *pNew = pParse->pNewTrigger;
sqlite3 *db = pParse->db;
- TriggerStep *pTriggerStep;
+ TriggerStep *pTriggerStep = 0;
- if( pParse->nErr ) return 0;
- pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
- if( pTriggerStep ){
- char *z = (char*)&pTriggerStep[1];
- memcpy(z, pName->z, pName->n);
- sqlite3Dequote(z);
- pTriggerStep->zTarget = z;
- pTriggerStep->op = op;
- pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd);
- if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName);
+ if( pParse->nErr==0 ){
+ if( pNew
+ && pNew->pSchema!=db->aDb[1].pSchema
+ && pTabList->a[0].u4.zDatabase
+ ){
+ sqlite3ErrorMsg(pParse,
+ "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
+ "statements within triggers");
+ }else{
+ pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
+ if( pTriggerStep ){
+ pTriggerStep->pSrc = sqlite3SrcListDup(db, pTabList, EXPRDUP_REDUCE);
+ pTriggerStep->op = op;
+ pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd);
+ if( pTriggerStep->pSrc && IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse,
+ pTriggerStep->pSrc->a[0].zName,
+ pTabList->a[0].zName
+ );
+ }
+ }
}
}
+
+ sqlite3SrcListDelete(db, pTabList);
return pTriggerStep;
}
@@ -156531,7 +159398,7 @@ static TriggerStep *triggerStepAllocate(
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
Parse *pParse, /* Parser */
- Token *pTableName, /* Name of the table into which we insert */
+ SrcList *pTabList, /* Table to INSERT into */
IdList *pColumn, /* List of columns in pTableName to insert into */
Select *pSelect, /* A SELECT statement that supplies values */
u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
@@ -156544,7 +159411,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
assert(pSelect != 0 || db->mallocFailed);
- pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd);
+ pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTabList, zStart, zEnd);
if( pTriggerStep ){
if( IN_RENAME_OBJECT ){
pTriggerStep->pSelect = pSelect;
@@ -156576,7 +159443,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
Parse *pParse, /* Parser */
- Token *pTableName, /* Name of the table to be updated */
+ SrcList *pTabList, /* Name of the table to be updated */
SrcList *pFrom, /* FROM clause for an UPDATE-FROM, or NULL */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
@@ -156587,21 +159454,36 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
- pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd);
+ pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTabList, zStart, zEnd);
if( pTriggerStep ){
+ SrcList *pFromDup = 0;
if( IN_RENAME_OBJECT ){
pTriggerStep->pExprList = pEList;
pTriggerStep->pWhere = pWhere;
- pTriggerStep->pFrom = pFrom;
+ pFromDup = pFrom;
pEList = 0;
pWhere = 0;
pFrom = 0;
}else{
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
- pTriggerStep->pFrom = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE);
+ pFromDup = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE);
}
pTriggerStep->orconf = orconf;
+
+ if( pFromDup && !IN_RENAME_OBJECT){
+ Select *pSub;
+ Token as = {0, 0};
+ pSub = sqlite3SelectNew(pParse, 0, pFromDup, 0,0,0,0, SF_NestedFrom, 0);
+ pFromDup = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &as, pSub ,0);
+ }
+ if( pFromDup && pTriggerStep->pSrc ){
+ pTriggerStep->pSrc = sqlite3SrcListAppendList(
+ pParse, pTriggerStep->pSrc, pFromDup
+ );
+ }else{
+ sqlite3SrcListDelete(db, pFromDup);
+ }
}
sqlite3ExprListDelete(db, pEList);
sqlite3ExprDelete(db, pWhere);
@@ -156616,7 +159498,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(
Parse *pParse, /* Parser */
- Token *pTableName, /* The table from which rows are deleted */
+ SrcList *pTabList, /* The table from which rows are deleted */
Expr *pWhere, /* The WHERE clause */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
@@ -156624,7 +159506,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(
sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
- pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd);
+ pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTabList, zStart, zEnd);
if( pTriggerStep ){
if( IN_RENAME_OBJECT ){
pTriggerStep->pWhere = pWhere;
@@ -156824,6 +159706,7 @@ static SQLITE_NOINLINE Trigger *triggersReallyExist(
p = pList;
if( (pParse->db->flags & SQLITE_EnableTrigger)==0
&& pTab->pTrigger!=0
+ && sqlite3SchemaToIndex(pParse->db, pTab->pTrigger->pSchema)!=1
){
/* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that
** only TEMP triggers are allowed. Truncate the pList so that it
@@ -156886,52 +159769,6 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist(
return triggersReallyExist(pParse,pTab,op,pChanges,pMask);
}
-/*
-** Convert the pStep->zTarget string into a SrcList and return a pointer
-** to that SrcList.
-**
-** This routine adds a specific database name, if needed, to the target when
-** forming the SrcList. This prevents a trigger in one database from
-** referring to a target in another database. An exception is when the
-** trigger is in TEMP in which case it can refer to any other database it
-** wants.
-*/
-SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(
- Parse *pParse, /* The parsing context */
- TriggerStep *pStep /* The trigger containing the target token */
-){
- sqlite3 *db = pParse->db;
- SrcList *pSrc; /* SrcList to be returned */
- char *zName = sqlite3DbStrDup(db, pStep->zTarget);
- pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
- assert( pSrc==0 || pSrc->nSrc==1 );
- assert( zName || pSrc==0 );
- if( pSrc ){
- Schema *pSchema = pStep->pTrig->pSchema;
- pSrc->a[0].zName = zName;
- if( pSchema!=db->aDb[1].pSchema ){
- assert( pSrc->a[0].fg.fixedSchema || pSrc->a[0].u4.zDatabase==0 );
- pSrc->a[0].u4.pSchema = pSchema;
- pSrc->a[0].fg.fixedSchema = 1;
- }
- if( pStep->pFrom ){
- SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
- if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){
- Select *pSubquery;
- Token as;
- pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0);
- as.n = 0;
- as.z = 0;
- pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
- }
- pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
- }
- }else{
- sqlite3DbFree(db, zName);
- }
- return pSrc;
-}
-
/*
** Return true if the pExpr term from the RETURNING clause argument
** list is of the form "*". Raise an error if the terms if of the
@@ -157197,7 +160034,7 @@ static int codeTriggerProgram(
switch( pStep->op ){
case TK_UPDATE: {
sqlite3Update(pParse,
- sqlite3TriggerStepSrc(pParse, pStep),
+ sqlite3SrcListDup(db, pStep->pSrc, 0),
sqlite3ExprListDup(db, pStep->pExprList, 0),
sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf, 0, 0, 0
@@ -157207,7 +160044,7 @@ static int codeTriggerProgram(
}
case TK_INSERT: {
sqlite3Insert(pParse,
- sqlite3TriggerStepSrc(pParse, pStep),
+ sqlite3SrcListDup(db, pStep->pSrc, 0),
sqlite3SelectDup(db, pStep->pSelect, 0),
sqlite3IdListDup(db, pStep->pIdList),
pParse->eOrconf,
@@ -157218,7 +160055,7 @@ static int codeTriggerProgram(
}
case TK_DELETE: {
sqlite3DeleteFrom(pParse,
- sqlite3TriggerStepSrc(pParse, pStep),
+ sqlite3SrcListDup(db, pStep->pSrc, 0),
sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
);
sqlite3VdbeAddOp0(v, OP_ResetCount);
@@ -157283,7 +160120,7 @@ static TriggerPrg *codeRowTrigger(
Table *pTab, /* The table pTrigger is attached to */
int orconf /* ON CONFLICT policy to code trigger program with */
){
- Parse *pTop = sqlite3ParseToplevel(pParse);
+ Parse *pTop; /* Top level Parse object */
sqlite3 *db = pParse->db; /* Database handle */
TriggerPrg *pPrg; /* Value to return */
Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */
@@ -157292,10 +160129,24 @@ static TriggerPrg *codeRowTrigger(
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
Parse sSubParse; /* Parse context for sub-vdbe */
+ int nDepth; /* Trigger depth */
+
+ /* Ensure that triggers are not chained too deep. This test is linear
+ ** in the chaining depth, but sensible code ought not be chaining
+ ** triggers excessively, so that shouldn't be a problem.
+ */
+ pTop = pParse;
+ for(nDepth=0; pTop->pOuterParse; pTop = pTop->pOuterParse, nDepth++){}
+ if( nDepth>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
+ sqlite3ErrorMsg(pParse, "triggers nested too deep");
+ return 0;
+ }
+ pTop = sqlite3ParseToplevel(pParse);
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTop->pVdbe );
+
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
** are freed if an error occurs, link them into the Parse.pTriggerPrg
** list of the top-level Parse object sooner rather than later. */
@@ -157671,26 +160522,37 @@ static void updateVirtualTable(
** integer. In that case, add an OP_RealAffinity opcode to make sure
** it has been converted into REAL.
*/
-SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
+static SQLITE_NOINLINE void columnDefaultUncommonCase(
+ Vdbe *v, /* Byte code under construction */
+ Table *pTab, /* The table */
+ Column *pCol /* Which column of the table */
+){
+ sqlite3_value *pValue = 0;
+ u8 enc = ENC(sqlite3VdbeDb(v));
+ Parse *pParse = sqlite3VdbeParser(v);
+ assert( !IsView(pTab) );
+ sqlite3ValueFromExpr(sqlite3VdbeDb(v),
+ sqlite3ColumnExprAuth(pTab,pCol,pParse), enc,
+ pCol->affinity, &pValue);
+ if( pValue ){
+ sqlite3VdbeAppendP4(v, pValue, P4_MEM);
+ }
+}
+SQLITE_PRIVATE void sqlite3ColumnDefault(
+ Vdbe *v, /* Byte code under construction */
+ Table *pTab, /* The table */
+ int i, /* Which column of the table */
+ int iReg /* Register in which results are stored */
+){
Column *pCol;
assert( pTab!=0 );
assert( pTab->nCol>i );
pCol = &pTab->aCol[i];
if( pCol->iDflt ){
- sqlite3_value *pValue = 0;
- u8 enc = ENC(sqlite3VdbeDb(v));
- assert( !IsView(pTab) );
- VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName));
- assert( inCol );
- sqlite3ValueFromExpr(sqlite3VdbeDb(v),
- sqlite3ColumnExpr(pTab,pCol), enc,
- pCol->affinity, &pValue);
- if( pValue ){
- sqlite3VdbeAppendP4(v, pValue, P4_MEM);
- }
+ columnDefaultUncommonCase(v,pTab,pCol);
}
#ifndef SQLITE_OMIT_FLOATING_POINT
- if( pCol->affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
+ if( pCol->affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
@@ -158505,6 +161367,7 @@ SQLITE_PRIVATE void sqlite3Update(
sqlite3VdbeAddOp3(v, OP_Column, iEph, iRowidExpr, regNewRowid);
}
sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v);
+ sqlite3MayAbort(pParse);
}
/* Compute the old pre-UPDATE content of the row being changed, if that
@@ -159296,7 +162159,8 @@ SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; inCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
- sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
+ int iStorage = pTop->regData + sqlite3TableColumnToStorage(pTab, i);
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iStorage);
}
}
sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
@@ -159540,9 +162404,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
pDb = &db->aDb[nDb];
assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
pTemp = pDb->pBt;
+ nRes = sqlite3BtreeGetRequestedReserve(pMain);
if( pOut ){
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
i64 sz = 0;
+ const char *zFilename;
if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
rc = SQLITE_ERROR;
sqlite3SetString(pzErrMsg, db, "output file already exists");
@@ -159554,8 +162420,16 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
** they are for the database being vacuumed, except that PAGER_CACHESPILL
** is always set. */
pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK);
+
+ /* If the VACUUM INTO target file is a URI filename and if the
+ ** "reserve=N" query parameter is present, reset the reserve to the
+ ** amount specified, if the amount is within range */
+ zFilename = sqlite3BtreeGetFilename(pTemp);
+ if( ALWAYS(zFilename) ){
+ int nNew = (int)sqlite3_uri_int64(zFilename, "reserve", nRes);
+ if( nNew>=0 && nNew<=255 ) nRes = nNew;
+ }
}
- nRes = sqlite3BtreeGetRequestedReserve(pMain);
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
@@ -159874,6 +162748,7 @@ SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
+ sqlite3_mutex_enter(db->mutex);
for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){
Module *pMod = (Module*)sqliteHashData(pThis);
pNext = sqliteHashNext(pThis);
@@ -159884,6 +162759,7 @@ SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){
}
createModule(db, pMod->zName, 0, 0, 0);
}
+ sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -160452,6 +163328,8 @@ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "%s", zErr);
pParse->rc = rc;
+ }else{
+ sqlite3MarkAllShadowTablesOf(db, pTab);
}
sqlite3DbFree(db, zErr);
}
@@ -161039,6 +163917,17 @@ SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){
}
}
+/*
+** Erase all eponymous virtual table instances associated with database
+** handle db.
+*/
+SQLITE_PRIVATE void sqlite3VtabEponymousTableClearAll(sqlite3 *db){
+ HashElem *pElem;
+ for(pElem=sqliteHashFirst(&db->aModule); pElem; pElem=sqliteHashNext(pElem)){
+ sqlite3VtabEponymousTableClear(db, (Module*)sqliteHashData(pElem));
+ }
+}
+
/*
** Return the ON CONFLICT resolution mode in effect for the virtual
** table update operation currently in progress.
@@ -161731,10 +164620,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
-
-
-
-
+SQLITE_PRIVATE int sqlite3WhereLoopBloomable(const WhereLoop*);
/*
** Bitmasks for the operators on WhereTerm objects. These are all
@@ -162374,6 +165260,7 @@ static Expr *removeUnindexableInClauseTerms(
ExprList *pRhs = 0; /* New RHS after modifications */
ExprList *pLhs = 0; /* New LHS after mods */
int i; /* Loop counter */
+ int nRhs = 0; /* Number of RHS terms added so far */
assert( ExprUseXSelect(pNew) );
pOrigRhs = pSelect->pEList;
@@ -162387,6 +165274,9 @@ static Expr *removeUnindexableInClauseTerms(
int iField;
assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
iField = pLoop->aLTerm[i]->u.x.iField - 1;
+ if( iField!=nRhs ){
+ ExprClearProperty(pNew, EP_Subrtn);
+ }
if( NEVER(pOrigRhs->a[iField].pExpr==0) ){
continue; /* Duplicate PK column */
}
@@ -162398,6 +165288,7 @@ static Expr *removeUnindexableInClauseTerms(
pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
pOrigLhs->a[iField].pExpr = 0;
}
+ nRhs++;
}
}
sqlite3ExprListDelete(db, pOrigRhs);
@@ -162497,8 +165388,20 @@ static SQLITE_NOINLINE void codeINTerm(
}else{
sqlite3 *db = pParse->db;
Expr *pXMod = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
+ if( nEq>1 ){
+ /* If this IN(SELECT ...) expression drives more than one column of
+ ** the index, disable the seek-scan optimization. The reasons for this
+ ** are that (a) it is only possible to make this happen by populating
+ ** the sqlite_stat1 table with inconsistent information, and (b) it
+ ** would require sqlite3FindInIndex() to find an index that is not
+ ** only unique for the columns in question, but also delivers them
+ ** in sorted order (requires checking asc/desc, and rejecting cases
+ ** where the indexed columns are not in the right order). */
+ pLoop->wsFlags &= ~WHERE_IN_SEEKSCAN;
+ }
if( !db->mallocFailed ){
- aiMap = (int*)sqlite3DbMallocZero(db, sizeof(int)*nEq);
+ int nCol = pX->x.pSelect->pEList->nExpr;
+ aiMap = (int*)sqlite3DbMallocZero(db, sizeof(int)*nCol);
eType = sqlite3FindInIndex(pParse, pXMod, IN_INDEX_LOOP, 0, aiMap, &iTab);
}
sqlite3ExprDelete(db, pXMod);
@@ -162745,12 +165648,7 @@ static int codeAllEqualityTerms(
testcase( pTerm->wtFlags & TERM_VIRTUAL );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
- if( nReg==1 ){
- sqlite3ReleaseTempReg(pParse, regBase);
- regBase = r1;
- }else{
- sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
- }
+ sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
}
if( pTerm->eOperator & WO_IN ){
if( pTerm->pExpr->flags & EP_xIsSelect ){
@@ -163203,6 +166101,7 @@ static SQLITE_NOINLINE void filterPullDown(
regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt);
VdbeCoverage(pParse->pVdbe);
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, regRowid, 1);
VdbeCoverage(pParse->pVdbe);
@@ -163216,6 +166115,7 @@ static SQLITE_NOINLINE void filterPullDown(
r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff);
codeApplyAffinity(pParse, r1, nEq, zStartAff);
sqlite3DbFree(pParse->db, zStartAff);
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, r1, nEq);
VdbeCoverage(pParse->pVdbe);
@@ -163246,6 +166146,49 @@ static int whereLoopIsOneRow(WhereLoop *pLoop){
return 0;
}
+/*
+** This is called while coding loop pLevel, which scans FROM clause item
+** pTabItem. pE is an expression for which all the prerequisites are
+** available. This function tests if pE can be coded as part of the current
+** loop, or whether it needs to be deferred to ensure outer joins are
+** processed correctly. This function returns non-zero if the expression
+** can be coded as part of the loop, or 0 if it must be deferred.
+**
+** The expression must be deferred if:
+**
+** * There are any RIGHT joins in the FROM clause and the expression
+** was not part of an ON clause, or was part of an ON clause to the
+** right of the join.
+**
+** * The table is the RHS of a LEFT JOIN and the expression was not
+** part of an ON clause on an OUTER join, or was part of an ON clause
+** on an OUTER join to the right of the join.
+*/
+static int whereExprIsReady(
+ WhereInfo *pWInfo,
+ WhereLevel *pLevel,
+ SrcItem *pTabItem,
+ Expr *pE
+){
+ u8 jtype = pTabItem->fg.jointype;
+ if( jtype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){
+ if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){
+ /* Defer processing WHERE clause constraints until after outer
+ ** join processing. tag-20220513a */
+ return 0;
+ }else if( (jtype & JT_LEFT) && !ExprHasProperty(pE,EP_OuterON) ){
+ return 0;
+ }else{
+ Bitmask m = sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin);
+ if( m & pLevel->notReady ){
+ /* An ON clause that is not ripe */
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
@@ -163325,6 +166268,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pLevel->iLeftJoin = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
VdbeComment((v, "init LEFT JOIN match flag"));
+ if( pTabItem->fg.viaCoroutine ){
+ sqlite3VdbeAddOp2(v, OP_NullRow, pTabItem->iCursor, 1);
+ }
}
/* Special case of a FROM clause subquery implemented as a co-routine */
@@ -163360,7 +166306,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){
int iTab = pParse->nTab++;
int iCache = ++pParse->nMem;
- sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab);
+ sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab, 0);
sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache);
}else{
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
@@ -163819,6 +166765,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
VdbeComment((v, "NULL-scan pass ctr"));
}
if( pLevel->regFilter ){
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
regBase, nEq);
VdbeCoverage(v);
@@ -164084,7 +167031,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
*/
- if( pWInfo->nLevel>1 ){
+ if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){
int nNotReady; /* The number of notReady tables */
SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
@@ -164097,6 +167044,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
for(k=1; k<=nNotReady; k++){
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
}
+
+ /* Clear the fromExists flag on the OR-optimized table entry so that
+ ** the calls to sqlite3WhereEnd() do not code early-exits after the
+ ** first row is visited. The early exit applies to this table's
+ ** overall loop - including the multiple OR branches and any WHERE
+ ** conditions not passed to the sub-loops - not to the sub-loops. */
+ pOrTab->a[0].fg.fromExists = 0;
}else{
pOrTab = pWInfo->pTabList;
}
@@ -164168,6 +167122,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */
+ if( whereExprIsReady(pWInfo, pLevel, pTabItem, pExpr)==0 ) continue;
pExpr = sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
}
@@ -164340,7 +167295,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
assert( pLevel->op==OP_Return );
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
- if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
+ if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); }
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
@@ -164408,22 +167363,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
pE = pTerm->pExpr;
assert( pE!=0 );
- if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){
- if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){
- /* Defer processing WHERE clause constraints until after outer
- ** join processing. tag-20220513a */
- continue;
- }else if( (pTabItem->fg.jointype & JT_LEFT)==JT_LEFT
- && !ExprHasProperty(pE,EP_OuterON) ){
- continue;
- }else{
- Bitmask m = sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin);
- if( m & pLevel->notReady ){
- /* An ON clause that is not ripe */
- continue;
- }
- }
- }
+ if( whereExprIsReady(pWInfo, pLevel, pTabItem, pE)==0 ) continue;
if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
iNext = 2;
continue;
@@ -164497,6 +167437,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
+ if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue;
if( (pAlt->eOperator & WO_IN)
&& ExprUseXSelect(pAlt->pExpr)
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
@@ -164548,8 +167489,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
VdbeComment((v, "match against %s", pTab->zName));
sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk);
- sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ if( pRJ->regBloom ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ }
sqlite3VdbeJumpHere(v, jmp1);
sqlite3ReleaseTempRange(pParse, r, nPk+1);
}
@@ -164573,9 +167516,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** loop will run that invokes this subroutine for unmatched rows
** of pTab, with all tables to left begin set to NULL.
*/
- WhereRightJoin *pRJ = pLevel->pRJ;
- sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn);
- pRJ->addrSubrtn = sqlite3VdbeCurrentAddr(v);
+ {
+ WhereRightJoin *pRJ = pLevel->pRJ;
+ sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn);
+ pRJ->addrSubrtn = sqlite3VdbeCurrentAddr(v);
+ }
assert( pParse->withinRJSubrtn < 255 );
pParse->withinRJSubrtn++;
@@ -164679,22 +167624,39 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
}
}
+ if( pLevel->iIdxCur ){
+ /* pSubWhere may contain expressions that read from an index on the
+ ** table on the RHS of the right join. All such expressions first test
+ ** if the index is pointing at a NULL row, and if so, read from the
+ ** table cursor instead. So ensure that the index cursor really is
+ ** pointing at a NULL row here, so that no values are read from it during
+ ** the scan of the RHS of the RIGHT join below. */
+ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
+ }
pFrom = &uSrc.sSrc;
pFrom->nSrc = 1;
pFrom->nAlloc = 1;
memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
pFrom->a[0].fg.jointype = 0;
- assert( pParse->withinRJSubrtn < 100 );
+ if( pParse->withinRJSubrtn >= 100 ){
+ /* This limit --------------^^^
+ ** is based on an historical assert(). It is not compile-time or
+ ** run-time configurable. It could perhaps be raised as high as 254,
+ ** but only an attack robot would ever do even 100 RIGHT JOINS within
+ ** a single query, so we'll just leave it as it is. */
+ sqlite3ErrorMsg(pParse, "too many RIGHT JOINs");
+ return;
+ }
pParse->withinRJSubrtn++;
pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,
WHERE_RIGHT_JOIN, 0);
if( pSubWInfo ){
- int iCur = pLevel->iTabCur;
- int r = ++pParse->nMem;
- int nPk;
- int jmp;
+ int iCur = pLevel->iTabCur; /* Table on RHS of RIGHT JOIN &*/
+ int r = ++pParse->nMem; /* Register range to hold primary key */
+ int nPk; /* Number of values in the primary key */
+ int r2; /* Register holding record for primary key */
int addrCont = sqlite3WhereContinueLabel(pSubWInfo);
- Table *pTab = pTabItem->pSTab;
+ Table *pTab = pTabItem->pSTab; /* Table on RHS of RIGHT JOIN */
if( HasRowid(pTab) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r);
nPk = 1;
@@ -164708,11 +167670,31 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
}
}
- jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk);
- VdbeCoverage(v);
+
+ /* Generate code that checks to see if the current row of the RHS table
+ ** has appeared in any prior output row. */
+ if( pRJ->regBloom ){
+ sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom,
+ sqlite3VdbeCurrentAddr(v)+2, r, nPk);
+ VdbeCoverage(v);
+ }
sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk);
VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, jmp);
+ r2 = sqlite3GetTempReg(pParse);
+
+ /* Generate code that inserts the PK of the RHS table into the
+ ** pRH->iMatch index to indicate that the current row has appeared
+ ** in the output set. */
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, r2);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r2, r, nPk);
+ sqlite3ReleaseTempReg(pParse, r2);
+ if( pRJ->regBloom ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r, nPk);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ }
+
+ /* Invoke the subroutine that actually puts the current RHS table row
+ ** into the output set, with NULLs for the LHS. */
sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn);
sqlite3WhereEnd(pSubWInfo);
}
@@ -164938,7 +167920,7 @@ static int isLikeOrGlob(
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = sqlite3_value_text(pVal);
}
- sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
+ sqlite3VdbeReprepareOnBind(pParse->pVdbe, iCol, 0);
assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
}else if( op==TK_STRING ){
assert( !ExprHasProperty(pRight, EP_IntValue) );
@@ -165019,13 +168001,14 @@ static int isLikeOrGlob(
){
int isNum;
double rDummy;
- isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
+ assert( zNew[iTo]==0 );
+ isNum = sqlite3AtoF(zNew, &rDummy);
if( isNum<=0 ){
if( iTo==1 && zNew[0]=='-' ){
isNum = +1;
}else{
zNew[iTo-1]++;
- isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
+ isNum = sqlite3AtoF(zNew, &rDummy);
zNew[iTo-1]--;
}
}
@@ -165042,7 +168025,7 @@ static int isLikeOrGlob(
** reprepare the statement when that parameter is rebound */
if( op==TK_VARIABLE ){
Vdbe *v = pParse->pVdbe;
- sqlite3VdbeSetVarmask(v, pRight->iColumn);
+ sqlite3VdbeReprepareOnBind(v, pRight->iColumn, 0);
assert( !ExprHasProperty(pRight, EP_IntValue) );
if( *pisComplete && pRight->u.zToken[1] ){
/* If the rhs of the LIKE expression is a variable, and the current
@@ -165068,6 +168051,34 @@ static int isLikeOrGlob(
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+/*
+** If pExpr is one of "like", "glob", "match", or "regexp", then
+** return the corresponding SQLITE_INDEX_CONSTRAINT_xxxx value.
+** If not, return 0.
+**
+** pExpr is guaranteed to be a TK_FUNCTION.
+*/
+SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr *pExpr){
+ static const struct {
+ const char *zOp;
+ unsigned char eOp;
+ } aOp[] = {
+ { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
+ { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
+ { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
+ { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
+ };
+ int i;
+ assert( pExpr->op==TK_FUNCTION );
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ for(i=0; iu.zToken, aOp[i].zOp)==0 ){
+ return aOp[i].eOp;
+ }
+ }
+ return 0;
+}
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
@@ -165104,15 +168115,6 @@ static int isAuxiliaryVtabOperator(
Expr **ppRight /* Expression to left of MATCH/op2 */
){
if( pExpr->op==TK_FUNCTION ){
- static const struct Op2 {
- const char *zOp;
- unsigned char eOp2;
- } aOp[] = {
- { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
- { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
- { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
- { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
- };
ExprList *pList;
Expr *pCol; /* Column reference */
int i;
@@ -165132,16 +168134,11 @@ static int isAuxiliaryVtabOperator(
*/
pCol = pList->a[1].pExpr;
assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
- if( ExprIsVtab(pCol) ){
- for(i=0; iu.zToken, aOp[i].zOp)==0 ){
- *peOp2 = aOp[i].eOp2;
- *ppRight = pList->a[0].pExpr;
- *ppLeft = pCol;
- return 1;
- }
- }
+ if( ExprIsVtab(pCol) && (i = sqlite3ExprIsLikeOperator(pExpr))!=0 ){
+ *peOp2 = i;
+ *ppRight = pList->a[0].pExpr;
+ *ppLeft = pCol;
+ return 1;
}
/* We can also match against the first column of overloaded
@@ -165226,7 +168223,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
pWC->a[iChild].iParent = iParent;
pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
+ assert( pWC->a[iParent].nChild < UMXV(pWC->a[0].nChild) );
pWC->a[iParent].nChild++;
+ testcase( pWC->a[iParent].nChild == UMXV(pWC->a[0].nChild) );
+
}
/*
@@ -165275,16 +168275,22 @@ static void whereCombineDisjuncts(
Expr *pNew; /* New virtual expression */
int op; /* Operator for the combined expression */
int idxNew; /* Index in pWC of the next virtual term */
+ Expr *pA, *pB; /* Expressions associated with pOne and pTwo */
if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
- assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
- assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
- if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
- if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
+ pA = pOne->pExpr;
+ pB = pTwo->pExpr;
+ assert( pA->pLeft!=0 && pA->pRight!=0 );
+ assert( pB->pLeft!=0 && pB->pRight!=0 );
+ if( sqlite3ExprCompare(0,pA->pLeft, pB->pLeft, -1) ) return;
+ if( sqlite3ExprCompare(0,pA->pRight, pB->pRight,-1) ) return;
+ if( ExprHasProperty(pA,EP_Commuted)!=ExprHasProperty(pB,EP_Commuted) ){
+ return;
+ }
/* If we reach this point, it means the two subterms can be combined */
if( (eOp & (eOp-1))!=0 ){
if( eOp & (WO_LT|WO_LE) ){
@@ -165295,7 +168301,7 @@ static void whereCombineDisjuncts(
}
}
db = pWC->pWInfo->pParse->db;
- pNew = sqlite3ExprDup(db, pOne->pExpr, 0);
+ pNew = sqlite3ExprDup(db, pA, 0);
if( pNew==0 ) return;
for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( opop = op;
@@ -165609,29 +168615,58 @@ static void exprAnalyzeOrTerm(
}
}
- /* At this point, okToChngToIN is true if original pTerm satisfies
- ** case 1. In that case, construct a new virtual term that is
- ** pTerm converted into an IN operator.
+ /* At this point, okToChngToIN is true if original pTerm is a
+ ** candidate to satisfy case 1, though we are not yet certain that
+ ** the collating sequences are all compatible. Try to construct a
+ ** new virtual term that is pTerm converted from an OR operator
+ ** into an IN operator.
+ **
+ ** During construction, verify that the collating sequences on all
+ ** subterms of the OR are compatible. Omit the construction of the
+ ** new IN operator if there are any collating sequence mismatches.
*/
if( okToChngToIN ){
Expr *pDup; /* A transient duplicate expression */
ExprList *pList = 0; /* The RHS of the IN operator */
Expr *pLeft = 0; /* The LHS of the IN operator */
+ CollSeq *pCollSeq = 0; /* Collating sequence to use */
Expr *pNew; /* The complete IN operator */
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
+ Expr *pThis;
if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.x.leftColumn==iColumn );
- pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
+ pThis = pOrTerm->pExpr;
+ pDup = sqlite3ExprDup(db, pThis->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
- pLeft = pOrTerm->pExpr->pLeft;
+ if( pLeft==0 ){
+ pLeft = pThis->pLeft;
+ pCollSeq = sqlite3ExprCompareCollSeq(pParse, pThis);
+ }else{
+ assert( 0==sqlite3ExprCompare(pParse,
+ sqlite3ExprSkipCollate(pThis->pLeft),
+ sqlite3ExprSkipCollate(pLeft), -1) );
+ if( pCollSeq!=sqlite3ExprCompareCollSeq(pParse, pThis) ){
+ pLeft = 0; /* Collating sequence mismatch */
+ break;
+ }
+ }
+ }
+ if( pLeft==0 ){
+ pNew = 0; /* Collating sequence mismatch */
+ }else{
+ pDup = sqlite3ExprDup(db, pLeft, 0);
+ if( sqlite3ExprCollSeq(pParse, pDup)!=pCollSeq
+ && ALWAYS(pCollSeq!=0)
+ ){
+ assert( pCollSeq->zName!=0 );
+ pDup = sqlite3ExprAddCollateString(pParse, pDup, pCollSeq->zName);
+ }
+ pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
}
- assert( pLeft!=0 );
- pDup = sqlite3ExprDup(db, pLeft, 0);
- pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
@@ -165659,8 +168694,8 @@ static void exprAnalyzeOrTerm(
** 3. Not originating in the ON clause of an OUTER JOIN
** 4. The operator is not IS or else the query does not contain RIGHT JOIN
** 5. The affinities of A and B must be compatible
-** 6a. Both operands use the same collating sequence OR
-** 6b. The overall collating sequence is BINARY
+** 6. Both operands use the same collating sequence, and they must not
+** use explicit COLLATE clauses.
** If this routine returns TRUE, that means that the RHS can be substituted
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
** This is an optimization. No harm comes from returning 0. But if 1 is
@@ -165668,10 +168703,9 @@ static void exprAnalyzeOrTerm(
*/
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
char aff1, aff2;
- CollSeq *pColl;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
- if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
+ if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */
assert( pSrc!=0 );
if( pExpr->op==TK_IS
&& pSrc->nSrc>=2
@@ -165686,10 +168720,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
){
return 0; /* (5) */
}
- pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
- if( !sqlite3IsBinary(pColl)
- && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
- ){
+ if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
return 0; /* (6) */
}
return 1;
@@ -165857,6 +168888,7 @@ static void exprAnalyze(
pExpr = pTerm->pExpr;
assert( pExpr!=0 ); /* Because malloc() has not failed */
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
+exprAnalyze_restart:
pMaskSet->bVarSelect = 0;
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
@@ -166001,6 +169033,7 @@ static void exprAnalyze(
pList = pExpr->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
+ assert( pWC->a[idxTerm].nChild==0 );
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
@@ -166021,7 +169054,12 @@ static void exprAnalyze(
/* Analyze a term that is composed of two or more subterms connected by
** an OR operator.
*/
- else if( pExpr->op==TK_OR ){
+ else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
+ Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
+ if( pAlt!=pExpr ){
+ pTerm->pExpr = pExpr = sqlite3ExprSkipCollateAndLikely(pAlt);
+ goto exprAnalyze_restart;
+ }
assert( pWC->op==TK_AND );
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
pTerm = &pWC->a[idxTerm];
@@ -166210,9 +169248,13 @@ static void exprAnalyze(
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
+ && (pExpr->x.pSelect->selFlags & SF_MinMaxAgg)==0
&& pWC->op==TK_AND
+ && pExpr->x.pSelect->pEList->nExpr <= UMXV(pTerm->nChild)
+ /* ^-- See bug 2026-06-04T10:00:49Z */
){
int i;
+ assert( pTerm->nChild==0 );
for(i=0; ipLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
@@ -166334,14 +169376,12 @@ static void whereAddLimitExpr(
Expr *pNew;
int iVal = 0;
- if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
- Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
+ if( sqlite3ExprIsInteger(pExpr, &iVal, pParse, 0) && iVal>=0 ){
+ Expr *pVal = sqlite3ExprInt32(db, iVal);
if( pVal==0 ) return;
- ExprSetProperty(pVal, EP_IntValue);
- pVal->u.iValue = iVal;
pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
}else{
- Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0);
+ Expr *pVal = sqlite3ExprAlloc(db, TK_REGISTER, 0, 0);
if( pVal==0 ) return;
pVal->iTable = iReg;
pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
@@ -166616,6 +169656,10 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
if( pItem->fg.isTabFunc==0 ) return;
pTab = pItem->pSTab;
assert( pTab!=0 );
+ if( !IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "'%s' is not a function", pItem->zName);
+ return;
+ }
pArgs = pItem->u1.pFuncArg;
if( pArgs==0 ) return;
for(j=k=0; jnExpr; j++){
@@ -166650,6 +169694,16 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
}
}
+/*
+** Return true if the WhereLoop pLoop can be use a Bloom filter.
+** tag-202607231411
+*/
+SQLITE_PRIVATE int sqlite3WhereLoopBloomable(const WhereLoop *pLoop){
+ if( pLoop->wsFlags & WHERE_IPK ) return 1;
+ if( NEVER((pLoop->wsFlags & WHERE_INDEXED)==0) ) return 0;
+ return sqlite3IndexBloomable(pLoop->u.btree.pIndex, pLoop->u.btree.nEq);
+}
+
/************** End of whereexpr.c *******************************************/
/************** Begin file where.c *******************************************/
/*
@@ -166817,7 +169871,7 @@ SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
** If the ONEPASS optimization is used (if this routine returns true)
** then also write the indices of open cursors used by ONEPASS
** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
-** table and iaCur[1] gets the cursor used by an auxiliary index.
+** table and aiCur[1] gets the cursor used by an auxiliary index.
** Either value may be -1, indicating that cursor is not used.
** Any cursors returned will have been opened for writing.
**
@@ -167661,7 +170715,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
Bitmask idxCols; /* Bitmap of columns used for indexing */
Bitmask extraCols; /* Bitmap of additional columns */
u8 sentWarning = 0; /* True if a warning has been issued */
- u8 useBloomFilter = 0; /* True to also add a Bloom filter */
+ u8 useBloomFilter = 1; /* True to also add a Bloom filter */
Expr *pPartial = 0; /* Partial Index Expression */
int iContinue = 0; /* Jump here to skip excluded rows */
SrcList *pTabList; /* The complete FROM clause */
@@ -167788,18 +170842,13 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
pIdx->aiColumn[n] = pTerm->u.x.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
+ if( !sqlite3IsBinary(pColl) ){
+ /* Disallow the use of a Bloom filter if any non-BINARY collating
+ ** sequence is involved. tag-202607231411 */
+ useBloomFilter = 0;
+ }
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
n++;
- if( ALWAYS(pX->pLeft!=0)
- && sqlite3ExprAffinity(pX->pLeft)!=SQLITE_AFF_TEXT
- ){
- /* TUNING: only use a Bloom filter on an automatic index
- ** if one or more key columns has the ability to hold numeric
- ** values, since strings all have the same hash in the Bloom
- ** filter implementation and hence a Bloom filter on a text column
- ** is not usually helpful. */
- useBloomFilter = 1;
- }
}
}
}
@@ -167869,6 +170918,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
);
if( pLevel->regFilter ){
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0,
regBase, pLoop->u.btree.nEq);
}
@@ -167909,9 +170959,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
** for pLevel.
**
** If there are inner loops within pLevel that have the WHERE_BLOOMFILTER
-** flag set, initialize a Bloomfilter for them as well. Except don't do
-** this recursive initialization if the SQLITE_BloomPulldown optimization has
-** been turned off.
+** flag set, initialize a Bloomfilter for them as well.
**
** When the Bloom filter is initialized, the WHERE_BLOOMFILTER flag is cleared
** from the loop, but the regFilter value is set to a register that implements
@@ -167984,6 +171032,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
}else if( sz>10000000 ){
sz = 10000000;
}
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter);
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
@@ -168006,6 +171055,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
int n = pLoop->u.btree.nEq;
int r1 = sqlite3GetTempRange(pParse, n);
int jj;
+ assert( pIdx!=0 );
for(jj=0; jjpTable==pItem->pSTab );
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj);
@@ -168018,7 +171068,6 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrTop);
pLoop->wsFlags &= ~WHERE_BLOOMFILTER;
- if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break;
while( ++iLevel < pWInfo->nLevel ){
const SrcItem *pTabItem;
pLevel = &pWInfo->a[iLevel];
@@ -168168,11 +171217,14 @@ static sqlite3_index_info *allocateIndexInfo(
break;
}
if( i==n ){
+ int bSortByGroup = (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0;
nOrderBy = n;
if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){
- eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
+ eDistinct = 2 + bSortByGroup;
}else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
- eDistinct = 1;
+ eDistinct = 1 - bSortByGroup;
+ }else if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
+ eDistinct = 3;
}
}
}
@@ -169100,11 +172152,16 @@ SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){
SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){
WhereInfo *pWInfo;
if( pWC ){
+ int nb;
+ SrcItem *pItem;
+ Table *pTab;
+ Bitmask mAll;
+
pWInfo = pWC->pWInfo;
- int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
- SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
- Table *pTab = pItem->pSTab;
- Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
+ nb = 1+(pWInfo->pTabList->nSrc+3)/4;
+ pItem = pWInfo->pTabList->a + p->iTab;
+ pTab = pItem->pSTab;
+ mAll = (((Bitmask)1)<<(nb*4)) - 1;
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
sqlite3DebugPrintf(" %12s",
@@ -169583,6 +172640,67 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
return rc;
}
+/*
+** Callback for estLikePatternLength().
+**
+** If this node is a string literal that is longer pWalker->sz, then set
+** pWalker->sz to the byte length of that string literal.
+**
+** pWalker->eCode indicates how to count characters:
+**
+** eCode==0 Count as a GLOB pattern
+** eCode==1 Count as a LIKE pattern
+*/
+static int exprNodePatternLengthEst(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_STRING ){
+ int sz = 0; /* Pattern size in bytes */
+ u8 *z = (u8*)pExpr->u.zToken; /* The pattern */
+ u8 c; /* Next character of the pattern */
+ u8 c1, c2, c3; /* Wildcards */
+ if( pWalker->eCode ){
+ c1 = '%';
+ c2 = '_';
+ c3 = 0;
+ }else{
+ c1 = '*';
+ c2 = '?';
+ c3 = '[';
+ }
+ while( (c = *(z++))!=0 ){
+ if( c==c3 ){
+ if( *z ) z++;
+ while( *z && *z!=']' ) z++;
+ }else if( c!=c1 && c!=c2 ){
+ sz++;
+ }
+ }
+ if( sz>pWalker->u.sz ) pWalker->u.sz = sz;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Return the length of the longest string literal in the given
+** expression.
+**
+** eCode indicates how to count characters:
+**
+** eCode==0 Count as a GLOB pattern
+** eCode==1 Count as a LIKE pattern
+*/
+static int estLikePatternLength(Expr *p, u16 eCode){
+ Walker w;
+ w.u.sz = 0;
+ w.eCode = eCode;
+ w.xExprCallback = exprNodePatternLengthEst;
+ w.xSelectCallback = sqlite3SelectWalkFail;
+#ifdef SQLITE_DEBUG
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
+#endif
+ sqlite3WalkExpr(&w, p);
+ return w.u.sz;
+}
+
/*
** Adjust the WhereLoop.nOut value downward to account for terms of the
** WHERE clause that reference the loop but which are not used by an
@@ -169611,6 +172729,13 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
** "x" column is boolean or else -1 or 0 or 1 is a common default value
** on the "x" column and so in that case only cap the output row estimate
** at 1/2 instead of 1/4.
+**
+** Heuristic 3: If there is a LIKE or GLOB (or REGEXP or MATCH) operator
+** with a large constant pattern, then reduce the size of the search
+** space according to the length of the pattern, under the theory that
+** longer patterns are less likely to match. This heuristic was added
+** to give better output-row count estimates when preparing queries for
+** the Join-Order Benchmarks. See forum thread 2026-01-30T09:57:54z
*/
static void whereLoopOutputAdjust(
WhereClause *pWC, /* The WHERE clause */
@@ -169622,6 +172747,13 @@ static void whereLoopOutputAdjust(
int i, j;
LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
+ /* Skip all this if the FROM clause of the query is a single table and
+ ** there is no ORDER BY. In this case it doesn't matter how accurate
+ ** the WhereLoop.nOut values are. */
+ if( pWC->pWInfo->pTabList->nSrc<=1 && pWC->pWInfo->pOrderBy==0 ){
+ return;
+ }
+
assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){
assert( pTerm!=0 );
@@ -169660,14 +172792,16 @@ static void whereLoopOutputAdjust(
}else{
/* In the absence of explicit truth probabilities, use heuristics to
** guess a reasonable truth probability. */
+ Expr *pOpExpr = pTerm->pExpr;
pLoop->nOut--;
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
&& (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
){
- Expr *pRight = pTerm->pExpr->pRight;
+ Expr *pRight = pOpExpr->pRight;
+ Parse *pParse = pWC->pWInfo->pParse;
int k = 0;
- testcase( pTerm->pExpr->op==TK_IS );
- if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
+ testcase( pOpExpr->op==TK_IS );
+ if( sqlite3ExprIsInteger(pRight, &k, pParse, 1) && k>=(-1) && k<=1 ){
k = 10;
}else{
k = 20;
@@ -169676,6 +172810,23 @@ static void whereLoopOutputAdjust(
pTerm->wtFlags |= TERM_HEURTRUTH;
iReduce = k;
}
+ }else
+ if( ExprHasProperty(pOpExpr, EP_InfixFunc)
+ && pOpExpr->op==TK_FUNCTION
+ ){
+ int eOp;
+ assert( ExprUseXList(pOpExpr) );
+ assert( pOpExpr->x.pList->nExpr>=2 );
+ eOp = sqlite3ExprIsLikeOperator(pOpExpr);
+ if( ALWAYS(eOp>0) ){
+ int szPattern;
+ Expr *pRHS = pOpExpr->x.pList->a[0].pExpr;
+ eOp = eOp==SQLITE_INDEX_CONSTRAINT_LIKE;
+ szPattern = estLikePatternLength(pRHS, eOp);
+ if( szPattern>0 ){
+ pLoop->nOut -= szPattern*2;
+ }
+ }
}
}
}
@@ -169747,6 +172898,7 @@ static int whereRangeVectorLen(
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
if( aff!=idxaff ) break;
+ if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
if( pColl==0 ) break;
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
@@ -170136,6 +173288,7 @@ static int whereLoopAddBtreeIndex(
pNew->rRun += nInMul + nIn;
pNew->nOut += nInMul + nIn;
whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize);
+ if( pSrc->fg.fromExists ) pNew->nOut = 0;
rc = whereLoopInsert(pBuilder, pNew);
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
@@ -170731,7 +173884,14 @@ static int whereLoopAddBtree(
whereLoopOutputAdjust(pWC, pNew, rSize);
if( pSrc->fg.isSubquery ){
if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE;
- pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
+ /* Do not set btree.pOrderBy for a recursive CTE. In this case
+ ** the ORDER BY clause does not determine the overall order that
+ ** rows are emitted from the CTE in. */
+ if( (pSrc->u4.pSubq->pSelect->selFlags & SF_Recursive)==0 ){
+ pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
+ }
+ }else if( pSrc->fg.fromExists ){
+ pNew->nOut = 0;
}
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
@@ -170834,6 +173994,7 @@ static int whereLoopAddBtree(
** positioned to the correct row during the right-join no-match
** loop. */
}else{
+ if( pSrc->fg.fromExists ) pNew->nOut = 0;
rc = whereLoopInsert(pBuilder, pNew);
}
pNew->nOut = rSize;
@@ -171496,7 +174657,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
sqlite3 *db = pWInfo->pParse->db;
int rc = SQLITE_OK;
int bFirstPastRJ = 0;
- int hasRightJoin = 0;
+ int hasRightCrossJoin = 0;
WhereLoop *pNew;
@@ -171523,22 +174684,41 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
** prevents the right operand of a RIGHT JOIN from being swapped with
** other elements even further to the right.
**
- ** The JT_LTORJ case and the hasRightJoin flag work together to
- ** prevent FROM-clause terms from moving from the right side of
- ** a LEFT JOIN over to the left side of that join if the LEFT JOIN
- ** is itself on the left side of a RIGHT JOIN.
+ ** The hasRightCrossJoin flag prevent FROM-clause terms from moving
+ ** from the right side of a LEFT JOIN or CROSS JOIN over to the
+ ** left side of that same join. This is a required restriction in
+ ** the case of LEFT JOIN - an incorrect answer may results if it is
+ ** not enforced. This restriction is not required for CROSS JOIN.
+ ** It is provided merely as a means of controlling join order, under
+ ** the theory that no real-world queries that care about performance
+ ** actually use the CROSS JOIN syntax.
*/
- if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1;
+ if( pItem->fg.jointype & (JT_LTORJ|JT_CROSS) ){
+ testcase( pItem->fg.jointype & JT_LTORJ );
+ testcase( pItem->fg.jointype & JT_CROSS );
+ hasRightCrossJoin = 1;
+ }
mPrereq |= mPrior;
bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
- }else if( !hasRightJoin ){
+ }else if( pItem->fg.fromExists ){
+ /* joins that result from the EXISTS-to-JOIN optimization should not
+ ** be moved to the left of any of their dependencies */
+ WhereClause *pWC = &pWInfo->sWC;
+ WhereTerm *pTerm;
+ int i;
+ for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){
+ if( (pNew->maskSelf & pTerm->prereqAll)!=0 ){
+ mPrereq |= (pTerm->prereqAll & (pNew->maskSelf-1));
+ }
+ }
+ }else if( !hasRightCrossJoin ){
mPrereq = 0;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pSTab) ){
SrcItem *p;
for(p=&pItem[1]; pfg.jointype & (JT_OUTER|JT_CROSS)) ){
+ if( (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){
mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
}
}
@@ -171607,13 +174787,13 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
** direction because there is no way to run a co-routine backwards.
*/
static SQLITE_NOINLINE int wherePathMatchSubqueryOB(
- WhereInfo *pWInfo, /* The WHERE clause */
WhereLoop *pLoop, /* The nested loop term that is a subquery */
int iLoop, /* Which level of the nested loop. 0==outermost */
int iCur, /* Cursor used by the this loop */
ExprList *pOrderBy, /* The ORDER BY clause on the whole query */
Bitmask *pRevMask, /* When loops need to go in reverse order */
- Bitmask *pOBSat /* Which terms of pOrderBy are satisfied so far */
+ Bitmask *pOBSat, /* Which terms of pOrderBy are satisfied so far */
+ u16 wctrlFlags /* WHERE_GROUPBY or _DISTINCTBY or _ORDERBY_LIMIT */
){
int iOB; /* Index into pOrderBy->a[] */
int jSub; /* Index into pSubOB->a[] */
@@ -171631,7 +174811,7 @@ static SQLITE_NOINLINE int wherePathMatchSubqueryOB(
if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) break;
if( pOBExpr->iTable!=iCur ) break;
if( pOBExpr->iColumn!=pSubOB->a[jSub].u.x.iOrderByCol-1 ) break;
- if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
+ if( (wctrlFlags & WHERE_GROUPBY)==0 ){
u8 sfOB = pOrderBy->a[iOB].fg.sortFlags; /* sortFlags for iOB */
u8 sfSub = pSubOB->a[jSub].fg.sortFlags; /* sortFlags for jSub */
if( (sfSub & KEYINFO_ORDER_BIGNULL) != (sfOB & KEYINFO_ORDER_BIGNULL) ){
@@ -171754,9 +174934,7 @@ static i8 wherePathSatisfiesOrderBy(
pLoop = pLast;
}
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
- if( pLoop->u.vtab.isOrdered
- && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
- ){
+ if( pLoop->u.vtab.isOrdered && pWInfo->pOrderBy==pOrderBy ){
obSat = obDone;
}else{
/* No further ORDER BY terms may be matched. So this call should
@@ -171793,12 +174971,20 @@ static i8 wherePathSatisfiesOrderBy(
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
Parse *pParse = pWInfo->pParse;
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[i].pExpr);
- CollSeq *pColl2 = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
+ const Expr *pCExpr = pTerm->pExpr;
+ CollSeq *pColl2 = sqlite3ExprCompareCollSeq(pParse, pCExpr);
+ char affRight;
assert( pColl1 );
if( pColl2==0 || sqlite3StrICmp(pColl1->zName, pColl2->zName) ){
continue;
}
- testcase( pTerm->pExpr->op==TK_IS );
+ affRight = sqlite3ExprAffinity(pCExpr->pRight);
+ /* Left operand must be a column, hence always has affinity */
+ assert( sqlite3ExprAffinity(pCExpr->pLeft)!=0 );
+ if( affRight!=0 && affRight!=sqlite3ExprAffinity(pCExpr->pLeft) ){
+ continue; /* An affinity conversion would be required */
+ }
+ testcase( pCExpr->op==TK_IS );
}
obSat |= MASKBIT(i);
}
@@ -171807,8 +174993,8 @@ static i8 wherePathSatisfiesOrderBy(
if( pLoop->wsFlags & WHERE_IPK ){
if( pLoop->u.btree.pOrderBy
&& OptimizationEnabled(db, SQLITE_OrderBySubq)
- && wherePathMatchSubqueryOB(pWInfo,pLoop,iLoop,iCur,
- pOrderBy,pRevMask, &obSat)
+ && wherePathMatchSubqueryOB(pLoop,iLoop,iCur,
+ pOrderBy,pRevMask, &obSat, wctrlFlags)
){
nColumn = 0;
isOrderDistinct = 0;
@@ -172132,12 +175318,21 @@ static LogEst whereSortingCost(
** 12 otherwise
**
** For the purposes of this heuristic, a star-query is defined as a query
-** with a large central table that is joined using an INNER JOIN,
-** not CROSS or OUTER JOINs, against four or more smaller tables.
-** The central table is called the "fact" table. The smaller tables
-** that get joined are "dimension tables". Also, any table that is
-** self-joined cannot be a dimension table; we assume that dimension
-** tables may only be joined against fact tables.
+** with a central "fact" table that is joined against multiple
+** "dimension" tables, subject to the following constraints:
+**
+** (aa) Only a five-way or larger join is considered for this
+** optimization. If there are fewer than four terms in the FROM
+** clause, this heuristic does not apply.
+**
+** (bb) The join between the fact table and the dimension tables must
+** be an INNER join. CROSS and OUTER JOINs do not qualify.
+**
+** (cc) A table must have 3 or more dimension tables in order to be
+** considered a fact table. (Was 4 prior to 2026-02-10.)
+**
+** (dd) A table that is a self-join cannot be a dimension table.
+** Dimension tables are joined against fact tables.
**
** SIDE EFFECT: (and really the whole point of this subroutine)
**
@@ -172190,7 +175385,7 @@ static int computeMxChoice(WhereInfo *pWInfo){
}
#endif /* SQLITE_DEBUG */
- if( nLoop>=5
+ if( nLoop>=4 /* Constraint (aa) */
&& !pWInfo->bStarDone
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery)
){
@@ -172202,7 +175397,7 @@ static int computeMxChoice(WhereInfo *pWInfo){
pWInfo->bStarDone = 1; /* Only do this computation once */
- /* Look for fact tables with four or more dimensions where the
+ /* Look for fact tables with three or more dimensions where the
** dimension tables are not separately from the fact tables by an outer
** or cross join. Adjust cost weights if found.
*/
@@ -172219,18 +175414,17 @@ static int computeMxChoice(WhereInfo *pWInfo){
if( (pFactTab->fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){
/* If the candidate fact-table is the right table of an outer join
** restrict the search for dimension-tables to be tables to the right
- ** of the fact-table. */
- if( iFromIdx+4 > nLoop ) break; /* Impossible to reach nDep>=4 */
+ ** of the fact-table. Constraint (bb) */
+ if( iFromIdx+3 > nLoop ){
+ break; /* ^-- Impossible to reach nDep>=2 - Constraint (cc) */
+ }
while( pStart && pStart->iTab<=iFromIdx ){
pStart = pStart->pNextLoop;
}
}
for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){
if( (aFromTabs[pWLoop->iTab].fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){
- /* Fact-tables and dimension-tables cannot be separated by an
- ** outer join (at least for the definition of fact- and dimension-
- ** used by this heuristic). */
- break;
+ break; /* Constraint (bb) */
}
if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */
&& (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */
@@ -172244,7 +175438,9 @@ static int computeMxChoice(WhereInfo *pWInfo){
}
}
}
- if( nDep<=3 ) continue;
+ if( nDep<=2 ){
+ continue; /* Constraint (cc) */
+ }
/* If we reach this point, it means that pFactTab is a fact table
** with four or more dimensions connected by inner joins. Proceed
@@ -172257,6 +175453,23 @@ static int computeMxChoice(WhereInfo *pWInfo){
pWLoop->rStarDelta = 0;
}
}
+#endif
+#ifdef WHERETRACE_ENABLED /* 0x80000 */
+ if( sqlite3WhereTrace & 0x80000 ){
+ Bitmask mShow = mSeen;
+ sqlite3DebugPrintf("Fact table %s(%d), dimensions:",
+ pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName,
+ iFromIdx);
+ for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){
+ if( mShow & pWLoop->maskSelf ){
+ SrcItem *pDim = aFromTabs + pWLoop->iTab;
+ mShow &= ~pWLoop->maskSelf;
+ sqlite3DebugPrintf(" %s(%d)",
+ pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab);
+ }
+ }
+ sqlite3DebugPrintf("\n");
+ }
#endif
pWInfo->bStarUsed = 1;
@@ -172280,10 +175493,8 @@ static int computeMxChoice(WhereInfo *pWInfo){
if( sqlite3WhereTrace & 0x80000 ){
SrcItem *pDim = aFromTabs + pWLoop->iTab;
sqlite3DebugPrintf(
- "Increase SCAN cost of dimension %s(%d) of fact %s(%d) to %d\n",
- pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab,
- pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName,
- iFromIdx, mxRun
+ "Increase SCAN cost of %s to %d\n",
+ pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, mxRun
);
}
pWLoop->rStarDelta = mxRun - pWLoop->rRun;
@@ -173097,6 +176308,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){
pTerm->wtFlags |= TERM_CODED;
+ pTerm->prereqAll = 0;
}
}
if( i!=pWInfo->nLevel-1 ){
@@ -173144,19 +176356,17 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
pTab->tabFlags |= TF_MaybeReanalyze;
if( i>=1
&& (pLoop->wsFlags & reqFlags)==reqFlags
- /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */
- && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0)
+ && sqlite3WhereLoopBloomable(pLoop)
+ && nSearch > pTab->nRowLogEst
){
- if( nSearch > pTab->nRowLogEst ){
- testcase( pItem->fg.jointype & JT_LEFT );
- pLoop->wsFlags |= WHERE_BLOOMFILTER;
- pLoop->wsFlags &= ~WHERE_IDX_ONLY;
- WHERETRACE(0xffffffff, (
- "-> use Bloom-filter on loop %c because there are ~%.1e "
- "lookups into %s which has only ~%.1e rows\n",
- pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
- (double)sqlite3LogEstToInt(pTab->nRowLogEst)));
- }
+ testcase( pItem->fg.jointype & JT_LEFT );
+ pLoop->wsFlags |= WHERE_BLOOMFILTER;
+ pLoop->wsFlags &= ~WHERE_IDX_ONLY;
+ WHERETRACE(0xffffffff, (
+ "-> use Bloom-filter on loop %c because there are ~%.1e "
+ "lookups into %s which has only ~%.1e rows\n",
+ pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
+ (double)sqlite3LogEstToInt(pTab->nRowLogEst)));
}
nSearch += pLoop->nOut;
}
@@ -173812,8 +177022,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
sqlite3VdbeChangeP5(v, bFordelete);
}
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0,
- (const u8*)&pTabItem->colUsed, P4_INT64);
+ sqlite3VdbeAddOp3(v, OP_ColumnsUsed, pTabItem->iCursor,
+ LOWER32(pTabItem->colUsed), UPPER32(pTabItem->colUsed));
#endif
if( ii>=2
&& (pTabItem[0].fg.jointype & (JT_LTORJ|JT_LEFT))==0
@@ -173890,10 +177100,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( (pTabItem->colUsed & MASKBIT(jj))==0 ) continue;
colUsed |= ((u64)1)<<(ii<63 ? ii : 63);
}
- sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0,
- (u8*)&colUsed, P4_INT64);
+ sqlite3VdbeAddOp3(v, OP_ColumnsUsed, iIndexCur,
+ LOWER32(colUsed),UPPER32(colUsed));
}
#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */
+#ifdef SQLITE_ENABLE_CURSOR_HINTS
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp3(v, OP_CursorHint, iIndexCur, 0, pTabItem->iCursor);
+ }
+#endif
}
}
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
@@ -173901,15 +177116,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
&& (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0
){
WhereRightJoin *pRJ = pLevel->pRJ;
+ int bBloomable = 0;
pRJ->iMatch = pParse->nTab++;
- pRJ->regBloom = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
pRJ->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
assert( pTab==pTabItem->pSTab );
if( HasRowid(pTab) ){
KeyInfo *pInfo;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1);
+ bBloomable = 1;
pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0);
if( pInfo ){
pInfo->aColl[0] = 0;
@@ -173920,6 +177135,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+ bBloomable = sqlite3IndexBloomable(pPk,pPk->nKeyCol);
+ }
+ if( bBloomable ){
+ pRJ->regBloom = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
+ }else{
+ pRJ->regBloom = 0;
}
pLoop->wsFlags &= ~WHERE_IDX_ONLY;
/* The nature of RIGHT JOIN processing is such that it messes up
@@ -174072,6 +177294,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
){
int r1 = pParse->nMem+1;
int j, op;
+ int addrIfNull = 0; /* Init to avoid false-positive compiler warning */
+ if( pLevel->iLeftJoin ){
+ addrIfNull = sqlite3VdbeAddOp2(v, OP_IfNullRow, pLevel->iIdxCur, r1);
+ }
for(j=0; jiIdxCur, j, r1+j);
}
@@ -174081,25 +177307,17 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
VdbeCoverageIf(v, op==OP_SeekLT);
VdbeCoverageIf(v, op==OP_SeekGT);
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
+ if( pLevel->iLeftJoin ){
+ sqlite3VdbeJumpHere(v, addrIfNull);
+ }
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
}
- if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){
- /* If the EXISTS-to-JOIN optimization was applied, then the EXISTS
- ** loop(s) will be the inner-most loops of the join. There might be
- ** multiple EXISTS loops, but they will all be nested, and the join
- ** order will not have been changed by the query planner. If the
- ** inner-most EXISTS loop sees a single successful row, it should
- ** break out of *all* EXISTS loops. But only the inner-most of the
- ** nested EXISTS loops should do this breakout. */
- int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
- while( nOutera[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
- nOuter++;
- }
- testcase( nOuter>0 );
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
- VdbeComment((v, "EXISTS break"));
+ if( pTabList->a[pLevel->iFrom].fg.fromExists ){
+ /* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
+ ** successful row, it should break out of itself. */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
+ VdbeComment((v, "EXISTS break %d", i));
}
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
@@ -174109,17 +177327,17 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
VdbeCoverageIf(v, pLevel->op==OP_Next);
VdbeCoverageIf(v, pLevel->op==OP_Prev);
VdbeCoverageIf(v, pLevel->op==OP_VNext);
- if( pLevel->regBignull ){
- sqlite3VdbeResolveLabel(v, pLevel->addrBignull);
- sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1);
- VdbeCoverage(v);
- }
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ){
sqlite3VdbeJumpHere(v, addrSeek);
addrSeek = 0;
}
#endif
+ if( pLevel->regBignull ){
+ sqlite3VdbeResolveLabel(v, pLevel->addrBignull);
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1);
+ VdbeCoverage(v);
+ }
}
if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
@@ -174135,16 +177353,14 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
(pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
&& (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
if( pLevel->iLeftJoin ){
- /* For LEFT JOIN queries, cursor pIn->iCur may not have been
- ** opened yet. This occurs for WHERE clauses such as
- ** "a = ? AND b IN (...)", where the index is on (a, b). If
- ** the RHS of the (a=?) is NULL, then the "b IN (...)" may
- ** never have been coded, but the body of the loop run to
- ** return the null-row. So, if the cursor is not open yet,
- ** jump over the OP_Next or OP_Prev instruction about to
- ** be coded. */
- sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
- sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut);
+ /* For LEFT JOIN queries, cursor pIn->iCur might have been
+ ** disabled by OP_NullRow. This occurs for WHERE clauses such
+ ** as "a = ? AND b IN (...)", where the index is on (a, b).
+ ** When the OP_IfNullRow jump is taken, the pIn->iBase register
+ ** is NULLed out as a side effect. But as that register is not
+ ** used when the jump is taken, the side-effect is harmless. */
+ sqlite3VdbeAddOp3(v, OP_IfNullRow, pIn->iCur,
+ sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut, pIn->iBase);
VdbeCoverage(v);
}
if( bEarlyOut ){
@@ -174213,6 +177429,15 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
}
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
+ if( ws & WHERE_IN_ABLE ){
+ int m;
+ for(m=0; mu.in.nIn; m++){
+ struct InLoop *pIn = &pLevel->u.in.aInLoop[m];
+ if( pIn->eEndLoopOp!=OP_Noop ){
+ sqlite3VdbeAddOp1(v, OP_NullRow, pIn->iCur);
+ }
+ }
+ }
if( pLevel->op==OP_Return ){
sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
}else{
@@ -174621,7 +177846,7 @@ static void nth_valueStepFunc(
break;
case SQLITE_FLOAT: {
double fVal = sqlite3_value_double(apArg[1]);
- if( ((i64)fVal)!=fVal ) goto error_out;
+ if( sqlite3RealToI64(fVal)!=fVal ) goto error_out;
iVal = (i64)fVal;
break;
}
@@ -174746,6 +177971,7 @@ static void percent_rankInvFunc(
UNUSED_PARAMETER(nArg); assert( nArg==0 );
UNUSED_PARAMETER(apArg);
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ assert( p!=0 );
p->nStep++;
}
static void percent_rankValueFunc(sqlite3_context *pCtx){
@@ -174791,6 +178017,7 @@ static void cume_distInvFunc(
UNUSED_PARAMETER(nArg); assert( nArg==0 );
UNUSED_PARAMETER(apArg);
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ assert( p!=0 );
p->nStep++;
}
static void cume_distValueFunc(sqlite3_context *pCtx){
@@ -174847,6 +178074,7 @@ static void ntileInvFunc(
assert( nArg==1 ); UNUSED_PARAMETER(nArg);
UNUSED_PARAMETER(apArg);
p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ assert( p!=0 );
p->iRow++;
}
static void ntileValueFunc(sqlite3_context *pCtx){
@@ -175116,7 +178344,7 @@ SQLITE_PRIVATE void sqlite3WindowUpdate(
pWin->eEnd = aUp[i].eEnd;
pWin->eExclude = 0;
if( pWin->eStart==TK_FOLLOWING ){
- pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1");
+ pWin->pStart = sqlite3ExprInt32(db, 1);
}
break;
}
@@ -175204,7 +178432,9 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
}
if( p->pSub ){
- int f = pExpr->flags & EP_Collate;
+ int f = pExpr->flags & (EP_Collate|EP_OuterON|EP_InnerON);
+ int iJoin = pExpr->w.iJoin;
+
assert( ExprHasProperty(pExpr, EP_Static)==0 );
ExprSetProperty(pExpr, EP_Static);
sqlite3ExprDelete(pParse->db, pExpr);
@@ -175216,6 +178446,7 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
pExpr->iTable = p->pWin->iEphCsr;
pExpr->y.pTab = p->pTab;
pExpr->flags = f;
+ if( (f & (EP_OuterON|EP_InnerON)) ) pExpr->w.iJoin = iJoin;
}
if( pParse->db->mallocFailed ) return WRC_Abort;
break;
@@ -175308,7 +178539,7 @@ static ExprList *exprListAppendList(
int iDummy;
Expr *pSub;
pSub = sqlite3ExprSkipCollateAndLikely(pDup);
- if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){
+ if( sqlite3ExprIsInteger(pSub, &iDummy, 0, 0) ){
pSub->op = TK_NULL;
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
pSub->u.zToken = 0;
@@ -175461,9 +178692,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
** keep everything legal in this case.
*/
if( pSublist==0 ){
- pSublist = sqlite3ExprListAppend(pParse, 0,
- sqlite3Expr(db, TK_INTEGER, "0")
- );
+ pSublist = sqlite3ExprListAppend(pParse, 0, sqlite3ExprInt32(db, 0));
}
pSub = sqlite3SelectNew(
@@ -177689,8 +180918,23 @@ static void updateDeleteLimitError(
** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate
** testing.
*/
- static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){
- return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize);
+ static void *parserStackRealloc(
+ void *pOld, /* Prior allocation */
+ sqlite3_uint64 newSize, /* Requested new alloation size */
+ Parse *pParse /* Parsing context */
+ ){
+ void *p = sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize);
+ if( p==0 ) sqlite3OomFault(pParse->db);
+ return p;
+ }
+ static void parserStackFree(void *pOld, Parse *pParse){
+ (void)pParse;
+ sqlite3_free(pOld);
+ }
+
+ /* Return an integer that is the maximum allowed stack size */
+ static int parserStackSizeLimit(Parse *pParse){
+ return pParse->db->aLimit[SQLITE_LIMIT_PARSER_DEPTH];
}
@@ -177729,15 +180973,46 @@ static void updateDeleteLimitError(
}
- /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
- ** unary TK_ISNULL or TK_NOTNULL expression. */
- static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
- sqlite3 *db = pParse->db;
- if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){
- pA->op = (u8)op;
- sqlite3ExprDelete(db, pA->pRight);
- pA->pRight = 0;
+ /* Create a TK_ISNULL or TK_NOTNULL expression, perhaps optimized to
+ ** to TK_TRUEFALSE, if possible */
+ static Expr *sqlite3PExprIsNull(
+ Parse *pParse, /* Parsing context */
+ int op, /* TK_ISNULL or TK_NOTNULL */
+ Expr *pLeft /* Operand */
+ ){
+ Expr *p = pLeft;
+ assert( op==TK_ISNULL || op==TK_NOTNULL );
+ assert( pLeft!=0 );
+ while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
+ p = p->pLeft;
+ assert( p!=0 );
}
+ switch( p->op ){
+ case TK_INTEGER:
+ case TK_STRING:
+ case TK_FLOAT:
+ case TK_BLOB:
+ sqlite3ExprDeferredDelete(pParse, pLeft);
+ return sqlite3ExprInt32(pParse->db, op==TK_NOTNULL);
+ default:
+ break;
+ }
+ return sqlite3PExpr(pParse, op, pLeft, 0);
+ }
+
+ /* Create a TK_IS or TK_ISNOT operator, perhaps optimized to
+ ** TK_ISNULL or TK_NOTNULL or TK_TRUEFALSE. */
+ static Expr *sqlite3PExprIs(
+ Parse *pParse, /* Parsing context */
+ int op, /* TK_IS or TK_ISNOT */
+ Expr *pLeft, /* Left operand */
+ Expr *pRight /* Right operand */
+ ){
+ if( pRight && pRight->op==TK_NULL ){
+ sqlite3ExprDeferredDelete(pParse, pRight);
+ return sqlite3PExprIsNull(pParse, op==TK_IS ? TK_ISNULL : TK_NOTNULL, pLeft);
+ }
+ return sqlite3PExpr(pParse, op, pLeft, pRight);
}
/* Add a single new term to an ExprList that is used to store a
@@ -178020,63 +181295,72 @@ static void updateDeleteLimitError(
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned short int
-#define YYNOCODE 323
+#define YYNOCODE 322
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 102
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
- u32 yy9;
- struct TrigEvent yy28;
- With* yy125;
- IdList* yy204;
- struct FrameBound yy205;
- TriggerStep* yy319;
- const char* yy342;
- Cte* yy361;
- ExprList* yy402;
- Upsert* yy403;
- OnOrUsing yy421;
- u8 yy444;
- struct {int value; int mask;} yy481;
- Window* yy483;
- int yy502;
- SrcList* yy563;
- Expr* yy590;
- Select* yy637;
+ ExprList* yy14;
+ With* yy59;
+ Cte* yy67;
+ Upsert* yy122;
+ IdList* yy132;
+ int yy144;
+ const char* yy168;
+ SrcList* yy203;
+ Window* yy211;
+ OnOrUsing yy269;
+ struct TrigEvent yy286;
+ struct {int value; int mask;} yy383;
+ u32 yy391;
+ TriggerStep* yy427;
+ Expr* yy454;
+ u8 yy462;
+ struct FrameBound yy509;
+ Select* yy555;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
-#define YYSTACKDEPTH 100
+#define YYSTACKDEPTH 50
#endif
#define sqlite3ParserARG_SDECL
#define sqlite3ParserARG_PDECL
#define sqlite3ParserARG_PARAM
#define sqlite3ParserARG_FETCH
#define sqlite3ParserARG_STORE
+#undef YYREALLOC
#define YYREALLOC parserStackRealloc
-#define YYFREE sqlite3_free
+#undef YYFREE
+#define YYFREE parserStackFree
+#undef YYDYNSTACK
#define YYDYNSTACK 1
+#undef YYSIZELIMIT
+#define YYSIZELIMIT parserStackSizeLimit
+#define sqlite3ParserCTX(P) ((P)->pParse)
#define sqlite3ParserCTX_SDECL Parse *pParse;
#define sqlite3ParserCTX_PDECL ,Parse *pParse
#define sqlite3ParserCTX_PARAM ,pParse
#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
#define sqlite3ParserCTX_STORE yypParser->pParse=pParse;
+#undef YYERRORSYMBOL
+#undef YYERRSYMDT
+#undef YYFALLBACK
#define YYFALLBACK 1
-#define YYNSTATE 587
-#define YYNRULE 409
-#define YYNRULE_WITH_ACTION 344
+#define YYNSTATE 604
+#define YYNRULE 412
+#define YYNRULE_WITH_ACTION 348
#define YYNTOKEN 187
-#define YY_MAX_SHIFT 586
-#define YY_MIN_SHIFTREDUCE 849
-#define YY_MAX_SHIFTREDUCE 1257
-#define YY_ERROR_ACTION 1258
-#define YY_ACCEPT_ACTION 1259
-#define YY_NO_ACTION 1260
-#define YY_MIN_REDUCE 1261
-#define YY_MAX_REDUCE 1669
+#define YY_MAX_SHIFT 603
+#define YY_MIN_SHIFTREDUCE 871
+#define YY_MAX_SHIFTREDUCE 1282
+#define YY_ERROR_ACTION 1283
+#define YY_ACCEPT_ACTION 1284
+#define YY_NO_ACTION 1285
+#define YY_MIN_REDUCE 1286
+#define YY_MAX_REDUCE 1697
#define YY_MIN_DSTRCTR 206
-#define YY_MAX_DSTRCTR 320
+#define YY_MAX_DSTRCTR 319
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@@ -178159,643 +181443,682 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (2207)
+#define YY_ACTTAB_COUNT (2379)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 130, 127, 234, 282, 282, 1332, 580, 1311, 464, 289,
- /* 10 */ 289, 580, 1626, 385, 580, 1332, 577, 580, 566, 417,
- /* 20 */ 1304, 1546, 577, 485, 566, 528, 464, 463, 562, 82,
- /* 30 */ 82, 987, 294, 379, 51, 51, 502, 61, 61, 988,
- /* 40 */ 82, 82, 1581, 137, 138, 91, 7, 1232, 1232, 1067,
- /* 50 */ 1070, 1057, 1057, 135, 135, 136, 136, 136, 136, 417,
- /* 60 */ 288, 288, 182, 288, 288, 485, 540, 288, 288, 130,
- /* 70 */ 127, 234, 436, 577, 529, 566, 577, 561, 566, 1294,
- /* 80 */ 577, 425, 566, 137, 138, 91, 563, 1232, 1232, 1067,
- /* 90 */ 1070, 1057, 1057, 135, 135, 136, 136, 136, 136, 296,
- /* 100 */ 464, 402, 1253, 134, 134, 134, 134, 133, 133, 132,
- /* 110 */ 132, 132, 131, 128, 455, 455, 1054, 1054, 1068, 1071,
- /* 120 */ 1259, 1, 1, 586, 2, 1263, 585, 1178, 1263, 1178,
- /* 130 */ 321, 417, 155, 321, 1588, 155, 383, 112, 485, 1345,
- /* 140 */ 460, 299, 1345, 134, 134, 134, 134, 133, 133, 132,
- /* 150 */ 132, 132, 131, 128, 455, 137, 138, 91, 502, 1232,
- /* 160 */ 1232, 1067, 1070, 1057, 1057, 135, 135, 136, 136, 136,
- /* 170 */ 136, 1208, 866, 1285, 288, 288, 283, 288, 288, 527,
- /* 180 */ 527, 1254, 139, 582, 7, 582, 1349, 577, 1173, 566,
- /* 190 */ 577, 1058, 566, 136, 136, 136, 136, 129, 577, 551,
- /* 200 */ 566, 1173, 245, 1545, 1173, 245, 133, 133, 132, 132,
- /* 210 */ 132, 131, 128, 455, 302, 134, 134, 134, 134, 133,
- /* 220 */ 133, 132, 132, 132, 131, 128, 455, 1579, 1208, 1209,
- /* 230 */ 1208, 7, 474, 554, 459, 417, 554, 459, 130, 127,
- /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132,
- /* 250 */ 131, 128, 455, 136, 136, 136, 136, 542, 487, 137,
- /* 260 */ 138, 91, 1023, 1232, 1232, 1067, 1070, 1057, 1057, 135,
- /* 270 */ 135, 136, 136, 136, 136, 1089, 580, 1208, 132, 132,
- /* 280 */ 132, 131, 128, 455, 93, 214, 134, 134, 134, 134,
- /* 290 */ 133, 133, 132, 132, 132, 131, 128, 455, 405, 19,
- /* 300 */ 19, 134, 134, 134, 134, 133, 133, 132, 132, 132,
- /* 310 */ 131, 128, 455, 1502, 430, 267, 348, 471, 334, 134,
- /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128,
- /* 330 */ 455, 1285, 580, 6, 1208, 1209, 1208, 257, 580, 417,
- /* 340 */ 515, 512, 511, 1283, 94, 1023, 468, 1208, 555, 555,
- /* 350 */ 510, 1228, 1575, 44, 38, 51, 51, 415, 580, 417,
- /* 360 */ 45, 51, 51, 137, 138, 91, 534, 1232, 1232, 1067,
- /* 370 */ 1070, 1057, 1057, 135, 135, 136, 136, 136, 136, 402,
- /* 380 */ 1152, 82, 82, 137, 138, 91, 39, 1232, 1232, 1067,
- /* 390 */ 1070, 1057, 1057, 135, 135, 136, 136, 136, 136, 348,
- /* 400 */ 44, 288, 288, 379, 1208, 1209, 1208, 209, 1208, 1228,
- /* 410 */ 320, 571, 475, 580, 577, 580, 566, 580, 316, 264,
- /* 420 */ 231, 46, 160, 134, 134, 134, 134, 133, 133, 132,
- /* 430 */ 132, 132, 131, 128, 455, 303, 82, 82, 82, 82,
- /* 440 */ 82, 82, 446, 134, 134, 134, 134, 133, 133, 132,
- /* 450 */ 132, 132, 131, 128, 455, 1586, 548, 320, 571, 1254,
- /* 460 */ 878, 1586, 384, 386, 417, 1208, 1209, 1208, 364, 182,
- /* 470 */ 288, 288, 1580, 561, 1343, 561, 7, 561, 1281, 476,
- /* 480 */ 350, 530, 535, 577, 560, 566, 443, 1515, 137, 138,
- /* 490 */ 91, 219, 1232, 1232, 1067, 1070, 1057, 1057, 135, 135,
- /* 500 */ 136, 136, 136, 136, 469, 1515, 1517, 536, 417, 288,
- /* 510 */ 288, 427, 516, 288, 288, 415, 288, 288, 878, 130,
- /* 520 */ 127, 234, 577, 1111, 566, 1208, 577, 1111, 566, 577,
- /* 530 */ 564, 566, 137, 138, 91, 1297, 1232, 1232, 1067, 1070,
- /* 540 */ 1057, 1057, 135, 135, 136, 136, 136, 136, 134, 134,
- /* 550 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 455,
- /* 560 */ 497, 507, 1296, 1208, 257, 288, 288, 515, 512, 511,
- /* 570 */ 1208, 1632, 1173, 123, 572, 275, 4, 510, 577, 1515,
- /* 580 */ 566, 331, 1208, 1209, 1208, 1173, 552, 552, 1173, 261,
- /* 590 */ 575, 7, 134, 134, 134, 134, 133, 133, 132, 132,
- /* 600 */ 132, 131, 128, 455, 108, 537, 130, 127, 234, 1208,
- /* 610 */ 452, 451, 417, 1455, 456, 987, 890, 96, 1602, 1237,
- /* 620 */ 1208, 1209, 1208, 988, 1239, 1454, 569, 1208, 1209, 1208,
- /* 630 */ 229, 526, 1238, 538, 1337, 1337, 137, 138, 91, 1453,
- /* 640 */ 1232, 1232, 1067, 1070, 1057, 1057, 135, 135, 136, 136,
- /* 650 */ 136, 136, 377, 1599, 975, 1044, 417, 1240, 422, 1240,
- /* 660 */ 883, 121, 121, 952, 377, 1599, 1208, 1209, 1208, 122,
- /* 670 */ 1208, 456, 581, 456, 367, 421, 1032, 886, 377, 1599,
- /* 680 */ 137, 138, 91, 466, 1232, 1232, 1067, 1070, 1057, 1057,
- /* 690 */ 135, 135, 136, 136, 136, 136, 134, 134, 134, 134,
- /* 700 */ 133, 133, 132, 132, 132, 131, 128, 455, 1032, 1032,
- /* 710 */ 1034, 1035, 35, 574, 574, 574, 197, 427, 1044, 198,
- /* 720 */ 1208, 123, 572, 1208, 4, 320, 571, 1208, 1209, 1208,
- /* 730 */ 40, 392, 580, 388, 886, 1033, 427, 1192, 575, 1032,
- /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
- /* 750 */ 128, 455, 533, 1572, 1208, 19, 19, 1208, 579, 496,
- /* 760 */ 417, 157, 456, 493, 1191, 1335, 1335, 5, 1208, 953,
- /* 770 */ 435, 1032, 1032, 1034, 569, 22, 22, 1208, 1209, 1208,
- /* 780 */ 1208, 1209, 1208, 481, 137, 138, 91, 212, 1232, 1232,
- /* 790 */ 1067, 1070, 1057, 1057, 135, 135, 136, 136, 136, 136,
- /* 800 */ 1192, 48, 111, 1044, 417, 1208, 213, 974, 1045, 121,
- /* 810 */ 121, 1208, 1209, 1208, 1208, 1209, 1208, 122, 221, 456,
- /* 820 */ 581, 456, 44, 491, 1032, 1208, 1209, 1208, 137, 138,
- /* 830 */ 91, 382, 1232, 1232, 1067, 1070, 1057, 1057, 135, 135,
- /* 840 */ 136, 136, 136, 136, 134, 134, 134, 134, 133, 133,
- /* 850 */ 132, 132, 132, 131, 128, 455, 1032, 1032, 1034, 1035,
- /* 860 */ 35, 465, 1208, 1209, 1208, 1573, 1044, 381, 214, 1153,
- /* 870 */ 1661, 539, 1661, 441, 906, 320, 571, 1572, 368, 320,
- /* 880 */ 571, 416, 329, 1033, 523, 1192, 3, 1032, 134, 134,
- /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 455,
- /* 900 */ 1663, 403, 1173, 307, 897, 307, 519, 580, 417, 214,
- /* 910 */ 502, 948, 1028, 544, 907, 1173, 947, 396, 1173, 1032,
- /* 920 */ 1032, 1034, 410, 298, 1208, 50, 1153, 1662, 417, 1662,
- /* 930 */ 145, 145, 137, 138, 91, 293, 1232, 1232, 1067, 1070,
- /* 940 */ 1057, 1057, 135, 135, 136, 136, 136, 136, 1192, 1151,
- /* 950 */ 518, 1572, 137, 138, 91, 1509, 1232, 1232, 1067, 1070,
- /* 960 */ 1057, 1057, 135, 135, 136, 136, 136, 136, 438, 323,
- /* 970 */ 439, 543, 111, 1510, 274, 291, 376, 521, 371, 520,
- /* 980 */ 262, 1208, 1209, 1208, 1578, 485, 367, 580, 7, 1573,
- /* 990 */ 1572, 381, 134, 134, 134, 134, 133, 133, 132, 132,
- /* 1000 */ 132, 131, 128, 455, 1572, 580, 1151, 580, 232, 580,
- /* 1010 */ 19, 19, 134, 134, 134, 134, 133, 133, 132, 132,
- /* 1020 */ 132, 131, 128, 455, 1173, 437, 580, 1211, 19, 19,
- /* 1030 */ 19, 19, 19, 19, 1631, 580, 915, 1173, 47, 120,
- /* 1040 */ 1173, 117, 417, 306, 502, 442, 1129, 206, 340, 19,
- /* 1050 */ 19, 1439, 49, 453, 453, 453, 1372, 315, 81, 81,
- /* 1060 */ 580, 304, 417, 1574, 207, 381, 137, 138, 91, 115,
- /* 1070 */ 1232, 1232, 1067, 1070, 1057, 1057, 135, 135, 136, 136,
- /* 1080 */ 136, 136, 580, 82, 82, 1211, 137, 138, 91, 1344,
- /* 1090 */ 1232, 1232, 1067, 1070, 1057, 1057, 135, 135, 136, 136,
- /* 1100 */ 136, 136, 1573, 390, 381, 82, 82, 467, 1130, 1556,
- /* 1110 */ 337, 467, 339, 131, 128, 455, 1573, 161, 381, 16,
- /* 1120 */ 317, 391, 432, 1131, 452, 451, 134, 134, 134, 134,
- /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 455, 1132, 580,
- /* 1140 */ 1109, 10, 449, 267, 580, 1558, 134, 134, 134, 134,
- /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 455, 536, 580,
- /* 1160 */ 926, 580, 19, 19, 580, 1577, 580, 147, 147, 7,
- /* 1170 */ 927, 1240, 502, 1240, 580, 491, 417, 556, 285, 1228,
- /* 1180 */ 973, 215, 82, 82, 66, 66, 1439, 67, 67, 21,
- /* 1190 */ 21, 1114, 1114, 499, 338, 297, 417, 53, 53, 297,
- /* 1200 */ 137, 138, 91, 119, 1232, 1232, 1067, 1070, 1057, 1057,
- /* 1210 */ 135, 135, 136, 136, 136, 136, 417, 1340, 1315, 450,
- /* 1220 */ 137, 138, 91, 227, 1232, 1232, 1067, 1070, 1057, 1057,
- /* 1230 */ 135, 135, 136, 136, 136, 136, 578, 1228, 940, 940,
- /* 1240 */ 137, 126, 91, 141, 1232, 1232, 1067, 1070, 1057, 1057,
- /* 1250 */ 135, 135, 136, 136, 136, 136, 537, 433, 476, 350,
- /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
- /* 1270 */ 128, 455, 580, 461, 233, 347, 1439, 407, 502, 1554,
- /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
- /* 1290 */ 128, 455, 580, 324, 580, 82, 82, 491, 580, 973,
- /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
- /* 1310 */ 128, 455, 288, 288, 550, 68, 68, 54, 54, 557,
- /* 1320 */ 417, 69, 69, 355, 6, 577, 948, 566, 414, 413,
- /* 1330 */ 1439, 947, 454, 549, 260, 259, 258, 580, 158, 580,
- /* 1340 */ 417, 222, 1184, 483, 973, 138, 91, 434, 1232, 1232,
- /* 1350 */ 1067, 1070, 1057, 1057, 135, 135, 136, 136, 136, 136,
- /* 1360 */ 70, 70, 71, 71, 580, 1130, 91, 580, 1232, 1232,
- /* 1370 */ 1067, 1070, 1057, 1057, 135, 135, 136, 136, 136, 136,
- /* 1380 */ 1131, 166, 854, 855, 856, 1286, 423, 72, 72, 108,
- /* 1390 */ 73, 73, 1314, 362, 1184, 1132, 580, 305, 580, 123,
- /* 1400 */ 572, 498, 4, 492, 134, 134, 134, 134, 133, 133,
- /* 1410 */ 132, 132, 132, 131, 128, 455, 575, 568, 538, 55,
- /* 1420 */ 55, 56, 56, 580, 134, 134, 134, 134, 133, 133,
- /* 1430 */ 132, 132, 132, 131, 128, 455, 580, 1108, 233, 1108,
- /* 1440 */ 456, 1606, 586, 2, 1263, 580, 57, 57, 580, 321,
- /* 1450 */ 580, 155, 569, 1439, 489, 357, 580, 360, 1345, 59,
- /* 1460 */ 59, 580, 44, 973, 573, 423, 580, 238, 60, 60,
- /* 1470 */ 261, 74, 74, 75, 75, 287, 231, 580, 1370, 76,
- /* 1480 */ 76, 1044, 424, 184, 20, 20, 580, 121, 121, 77,
- /* 1490 */ 77, 97, 218, 288, 288, 122, 125, 456, 581, 456,
- /* 1500 */ 143, 143, 1032, 580, 524, 580, 577, 580, 566, 144,
- /* 1510 */ 144, 478, 227, 1248, 482, 123, 572, 580, 4, 320,
- /* 1520 */ 571, 245, 415, 580, 447, 415, 78, 78, 62, 62,
- /* 1530 */ 79, 79, 575, 319, 1032, 1032, 1034, 1035, 35, 422,
- /* 1540 */ 63, 63, 580, 290, 415, 9, 80, 80, 1148, 580,
- /* 1550 */ 404, 580, 490, 459, 580, 1227, 456, 580, 325, 346,
- /* 1560 */ 580, 111, 580, 1192, 242, 64, 64, 477, 569, 580,
- /* 1570 */ 23, 580, 170, 170, 171, 171, 580, 87, 87, 328,
- /* 1580 */ 65, 65, 546, 83, 83, 146, 146, 545, 123, 572,
- /* 1590 */ 345, 4, 84, 84, 168, 168, 580, 1044, 580, 148,
- /* 1600 */ 148, 580, 1384, 121, 121, 575, 1025, 580, 266, 580,
- /* 1610 */ 428, 122, 580, 456, 581, 456, 580, 557, 1032, 142,
- /* 1620 */ 142, 169, 169, 580, 162, 162, 532, 893, 375, 456,
- /* 1630 */ 152, 152, 151, 151, 1383, 149, 149, 109, 374, 150,
- /* 1640 */ 150, 569, 580, 484, 580, 266, 86, 86, 580, 1096,
- /* 1650 */ 1032, 1032, 1034, 1035, 35, 546, 486, 580, 266, 470,
- /* 1660 */ 547, 123, 572, 1620, 4, 88, 88, 85, 85, 479,
- /* 1670 */ 1044, 52, 52, 222, 905, 904, 121, 121, 575, 1192,
- /* 1680 */ 58, 58, 244, 1036, 122, 893, 456, 581, 456, 912,
- /* 1690 */ 913, 1032, 300, 351, 508, 111, 263, 365, 165, 111,
- /* 1700 */ 111, 1092, 456, 263, 978, 1157, 266, 1096, 990, 991,
- /* 1710 */ 946, 943, 125, 125, 569, 1107, 876, 1107, 159, 945,
- /* 1720 */ 1313, 125, 1561, 1032, 1032, 1034, 1035, 35, 546, 341,
- /* 1730 */ 1534, 205, 1533, 545, 503, 1593, 494, 352, 1380, 356,
- /* 1740 */ 359, 1036, 361, 1044, 363, 1328, 1312, 370, 567, 121,
- /* 1750 */ 121, 380, 1192, 1393, 1438, 1366, 280, 122, 1378, 456,
- /* 1760 */ 581, 456, 167, 1443, 1032, 1293, 1284, 1272, 1271, 1273,
- /* 1770 */ 1613, 1363, 312, 313, 314, 401, 12, 237, 224, 1425,
- /* 1780 */ 295, 333, 336, 1430, 343, 488, 344, 513, 1375, 1616,
- /* 1790 */ 1376, 1429, 1248, 408, 301, 228, 1032, 1032, 1034, 1035,
- /* 1800 */ 35, 1605, 1196, 458, 349, 1311, 292, 373, 1506, 1505,
- /* 1810 */ 270, 400, 400, 399, 277, 397, 1374, 1373, 863, 1553,
- /* 1820 */ 186, 123, 572, 235, 4, 1192, 395, 210, 211, 223,
- /* 1830 */ 1551, 239, 1245, 327, 426, 96, 220, 195, 575, 140,
- /* 1840 */ 557, 326, 180, 472, 1420, 332, 188, 1413, 335, 570,
- /* 1850 */ 190, 191, 192, 193, 473, 506, 247, 109, 1434, 495,
- /* 1860 */ 251, 199, 456, 406, 480, 1426, 13, 409, 102, 14,
- /* 1870 */ 501, 1511, 241, 1432, 569, 1431, 203, 92, 95, 1500,
- /* 1880 */ 175, 281, 358, 43, 504, 253, 411, 254, 522, 1331,
- /* 1890 */ 104, 1274, 1522, 354, 440, 1322, 255, 1330, 1630, 1629,
- /* 1900 */ 240, 897, 229, 1044, 444, 1321, 445, 448, 269, 121,
- /* 1910 */ 121, 1329, 531, 268, 310, 412, 1398, 122, 1301, 456,
- /* 1920 */ 581, 456, 1300, 372, 1032, 1299, 1628, 378, 311, 90,
- /* 1930 */ 572, 11, 4, 1397, 1598, 418, 1487, 389, 116, 110,
- /* 1940 */ 320, 571, 1584, 559, 318, 541, 575, 1583, 42, 1354,
- /* 1950 */ 387, 583, 216, 1353, 1202, 276, 1032, 1032, 1034, 1035,
- /* 1960 */ 35, 393, 394, 278, 462, 279, 419, 584, 1538, 1269,
- /* 1970 */ 456, 1264, 172, 420, 173, 1539, 1537, 1536, 156, 308,
- /* 1980 */ 225, 89, 569, 850, 226, 1192, 457, 174, 217, 236,
- /* 1990 */ 322, 154, 1106, 1104, 187, 330, 176, 1227, 929, 189,
- /* 2000 */ 243, 342, 246, 1120, 194, 177, 178, 429, 431, 98,
- /* 2010 */ 196, 1044, 99, 185, 100, 101, 179, 121, 121, 1123,
- /* 2020 */ 248, 249, 1119, 163, 250, 122, 24, 456, 581, 456,
- /* 2030 */ 1196, 458, 1032, 353, 292, 266, 1112, 200, 1242, 400,
- /* 2040 */ 400, 399, 277, 397, 500, 252, 863, 201, 292, 15,
- /* 2050 */ 865, 558, 505, 400, 400, 399, 277, 397, 374, 239,
- /* 2060 */ 863, 327, 256, 202, 1032, 1032, 1034, 1035, 35, 326,
- /* 2070 */ 103, 25, 26, 239, 509, 327, 366, 514, 369, 895,
- /* 2080 */ 908, 517, 105, 326, 309, 164, 525, 106, 181, 27,
- /* 2090 */ 1189, 1073, 17, 1192, 107, 1159, 1158, 284, 230, 286,
- /* 2100 */ 241, 204, 125, 1175, 982, 265, 1182, 976, 175, 28,
- /* 2110 */ 1179, 43, 29, 1177, 241, 30, 31, 8, 1183, 32,
- /* 2120 */ 1164, 41, 175, 208, 553, 43, 111, 33, 240, 1087,
- /* 2130 */ 1074, 113, 114, 1072, 1076, 34, 1077, 565, 1128, 118,
- /* 2140 */ 271, 36, 240, 18, 939, 1037, 877, 272, 124, 37,
- /* 2150 */ 398, 1198, 1197, 576, 183, 273, 153, 1621, 1260, 1260,
- /* 2160 */ 1260, 1260, 1260, 418, 1260, 1260, 1260, 1260, 320, 571,
- /* 2170 */ 1260, 1260, 1260, 1260, 1260, 1260, 1260, 418, 1260, 1260,
- /* 2180 */ 1260, 1260, 320, 571, 1260, 1260, 1260, 1260, 1260, 1260,
- /* 2190 */ 1260, 1260, 462, 1260, 1260, 1260, 1260, 1260, 1260, 1260,
- /* 2200 */ 1260, 1260, 1260, 1260, 1260, 1260, 462,
+ /* 0 */ 134, 131, 238, 290, 290, 1357, 597, 1336, 482, 1610,
+ /* 10 */ 597, 1319, 597, 7, 597, 1357, 594, 597, 583, 428,
+ /* 20 */ 1570, 134, 131, 238, 1322, 545, 482, 481, 579, 84,
+ /* 30 */ 84, 1009, 303, 84, 84, 51, 51, 63, 63, 1010,
+ /* 40 */ 84, 84, 502, 141, 142, 93, 446, 1258, 1258, 1089,
+ /* 50 */ 1092, 1079, 1079, 139, 139, 140, 140, 140, 140, 428,
+ /* 60 */ 296, 296, 502, 296, 296, 571, 557, 296, 296, 1310,
+ /* 70 */ 578, 1362, 1362, 594, 546, 583, 594, 578, 583, 552,
+ /* 80 */ 594, 1308, 583, 141, 142, 93, 580, 1258, 1258, 1089,
+ /* 90 */ 1092, 1079, 1079, 139, 139, 140, 140, 140, 140, 403,
+ /* 100 */ 482, 399, 6, 138, 138, 138, 138, 137, 137, 136,
+ /* 110 */ 136, 136, 135, 132, 467, 44, 342, 597, 305, 1131,
+ /* 120 */ 1284, 1, 1, 603, 2, 1288, 602, 1204, 1288, 1204,
+ /* 130 */ 330, 428, 158, 330, 1617, 158, 394, 116, 308, 1370,
+ /* 140 */ 51, 51, 1370, 138, 138, 138, 138, 137, 137, 136,
+ /* 150 */ 136, 136, 135, 132, 467, 141, 142, 93, 519, 1258,
+ /* 160 */ 1258, 1089, 1092, 1079, 1079, 139, 139, 140, 140, 140,
+ /* 170 */ 140, 1234, 329, 588, 296, 296, 212, 296, 296, 572,
+ /* 180 */ 572, 492, 143, 1076, 1076, 1090, 1093, 594, 1199, 583,
+ /* 190 */ 594, 340, 583, 140, 140, 140, 140, 133, 396, 568,
+ /* 200 */ 540, 1199, 250, 429, 1199, 250, 137, 137, 136, 136,
+ /* 210 */ 136, 135, 132, 467, 291, 138, 138, 138, 138, 137,
+ /* 220 */ 137, 136, 136, 136, 135, 132, 467, 970, 1234, 1235,
+ /* 230 */ 1234, 416, 969, 471, 416, 428, 471, 493, 361, 1615,
+ /* 240 */ 395, 138, 138, 138, 138, 137, 137, 136, 136, 136,
+ /* 250 */ 135, 132, 467, 467, 134, 131, 238, 559, 1080, 141,
+ /* 260 */ 142, 93, 597, 1258, 1258, 1089, 1092, 1079, 1079, 139,
+ /* 270 */ 139, 140, 140, 140, 140, 1321, 134, 131, 238, 428,
+ /* 280 */ 553, 1601, 1535, 333, 97, 83, 83, 140, 140, 140,
+ /* 290 */ 140, 138, 138, 138, 138, 137, 137, 136, 136, 136,
+ /* 300 */ 135, 132, 467, 141, 142, 93, 1661, 1258, 1258, 1089,
+ /* 310 */ 1092, 1079, 1079, 139, 139, 140, 140, 140, 140, 138,
+ /* 320 */ 138, 138, 138, 137, 137, 136, 136, 136, 135, 132,
+ /* 330 */ 467, 595, 1234, 962, 962, 138, 138, 138, 138, 137,
+ /* 340 */ 137, 136, 136, 136, 135, 132, 467, 44, 402, 551,
+ /* 350 */ 1310, 136, 136, 136, 135, 132, 467, 390, 597, 446,
+ /* 360 */ 599, 145, 599, 138, 138, 138, 138, 137, 137, 136,
+ /* 370 */ 136, 136, 135, 132, 467, 504, 1234, 112, 554, 464,
+ /* 380 */ 463, 51, 51, 428, 296, 296, 483, 334, 1263, 1234,
+ /* 390 */ 1235, 1234, 1603, 1265, 392, 312, 448, 594, 246, 583,
+ /* 400 */ 550, 1264, 271, 235, 329, 588, 555, 141, 142, 93,
+ /* 410 */ 433, 1258, 1258, 1089, 1092, 1079, 1079, 139, 139, 140,
+ /* 420 */ 140, 140, 140, 22, 22, 1234, 1266, 428, 1266, 216,
+ /* 430 */ 296, 296, 98, 1234, 1235, 1234, 264, 888, 45, 532,
+ /* 440 */ 529, 528, 1045, 594, 1273, 583, 425, 424, 397, 527,
+ /* 450 */ 44, 141, 142, 93, 502, 1258, 1258, 1089, 1092, 1079,
+ /* 460 */ 1079, 139, 139, 140, 140, 140, 140, 138, 138, 138,
+ /* 470 */ 138, 137, 137, 136, 136, 136, 135, 132, 467, 597,
+ /* 480 */ 1615, 565, 1234, 1235, 1234, 23, 264, 519, 200, 532,
+ /* 490 */ 529, 528, 127, 589, 513, 4, 359, 491, 510, 527,
+ /* 500 */ 597, 502, 84, 84, 134, 131, 238, 329, 588, 592,
+ /* 510 */ 1631, 138, 138, 138, 138, 137, 137, 136, 136, 136,
+ /* 520 */ 135, 132, 467, 19, 19, 439, 1234, 1464, 297, 297,
+ /* 530 */ 311, 428, 1569, 468, 1635, 603, 2, 1288, 441, 578,
+ /* 540 */ 1111, 594, 330, 583, 158, 586, 493, 361, 577, 597,
+ /* 550 */ 596, 1370, 413, 1278, 1234, 141, 142, 93, 1368, 1258,
+ /* 560 */ 1258, 1089, 1092, 1079, 1079, 139, 139, 140, 140, 140,
+ /* 570 */ 140, 393, 84, 84, 1066, 571, 1234, 313, 1527, 597,
+ /* 580 */ 125, 125, 974, 1234, 1235, 1234, 296, 296, 126, 46,
+ /* 590 */ 468, 598, 468, 296, 296, 1054, 1234, 218, 443, 594,
+ /* 600 */ 1608, 583, 84, 84, 7, 407, 594, 519, 583, 325,
+ /* 610 */ 421, 1234, 1235, 1234, 250, 138, 138, 138, 138, 137,
+ /* 620 */ 137, 136, 136, 136, 135, 132, 467, 1054, 1054, 1056,
+ /* 630 */ 1057, 35, 1279, 1234, 1235, 1234, 428, 1374, 997, 578,
+ /* 640 */ 375, 418, 274, 416, 1601, 471, 1306, 556, 455, 594,
+ /* 650 */ 547, 583, 1534, 1234, 1235, 1234, 1218, 201, 413, 1178,
+ /* 660 */ 141, 142, 93, 223, 1258, 1258, 1089, 1092, 1079, 1079,
+ /* 670 */ 139, 139, 140, 140, 140, 140, 296, 296, 1254, 597,
+ /* 680 */ 428, 296, 296, 236, 533, 296, 296, 519, 100, 594,
+ /* 690 */ 1604, 583, 48, 1609, 594, 1234, 583, 7, 594, 581,
+ /* 700 */ 583, 908, 84, 84, 141, 142, 93, 500, 1258, 1258,
+ /* 710 */ 1089, 1092, 1079, 1079, 139, 139, 140, 140, 140, 140,
+ /* 720 */ 138, 138, 138, 138, 137, 137, 136, 136, 136, 135,
+ /* 730 */ 132, 467, 1369, 1234, 296, 296, 1254, 115, 1279, 326,
+ /* 740 */ 233, 543, 1066, 40, 282, 127, 589, 594, 4, 583,
+ /* 750 */ 329, 588, 1234, 1235, 1234, 1602, 597, 392, 908, 1055,
+ /* 760 */ 1360, 1360, 592, 1054, 138, 138, 138, 138, 137, 137,
+ /* 770 */ 136, 136, 136, 135, 132, 467, 185, 597, 1234, 19,
+ /* 780 */ 19, 1234, 975, 1601, 428, 1655, 468, 129, 912, 1199,
+ /* 790 */ 1234, 1235, 1234, 1329, 447, 1054, 1054, 1056, 586, 1607,
+ /* 800 */ 149, 149, 1199, 7, 5, 1199, 1691, 414, 141, 142,
+ /* 810 */ 93, 1540, 1258, 1258, 1089, 1092, 1079, 1079, 139, 139,
+ /* 820 */ 140, 140, 140, 140, 1218, 401, 597, 1066, 428, 1540,
+ /* 830 */ 1542, 50, 905, 125, 125, 1234, 1235, 1234, 1234, 1235,
+ /* 840 */ 1234, 126, 1234, 468, 598, 468, 519, 1234, 1054, 84,
+ /* 850 */ 84, 3, 141, 142, 93, 928, 1258, 1258, 1089, 1092,
+ /* 860 */ 1079, 1079, 139, 139, 140, 140, 140, 140, 138, 138,
+ /* 870 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 467,
+ /* 880 */ 1054, 1054, 1056, 1057, 35, 446, 461, 536, 437, 1234,
+ /* 890 */ 1066, 1365, 544, 544, 1602, 929, 392, 7, 1133, 1234,
+ /* 900 */ 1235, 1234, 1133, 1540, 1234, 1235, 1234, 1055, 574, 1218,
+ /* 910 */ 597, 1054, 138, 138, 138, 138, 137, 137, 136, 136,
+ /* 920 */ 136, 135, 132, 467, 6, 185, 1199, 1234, 231, 597,
+ /* 930 */ 386, 996, 428, 151, 151, 514, 1217, 561, 486, 1199,
+ /* 940 */ 385, 160, 1199, 1054, 1054, 1056, 1234, 1235, 1234, 426,
+ /* 950 */ 597, 451, 84, 84, 597, 217, 141, 142, 93, 597,
+ /* 960 */ 1258, 1258, 1089, 1092, 1079, 1079, 139, 139, 140, 140,
+ /* 970 */ 140, 140, 1218, 19, 19, 597, 428, 19, 19, 446,
+ /* 980 */ 1067, 446, 19, 19, 1234, 1235, 1234, 519, 449, 462,
+ /* 990 */ 1601, 390, 315, 1179, 1689, 560, 1689, 454, 84, 84,
+ /* 1000 */ 141, 142, 93, 509, 1258, 1258, 1089, 1092, 1079, 1079,
+ /* 1010 */ 139, 139, 140, 140, 140, 140, 138, 138, 138, 138,
+ /* 1020 */ 137, 137, 136, 136, 136, 135, 132, 467, 446, 1151,
+ /* 1030 */ 458, 1601, 366, 1045, 597, 466, 1464, 1237, 47, 1397,
+ /* 1040 */ 324, 569, 569, 115, 1152, 453, 7, 464, 463, 307,
+ /* 1050 */ 379, 358, 597, 113, 597, 329, 588, 19, 19, 1153,
+ /* 1060 */ 138, 138, 138, 138, 137, 137, 136, 136, 136, 135,
+ /* 1070 */ 132, 467, 209, 1177, 567, 19, 19, 19, 19, 49,
+ /* 1080 */ 428, 948, 1179, 1690, 1050, 1690, 218, 359, 488, 345,
+ /* 1090 */ 210, 949, 573, 566, 1266, 1237, 1266, 494, 314, 427,
+ /* 1100 */ 428, 1602, 1210, 392, 141, 142, 93, 444, 1258, 1258,
+ /* 1110 */ 1089, 1092, 1079, 1079, 139, 139, 140, 140, 140, 140,
+ /* 1120 */ 356, 316, 535, 316, 141, 142, 93, 553, 1258, 1258,
+ /* 1130 */ 1089, 1092, 1079, 1079, 139, 139, 140, 140, 140, 140,
+ /* 1140 */ 450, 10, 1602, 274, 392, 919, 281, 299, 387, 538,
+ /* 1150 */ 382, 537, 269, 597, 1210, 591, 591, 591, 378, 293,
+ /* 1160 */ 1583, 995, 1177, 302, 138, 138, 138, 138, 137, 137,
+ /* 1170 */ 136, 136, 136, 135, 132, 467, 53, 53, 524, 1254,
+ /* 1180 */ 597, 1151, 1580, 435, 138, 138, 138, 138, 137, 137,
+ /* 1190 */ 136, 136, 136, 135, 132, 467, 1152, 301, 597, 1581,
+ /* 1200 */ 597, 1311, 435, 54, 54, 597, 268, 597, 465, 465,
+ /* 1210 */ 465, 1153, 351, 496, 428, 135, 132, 467, 1150, 1199,
+ /* 1220 */ 478, 68, 68, 69, 69, 554, 332, 287, 21, 21,
+ /* 1230 */ 55, 55, 1199, 585, 428, 1199, 309, 1254, 141, 142,
+ /* 1240 */ 93, 119, 1258, 1258, 1089, 1092, 1079, 1079, 139, 139,
+ /* 1250 */ 140, 140, 140, 140, 597, 237, 484, 1480, 141, 142,
+ /* 1260 */ 93, 597, 1258, 1258, 1089, 1092, 1079, 1079, 139, 139,
+ /* 1270 */ 140, 140, 140, 140, 348, 434, 350, 70, 70, 498,
+ /* 1280 */ 995, 1136, 1136, 516, 56, 56, 1273, 597, 268, 597,
+ /* 1290 */ 373, 378, 597, 485, 215, 388, 1628, 485, 138, 138,
+ /* 1300 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 467,
+ /* 1310 */ 71, 71, 72, 72, 225, 73, 73, 597, 138, 138,
+ /* 1320 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 467,
+ /* 1330 */ 590, 435, 597, 876, 877, 878, 597, 915, 597, 1606,
+ /* 1340 */ 74, 74, 597, 7, 1464, 242, 597, 306, 428, 1582,
+ /* 1350 */ 476, 306, 368, 219, 371, 75, 75, 434, 349, 57,
+ /* 1360 */ 57, 58, 58, 436, 187, 59, 59, 597, 428, 61,
+ /* 1370 */ 61, 1479, 141, 142, 93, 123, 1258, 1258, 1089, 1092,
+ /* 1380 */ 1079, 1079, 139, 139, 140, 140, 140, 140, 428, 574,
+ /* 1390 */ 62, 62, 141, 142, 93, 915, 1258, 1258, 1089, 1092,
+ /* 1400 */ 1079, 1079, 139, 139, 140, 140, 140, 140, 161, 388,
+ /* 1410 */ 1628, 1478, 141, 130, 93, 445, 1258, 1258, 1089, 1092,
+ /* 1420 */ 1079, 1079, 139, 139, 140, 140, 140, 140, 267, 266,
+ /* 1430 */ 265, 1464, 138, 138, 138, 138, 137, 137, 136, 136,
+ /* 1440 */ 136, 135, 132, 467, 597, 1340, 597, 1273, 1464, 388,
+ /* 1450 */ 1628, 231, 138, 138, 138, 138, 137, 137, 136, 136,
+ /* 1460 */ 136, 135, 132, 467, 597, 163, 597, 76, 76, 77,
+ /* 1470 */ 77, 597, 138, 138, 138, 138, 137, 137, 136, 136,
+ /* 1480 */ 136, 135, 132, 467, 479, 597, 487, 78, 78, 20,
+ /* 1490 */ 20, 1253, 428, 495, 79, 79, 499, 426, 295, 235,
+ /* 1500 */ 1578, 38, 515, 900, 426, 335, 240, 426, 147, 147,
+ /* 1510 */ 112, 597, 428, 597, 101, 222, 995, 142, 93, 459,
+ /* 1520 */ 1258, 1258, 1089, 1092, 1079, 1079, 139, 139, 140, 140,
+ /* 1530 */ 140, 140, 597, 39, 148, 148, 80, 80, 93, 555,
+ /* 1540 */ 1258, 1258, 1089, 1092, 1079, 1079, 139, 139, 140, 140,
+ /* 1550 */ 140, 140, 328, 927, 926, 64, 64, 506, 1660, 1009,
+ /* 1560 */ 937, 900, 124, 426, 121, 254, 597, 1010, 597, 226,
+ /* 1570 */ 597, 127, 589, 164, 4, 16, 138, 138, 138, 138,
+ /* 1580 */ 137, 137, 136, 136, 136, 135, 132, 467, 592, 81,
+ /* 1590 */ 81, 65, 65, 82, 82, 597, 138, 138, 138, 138,
+ /* 1600 */ 137, 137, 136, 136, 136, 135, 132, 467, 597, 226,
+ /* 1610 */ 237, 970, 468, 597, 298, 597, 969, 597, 66, 66,
+ /* 1620 */ 597, 1174, 597, 415, 586, 357, 473, 115, 597, 475,
+ /* 1630 */ 169, 173, 173, 597, 44, 995, 174, 174, 89, 89,
+ /* 1640 */ 67, 67, 597, 85, 85, 150, 150, 1118, 1047, 597,
+ /* 1650 */ 273, 86, 86, 1066, 597, 507, 171, 171, 597, 125,
+ /* 1660 */ 125, 501, 597, 273, 336, 152, 152, 126, 1339, 468,
+ /* 1670 */ 598, 468, 146, 146, 1054, 597, 549, 172, 172, 597,
+ /* 1680 */ 1058, 165, 165, 256, 339, 156, 156, 127, 589, 1590,
+ /* 1690 */ 4, 329, 588, 503, 362, 273, 115, 352, 155, 155,
+ /* 1700 */ 934, 935, 153, 153, 592, 1118, 1054, 1054, 1056, 1057,
+ /* 1710 */ 35, 1558, 525, 597, 270, 1012, 1013, 9, 597, 376,
+ /* 1720 */ 597, 115, 597, 168, 597, 115, 597, 1114, 468, 270,
+ /* 1730 */ 1000, 968, 273, 129, 1649, 1218, 154, 154, 1058, 1408,
+ /* 1740 */ 586, 88, 88, 90, 90, 87, 87, 52, 52, 60,
+ /* 1750 */ 60, 1409, 508, 541, 563, 1183, 965, 511, 129, 562,
+ /* 1760 */ 127, 589, 1130, 4, 1130, 1129, 898, 1129, 162, 1066,
+ /* 1770 */ 967, 363, 129, 1405, 367, 125, 125, 592, 370, 372,
+ /* 1780 */ 374, 1353, 1338, 126, 1337, 468, 598, 468, 381, 391,
+ /* 1790 */ 1054, 1395, 1418, 1622, 1463, 1391, 1403, 208, 584, 1468,
+ /* 1800 */ 1318, 468, 243, 520, 1309, 1297, 1388, 1296, 1298, 1642,
+ /* 1810 */ 288, 170, 228, 586, 12, 412, 321, 322, 241, 323,
+ /* 1820 */ 245, 1450, 1054, 1054, 1056, 1057, 35, 563, 304, 354,
+ /* 1830 */ 355, 505, 564, 127, 589, 344, 4, 1455, 347, 310,
+ /* 1840 */ 1454, 530, 1066, 1336, 419, 384, 232, 1531, 125, 125,
+ /* 1850 */ 592, 1218, 1400, 360, 1530, 587, 126, 1401, 468, 598,
+ /* 1860 */ 468, 1645, 539, 1054, 1585, 1399, 1273, 1587, 1586, 213,
+ /* 1870 */ 406, 277, 214, 227, 468, 1577, 239, 1575, 1270, 1398,
+ /* 1880 */ 438, 198, 100, 224, 96, 144, 586, 1445, 574, 183,
+ /* 1890 */ 343, 191, 1438, 346, 489, 1054, 1054, 1056, 1057, 35,
+ /* 1900 */ 563, 193, 523, 194, 1451, 562, 195, 13, 196, 113,
+ /* 1910 */ 14, 490, 252, 417, 497, 1066, 1536, 1459, 1457, 202,
+ /* 1920 */ 1456, 125, 125, 99, 1218, 420, 512, 1525, 258, 126,
+ /* 1930 */ 106, 468, 598, 468, 1547, 518, 1054, 289, 365, 260,
+ /* 1940 */ 206, 521, 369, 422, 452, 261, 1356, 1299, 1355, 262,
+ /* 1950 */ 1347, 1354, 108, 919, 1346, 233, 456, 548, 457, 319,
+ /* 1960 */ 1659, 320, 423, 1658, 1627, 275, 276, 1423, 1054, 1054,
+ /* 1970 */ 1056, 1057, 35, 1634, 1222, 470, 1326, 1325, 300, 1613,
+ /* 1980 */ 383, 1324, 1657, 411, 411, 410, 284, 408, 389, 460,
+ /* 1990 */ 885, 1422, 1612, 127, 589, 1512, 4, 1218, 11, 400,
+ /* 2000 */ 120, 1379, 398, 247, 327, 338, 1378, 220, 114, 558,
+ /* 2010 */ 592, 42, 405, 337, 600, 404, 1228, 283, 285, 286,
+ /* 2020 */ 175, 601, 1294, 1289, 431, 159, 176, 1562, 1563, 872,
+ /* 2030 */ 1561, 1560, 317, 91, 468, 229, 230, 469, 221, 177,
+ /* 2040 */ 472, 331, 1169, 474, 249, 94, 586, 477, 95, 189,
+ /* 2050 */ 244, 1128, 178, 1126, 341, 43, 190, 432, 179, 192,
+ /* 2060 */ 188, 1253, 951, 353, 1142, 180, 251, 197, 181, 440,
+ /* 2070 */ 182, 102, 248, 103, 442, 1066, 104, 199, 1144, 253,
+ /* 2080 */ 255, 125, 125, 105, 1141, 166, 24, 257, 364, 126,
+ /* 2090 */ 273, 468, 598, 468, 1268, 517, 1054, 259, 204, 15,
+ /* 2100 */ 1134, 92, 589, 522, 4, 887, 263, 430, 203, 385,
+ /* 2110 */ 205, 526, 329, 588, 107, 576, 25, 26, 592, 377,
+ /* 2120 */ 531, 917, 380, 109, 534, 930, 318, 184, 1054, 1054,
+ /* 2130 */ 1056, 1057, 35, 167, 27, 110, 480, 542, 111, 1215,
+ /* 2140 */ 1095, 1185, 468, 17, 1184, 292, 234, 294, 272, 1004,
+ /* 2150 */ 207, 129, 998, 28, 586, 1201, 1203, 1218, 1190, 29,
+ /* 2160 */ 41, 30, 1205, 31, 8, 1209, 1208, 32, 570, 34,
+ /* 2170 */ 211, 115, 1109, 33, 1096, 1094, 1098, 1099, 278, 582,
+ /* 2180 */ 122, 117, 1149, 1066, 118, 36, 18, 593, 1059, 125,
+ /* 2190 */ 125, 899, 128, 37, 186, 961, 157, 126, 409, 468,
+ /* 2200 */ 598, 468, 1222, 470, 1054, 1224, 300, 1223, 1285, 279,
+ /* 2210 */ 280, 411, 411, 410, 284, 408, 1650, 1285, 885, 1285,
+ /* 2220 */ 300, 1285, 1285, 575, 1285, 411, 411, 410, 284, 408,
+ /* 2230 */ 1285, 247, 885, 338, 1285, 1285, 1054, 1054, 1056, 1057,
+ /* 2240 */ 35, 337, 1285, 1285, 1285, 247, 1285, 338, 1285, 1285,
+ /* 2250 */ 1285, 1285, 1285, 1285, 1285, 337, 1285, 1285, 1285, 1285,
+ /* 2260 */ 1285, 1285, 1285, 1285, 1285, 1218, 1285, 1285, 1285, 1285,
+ /* 2270 */ 1285, 1285, 249, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
+ /* 2280 */ 178, 1285, 1285, 43, 1285, 1285, 249, 1285, 1285, 1285,
+ /* 2290 */ 1285, 1285, 1285, 1285, 178, 1285, 1285, 43, 1285, 1285,
+ /* 2300 */ 248, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
+ /* 2310 */ 1285, 1285, 1285, 1285, 248, 1285, 1285, 1285, 1285, 1285,
+ /* 2320 */ 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
+ /* 2330 */ 1285, 1285, 1285, 1285, 1285, 430, 1285, 1285, 1285, 1285,
+ /* 2340 */ 329, 588, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 430,
+ /* 2350 */ 1285, 1285, 1285, 1285, 329, 588, 1285, 1285, 1285, 1285,
+ /* 2360 */ 1285, 1285, 1285, 1285, 480, 1285, 1285, 1285, 1285, 1285,
+ /* 2370 */ 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 480,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 241,
- /* 10 */ 242, 195, 217, 221, 195, 235, 254, 195, 256, 19,
- /* 20 */ 225, 298, 254, 195, 256, 206, 213, 214, 206, 218,
- /* 30 */ 219, 31, 206, 195, 218, 219, 195, 218, 219, 39,
- /* 40 */ 218, 219, 313, 43, 44, 45, 317, 47, 48, 49,
+ /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 312,
+ /* 10 */ 195, 218, 195, 316, 195, 235, 254, 195, 256, 19,
+ /* 20 */ 297, 277, 278, 279, 218, 206, 213, 214, 206, 218,
+ /* 30 */ 219, 31, 206, 218, 219, 218, 219, 218, 219, 39,
+ /* 40 */ 218, 219, 195, 43, 44, 45, 195, 47, 48, 49,
/* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19,
- /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 277,
- /* 70 */ 278, 279, 234, 254, 255, 256, 254, 255, 256, 218,
- /* 80 */ 254, 240, 256, 43, 44, 45, 264, 47, 48, 49,
- /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 271,
- /* 100 */ 287, 22, 23, 103, 104, 105, 106, 107, 108, 109,
- /* 110 */ 110, 111, 112, 113, 114, 114, 47, 48, 49, 50,
+ /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 195,
+ /* 70 */ 255, 237, 238, 254, 255, 256, 254, 255, 256, 264,
+ /* 80 */ 254, 207, 256, 43, 44, 45, 264, 47, 48, 49,
+ /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 251,
+ /* 100 */ 287, 253, 215, 103, 104, 105, 106, 107, 108, 109,
+ /* 110 */ 110, 111, 112, 113, 114, 82, 265, 195, 271, 11,
/* 120 */ 187, 188, 189, 190, 191, 192, 190, 87, 192, 89,
- /* 130 */ 197, 19, 199, 197, 318, 199, 320, 25, 195, 206,
- /* 140 */ 299, 271, 206, 103, 104, 105, 106, 107, 108, 109,
+ /* 130 */ 197, 19, 199, 197, 317, 199, 319, 25, 271, 206,
+ /* 140 */ 218, 219, 206, 103, 104, 105, 106, 107, 108, 109,
/* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 195, 47,
/* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 170 */ 58, 60, 21, 195, 241, 242, 215, 241, 242, 312,
- /* 180 */ 313, 102, 70, 205, 317, 207, 242, 254, 77, 256,
- /* 190 */ 254, 122, 256, 55, 56, 57, 58, 59, 254, 88,
- /* 200 */ 256, 90, 269, 240, 93, 269, 107, 108, 109, 110,
- /* 210 */ 111, 112, 113, 114, 271, 103, 104, 105, 106, 107,
- /* 220 */ 108, 109, 110, 111, 112, 113, 114, 313, 117, 118,
- /* 230 */ 119, 317, 81, 195, 301, 19, 195, 301, 277, 278,
- /* 240 */ 279, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 195, 43,
- /* 260 */ 44, 45, 74, 47, 48, 49, 50, 51, 52, 53,
- /* 270 */ 54, 55, 56, 57, 58, 124, 195, 60, 109, 110,
- /* 280 */ 111, 112, 113, 114, 68, 195, 103, 104, 105, 106,
- /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 208, 218,
- /* 300 */ 219, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- /* 310 */ 112, 113, 114, 162, 233, 24, 128, 129, 130, 103,
+ /* 170 */ 58, 60, 139, 140, 241, 242, 289, 241, 242, 309,
+ /* 180 */ 310, 294, 70, 47, 48, 49, 50, 254, 77, 256,
+ /* 190 */ 254, 195, 256, 55, 56, 57, 58, 59, 221, 88,
+ /* 200 */ 109, 90, 269, 240, 93, 269, 107, 108, 109, 110,
+ /* 210 */ 111, 112, 113, 114, 215, 103, 104, 105, 106, 107,
+ /* 220 */ 108, 109, 110, 111, 112, 113, 114, 136, 117, 118,
+ /* 230 */ 119, 298, 141, 300, 298, 19, 300, 129, 130, 317,
+ /* 240 */ 318, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ /* 250 */ 112, 113, 114, 114, 277, 278, 279, 146, 122, 43,
+ /* 260 */ 44, 45, 195, 47, 48, 49, 50, 51, 52, 53,
+ /* 270 */ 54, 55, 56, 57, 58, 218, 277, 278, 279, 19,
+ /* 280 */ 19, 195, 286, 23, 68, 218, 219, 55, 56, 57,
+ /* 290 */ 58, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ /* 300 */ 112, 113, 114, 43, 44, 45, 232, 47, 48, 49,
+ /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 103,
/* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
- /* 330 */ 114, 195, 195, 215, 117, 118, 119, 120, 195, 19,
- /* 340 */ 123, 124, 125, 207, 24, 74, 246, 60, 310, 311,
- /* 350 */ 133, 60, 311, 82, 22, 218, 219, 257, 195, 19,
- /* 360 */ 73, 218, 219, 43, 44, 45, 206, 47, 48, 49,
- /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 22,
- /* 380 */ 23, 218, 219, 43, 44, 45, 54, 47, 48, 49,
- /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 128,
- /* 400 */ 82, 241, 242, 195, 117, 118, 119, 289, 60, 118,
- /* 410 */ 139, 140, 294, 195, 254, 195, 256, 195, 255, 259,
- /* 420 */ 260, 73, 22, 103, 104, 105, 106, 107, 108, 109,
- /* 430 */ 110, 111, 112, 113, 114, 206, 218, 219, 218, 219,
- /* 440 */ 218, 219, 234, 103, 104, 105, 106, 107, 108, 109,
- /* 450 */ 110, 111, 112, 113, 114, 318, 319, 139, 140, 102,
- /* 460 */ 60, 318, 319, 221, 19, 117, 118, 119, 23, 195,
- /* 470 */ 241, 242, 313, 255, 206, 255, 317, 255, 206, 129,
- /* 480 */ 130, 206, 264, 254, 264, 256, 264, 195, 43, 44,
- /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 500 */ 55, 56, 57, 58, 246, 213, 214, 19, 19, 241,
- /* 510 */ 242, 195, 23, 241, 242, 257, 241, 242, 118, 277,
- /* 520 */ 278, 279, 254, 29, 256, 60, 254, 33, 256, 254,
- /* 530 */ 206, 256, 43, 44, 45, 218, 47, 48, 49, 50,
- /* 540 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104,
- /* 550 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
- /* 560 */ 66, 19, 218, 60, 120, 241, 242, 123, 124, 125,
- /* 570 */ 60, 232, 77, 19, 20, 26, 22, 133, 254, 287,
- /* 580 */ 256, 265, 117, 118, 119, 90, 312, 313, 93, 47,
- /* 590 */ 36, 317, 103, 104, 105, 106, 107, 108, 109, 110,
- /* 600 */ 111, 112, 113, 114, 116, 117, 277, 278, 279, 60,
- /* 610 */ 107, 108, 19, 276, 60, 31, 23, 152, 195, 116,
- /* 620 */ 117, 118, 119, 39, 121, 276, 72, 117, 118, 119,
- /* 630 */ 166, 167, 129, 145, 237, 238, 43, 44, 45, 276,
- /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 650 */ 57, 58, 315, 316, 144, 101, 19, 154, 116, 156,
- /* 660 */ 23, 107, 108, 109, 315, 316, 117, 118, 119, 115,
- /* 670 */ 60, 117, 118, 119, 132, 200, 122, 60, 315, 316,
- /* 680 */ 43, 44, 45, 272, 47, 48, 49, 50, 51, 52,
- /* 690 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106,
- /* 700 */ 107, 108, 109, 110, 111, 112, 113, 114, 154, 155,
- /* 710 */ 156, 157, 158, 212, 213, 214, 22, 195, 101, 22,
- /* 720 */ 60, 19, 20, 60, 22, 139, 140, 117, 118, 119,
- /* 730 */ 22, 251, 195, 253, 117, 118, 195, 183, 36, 122,
- /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- /* 750 */ 113, 114, 195, 195, 60, 218, 219, 60, 195, 284,
- /* 760 */ 19, 25, 60, 288, 23, 237, 238, 22, 60, 109,
- /* 770 */ 233, 154, 155, 156, 72, 218, 219, 117, 118, 119,
- /* 780 */ 117, 118, 119, 116, 43, 44, 45, 265, 47, 48,
- /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
- /* 800 */ 183, 243, 25, 101, 19, 60, 265, 144, 23, 107,
- /* 810 */ 108, 117, 118, 119, 117, 118, 119, 115, 151, 117,
- /* 820 */ 118, 119, 82, 195, 122, 117, 118, 119, 43, 44,
- /* 830 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 840 */ 55, 56, 57, 58, 103, 104, 105, 106, 107, 108,
- /* 850 */ 109, 110, 111, 112, 113, 114, 154, 155, 156, 157,
- /* 860 */ 158, 121, 117, 118, 119, 307, 101, 309, 195, 22,
- /* 870 */ 23, 195, 25, 19, 35, 139, 140, 195, 24, 139,
- /* 880 */ 140, 208, 195, 118, 109, 183, 22, 122, 103, 104,
- /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
- /* 900 */ 304, 305, 77, 230, 127, 232, 67, 195, 19, 195,
- /* 910 */ 195, 136, 23, 88, 75, 90, 141, 203, 93, 154,
- /* 920 */ 155, 156, 208, 295, 60, 243, 22, 23, 19, 25,
- /* 930 */ 218, 219, 43, 44, 45, 100, 47, 48, 49, 50,
- /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 183, 102,
- /* 950 */ 96, 195, 43, 44, 45, 240, 47, 48, 49, 50,
- /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 134,
- /* 970 */ 131, 146, 25, 286, 120, 121, 122, 123, 124, 125,
- /* 980 */ 126, 117, 118, 119, 313, 195, 132, 195, 317, 307,
- /* 990 */ 195, 309, 103, 104, 105, 106, 107, 108, 109, 110,
- /* 1000 */ 111, 112, 113, 114, 195, 195, 102, 195, 195, 195,
- /* 1010 */ 218, 219, 103, 104, 105, 106, 107, 108, 109, 110,
- /* 1020 */ 111, 112, 113, 114, 77, 233, 195, 60, 218, 219,
- /* 1030 */ 218, 219, 218, 219, 23, 195, 25, 90, 243, 159,
- /* 1040 */ 93, 161, 19, 233, 195, 233, 23, 233, 16, 218,
- /* 1050 */ 219, 195, 243, 212, 213, 214, 262, 263, 218, 219,
- /* 1060 */ 195, 271, 19, 307, 233, 309, 43, 44, 45, 160,
- /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 1080 */ 57, 58, 195, 218, 219, 118, 43, 44, 45, 240,
- /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 1100 */ 57, 58, 307, 195, 309, 218, 219, 263, 12, 195,
- /* 1110 */ 78, 267, 80, 112, 113, 114, 307, 22, 309, 24,
- /* 1120 */ 255, 281, 266, 27, 107, 108, 103, 104, 105, 106,
- /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 195,
- /* 1140 */ 11, 22, 255, 24, 195, 195, 103, 104, 105, 106,
- /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 19, 195,
- /* 1160 */ 64, 195, 218, 219, 195, 313, 195, 218, 219, 317,
- /* 1170 */ 74, 154, 195, 156, 195, 195, 19, 233, 23, 60,
- /* 1180 */ 25, 24, 218, 219, 218, 219, 195, 218, 219, 218,
- /* 1190 */ 219, 128, 129, 130, 162, 263, 19, 218, 219, 267,
- /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52,
- /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 240, 228, 255,
- /* 1220 */ 43, 44, 45, 25, 47, 48, 49, 50, 51, 52,
- /* 1230 */ 53, 54, 55, 56, 57, 58, 135, 118, 137, 138,
- /* 1240 */ 43, 44, 45, 22, 47, 48, 49, 50, 51, 52,
- /* 1250 */ 53, 54, 55, 56, 57, 58, 117, 266, 129, 130,
- /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- /* 1270 */ 113, 114, 195, 195, 119, 295, 195, 206, 195, 195,
- /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- /* 1290 */ 113, 114, 195, 195, 195, 218, 219, 195, 195, 144,
- /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- /* 1310 */ 113, 114, 241, 242, 67, 218, 219, 218, 219, 146,
- /* 1320 */ 19, 218, 219, 240, 215, 254, 136, 256, 107, 108,
- /* 1330 */ 195, 141, 255, 86, 128, 129, 130, 195, 165, 195,
- /* 1340 */ 19, 143, 95, 272, 25, 44, 45, 266, 47, 48,
- /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
- /* 1360 */ 218, 219, 218, 219, 195, 12, 45, 195, 47, 48,
- /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
- /* 1380 */ 27, 23, 7, 8, 9, 210, 211, 218, 219, 116,
- /* 1390 */ 218, 219, 228, 16, 147, 42, 195, 295, 195, 19,
- /* 1400 */ 20, 266, 22, 294, 103, 104, 105, 106, 107, 108,
- /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 218,
- /* 1420 */ 219, 218, 219, 195, 103, 104, 105, 106, 107, 108,
- /* 1430 */ 109, 110, 111, 112, 113, 114, 195, 154, 119, 156,
- /* 1440 */ 60, 189, 190, 191, 192, 195, 218, 219, 195, 197,
- /* 1450 */ 195, 199, 72, 195, 19, 78, 195, 80, 206, 218,
- /* 1460 */ 219, 195, 82, 144, 210, 211, 195, 15, 218, 219,
- /* 1470 */ 47, 218, 219, 218, 219, 259, 260, 195, 261, 218,
- /* 1480 */ 219, 101, 302, 303, 218, 219, 195, 107, 108, 218,
- /* 1490 */ 219, 150, 151, 241, 242, 115, 25, 117, 118, 119,
- /* 1500 */ 218, 219, 122, 195, 146, 195, 254, 195, 256, 218,
- /* 1510 */ 219, 246, 25, 61, 246, 19, 20, 195, 22, 139,
- /* 1520 */ 140, 269, 257, 195, 266, 257, 218, 219, 218, 219,
- /* 1530 */ 218, 219, 36, 246, 154, 155, 156, 157, 158, 116,
- /* 1540 */ 218, 219, 195, 22, 257, 49, 218, 219, 23, 195,
- /* 1550 */ 25, 195, 117, 301, 195, 25, 60, 195, 195, 23,
- /* 1560 */ 195, 25, 195, 183, 24, 218, 219, 130, 72, 195,
- /* 1570 */ 22, 195, 218, 219, 218, 219, 195, 218, 219, 195,
- /* 1580 */ 218, 219, 86, 218, 219, 218, 219, 91, 19, 20,
- /* 1590 */ 153, 22, 218, 219, 218, 219, 195, 101, 195, 218,
- /* 1600 */ 219, 195, 195, 107, 108, 36, 23, 195, 25, 195,
- /* 1610 */ 62, 115, 195, 117, 118, 119, 195, 146, 122, 218,
- /* 1620 */ 219, 218, 219, 195, 218, 219, 19, 60, 122, 60,
- /* 1630 */ 218, 219, 218, 219, 195, 218, 219, 150, 132, 218,
- /* 1640 */ 219, 72, 195, 23, 195, 25, 218, 219, 195, 60,
- /* 1650 */ 154, 155, 156, 157, 158, 86, 23, 195, 25, 195,
- /* 1660 */ 91, 19, 20, 142, 22, 218, 219, 218, 219, 130,
- /* 1670 */ 101, 218, 219, 143, 121, 122, 107, 108, 36, 183,
- /* 1680 */ 218, 219, 142, 60, 115, 118, 117, 118, 119, 7,
- /* 1690 */ 8, 122, 153, 23, 23, 25, 25, 23, 23, 25,
- /* 1700 */ 25, 23, 60, 25, 23, 98, 25, 118, 84, 85,
- /* 1710 */ 23, 23, 25, 25, 72, 154, 23, 156, 25, 23,
- /* 1720 */ 228, 25, 195, 154, 155, 156, 157, 158, 86, 195,
- /* 1730 */ 195, 258, 195, 91, 291, 322, 195, 195, 195, 195,
- /* 1740 */ 195, 118, 195, 101, 195, 195, 195, 195, 238, 107,
- /* 1750 */ 108, 195, 183, 195, 195, 195, 290, 115, 195, 117,
- /* 1760 */ 118, 119, 244, 195, 122, 195, 195, 195, 195, 195,
- /* 1770 */ 195, 258, 258, 258, 258, 193, 245, 300, 216, 274,
- /* 1780 */ 247, 270, 270, 274, 296, 296, 248, 222, 262, 198,
- /* 1790 */ 262, 274, 61, 274, 248, 231, 154, 155, 156, 157,
- /* 1800 */ 158, 0, 1, 2, 247, 227, 5, 221, 221, 221,
- /* 1810 */ 142, 10, 11, 12, 13, 14, 262, 262, 17, 202,
- /* 1820 */ 300, 19, 20, 300, 22, 183, 247, 251, 251, 245,
- /* 1830 */ 202, 30, 38, 32, 202, 152, 151, 22, 36, 149,
- /* 1840 */ 146, 40, 43, 18, 252, 251, 236, 252, 251, 283,
- /* 1850 */ 239, 239, 239, 239, 202, 18, 201, 150, 236, 202,
- /* 1860 */ 201, 236, 60, 248, 248, 275, 273, 248, 159, 273,
- /* 1870 */ 63, 286, 71, 275, 72, 275, 22, 297, 297, 248,
- /* 1880 */ 79, 202, 202, 82, 223, 201, 223, 201, 116, 220,
- /* 1890 */ 22, 202, 293, 292, 65, 229, 201, 220, 226, 226,
- /* 1900 */ 99, 127, 166, 101, 24, 229, 114, 83, 92, 107,
- /* 1910 */ 108, 220, 308, 202, 285, 223, 268, 115, 220, 117,
- /* 1920 */ 118, 119, 222, 220, 122, 220, 220, 223, 285, 19,
- /* 1930 */ 20, 22, 22, 268, 316, 134, 280, 202, 159, 148,
- /* 1940 */ 139, 140, 321, 141, 282, 147, 36, 321, 25, 252,
- /* 1950 */ 251, 204, 250, 252, 13, 196, 154, 155, 156, 157,
- /* 1960 */ 158, 249, 248, 196, 163, 6, 306, 194, 215, 194,
- /* 1970 */ 60, 194, 209, 306, 209, 215, 215, 215, 224, 224,
- /* 1980 */ 216, 215, 72, 4, 216, 183, 3, 209, 22, 15,
- /* 1990 */ 164, 16, 23, 23, 152, 140, 131, 25, 20, 143,
- /* 2000 */ 24, 16, 145, 1, 143, 131, 131, 62, 37, 54,
- /* 2010 */ 152, 101, 54, 303, 54, 54, 131, 107, 108, 117,
- /* 2020 */ 34, 142, 1, 5, 116, 115, 22, 117, 118, 119,
- /* 2030 */ 1, 2, 122, 162, 5, 25, 69, 69, 76, 10,
- /* 2040 */ 11, 12, 13, 14, 41, 142, 17, 116, 5, 24,
- /* 2050 */ 20, 141, 19, 10, 11, 12, 13, 14, 132, 30,
- /* 2060 */ 17, 32, 126, 22, 154, 155, 156, 157, 158, 40,
- /* 2070 */ 22, 22, 22, 30, 68, 32, 23, 68, 24, 60,
- /* 2080 */ 28, 97, 22, 40, 68, 23, 22, 150, 37, 34,
- /* 2090 */ 23, 23, 22, 183, 25, 23, 98, 23, 142, 23,
- /* 2100 */ 71, 22, 25, 89, 117, 34, 94, 144, 79, 34,
- /* 2110 */ 76, 82, 34, 87, 71, 34, 34, 44, 76, 34,
- /* 2120 */ 23, 22, 79, 25, 24, 82, 25, 34, 99, 23,
- /* 2130 */ 23, 143, 143, 23, 23, 22, 11, 25, 23, 25,
- /* 2140 */ 22, 22, 99, 22, 136, 23, 23, 142, 22, 22,
- /* 2150 */ 15, 1, 1, 25, 25, 142, 23, 142, 323, 323,
- /* 2160 */ 323, 323, 323, 134, 323, 323, 323, 323, 139, 140,
- /* 2170 */ 323, 323, 323, 323, 323, 323, 323, 134, 323, 323,
- /* 2180 */ 323, 323, 139, 140, 323, 323, 323, 323, 323, 323,
- /* 2190 */ 323, 323, 163, 323, 323, 323, 323, 323, 323, 323,
- /* 2200 */ 323, 323, 323, 323, 323, 323, 163, 323, 323, 323,
- /* 2210 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2220 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2230 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2240 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2250 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2260 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2270 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2280 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2290 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2300 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2310 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2320 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2330 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
- /* 2340 */ 323, 323, 323, 323, 323, 187, 187, 187, 187, 187,
- /* 2350 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
- /* 2360 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
- /* 2370 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
- /* 2380 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
- /* 2390 */ 187, 187, 187, 187,
+ /* 330 */ 114, 135, 60, 137, 138, 103, 104, 105, 106, 107,
+ /* 340 */ 108, 109, 110, 111, 112, 113, 114, 82, 281, 206,
+ /* 350 */ 195, 109, 110, 111, 112, 113, 114, 195, 195, 195,
+ /* 360 */ 205, 22, 207, 103, 104, 105, 106, 107, 108, 109,
+ /* 370 */ 110, 111, 112, 113, 114, 195, 60, 116, 117, 107,
+ /* 380 */ 108, 218, 219, 19, 241, 242, 121, 23, 116, 117,
+ /* 390 */ 118, 119, 306, 121, 308, 206, 234, 254, 15, 256,
+ /* 400 */ 195, 129, 259, 260, 139, 140, 145, 43, 44, 45,
+ /* 410 */ 200, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ /* 420 */ 56, 57, 58, 218, 219, 60, 154, 19, 156, 265,
+ /* 430 */ 241, 242, 24, 117, 118, 119, 120, 21, 73, 123,
+ /* 440 */ 124, 125, 74, 254, 61, 256, 107, 108, 221, 133,
+ /* 450 */ 82, 43, 44, 45, 195, 47, 48, 49, 50, 51,
+ /* 460 */ 52, 53, 54, 55, 56, 57, 58, 103, 104, 105,
+ /* 470 */ 106, 107, 108, 109, 110, 111, 112, 113, 114, 195,
+ /* 480 */ 317, 318, 117, 118, 119, 22, 120, 195, 22, 123,
+ /* 490 */ 124, 125, 19, 20, 284, 22, 128, 81, 288, 133,
+ /* 500 */ 195, 195, 218, 219, 277, 278, 279, 139, 140, 36,
+ /* 510 */ 195, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ /* 520 */ 112, 113, 114, 218, 219, 62, 60, 195, 241, 242,
+ /* 530 */ 271, 19, 240, 60, 189, 190, 191, 192, 233, 255,
+ /* 540 */ 124, 254, 197, 256, 199, 72, 129, 130, 264, 195,
+ /* 550 */ 195, 206, 22, 23, 60, 43, 44, 45, 206, 47,
+ /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ /* 570 */ 58, 195, 218, 219, 101, 195, 60, 271, 162, 195,
+ /* 580 */ 107, 108, 109, 117, 118, 119, 241, 242, 115, 73,
+ /* 590 */ 117, 118, 119, 241, 242, 122, 60, 195, 266, 254,
+ /* 600 */ 312, 256, 218, 219, 316, 203, 254, 195, 256, 255,
+ /* 610 */ 208, 117, 118, 119, 269, 103, 104, 105, 106, 107,
+ /* 620 */ 108, 109, 110, 111, 112, 113, 114, 154, 155, 156,
+ /* 630 */ 157, 158, 102, 117, 118, 119, 19, 242, 144, 255,
+ /* 640 */ 23, 206, 24, 298, 195, 300, 206, 195, 264, 254,
+ /* 650 */ 206, 256, 240, 117, 118, 119, 183, 22, 22, 23,
+ /* 660 */ 43, 44, 45, 151, 47, 48, 49, 50, 51, 52,
+ /* 670 */ 53, 54, 55, 56, 57, 58, 241, 242, 60, 195,
+ /* 680 */ 19, 241, 242, 195, 23, 241, 242, 195, 152, 254,
+ /* 690 */ 310, 256, 243, 312, 254, 60, 256, 316, 254, 206,
+ /* 700 */ 256, 60, 218, 219, 43, 44, 45, 272, 47, 48,
+ /* 710 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ /* 720 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 730 */ 113, 114, 240, 60, 241, 242, 118, 25, 102, 255,
+ /* 740 */ 166, 167, 101, 22, 26, 19, 20, 254, 22, 256,
+ /* 750 */ 139, 140, 117, 118, 119, 306, 195, 308, 117, 118,
+ /* 760 */ 237, 238, 36, 122, 103, 104, 105, 106, 107, 108,
+ /* 770 */ 109, 110, 111, 112, 113, 114, 195, 195, 60, 218,
+ /* 780 */ 219, 60, 109, 195, 19, 217, 60, 25, 23, 77,
+ /* 790 */ 117, 118, 119, 225, 233, 154, 155, 156, 72, 312,
+ /* 800 */ 218, 219, 90, 316, 22, 93, 303, 304, 43, 44,
+ /* 810 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54,
+ /* 820 */ 55, 56, 57, 58, 183, 195, 195, 101, 19, 213,
+ /* 830 */ 214, 243, 23, 107, 108, 117, 118, 119, 117, 118,
+ /* 840 */ 119, 115, 60, 117, 118, 119, 195, 60, 122, 218,
+ /* 850 */ 219, 22, 43, 44, 45, 35, 47, 48, 49, 50,
+ /* 860 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104,
+ /* 870 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ /* 880 */ 154, 155, 156, 157, 158, 195, 255, 67, 195, 60,
+ /* 890 */ 101, 240, 311, 312, 306, 75, 308, 316, 29, 117,
+ /* 900 */ 118, 119, 33, 287, 117, 118, 119, 118, 146, 183,
+ /* 910 */ 195, 122, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 920 */ 111, 112, 113, 114, 215, 195, 77, 60, 25, 195,
+ /* 930 */ 122, 144, 19, 218, 219, 66, 23, 88, 246, 90,
+ /* 940 */ 132, 25, 93, 154, 155, 156, 117, 118, 119, 257,
+ /* 950 */ 195, 131, 218, 219, 195, 265, 43, 44, 45, 195,
+ /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 970 */ 57, 58, 183, 218, 219, 195, 19, 218, 219, 195,
+ /* 980 */ 23, 195, 218, 219, 117, 118, 119, 195, 233, 255,
+ /* 990 */ 195, 195, 233, 22, 23, 146, 25, 233, 218, 219,
+ /* 1000 */ 43, 44, 45, 294, 47, 48, 49, 50, 51, 52,
+ /* 1010 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106,
+ /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 114, 195, 12,
+ /* 1030 */ 234, 195, 240, 74, 195, 255, 195, 60, 243, 262,
+ /* 1040 */ 263, 311, 312, 25, 27, 19, 316, 107, 108, 265,
+ /* 1050 */ 24, 265, 195, 150, 195, 139, 140, 218, 219, 42,
+ /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 1070 */ 113, 114, 233, 102, 67, 218, 219, 218, 219, 243,
+ /* 1080 */ 19, 64, 22, 23, 23, 25, 195, 128, 129, 130,
+ /* 1090 */ 233, 74, 233, 86, 154, 118, 156, 130, 265, 208,
+ /* 1100 */ 19, 306, 95, 308, 43, 44, 45, 266, 47, 48,
+ /* 1110 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ /* 1120 */ 153, 230, 96, 232, 43, 44, 45, 19, 47, 48,
+ /* 1130 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ /* 1140 */ 114, 22, 306, 24, 308, 127, 120, 121, 122, 123,
+ /* 1150 */ 124, 125, 126, 195, 147, 212, 213, 214, 132, 23,
+ /* 1160 */ 195, 25, 102, 100, 103, 104, 105, 106, 107, 108,
+ /* 1170 */ 109, 110, 111, 112, 113, 114, 218, 219, 19, 60,
+ /* 1180 */ 195, 12, 210, 211, 103, 104, 105, 106, 107, 108,
+ /* 1190 */ 109, 110, 111, 112, 113, 114, 27, 134, 195, 195,
+ /* 1200 */ 195, 210, 211, 218, 219, 195, 47, 195, 212, 213,
+ /* 1210 */ 214, 42, 16, 130, 19, 112, 113, 114, 23, 77,
+ /* 1220 */ 195, 218, 219, 218, 219, 117, 163, 164, 218, 219,
+ /* 1230 */ 218, 219, 90, 64, 19, 93, 153, 118, 43, 44,
+ /* 1240 */ 45, 160, 47, 48, 49, 50, 51, 52, 53, 54,
+ /* 1250 */ 55, 56, 57, 58, 195, 119, 272, 276, 43, 44,
+ /* 1260 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54,
+ /* 1270 */ 55, 56, 57, 58, 78, 116, 80, 218, 219, 116,
+ /* 1280 */ 144, 128, 129, 130, 218, 219, 61, 195, 47, 195,
+ /* 1290 */ 16, 132, 195, 263, 195, 314, 315, 267, 103, 104,
+ /* 1300 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ /* 1310 */ 218, 219, 218, 219, 151, 218, 219, 195, 103, 104,
+ /* 1320 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ /* 1330 */ 210, 211, 195, 7, 8, 9, 195, 60, 195, 312,
+ /* 1340 */ 218, 219, 195, 316, 195, 120, 195, 263, 19, 195,
+ /* 1350 */ 125, 267, 78, 24, 80, 218, 219, 116, 162, 218,
+ /* 1360 */ 219, 218, 219, 301, 302, 218, 219, 195, 19, 218,
+ /* 1370 */ 219, 276, 43, 44, 45, 160, 47, 48, 49, 50,
+ /* 1380 */ 51, 52, 53, 54, 55, 56, 57, 58, 19, 146,
+ /* 1390 */ 218, 219, 43, 44, 45, 118, 47, 48, 49, 50,
+ /* 1400 */ 51, 52, 53, 54, 55, 56, 57, 58, 165, 314,
+ /* 1410 */ 315, 276, 43, 44, 45, 266, 47, 48, 49, 50,
+ /* 1420 */ 51, 52, 53, 54, 55, 56, 57, 58, 128, 129,
+ /* 1430 */ 130, 195, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 1440 */ 111, 112, 113, 114, 195, 228, 195, 61, 195, 314,
+ /* 1450 */ 315, 25, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 1460 */ 111, 112, 113, 114, 195, 22, 195, 218, 219, 218,
+ /* 1470 */ 219, 195, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 1480 */ 111, 112, 113, 114, 195, 195, 246, 218, 219, 218,
+ /* 1490 */ 219, 25, 19, 246, 218, 219, 246, 257, 259, 260,
+ /* 1500 */ 195, 22, 266, 60, 257, 195, 120, 257, 218, 219,
+ /* 1510 */ 116, 195, 19, 195, 150, 151, 25, 44, 45, 266,
+ /* 1520 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 1530 */ 57, 58, 195, 54, 218, 219, 218, 219, 45, 145,
+ /* 1540 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 1550 */ 57, 58, 246, 121, 122, 218, 219, 19, 23, 31,
+ /* 1560 */ 25, 118, 159, 257, 161, 24, 195, 39, 195, 143,
+ /* 1570 */ 195, 19, 20, 22, 22, 24, 103, 104, 105, 106,
+ /* 1580 */ 107, 108, 109, 110, 111, 112, 113, 114, 36, 218,
+ /* 1590 */ 219, 218, 219, 218, 219, 195, 103, 104, 105, 106,
+ /* 1600 */ 107, 108, 109, 110, 111, 112, 113, 114, 195, 143,
+ /* 1610 */ 119, 136, 60, 195, 22, 195, 141, 195, 218, 219,
+ /* 1620 */ 195, 23, 195, 25, 72, 23, 131, 25, 195, 134,
+ /* 1630 */ 23, 218, 219, 195, 82, 144, 218, 219, 218, 219,
+ /* 1640 */ 218, 219, 195, 218, 219, 218, 219, 60, 23, 195,
+ /* 1650 */ 25, 218, 219, 101, 195, 117, 218, 219, 195, 107,
+ /* 1660 */ 108, 23, 195, 25, 195, 218, 219, 115, 228, 117,
+ /* 1670 */ 118, 119, 218, 219, 122, 195, 19, 218, 219, 195,
+ /* 1680 */ 60, 218, 219, 142, 195, 218, 219, 19, 20, 195,
+ /* 1690 */ 22, 139, 140, 23, 23, 25, 25, 195, 218, 219,
+ /* 1700 */ 7, 8, 218, 219, 36, 118, 154, 155, 156, 157,
+ /* 1710 */ 158, 195, 23, 195, 25, 84, 85, 49, 195, 23,
+ /* 1720 */ 195, 25, 195, 23, 195, 25, 195, 23, 60, 25,
+ /* 1730 */ 23, 23, 25, 25, 142, 183, 218, 219, 118, 195,
+ /* 1740 */ 72, 218, 219, 218, 219, 218, 219, 218, 219, 218,
+ /* 1750 */ 219, 195, 195, 146, 86, 98, 23, 195, 25, 91,
+ /* 1760 */ 19, 20, 154, 22, 156, 154, 23, 156, 25, 101,
+ /* 1770 */ 23, 195, 25, 195, 195, 107, 108, 36, 195, 195,
+ /* 1780 */ 195, 195, 228, 115, 195, 117, 118, 119, 195, 195,
+ /* 1790 */ 122, 261, 195, 321, 195, 195, 195, 258, 238, 195,
+ /* 1800 */ 195, 60, 299, 291, 195, 195, 258, 195, 195, 195,
+ /* 1810 */ 290, 244, 216, 72, 245, 193, 258, 258, 299, 258,
+ /* 1820 */ 299, 274, 154, 155, 156, 157, 158, 86, 247, 295,
+ /* 1830 */ 248, 295, 91, 19, 20, 270, 22, 274, 270, 248,
+ /* 1840 */ 274, 222, 101, 227, 274, 221, 231, 221, 107, 108,
+ /* 1850 */ 36, 183, 262, 247, 221, 283, 115, 262, 117, 118,
+ /* 1860 */ 119, 198, 116, 122, 220, 262, 61, 220, 220, 251,
+ /* 1870 */ 247, 142, 251, 245, 60, 202, 299, 202, 38, 262,
+ /* 1880 */ 202, 22, 152, 151, 296, 149, 72, 252, 146, 43,
+ /* 1890 */ 251, 236, 252, 251, 18, 154, 155, 156, 157, 158,
+ /* 1900 */ 86, 239, 18, 239, 275, 91, 239, 273, 239, 150,
+ /* 1910 */ 273, 202, 201, 248, 248, 101, 286, 236, 275, 236,
+ /* 1920 */ 275, 107, 108, 296, 183, 248, 202, 248, 201, 115,
+ /* 1930 */ 159, 117, 118, 119, 293, 63, 122, 202, 292, 201,
+ /* 1940 */ 22, 223, 202, 223, 65, 201, 220, 202, 220, 201,
+ /* 1950 */ 229, 220, 22, 127, 229, 166, 24, 307, 114, 285,
+ /* 1960 */ 226, 285, 223, 226, 315, 202, 92, 268, 154, 155,
+ /* 1970 */ 156, 157, 158, 0, 1, 2, 220, 222, 5, 320,
+ /* 1980 */ 220, 220, 220, 10, 11, 12, 13, 14, 223, 83,
+ /* 1990 */ 17, 268, 320, 19, 20, 280, 22, 183, 22, 202,
+ /* 2000 */ 159, 252, 251, 30, 282, 32, 252, 250, 148, 147,
+ /* 2010 */ 36, 25, 248, 40, 204, 249, 13, 196, 196, 6,
+ /* 2020 */ 209, 194, 194, 194, 305, 224, 209, 215, 215, 4,
+ /* 2030 */ 215, 215, 224, 215, 60, 216, 216, 3, 22, 209,
+ /* 2040 */ 19, 122, 122, 19, 71, 22, 72, 125, 22, 16,
+ /* 2050 */ 15, 23, 79, 23, 140, 82, 152, 305, 131, 143,
+ /* 2060 */ 302, 25, 20, 16, 1, 131, 145, 143, 131, 62,
+ /* 2070 */ 131, 54, 99, 54, 37, 101, 54, 152, 117, 34,
+ /* 2080 */ 24, 107, 108, 54, 1, 5, 22, 116, 162, 115,
+ /* 2090 */ 25, 117, 118, 119, 76, 41, 122, 142, 116, 24,
+ /* 2100 */ 69, 19, 20, 19, 22, 20, 126, 134, 69, 132,
+ /* 2110 */ 22, 68, 139, 140, 22, 141, 22, 22, 36, 23,
+ /* 2120 */ 68, 60, 24, 22, 97, 28, 68, 37, 154, 155,
+ /* 2130 */ 156, 157, 158, 23, 34, 150, 163, 22, 25, 23,
+ /* 2140 */ 23, 23, 60, 22, 98, 23, 142, 23, 34, 117,
+ /* 2150 */ 22, 25, 144, 34, 72, 89, 87, 183, 23, 34,
+ /* 2160 */ 22, 34, 76, 34, 44, 76, 94, 34, 24, 22,
+ /* 2170 */ 25, 25, 23, 34, 23, 23, 23, 11, 22, 25,
+ /* 2180 */ 25, 143, 23, 101, 143, 22, 22, 25, 23, 107,
+ /* 2190 */ 108, 23, 22, 22, 25, 136, 23, 115, 15, 117,
+ /* 2200 */ 118, 119, 1, 2, 122, 1, 5, 1, 322, 142,
+ /* 2210 */ 142, 10, 11, 12, 13, 14, 142, 322, 17, 322,
+ /* 2220 */ 5, 322, 322, 141, 322, 10, 11, 12, 13, 14,
+ /* 2230 */ 322, 30, 17, 32, 322, 322, 154, 155, 156, 157,
+ /* 2240 */ 158, 40, 322, 322, 322, 30, 322, 32, 322, 322,
+ /* 2250 */ 322, 322, 322, 322, 322, 40, 322, 322, 322, 322,
+ /* 2260 */ 322, 322, 322, 322, 322, 183, 322, 322, 322, 322,
+ /* 2270 */ 322, 322, 71, 322, 322, 322, 322, 322, 322, 322,
+ /* 2280 */ 79, 322, 322, 82, 322, 322, 71, 322, 322, 322,
+ /* 2290 */ 322, 322, 322, 322, 79, 322, 322, 82, 322, 322,
+ /* 2300 */ 99, 322, 322, 322, 322, 322, 322, 322, 322, 322,
+ /* 2310 */ 322, 322, 322, 322, 99, 322, 322, 322, 322, 322,
+ /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
+ /* 2330 */ 322, 322, 322, 322, 322, 134, 322, 322, 322, 322,
+ /* 2340 */ 139, 140, 322, 322, 322, 322, 322, 322, 322, 134,
+ /* 2350 */ 322, 322, 322, 322, 139, 140, 322, 322, 322, 322,
+ /* 2360 */ 322, 322, 322, 322, 163, 322, 322, 322, 322, 322,
+ /* 2370 */ 322, 322, 322, 322, 322, 322, 322, 322, 163, 322,
+ /* 2380 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
+ /* 2390 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
+ /* 2400 */ 322, 322, 322, 322, 322, 322, 322, 322, 187, 187,
+ /* 2410 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2420 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2430 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2440 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2450 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2460 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2470 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2480 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2490 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2500 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2510 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2520 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2530 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2540 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2550 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2560 */ 187, 187, 187, 187, 187, 187,
};
-#define YY_SHIFT_COUNT (586)
+#define YY_SHIFT_COUNT (603)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (2151)
+#define YY_SHIFT_MAX (2215)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 2029, 1801, 2043, 1380, 1380, 318, 271, 1496, 1569, 1642,
- /* 10 */ 702, 702, 702, 740, 318, 318, 318, 318, 318, 0,
- /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702,
- /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 503, 503,
- /* 40 */ 111, 111, 217, 287, 348, 610, 610, 736, 736, 736,
- /* 50 */ 736, 40, 112, 320, 340, 445, 489, 593, 637, 741,
- /* 60 */ 785, 889, 909, 1023, 1043, 1157, 1177, 1177, 1177, 1177,
- /* 70 */ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177,
- /* 80 */ 1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321, 554,
- /* 90 */ 1802, 1910, 702, 702, 702, 702, 702, 702, 702, 702,
- /* 100 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
- /* 110 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
- /* 120 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
- /* 130 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
- /* 140 */ 702, 702, 138, 198, 198, 198, 198, 198, 198, 198,
- /* 150 */ 183, 99, 169, 549, 610, 151, 542, 610, 610, 1017,
- /* 160 */ 1017, 610, 1001, 350, 464, 464, 464, 586, 1, 1,
- /* 170 */ 2207, 2207, 854, 854, 854, 465, 694, 694, 694, 694,
- /* 180 */ 1096, 1096, 825, 549, 847, 904, 610, 610, 610, 610,
- /* 190 */ 610, 610, 610, 610, 610, 610, 610, 610, 610, 610,
- /* 200 */ 610, 610, 610, 610, 610, 488, 947, 947, 610, 1129,
- /* 210 */ 495, 495, 1139, 1139, 967, 967, 1173, 2207, 2207, 2207,
- /* 220 */ 2207, 2207, 2207, 2207, 617, 765, 765, 697, 444, 708,
- /* 230 */ 660, 745, 510, 663, 864, 610, 610, 610, 610, 610,
- /* 240 */ 610, 610, 610, 610, 610, 188, 610, 610, 610, 610,
- /* 250 */ 610, 610, 610, 610, 610, 610, 610, 610, 839, 839,
- /* 260 */ 839, 610, 610, 610, 1155, 610, 610, 610, 1119, 1247,
- /* 270 */ 610, 1353, 610, 610, 610, 610, 610, 610, 610, 610,
- /* 280 */ 1063, 494, 1101, 291, 291, 291, 291, 1319, 1101, 1101,
- /* 290 */ 775, 1221, 1375, 1452, 667, 1341, 1198, 1341, 1435, 1487,
- /* 300 */ 667, 667, 1487, 667, 1198, 1435, 777, 1011, 1423, 584,
- /* 310 */ 584, 584, 1273, 1273, 1273, 1273, 1471, 1471, 880, 1530,
- /* 320 */ 1190, 1095, 1731, 1731, 1668, 1668, 1794, 1794, 1668, 1683,
- /* 330 */ 1685, 1815, 1690, 1694, 1799, 1690, 1694, 1825, 1825, 1825,
- /* 340 */ 1825, 1668, 1837, 1707, 1685, 1685, 1707, 1815, 1799, 1707,
- /* 350 */ 1799, 1707, 1668, 1837, 1709, 1807, 1668, 1837, 1854, 1668,
- /* 360 */ 1837, 1668, 1837, 1854, 1772, 1772, 1772, 1829, 1868, 1868,
- /* 370 */ 1854, 1772, 1774, 1772, 1829, 1772, 1772, 1736, 1880, 1792,
- /* 380 */ 1792, 1854, 1668, 1816, 1816, 1824, 1824, 1690, 1694, 1909,
- /* 390 */ 1668, 1779, 1690, 1791, 1798, 1707, 1923, 1941, 1941, 1959,
- /* 400 */ 1959, 1959, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207,
- /* 410 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 69, 1032, 79,
- /* 420 */ 357, 1377, 1206, 400, 1525, 835, 332, 1540, 1437, 1539,
- /* 430 */ 1536, 1548, 1583, 1620, 1633, 1670, 1671, 1674, 1567, 1553,
- /* 440 */ 1682, 1506, 1675, 1358, 1607, 1589, 1678, 1681, 1624, 1687,
- /* 450 */ 1688, 1283, 1561, 1693, 1696, 1623, 1521, 1979, 1983, 1966,
- /* 460 */ 1826, 1974, 1975, 1969, 1970, 1855, 1842, 1865, 1972, 1972,
- /* 470 */ 1976, 1856, 1978, 1857, 1985, 2002, 1861, 1874, 1972, 1875,
- /* 480 */ 1945, 1971, 1972, 1858, 1955, 1958, 1960, 1961, 1885, 1902,
- /* 490 */ 1986, 1879, 2021, 2018, 2004, 1908, 1871, 1967, 2010, 1968,
- /* 500 */ 1962, 2003, 1903, 1931, 2025, 2030, 2033, 1926, 1936, 2041,
- /* 510 */ 2006, 2048, 2049, 2053, 2050, 2009, 2019, 2054, 1984, 2052,
- /* 520 */ 2060, 2016, 2051, 2062, 2055, 1937, 2064, 2067, 2068, 2069,
- /* 530 */ 2072, 2070, 1998, 1956, 2074, 2076, 1987, 2071, 2079, 1963,
- /* 540 */ 2077, 2075, 2078, 2081, 2082, 2014, 2034, 2026, 2073, 2042,
- /* 550 */ 2012, 2085, 2097, 2099, 2100, 2098, 2101, 2093, 1988, 1989,
- /* 560 */ 2106, 2077, 2107, 2110, 2111, 2113, 2112, 2114, 2115, 2118,
- /* 570 */ 2125, 2119, 2121, 2122, 2123, 2126, 2127, 2128, 2008, 2005,
- /* 580 */ 2013, 2015, 2129, 2133, 2135, 2150, 2151,
+ /* 0 */ 2201, 1973, 2215, 1552, 1552, 33, 368, 1668, 1741, 1814,
+ /* 10 */ 726, 726, 726, 265, 33, 33, 33, 33, 33, 0,
+ /* 20 */ 0, 216, 1349, 726, 726, 726, 726, 726, 726, 726,
+ /* 30 */ 726, 726, 726, 726, 726, 726, 726, 726, 272, 272,
+ /* 40 */ 111, 111, 316, 365, 516, 867, 867, 916, 916, 916,
+ /* 50 */ 916, 40, 112, 260, 364, 408, 512, 617, 661, 765,
+ /* 60 */ 809, 913, 957, 1061, 1081, 1195, 1215, 1329, 1349, 1349,
+ /* 70 */ 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349,
+ /* 80 */ 1349, 1349, 1349, 1349, 1349, 1349, 1369, 1349, 1473, 1493,
+ /* 90 */ 1493, 473, 1974, 2082, 726, 726, 726, 726, 726, 726,
+ /* 100 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726,
+ /* 110 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726,
+ /* 120 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726,
+ /* 130 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726,
+ /* 140 */ 726, 726, 726, 726, 726, 726, 138, 232, 232, 232,
+ /* 150 */ 232, 232, 232, 232, 188, 99, 242, 718, 416, 1159,
+ /* 160 */ 867, 867, 940, 940, 867, 1103, 417, 574, 574, 574,
+ /* 170 */ 611, 139, 139, 2379, 2379, 1026, 1026, 1026, 536, 466,
+ /* 180 */ 466, 466, 466, 1017, 1017, 849, 718, 971, 1060, 867,
+ /* 190 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867,
+ /* 200 */ 867, 867, 867, 867, 867, 867, 867, 867, 261, 712,
+ /* 210 */ 712, 867, 108, 1142, 1142, 977, 1108, 1108, 977, 977,
+ /* 220 */ 1243, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 641, 789,
+ /* 230 */ 789, 635, 366, 721, 673, 782, 494, 787, 829, 867,
+ /* 240 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867,
+ /* 250 */ 959, 867, 867, 867, 867, 867, 867, 867, 867, 867,
+ /* 260 */ 867, 867, 867, 867, 867, 820, 820, 820, 867, 867,
+ /* 270 */ 867, 1136, 867, 867, 867, 1119, 1007, 867, 1169, 867,
+ /* 280 */ 867, 867, 867, 867, 867, 867, 867, 1225, 1153, 869,
+ /* 290 */ 196, 618, 618, 618, 618, 1491, 196, 196, 91, 339,
+ /* 300 */ 1326, 1386, 383, 1163, 1364, 1426, 1364, 1538, 903, 1163,
+ /* 310 */ 1163, 903, 1163, 1426, 1538, 1018, 1535, 1241, 1528, 1528,
+ /* 320 */ 1528, 1394, 1394, 1394, 1394, 762, 762, 1403, 1466, 1475,
+ /* 330 */ 1551, 1746, 1805, 1746, 1746, 1729, 1729, 1840, 1840, 1729,
+ /* 340 */ 1730, 1732, 1859, 1736, 1742, 1846, 1736, 1742, 1876, 1876,
+ /* 350 */ 1876, 1876, 1729, 1884, 1759, 1732, 1732, 1759, 1859, 1846,
+ /* 360 */ 1759, 1846, 1759, 1729, 1884, 1771, 1872, 1729, 1884, 1918,
+ /* 370 */ 1729, 1884, 1729, 1884, 1918, 1746, 1746, 1746, 1879, 1930,
+ /* 380 */ 1930, 1918, 1746, 1826, 1746, 1879, 1746, 1746, 1789, 1932,
+ /* 390 */ 1844, 1844, 1918, 1729, 1874, 1874, 1906, 1906, 1736, 1742,
+ /* 400 */ 1976, 1729, 1841, 1736, 1860, 1862, 1759, 1986, 2003, 2003,
+ /* 410 */ 2013, 2013, 2013, 2379, 2379, 2379, 2379, 2379, 2379, 2379,
+ /* 420 */ 2379, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 136, 1063,
+ /* 430 */ 1196, 530, 636, 1274, 1300, 1443, 1598, 1495, 1479, 967,
+ /* 440 */ 1083, 1602, 463, 1625, 1638, 1670, 1541, 1671, 1689, 1696,
+ /* 450 */ 1277, 1432, 1693, 808, 1700, 1607, 1657, 1587, 1704, 1707,
+ /* 460 */ 1631, 1708, 1733, 1608, 1611, 1743, 1747, 1620, 1592, 2025,
+ /* 470 */ 2034, 2016, 1919, 2021, 1920, 2024, 2023, 2026, 1922, 2035,
+ /* 480 */ 2033, 2028, 2030, 1914, 1904, 1927, 2036, 2036, 1916, 2042,
+ /* 490 */ 1921, 2047, 2063, 1924, 1934, 2036, 1937, 2007, 2037, 2036,
+ /* 500 */ 1925, 2017, 2019, 2022, 2029, 1939, 1961, 2045, 2056, 2083,
+ /* 510 */ 2080, 2064, 1971, 1926, 2031, 2065, 2039, 2018, 2054, 1955,
+ /* 520 */ 1982, 2075, 2085, 2084, 1977, 1980, 2088, 2043, 2092, 2094,
+ /* 530 */ 2096, 2095, 2052, 2061, 2098, 2027, 2097, 2101, 2058, 2090,
+ /* 540 */ 2110, 2100, 1985, 2115, 2116, 2117, 2113, 2118, 2121, 2046,
+ /* 550 */ 2004, 2122, 2124, 2032, 2114, 2128, 2008, 2126, 2119, 2125,
+ /* 560 */ 2127, 2129, 2066, 2086, 2069, 2120, 2089, 2072, 2133, 2135,
+ /* 570 */ 2138, 2144, 2145, 2146, 2139, 2038, 2041, 2149, 2126, 2151,
+ /* 580 */ 2152, 2153, 2147, 2154, 2155, 2159, 2156, 2166, 2163, 2164,
+ /* 590 */ 2165, 2168, 2170, 2171, 2162, 2059, 2067, 2068, 2074, 2169,
+ /* 600 */ 2173, 2183, 2204, 2206,
};
-#define YY_REDUCE_COUNT (416)
-#define YY_REDUCE_MIN (-277)
-#define YY_REDUCE_MAX (1778)
+#define YY_REDUCE_COUNT (427)
+#define YY_REDUCE_MIN (-303)
+#define YY_REDUCE_MAX (1830)
static const short yy_reduce_ofst[] = {
- /* 0 */ -67, 1252, -64, -178, -181, 160, 1071, 143, -184, 137,
- /* 10 */ 218, 220, 222, -174, 229, 268, 272, 275, 324, -208,
- /* 20 */ 242, -277, -39, 81, 537, 792, 810, 812, -189, 814,
- /* 30 */ 831, 163, 865, 944, 887, 840, 964, 1077, -187, 292,
- /* 40 */ -133, 274, 673, 558, 682, 795, 809, -238, -232, -238,
- /* 50 */ -232, 329, 329, 329, 329, 329, 329, 329, 329, 329,
- /* 60 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329,
- /* 70 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329,
- /* 80 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 557,
- /* 90 */ 712, 949, 966, 969, 971, 979, 1097, 1099, 1103, 1142,
- /* 100 */ 1144, 1169, 1172, 1201, 1203, 1228, 1241, 1250, 1253, 1255,
- /* 110 */ 1261, 1266, 1271, 1282, 1291, 1308, 1310, 1312, 1322, 1328,
- /* 120 */ 1347, 1354, 1356, 1359, 1362, 1365, 1367, 1374, 1376, 1381,
- /* 130 */ 1401, 1403, 1406, 1412, 1414, 1417, 1421, 1428, 1447, 1449,
- /* 140 */ 1453, 1462, 329, 329, 329, 329, 329, 329, 329, 329,
- /* 150 */ 329, 329, 329, -22, -159, 475, -220, 756, 38, 501,
- /* 160 */ 841, 714, 329, 118, 337, 349, 363, -56, 329, 329,
- /* 170 */ 329, 329, -205, -205, -205, 687, -172, -130, -57, 790,
- /* 180 */ 397, 528, -271, 136, 596, 596, 90, 316, 522, 541,
- /* 190 */ -37, 715, 849, 977, 628, 856, 980, 991, 1081, 1102,
- /* 200 */ 1135, 1083, -162, 208, 1258, 794, -86, 159, 41, 1109,
- /* 210 */ 671, 852, 844, 932, 1175, 1254, 480, 1180, 100, 258,
- /* 220 */ 1265, 1268, 1216, 1287, -139, 317, 344, 63, 339, 423,
- /* 230 */ 563, 636, 676, 813, 908, 914, 950, 1078, 1084, 1098,
- /* 240 */ 1363, 1384, 1407, 1439, 1464, 411, 1527, 1534, 1535, 1537,
- /* 250 */ 1541, 1542, 1543, 1544, 1545, 1547, 1549, 1550, 990, 1164,
- /* 260 */ 1492, 1551, 1552, 1556, 1217, 1558, 1559, 1560, 1473, 1413,
- /* 270 */ 1563, 1510, 1568, 563, 1570, 1571, 1572, 1573, 1574, 1575,
- /* 280 */ 1443, 1466, 1518, 1513, 1514, 1515, 1516, 1217, 1518, 1518,
- /* 290 */ 1531, 1562, 1582, 1477, 1505, 1511, 1533, 1512, 1488, 1538,
- /* 300 */ 1509, 1517, 1546, 1519, 1557, 1489, 1565, 1564, 1578, 1586,
- /* 310 */ 1587, 1588, 1526, 1528, 1554, 1555, 1576, 1577, 1566, 1579,
- /* 320 */ 1584, 1591, 1520, 1523, 1617, 1628, 1580, 1581, 1632, 1585,
- /* 330 */ 1590, 1593, 1592, 1594, 1610, 1595, 1597, 1611, 1612, 1613,
- /* 340 */ 1614, 1652, 1655, 1615, 1598, 1600, 1616, 1596, 1622, 1619,
- /* 350 */ 1625, 1631, 1657, 1659, 1599, 1601, 1679, 1684, 1661, 1680,
- /* 360 */ 1686, 1689, 1695, 1663, 1669, 1677, 1691, 1666, 1672, 1673,
- /* 370 */ 1692, 1698, 1700, 1703, 1676, 1705, 1706, 1618, 1604, 1629,
- /* 380 */ 1643, 1704, 1711, 1621, 1626, 1648, 1665, 1697, 1699, 1656,
- /* 390 */ 1735, 1662, 1701, 1702, 1712, 1714, 1747, 1759, 1767, 1773,
- /* 400 */ 1775, 1777, 1660, 1667, 1710, 1763, 1753, 1760, 1761, 1762,
- /* 410 */ 1765, 1754, 1755, 1764, 1768, 1766, 1778,
+ /* 0 */ -67, 345, -64, -178, -181, 143, 435, -78, -183, 163,
+ /* 10 */ -185, 284, 384, -174, 189, 352, 440, 444, 493, -23,
+ /* 20 */ 227, -277, -1, 305, 561, 755, 759, 764, -189, 839,
+ /* 30 */ 857, 354, 484, 859, 631, 67, 734, 780, -187, 616,
+ /* 40 */ 581, 730, 891, 449, 588, 795, 836, -238, 287, -238,
+ /* 50 */ 287, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+ /* 60 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+ /* 70 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+ /* 80 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+ /* 90 */ -256, 205, 582, 715, 958, 985, 1003, 1005, 1010, 1012,
+ /* 100 */ 1059, 1066, 1092, 1094, 1097, 1122, 1137, 1141, 1143, 1147,
+ /* 110 */ 1151, 1172, 1249, 1251, 1269, 1271, 1276, 1290, 1316, 1318,
+ /* 120 */ 1337, 1371, 1373, 1375, 1400, 1413, 1418, 1420, 1422, 1425,
+ /* 130 */ 1427, 1433, 1438, 1447, 1454, 1459, 1463, 1467, 1480, 1484,
+ /* 140 */ 1518, 1523, 1525, 1527, 1529, 1531, -256, -256, -256, -256,
+ /* 150 */ -256, -256, -256, -256, -256, -256, -256, 155, 210, -220,
+ /* 160 */ 86, -130, 943, 996, 402, -256, -113, 981, 1095, 1135,
+ /* 170 */ 395, -256, -256, -256, -256, 568, 568, 568, -4, -153,
+ /* 180 */ -133, 259, 306, -166, 523, -303, -126, 503, 503, -37,
+ /* 190 */ -149, 164, 690, 292, 412, 492, 651, 784, 332, 786,
+ /* 200 */ 841, 1149, 833, 1236, 792, 162, 796, 1253, 777, 288,
+ /* 210 */ 381, 380, 709, 487, 1027, 972, 1030, 1084, 991, 1120,
+ /* 220 */ -152, 1062, 692, 1240, 1247, 1250, 1239, 1306, -207, -194,
+ /* 230 */ 57, 180, 74, 315, 355, 376, 452, 488, 630, 693,
+ /* 240 */ 965, 1004, 1025, 1099, 1154, 1289, 1305, 1310, 1469, 1489,
+ /* 250 */ 984, 1494, 1502, 1516, 1544, 1556, 1557, 1562, 1576, 1578,
+ /* 260 */ 1579, 1583, 1584, 1585, 1586, 1217, 1440, 1554, 1589, 1593,
+ /* 270 */ 1594, 1530, 1597, 1599, 1600, 1539, 1472, 1601, 1560, 1604,
+ /* 280 */ 355, 1605, 1609, 1610, 1612, 1613, 1614, 1503, 1512, 1520,
+ /* 290 */ 1567, 1548, 1558, 1559, 1561, 1530, 1567, 1567, 1569, 1596,
+ /* 300 */ 1622, 1519, 1521, 1547, 1565, 1581, 1568, 1534, 1582, 1563,
+ /* 310 */ 1566, 1591, 1570, 1606, 1536, 1619, 1615, 1616, 1624, 1626,
+ /* 320 */ 1633, 1590, 1595, 1603, 1617, 1618, 1621, 1572, 1623, 1628,
+ /* 330 */ 1663, 1644, 1577, 1647, 1648, 1673, 1675, 1588, 1627, 1678,
+ /* 340 */ 1630, 1629, 1634, 1635, 1639, 1655, 1640, 1642, 1662, 1664,
+ /* 350 */ 1667, 1669, 1709, 1711, 1665, 1643, 1645, 1666, 1637, 1681,
+ /* 360 */ 1677, 1683, 1679, 1724, 1727, 1641, 1646, 1735, 1738, 1718,
+ /* 370 */ 1740, 1744, 1745, 1748, 1720, 1726, 1728, 1731, 1721, 1734,
+ /* 380 */ 1737, 1739, 1756, 1755, 1760, 1725, 1761, 1762, 1649, 1650,
+ /* 390 */ 1674, 1676, 1765, 1763, 1659, 1672, 1699, 1723, 1749, 1751,
+ /* 400 */ 1715, 1797, 1722, 1754, 1757, 1766, 1764, 1810, 1821, 1822,
+ /* 410 */ 1827, 1828, 1829, 1719, 1752, 1758, 1811, 1812, 1813, 1815,
+ /* 420 */ 1816, 1817, 1801, 1808, 1819, 1820, 1818, 1830,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1667, 1667, 1667, 1495, 1258, 1371, 1258, 1258, 1258, 1258,
- /* 10 */ 1495, 1495, 1495, 1258, 1258, 1258, 1258, 1258, 1258, 1401,
- /* 20 */ 1401, 1548, 1291, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 30 */ 1258, 1258, 1258, 1258, 1258, 1494, 1258, 1258, 1258, 1258,
- /* 40 */ 1582, 1582, 1258, 1258, 1258, 1258, 1258, 1567, 1566, 1258,
- /* 50 */ 1258, 1258, 1410, 1258, 1417, 1258, 1258, 1258, 1258, 1258,
- /* 60 */ 1496, 1497, 1258, 1258, 1258, 1258, 1547, 1549, 1512, 1424,
- /* 70 */ 1423, 1422, 1421, 1530, 1389, 1415, 1408, 1412, 1491, 1492,
- /* 80 */ 1490, 1645, 1497, 1496, 1258, 1411, 1459, 1475, 1458, 1258,
- /* 90 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 100 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 110 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 120 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 130 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 140 */ 1258, 1258, 1467, 1474, 1473, 1472, 1481, 1471, 1468, 1461,
- /* 150 */ 1460, 1462, 1463, 1282, 1258, 1279, 1333, 1258, 1258, 1258,
- /* 160 */ 1258, 1258, 1464, 1291, 1452, 1451, 1450, 1258, 1478, 1465,
- /* 170 */ 1477, 1476, 1555, 1619, 1618, 1513, 1258, 1258, 1258, 1258,
- /* 180 */ 1258, 1258, 1582, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 190 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 200 */ 1258, 1258, 1258, 1258, 1258, 1391, 1582, 1582, 1258, 1291,
- /* 210 */ 1582, 1582, 1392, 1392, 1287, 1287, 1395, 1562, 1362, 1362,
- /* 220 */ 1362, 1362, 1371, 1362, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 230 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1552,
- /* 240 */ 1550, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 250 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 260 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1367, 1258,
- /* 270 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1612,
- /* 280 */ 1258, 1525, 1347, 1367, 1367, 1367, 1367, 1369, 1348, 1346,
- /* 290 */ 1361, 1292, 1265, 1659, 1427, 1416, 1368, 1416, 1656, 1414,
- /* 300 */ 1427, 1427, 1414, 1427, 1368, 1656, 1308, 1634, 1303, 1401,
- /* 310 */ 1401, 1401, 1391, 1391, 1391, 1391, 1395, 1395, 1493, 1368,
- /* 320 */ 1361, 1258, 1659, 1659, 1377, 1377, 1658, 1658, 1377, 1513,
- /* 330 */ 1642, 1436, 1409, 1395, 1336, 1409, 1395, 1342, 1342, 1342,
- /* 340 */ 1342, 1377, 1276, 1414, 1642, 1642, 1414, 1436, 1336, 1414,
- /* 350 */ 1336, 1414, 1377, 1276, 1529, 1653, 1377, 1276, 1503, 1377,
- /* 360 */ 1276, 1377, 1276, 1503, 1334, 1334, 1334, 1323, 1258, 1258,
- /* 370 */ 1503, 1334, 1308, 1334, 1323, 1334, 1334, 1600, 1258, 1507,
- /* 380 */ 1507, 1503, 1377, 1592, 1592, 1404, 1404, 1409, 1395, 1498,
- /* 390 */ 1377, 1258, 1409, 1407, 1405, 1414, 1326, 1615, 1615, 1611,
- /* 400 */ 1611, 1611, 1664, 1664, 1562, 1627, 1291, 1291, 1291, 1291,
- /* 410 */ 1627, 1310, 1310, 1292, 1292, 1291, 1627, 1258, 1258, 1258,
- /* 420 */ 1258, 1258, 1258, 1622, 1258, 1557, 1514, 1381, 1258, 1258,
- /* 430 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 440 */ 1258, 1258, 1258, 1258, 1568, 1258, 1258, 1258, 1258, 1258,
- /* 450 */ 1258, 1258, 1258, 1258, 1258, 1258, 1441, 1258, 1261, 1559,
- /* 460 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1418, 1419,
- /* 470 */ 1382, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1433, 1258,
- /* 480 */ 1258, 1258, 1428, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 490 */ 1258, 1655, 1258, 1258, 1258, 1258, 1258, 1258, 1528, 1527,
- /* 500 */ 1258, 1258, 1379, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 510 */ 1258, 1258, 1258, 1258, 1258, 1258, 1306, 1258, 1258, 1258,
- /* 520 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 530 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 540 */ 1406, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
- /* 550 */ 1258, 1258, 1258, 1258, 1258, 1597, 1396, 1258, 1258, 1258,
- /* 560 */ 1258, 1646, 1258, 1258, 1258, 1258, 1356, 1258, 1258, 1258,
- /* 570 */ 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1638, 1350, 1442,
- /* 580 */ 1258, 1445, 1280, 1258, 1270, 1258, 1258,
+ /* 0 */ 1695, 1695, 1695, 1520, 1283, 1396, 1283, 1283, 1283, 1283,
+ /* 10 */ 1520, 1520, 1520, 1283, 1283, 1283, 1283, 1283, 1283, 1426,
+ /* 20 */ 1426, 1572, 1316, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 30 */ 1283, 1283, 1283, 1283, 1283, 1519, 1283, 1283, 1283, 1283,
+ /* 40 */ 1611, 1611, 1283, 1283, 1283, 1283, 1283, 1596, 1595, 1283,
+ /* 50 */ 1283, 1283, 1435, 1283, 1283, 1283, 1442, 1283, 1283, 1283,
+ /* 60 */ 1283, 1283, 1521, 1522, 1283, 1283, 1283, 1283, 1571, 1573,
+ /* 70 */ 1537, 1449, 1448, 1447, 1446, 1555, 1414, 1440, 1433, 1437,
+ /* 80 */ 1516, 1517, 1515, 1674, 1522, 1521, 1283, 1436, 1484, 1500,
+ /* 90 */ 1483, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 100 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 110 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 120 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 130 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 140 */ 1283, 1283, 1283, 1283, 1283, 1283, 1492, 1499, 1498, 1497,
+ /* 150 */ 1506, 1496, 1493, 1486, 1485, 1487, 1488, 1307, 1304, 1358,
+ /* 160 */ 1283, 1283, 1283, 1283, 1283, 1489, 1316, 1477, 1476, 1475,
+ /* 170 */ 1283, 1503, 1490, 1502, 1501, 1579, 1648, 1647, 1538, 1283,
+ /* 180 */ 1283, 1283, 1283, 1283, 1283, 1611, 1283, 1283, 1283, 1283,
+ /* 190 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 200 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1416, 1611,
+ /* 210 */ 1611, 1283, 1316, 1611, 1611, 1312, 1417, 1417, 1312, 1312,
+ /* 220 */ 1420, 1591, 1387, 1387, 1387, 1387, 1396, 1387, 1283, 1283,
+ /* 230 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 240 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1576, 1574, 1283,
+ /* 250 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 260 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 270 */ 1283, 1283, 1283, 1283, 1283, 1392, 1283, 1283, 1283, 1283,
+ /* 280 */ 1283, 1283, 1283, 1283, 1283, 1283, 1641, 1687, 1283, 1550,
+ /* 290 */ 1372, 1392, 1392, 1392, 1392, 1394, 1373, 1371, 1386, 1317,
+ /* 300 */ 1290, 1687, 1687, 1452, 1441, 1393, 1441, 1684, 1439, 1452,
+ /* 310 */ 1452, 1439, 1452, 1393, 1684, 1333, 1663, 1328, 1426, 1426,
+ /* 320 */ 1426, 1416, 1416, 1416, 1416, 1420, 1420, 1518, 1393, 1386,
+ /* 330 */ 1283, 1359, 1687, 1359, 1359, 1402, 1402, 1686, 1686, 1402,
+ /* 340 */ 1538, 1671, 1461, 1434, 1420, 1361, 1434, 1420, 1367, 1367,
+ /* 350 */ 1367, 1367, 1402, 1301, 1439, 1671, 1671, 1439, 1461, 1361,
+ /* 360 */ 1439, 1361, 1439, 1402, 1301, 1554, 1682, 1402, 1301, 1528,
+ /* 370 */ 1402, 1301, 1402, 1301, 1528, 1359, 1359, 1359, 1348, 1283,
+ /* 380 */ 1283, 1528, 1359, 1333, 1359, 1348, 1359, 1359, 1629, 1283,
+ /* 390 */ 1532, 1532, 1528, 1402, 1621, 1621, 1429, 1429, 1434, 1420,
+ /* 400 */ 1523, 1402, 1283, 1434, 1432, 1430, 1439, 1351, 1644, 1644,
+ /* 410 */ 1640, 1640, 1640, 1692, 1692, 1591, 1656, 1316, 1316, 1316,
+ /* 420 */ 1316, 1656, 1335, 1335, 1317, 1317, 1316, 1656, 1283, 1283,
+ /* 430 */ 1283, 1283, 1283, 1283, 1283, 1651, 1283, 1283, 1539, 1283,
+ /* 440 */ 1283, 1283, 1283, 1283, 1283, 1283, 1406, 1283, 1283, 1283,
+ /* 450 */ 1283, 1283, 1283, 1283, 1283, 1283, 1597, 1283, 1283, 1283,
+ /* 460 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1466, 1283,
+ /* 470 */ 1286, 1588, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 480 */ 1283, 1283, 1283, 1283, 1283, 1283, 1443, 1444, 1283, 1283,
+ /* 490 */ 1283, 1283, 1283, 1283, 1283, 1458, 1283, 1283, 1283, 1453,
+ /* 500 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1407, 1283,
+ /* 510 */ 1283, 1283, 1283, 1283, 1283, 1553, 1552, 1283, 1283, 1404,
+ /* 520 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 530 */ 1283, 1283, 1283, 1331, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 540 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 550 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1431, 1283, 1283,
+ /* 560 */ 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 570 */ 1283, 1283, 1626, 1421, 1283, 1283, 1283, 1283, 1675, 1283,
+ /* 580 */ 1283, 1283, 1283, 1381, 1283, 1283, 1283, 1283, 1283, 1283,
+ /* 590 */ 1283, 1283, 1283, 1283, 1667, 1375, 1467, 1283, 1470, 1305,
+ /* 600 */ 1283, 1295, 1283, 1283,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -179380,34 +182703,33 @@ static const char *const yyTokenName[] = {
/* 292 */ "foreach_clause",
/* 293 */ "when_clause",
/* 294 */ "trigger_cmd",
- /* 295 */ "trnm",
- /* 296 */ "tridxby",
- /* 297 */ "database_kw_opt",
- /* 298 */ "key_opt",
- /* 299 */ "add_column_fullname",
- /* 300 */ "kwcolumn_opt",
- /* 301 */ "create_vtab",
- /* 302 */ "vtabarglist",
- /* 303 */ "vtabarg",
- /* 304 */ "vtabargtoken",
- /* 305 */ "lp",
- /* 306 */ "anylist",
- /* 307 */ "wqitem",
- /* 308 */ "wqas",
- /* 309 */ "withnm",
- /* 310 */ "windowdefn_list",
- /* 311 */ "windowdefn",
- /* 312 */ "window",
- /* 313 */ "frame_opt",
- /* 314 */ "part_opt",
- /* 315 */ "filter_clause",
- /* 316 */ "over_clause",
- /* 317 */ "range_or_rows",
- /* 318 */ "frame_bound",
- /* 319 */ "frame_bound_s",
- /* 320 */ "frame_bound_e",
- /* 321 */ "frame_exclude_opt",
- /* 322 */ "frame_exclude",
+ /* 295 */ "tridxby",
+ /* 296 */ "database_kw_opt",
+ /* 297 */ "key_opt",
+ /* 298 */ "alter_add",
+ /* 299 */ "kwcolumn_opt",
+ /* 300 */ "create_vtab",
+ /* 301 */ "vtabarglist",
+ /* 302 */ "vtabarg",
+ /* 303 */ "vtabargtoken",
+ /* 304 */ "lp",
+ /* 305 */ "anylist",
+ /* 306 */ "wqitem",
+ /* 307 */ "wqas",
+ /* 308 */ "withnm",
+ /* 309 */ "windowdefn_list",
+ /* 310 */ "windowdefn",
+ /* 311 */ "window",
+ /* 312 */ "frame_opt",
+ /* 313 */ "part_opt",
+ /* 314 */ "filter_clause",
+ /* 315 */ "over_clause",
+ /* 316 */ "range_or_rows",
+ /* 317 */ "frame_bound",
+ /* 318 */ "frame_bound_s",
+ /* 319 */ "frame_bound_e",
+ /* 320 */ "frame_exclude_opt",
+ /* 321 */ "frame_exclude",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -179537,8 +182859,8 @@ static const char *const yyRuleName[] = {
/* 119 */ "fullname ::= nm DOT nm",
/* 120 */ "xfullname ::= nm",
/* 121 */ "xfullname ::= nm DOT nm",
- /* 122 */ "xfullname ::= nm DOT nm AS nm",
- /* 123 */ "xfullname ::= nm AS nm",
+ /* 122 */ "xfullname ::= nm AS nm",
+ /* 123 */ "xfullname ::= nm DOT nm AS nm",
/* 124 */ "joinop ::= COMMA|JOIN",
/* 125 */ "joinop ::= JOIN_KW JOIN",
/* 126 */ "joinop ::= JOIN_KW nm JOIN",
@@ -179687,143 +183009,146 @@ static const char *const yyRuleName[] = {
/* 269 */ "when_clause ::= WHEN expr",
/* 270 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
/* 271 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 272 */ "trnm ::= nm DOT nm",
- /* 273 */ "tridxby ::= INDEXED BY nm",
- /* 274 */ "tridxby ::= NOT INDEXED",
- /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
- /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
- /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
- /* 278 */ "trigger_cmd ::= scanpt select scanpt",
- /* 279 */ "expr ::= RAISE LP IGNORE RP",
- /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP",
- /* 281 */ "raisetype ::= ROLLBACK",
- /* 282 */ "raisetype ::= ABORT",
- /* 283 */ "raisetype ::= FAIL",
- /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 286 */ "cmd ::= DETACH database_kw_opt expr",
- /* 287 */ "key_opt ::=",
- /* 288 */ "key_opt ::= KEY expr",
- /* 289 */ "cmd ::= REINDEX",
- /* 290 */ "cmd ::= REINDEX nm dbnm",
- /* 291 */ "cmd ::= ANALYZE",
- /* 292 */ "cmd ::= ANALYZE nm dbnm",
- /* 293 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 294 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 272 */ "tridxby ::= INDEXED BY nm",
+ /* 273 */ "tridxby ::= NOT INDEXED",
+ /* 274 */ "trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt",
+ /* 275 */ "trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt",
+ /* 276 */ "trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt",
+ /* 277 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 278 */ "expr ::= RAISE LP IGNORE RP",
+ /* 279 */ "expr ::= RAISE LP raisetype COMMA expr RP",
+ /* 280 */ "raisetype ::= ROLLBACK",
+ /* 281 */ "raisetype ::= ABORT",
+ /* 282 */ "raisetype ::= FAIL",
+ /* 283 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 284 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 285 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 286 */ "key_opt ::=",
+ /* 287 */ "key_opt ::= KEY expr",
+ /* 288 */ "cmd ::= REINDEX",
+ /* 289 */ "cmd ::= REINDEX nm dbnm",
+ /* 290 */ "cmd ::= ANALYZE",
+ /* 291 */ "cmd ::= ANALYZE nm dbnm",
+ /* 292 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 293 */ "cmd ::= alter_add carglist",
+ /* 294 */ "alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken",
/* 295 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm",
- /* 296 */ "add_column_fullname ::= fullname",
- /* 297 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
- /* 298 */ "cmd ::= create_vtab",
- /* 299 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 300 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 301 */ "vtabarg ::=",
- /* 302 */ "vtabargtoken ::= ANY",
- /* 303 */ "vtabargtoken ::= lp anylist RP",
- /* 304 */ "lp ::= LP",
- /* 305 */ "with ::= WITH wqlist",
- /* 306 */ "with ::= WITH RECURSIVE wqlist",
- /* 307 */ "wqas ::= AS",
- /* 308 */ "wqas ::= AS MATERIALIZED",
- /* 309 */ "wqas ::= AS NOT MATERIALIZED",
- /* 310 */ "wqitem ::= withnm eidlist_opt wqas LP select RP",
- /* 311 */ "withnm ::= nm",
- /* 312 */ "wqlist ::= wqitem",
- /* 313 */ "wqlist ::= wqlist COMMA wqitem",
- /* 314 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
- /* 315 */ "windowdefn ::= nm AS LP window RP",
- /* 316 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
- /* 317 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
- /* 318 */ "window ::= ORDER BY sortlist frame_opt",
- /* 319 */ "window ::= nm ORDER BY sortlist frame_opt",
- /* 320 */ "window ::= nm frame_opt",
- /* 321 */ "frame_opt ::=",
- /* 322 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
- /* 323 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
- /* 324 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
- /* 325 */ "frame_bound_s ::= frame_bound",
- /* 326 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
- /* 327 */ "frame_bound_e ::= frame_bound",
- /* 328 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
- /* 329 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
- /* 330 */ "frame_bound ::= CURRENT ROW",
- /* 331 */ "frame_exclude_opt ::=",
- /* 332 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
- /* 333 */ "frame_exclude ::= NO OTHERS",
- /* 334 */ "frame_exclude ::= CURRENT ROW",
- /* 335 */ "frame_exclude ::= GROUP|TIES",
- /* 336 */ "window_clause ::= WINDOW windowdefn_list",
- /* 337 */ "filter_over ::= filter_clause over_clause",
- /* 338 */ "filter_over ::= over_clause",
- /* 339 */ "filter_over ::= filter_clause",
- /* 340 */ "over_clause ::= OVER LP window RP",
- /* 341 */ "over_clause ::= OVER nm",
- /* 342 */ "filter_clause ::= FILTER LP WHERE expr RP",
- /* 343 */ "term ::= QNUMBER",
- /* 344 */ "input ::= cmdlist",
- /* 345 */ "cmdlist ::= cmdlist ecmd",
- /* 346 */ "cmdlist ::= ecmd",
- /* 347 */ "ecmd ::= SEMI",
- /* 348 */ "ecmd ::= cmdx SEMI",
- /* 349 */ "ecmd ::= explain cmdx SEMI",
- /* 350 */ "trans_opt ::=",
- /* 351 */ "trans_opt ::= TRANSACTION",
- /* 352 */ "trans_opt ::= TRANSACTION nm",
- /* 353 */ "savepoint_opt ::= SAVEPOINT",
- /* 354 */ "savepoint_opt ::=",
- /* 355 */ "cmd ::= create_table create_table_args",
- /* 356 */ "table_option_set ::= table_option",
- /* 357 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 358 */ "columnlist ::= columnname carglist",
- /* 359 */ "nm ::= ID|INDEXED|JOIN_KW",
- /* 360 */ "nm ::= STRING",
- /* 361 */ "typetoken ::= typename",
- /* 362 */ "typename ::= ID|STRING",
- /* 363 */ "signed ::= plus_num",
- /* 364 */ "signed ::= minus_num",
- /* 365 */ "carglist ::= carglist ccons",
- /* 366 */ "carglist ::=",
- /* 367 */ "ccons ::= NULL onconf",
- /* 368 */ "ccons ::= GENERATED ALWAYS AS generated",
- /* 369 */ "ccons ::= AS generated",
- /* 370 */ "conslist_opt ::= COMMA conslist",
- /* 371 */ "conslist ::= conslist tconscomma tcons",
- /* 372 */ "conslist ::= tcons",
- /* 373 */ "tconscomma ::=",
- /* 374 */ "defer_subclause_opt ::= defer_subclause",
- /* 375 */ "resolvetype ::= raisetype",
- /* 376 */ "selectnowith ::= oneselect",
- /* 377 */ "oneselect ::= values",
- /* 378 */ "sclp ::= selcollist COMMA",
- /* 379 */ "as ::= ID|STRING",
- /* 380 */ "indexed_opt ::= indexed_by",
- /* 381 */ "returning ::=",
- /* 382 */ "expr ::= term",
- /* 383 */ "likeop ::= LIKE_KW|MATCH",
- /* 384 */ "case_operand ::= expr",
- /* 385 */ "exprlist ::= nexprlist",
- /* 386 */ "nmnum ::= plus_num",
- /* 387 */ "nmnum ::= nm",
- /* 388 */ "nmnum ::= ON",
- /* 389 */ "nmnum ::= DELETE",
- /* 390 */ "nmnum ::= DEFAULT",
- /* 391 */ "plus_num ::= INTEGER|FLOAT",
- /* 392 */ "foreach_clause ::=",
- /* 393 */ "foreach_clause ::= FOR EACH ROW",
- /* 394 */ "trnm ::= nm",
- /* 395 */ "tridxby ::=",
- /* 396 */ "database_kw_opt ::= DATABASE",
- /* 397 */ "database_kw_opt ::=",
- /* 398 */ "kwcolumn_opt ::=",
- /* 399 */ "kwcolumn_opt ::= COLUMNKW",
- /* 400 */ "vtabarglist ::= vtabarg",
- /* 401 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 402 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 403 */ "anylist ::=",
- /* 404 */ "anylist ::= anylist LP anylist RP",
- /* 405 */ "anylist ::= anylist ANY",
- /* 406 */ "with ::=",
- /* 407 */ "windowdefn_list ::= windowdefn",
- /* 408 */ "window ::= frame_opt",
+ /* 296 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
+ /* 297 */ "cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm",
+ /* 298 */ "cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL",
+ /* 299 */ "cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf",
+ /* 300 */ "cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf",
+ /* 301 */ "cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf",
+ /* 302 */ "cmd ::= create_vtab",
+ /* 303 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 304 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 305 */ "vtabarg ::=",
+ /* 306 */ "vtabargtoken ::= ANY",
+ /* 307 */ "vtabargtoken ::= lp anylist RP",
+ /* 308 */ "lp ::= LP",
+ /* 309 */ "with ::= WITH wqlist",
+ /* 310 */ "with ::= WITH RECURSIVE wqlist",
+ /* 311 */ "wqas ::= AS",
+ /* 312 */ "wqas ::= AS MATERIALIZED",
+ /* 313 */ "wqas ::= AS NOT MATERIALIZED",
+ /* 314 */ "wqitem ::= withnm eidlist_opt wqas LP select RP",
+ /* 315 */ "withnm ::= nm",
+ /* 316 */ "wqlist ::= wqitem",
+ /* 317 */ "wqlist ::= wqlist COMMA wqitem",
+ /* 318 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
+ /* 319 */ "windowdefn ::= nm AS LP window RP",
+ /* 320 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 321 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 322 */ "window ::= ORDER BY sortlist frame_opt",
+ /* 323 */ "window ::= nm ORDER BY sortlist frame_opt",
+ /* 324 */ "window ::= nm frame_opt",
+ /* 325 */ "frame_opt ::=",
+ /* 326 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
+ /* 327 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
+ /* 328 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
+ /* 329 */ "frame_bound_s ::= frame_bound",
+ /* 330 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
+ /* 331 */ "frame_bound_e ::= frame_bound",
+ /* 332 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
+ /* 333 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
+ /* 334 */ "frame_bound ::= CURRENT ROW",
+ /* 335 */ "frame_exclude_opt ::=",
+ /* 336 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
+ /* 337 */ "frame_exclude ::= NO OTHERS",
+ /* 338 */ "frame_exclude ::= CURRENT ROW",
+ /* 339 */ "frame_exclude ::= GROUP|TIES",
+ /* 340 */ "window_clause ::= WINDOW windowdefn_list",
+ /* 341 */ "filter_over ::= filter_clause over_clause",
+ /* 342 */ "filter_over ::= over_clause",
+ /* 343 */ "filter_over ::= filter_clause",
+ /* 344 */ "over_clause ::= OVER LP window RP",
+ /* 345 */ "over_clause ::= OVER nm",
+ /* 346 */ "filter_clause ::= FILTER LP WHERE expr RP",
+ /* 347 */ "term ::= QNUMBER",
+ /* 348 */ "input ::= cmdlist",
+ /* 349 */ "cmdlist ::= cmdlist ecmd",
+ /* 350 */ "cmdlist ::= ecmd",
+ /* 351 */ "ecmd ::= SEMI",
+ /* 352 */ "ecmd ::= cmdx SEMI",
+ /* 353 */ "ecmd ::= explain cmdx SEMI",
+ /* 354 */ "trans_opt ::=",
+ /* 355 */ "trans_opt ::= TRANSACTION",
+ /* 356 */ "trans_opt ::= TRANSACTION nm",
+ /* 357 */ "savepoint_opt ::= SAVEPOINT",
+ /* 358 */ "savepoint_opt ::=",
+ /* 359 */ "cmd ::= create_table create_table_args",
+ /* 360 */ "table_option_set ::= table_option",
+ /* 361 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 362 */ "columnlist ::= columnname carglist",
+ /* 363 */ "nm ::= ID|INDEXED|JOIN_KW",
+ /* 364 */ "nm ::= STRING",
+ /* 365 */ "typetoken ::= typename",
+ /* 366 */ "typename ::= ID|STRING",
+ /* 367 */ "signed ::= plus_num",
+ /* 368 */ "signed ::= minus_num",
+ /* 369 */ "carglist ::= carglist ccons",
+ /* 370 */ "carglist ::=",
+ /* 371 */ "ccons ::= NULL onconf",
+ /* 372 */ "ccons ::= GENERATED ALWAYS AS generated",
+ /* 373 */ "ccons ::= AS generated",
+ /* 374 */ "conslist_opt ::= COMMA conslist",
+ /* 375 */ "conslist ::= conslist tconscomma tcons",
+ /* 376 */ "conslist ::= tcons",
+ /* 377 */ "tconscomma ::=",
+ /* 378 */ "defer_subclause_opt ::= defer_subclause",
+ /* 379 */ "resolvetype ::= raisetype",
+ /* 380 */ "selectnowith ::= oneselect",
+ /* 381 */ "oneselect ::= values",
+ /* 382 */ "sclp ::= selcollist COMMA",
+ /* 383 */ "as ::= ID|STRING",
+ /* 384 */ "indexed_opt ::= indexed_by",
+ /* 385 */ "returning ::=",
+ /* 386 */ "expr ::= term",
+ /* 387 */ "likeop ::= LIKE_KW|MATCH",
+ /* 388 */ "case_operand ::= expr",
+ /* 389 */ "exprlist ::= nexprlist",
+ /* 390 */ "nmnum ::= plus_num",
+ /* 391 */ "nmnum ::= nm",
+ /* 392 */ "nmnum ::= ON",
+ /* 393 */ "nmnum ::= DELETE",
+ /* 394 */ "nmnum ::= DEFAULT",
+ /* 395 */ "plus_num ::= INTEGER|FLOAT",
+ /* 396 */ "foreach_clause ::=",
+ /* 397 */ "foreach_clause ::= FOR EACH ROW",
+ /* 398 */ "tridxby ::=",
+ /* 399 */ "database_kw_opt ::= DATABASE",
+ /* 400 */ "database_kw_opt ::=",
+ /* 401 */ "kwcolumn_opt ::=",
+ /* 402 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 403 */ "vtabarglist ::= vtabarg",
+ /* 404 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 405 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 406 */ "anylist ::=",
+ /* 407 */ "anylist ::= anylist LP anylist RP",
+ /* 408 */ "anylist ::= anylist ANY",
+ /* 409 */ "with ::=",
+ /* 410 */ "windowdefn_list ::= windowdefn",
+ /* 411 */ "window ::= frame_opt",
};
#endif /* NDEBUG */
@@ -179838,15 +183163,24 @@ static int yyGrowStack(yyParser *p){
int newSize;
int idx;
yyStackEntry *pNew;
+#ifdef YYSIZELIMIT
+ int nLimit = YYSIZELIMIT(sqlite3ParserCTX(p));
+#endif
newSize = oldSize*2 + 100;
+#ifdef YYSIZELIMIT
+ if( newSize>nLimit ){
+ newSize = nLimit;
+ if( newSize<=oldSize ) return 1;
+ }
+#endif
idx = (int)(p->yytos - p->yystack);
if( p->yystack==p->yystk0 ){
- pNew = YYREALLOC(0, newSize*sizeof(pNew[0]));
+ pNew = YYREALLOC(0, newSize*sizeof(pNew[0]), sqlite3ParserCTX(p));
if( pNew==0 ) return 1;
memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0]));
}else{
- pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]));
+ pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]), sqlite3ParserCTX(p));
if( pNew==0 ) return 1;
}
p->yystack = pNew;
@@ -179953,7 +183287,7 @@ static void yy_destructor(
case 254: /* values */
case 256: /* mvalues */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy637));
+sqlite3SelectDelete(pParse->db, (yypminor->yy555));
}
break;
case 218: /* term */
@@ -179965,10 +183299,10 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy637));
case 283: /* case_else */
case 286: /* vinto */
case 293: /* when_clause */
- case 298: /* key_opt */
- case 315: /* filter_clause */
+ case 297: /* key_opt */
+ case 314: /* filter_clause */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy590));
+sqlite3ExprDelete(pParse->db, (yypminor->yy454));
}
break;
case 223: /* eidlist_opt */
@@ -179983,9 +183317,9 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy590));
case 271: /* setlist */
case 280: /* paren_exprlist */
case 282: /* case_exprlist */
- case 314: /* part_opt */
+ case 313: /* part_opt */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy402));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy14));
}
break;
case 240: /* fullname */
@@ -179994,51 +183328,51 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy402));
case 260: /* stl_prefix */
case 265: /* xfullname */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy563));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy203));
}
break;
case 243: /* wqlist */
{
-sqlite3WithDelete(pParse->db, (yypminor->yy125));
+sqlite3WithDelete(pParse->db, (yypminor->yy59));
}
break;
case 253: /* window_clause */
- case 310: /* windowdefn_list */
+ case 309: /* windowdefn_list */
{
-sqlite3WindowListDelete(pParse->db, (yypminor->yy483));
+sqlite3WindowListDelete(pParse->db, (yypminor->yy211));
}
break;
case 266: /* idlist */
case 273: /* idlist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy204));
+sqlite3IdListDelete(pParse->db, (yypminor->yy132));
}
break;
case 276: /* filter_over */
- case 311: /* windowdefn */
- case 312: /* window */
- case 313: /* frame_opt */
- case 316: /* over_clause */
+ case 310: /* windowdefn */
+ case 311: /* window */
+ case 312: /* frame_opt */
+ case 315: /* over_clause */
{
-sqlite3WindowDelete(pParse->db, (yypminor->yy483));
+sqlite3WindowDelete(pParse->db, (yypminor->yy211));
}
break;
case 289: /* trigger_cmd_list */
case 294: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy319));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427));
}
break;
case 291: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy28).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy286).b);
}
break;
- case 318: /* frame_bound */
- case 319: /* frame_bound_s */
- case 320: /* frame_bound_e */
+ case 317: /* frame_bound */
+ case 318: /* frame_bound_s */
+ case 319: /* frame_bound_e */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy205).pExpr);
+sqlite3ExprDelete(pParse->db, (yypminor->yy509).pExpr);
}
break;
/********* End destructor definitions *****************************************/
@@ -180091,7 +183425,9 @@ SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){
}
#if YYGROWABLESTACK
- if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack);
+ if( pParser->yystack!=pParser->yystk0 ){
+ YYFREE(pParser->yystack, sqlite3ParserCTX(pParser));
+ }
#endif
}
@@ -180274,7 +183610,7 @@ static void yyStackOverflow(yyParser *yypParser){
** stack every overflows */
/******** Begin %stack_overflow code ******************************************/
- sqlite3OomFault(pParse->db);
+ if( pParse->nErr==0 ) sqlite3ErrorMsg(pParse, "Recursion limit");
/******** End %stack_overflow code ********************************************/
sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */
sqlite3ParserCTX_STORE
@@ -180462,8 +183798,8 @@ static const YYCODETYPE yyRuleInfoLhs[] = {
240, /* (119) fullname ::= nm DOT nm */
265, /* (120) xfullname ::= nm */
265, /* (121) xfullname ::= nm DOT nm */
- 265, /* (122) xfullname ::= nm DOT nm AS nm */
- 265, /* (123) xfullname ::= nm AS nm */
+ 265, /* (122) xfullname ::= nm AS nm */
+ 265, /* (123) xfullname ::= nm DOT nm AS nm */
261, /* (124) joinop ::= COMMA|JOIN */
261, /* (125) joinop ::= JOIN_KW JOIN */
261, /* (126) joinop ::= JOIN_KW nm JOIN */
@@ -180612,143 +183948,146 @@ static const YYCODETYPE yyRuleInfoLhs[] = {
293, /* (269) when_clause ::= WHEN expr */
289, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
289, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */
- 295, /* (272) trnm ::= nm DOT nm */
- 296, /* (273) tridxby ::= INDEXED BY nm */
- 296, /* (274) tridxby ::= NOT INDEXED */
- 294, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
- 294, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- 294, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- 294, /* (278) trigger_cmd ::= scanpt select scanpt */
- 219, /* (279) expr ::= RAISE LP IGNORE RP */
- 219, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
- 238, /* (281) raisetype ::= ROLLBACK */
- 238, /* (282) raisetype ::= ABORT */
- 238, /* (283) raisetype ::= FAIL */
- 192, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
- 192, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- 192, /* (286) cmd ::= DETACH database_kw_opt expr */
- 298, /* (287) key_opt ::= */
- 298, /* (288) key_opt ::= KEY expr */
- 192, /* (289) cmd ::= REINDEX */
- 192, /* (290) cmd ::= REINDEX nm dbnm */
- 192, /* (291) cmd ::= ANALYZE */
- 192, /* (292) cmd ::= ANALYZE nm dbnm */
- 192, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */
- 192, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ 295, /* (272) tridxby ::= INDEXED BY nm */
+ 295, /* (273) tridxby ::= NOT INDEXED */
+ 294, /* (274) trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */
+ 294, /* (275) trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */
+ 294, /* (276) trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */
+ 294, /* (277) trigger_cmd ::= scanpt select scanpt */
+ 219, /* (278) expr ::= RAISE LP IGNORE RP */
+ 219, /* (279) expr ::= RAISE LP raisetype COMMA expr RP */
+ 238, /* (280) raisetype ::= ROLLBACK */
+ 238, /* (281) raisetype ::= ABORT */
+ 238, /* (282) raisetype ::= FAIL */
+ 192, /* (283) cmd ::= DROP TRIGGER ifexists fullname */
+ 192, /* (284) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ 192, /* (285) cmd ::= DETACH database_kw_opt expr */
+ 297, /* (286) key_opt ::= */
+ 297, /* (287) key_opt ::= KEY expr */
+ 192, /* (288) cmd ::= REINDEX */
+ 192, /* (289) cmd ::= REINDEX nm dbnm */
+ 192, /* (290) cmd ::= ANALYZE */
+ 192, /* (291) cmd ::= ANALYZE nm dbnm */
+ 192, /* (292) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ 192, /* (293) cmd ::= alter_add carglist */
+ 298, /* (294) alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */
192, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
- 299, /* (296) add_column_fullname ::= fullname */
- 192, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- 192, /* (298) cmd ::= create_vtab */
- 192, /* (299) cmd ::= create_vtab LP vtabarglist RP */
- 301, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 303, /* (301) vtabarg ::= */
- 304, /* (302) vtabargtoken ::= ANY */
- 304, /* (303) vtabargtoken ::= lp anylist RP */
- 305, /* (304) lp ::= LP */
- 269, /* (305) with ::= WITH wqlist */
- 269, /* (306) with ::= WITH RECURSIVE wqlist */
- 308, /* (307) wqas ::= AS */
- 308, /* (308) wqas ::= AS MATERIALIZED */
- 308, /* (309) wqas ::= AS NOT MATERIALIZED */
- 307, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */
- 309, /* (311) withnm ::= nm */
- 243, /* (312) wqlist ::= wqitem */
- 243, /* (313) wqlist ::= wqlist COMMA wqitem */
- 310, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */
- 311, /* (315) windowdefn ::= nm AS LP window RP */
- 312, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
- 312, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
- 312, /* (318) window ::= ORDER BY sortlist frame_opt */
- 312, /* (319) window ::= nm ORDER BY sortlist frame_opt */
- 312, /* (320) window ::= nm frame_opt */
- 313, /* (321) frame_opt ::= */
- 313, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
- 313, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
- 317, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */
- 319, /* (325) frame_bound_s ::= frame_bound */
- 319, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */
- 320, /* (327) frame_bound_e ::= frame_bound */
- 320, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */
- 318, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */
- 318, /* (330) frame_bound ::= CURRENT ROW */
- 321, /* (331) frame_exclude_opt ::= */
- 321, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */
- 322, /* (333) frame_exclude ::= NO OTHERS */
- 322, /* (334) frame_exclude ::= CURRENT ROW */
- 322, /* (335) frame_exclude ::= GROUP|TIES */
- 253, /* (336) window_clause ::= WINDOW windowdefn_list */
- 276, /* (337) filter_over ::= filter_clause over_clause */
- 276, /* (338) filter_over ::= over_clause */
- 276, /* (339) filter_over ::= filter_clause */
- 316, /* (340) over_clause ::= OVER LP window RP */
- 316, /* (341) over_clause ::= OVER nm */
- 315, /* (342) filter_clause ::= FILTER LP WHERE expr RP */
- 218, /* (343) term ::= QNUMBER */
- 187, /* (344) input ::= cmdlist */
- 188, /* (345) cmdlist ::= cmdlist ecmd */
- 188, /* (346) cmdlist ::= ecmd */
- 189, /* (347) ecmd ::= SEMI */
- 189, /* (348) ecmd ::= cmdx SEMI */
- 189, /* (349) ecmd ::= explain cmdx SEMI */
- 194, /* (350) trans_opt ::= */
- 194, /* (351) trans_opt ::= TRANSACTION */
- 194, /* (352) trans_opt ::= TRANSACTION nm */
- 196, /* (353) savepoint_opt ::= SAVEPOINT */
- 196, /* (354) savepoint_opt ::= */
- 192, /* (355) cmd ::= create_table create_table_args */
- 205, /* (356) table_option_set ::= table_option */
- 203, /* (357) columnlist ::= columnlist COMMA columnname carglist */
- 203, /* (358) columnlist ::= columnname carglist */
- 195, /* (359) nm ::= ID|INDEXED|JOIN_KW */
- 195, /* (360) nm ::= STRING */
- 210, /* (361) typetoken ::= typename */
- 211, /* (362) typename ::= ID|STRING */
- 212, /* (363) signed ::= plus_num */
- 212, /* (364) signed ::= minus_num */
- 209, /* (365) carglist ::= carglist ccons */
- 209, /* (366) carglist ::= */
- 217, /* (367) ccons ::= NULL onconf */
- 217, /* (368) ccons ::= GENERATED ALWAYS AS generated */
- 217, /* (369) ccons ::= AS generated */
- 204, /* (370) conslist_opt ::= COMMA conslist */
- 230, /* (371) conslist ::= conslist tconscomma tcons */
- 230, /* (372) conslist ::= tcons */
- 231, /* (373) tconscomma ::= */
- 235, /* (374) defer_subclause_opt ::= defer_subclause */
- 237, /* (375) resolvetype ::= raisetype */
- 241, /* (376) selectnowith ::= oneselect */
- 242, /* (377) oneselect ::= values */
- 257, /* (378) sclp ::= selcollist COMMA */
- 258, /* (379) as ::= ID|STRING */
- 267, /* (380) indexed_opt ::= indexed_by */
- 275, /* (381) returning ::= */
- 219, /* (382) expr ::= term */
- 277, /* (383) likeop ::= LIKE_KW|MATCH */
- 281, /* (384) case_operand ::= expr */
- 264, /* (385) exprlist ::= nexprlist */
- 287, /* (386) nmnum ::= plus_num */
- 287, /* (387) nmnum ::= nm */
- 287, /* (388) nmnum ::= ON */
- 287, /* (389) nmnum ::= DELETE */
- 287, /* (390) nmnum ::= DEFAULT */
- 213, /* (391) plus_num ::= INTEGER|FLOAT */
- 292, /* (392) foreach_clause ::= */
- 292, /* (393) foreach_clause ::= FOR EACH ROW */
- 295, /* (394) trnm ::= nm */
- 296, /* (395) tridxby ::= */
- 297, /* (396) database_kw_opt ::= DATABASE */
- 297, /* (397) database_kw_opt ::= */
- 300, /* (398) kwcolumn_opt ::= */
- 300, /* (399) kwcolumn_opt ::= COLUMNKW */
- 302, /* (400) vtabarglist ::= vtabarg */
- 302, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */
- 303, /* (402) vtabarg ::= vtabarg vtabargtoken */
- 306, /* (403) anylist ::= */
- 306, /* (404) anylist ::= anylist LP anylist RP */
- 306, /* (405) anylist ::= anylist ANY */
- 269, /* (406) with ::= */
- 310, /* (407) windowdefn_list ::= windowdefn */
- 312, /* (408) window ::= frame_opt */
+ 192, /* (296) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ 192, /* (297) cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */
+ 192, /* (298) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */
+ 192, /* (299) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */
+ 192, /* (300) cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */
+ 192, /* (301) cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */
+ 192, /* (302) cmd ::= create_vtab */
+ 192, /* (303) cmd ::= create_vtab LP vtabarglist RP */
+ 300, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 302, /* (305) vtabarg ::= */
+ 303, /* (306) vtabargtoken ::= ANY */
+ 303, /* (307) vtabargtoken ::= lp anylist RP */
+ 304, /* (308) lp ::= LP */
+ 269, /* (309) with ::= WITH wqlist */
+ 269, /* (310) with ::= WITH RECURSIVE wqlist */
+ 307, /* (311) wqas ::= AS */
+ 307, /* (312) wqas ::= AS MATERIALIZED */
+ 307, /* (313) wqas ::= AS NOT MATERIALIZED */
+ 306, /* (314) wqitem ::= withnm eidlist_opt wqas LP select RP */
+ 308, /* (315) withnm ::= nm */
+ 243, /* (316) wqlist ::= wqitem */
+ 243, /* (317) wqlist ::= wqlist COMMA wqitem */
+ 309, /* (318) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ 310, /* (319) windowdefn ::= nm AS LP window RP */
+ 311, /* (320) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ 311, /* (321) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ 311, /* (322) window ::= ORDER BY sortlist frame_opt */
+ 311, /* (323) window ::= nm ORDER BY sortlist frame_opt */
+ 311, /* (324) window ::= nm frame_opt */
+ 312, /* (325) frame_opt ::= */
+ 312, /* (326) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ 312, /* (327) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ 316, /* (328) range_or_rows ::= RANGE|ROWS|GROUPS */
+ 318, /* (329) frame_bound_s ::= frame_bound */
+ 318, /* (330) frame_bound_s ::= UNBOUNDED PRECEDING */
+ 319, /* (331) frame_bound_e ::= frame_bound */
+ 319, /* (332) frame_bound_e ::= UNBOUNDED FOLLOWING */
+ 317, /* (333) frame_bound ::= expr PRECEDING|FOLLOWING */
+ 317, /* (334) frame_bound ::= CURRENT ROW */
+ 320, /* (335) frame_exclude_opt ::= */
+ 320, /* (336) frame_exclude_opt ::= EXCLUDE frame_exclude */
+ 321, /* (337) frame_exclude ::= NO OTHERS */
+ 321, /* (338) frame_exclude ::= CURRENT ROW */
+ 321, /* (339) frame_exclude ::= GROUP|TIES */
+ 253, /* (340) window_clause ::= WINDOW windowdefn_list */
+ 276, /* (341) filter_over ::= filter_clause over_clause */
+ 276, /* (342) filter_over ::= over_clause */
+ 276, /* (343) filter_over ::= filter_clause */
+ 315, /* (344) over_clause ::= OVER LP window RP */
+ 315, /* (345) over_clause ::= OVER nm */
+ 314, /* (346) filter_clause ::= FILTER LP WHERE expr RP */
+ 218, /* (347) term ::= QNUMBER */
+ 187, /* (348) input ::= cmdlist */
+ 188, /* (349) cmdlist ::= cmdlist ecmd */
+ 188, /* (350) cmdlist ::= ecmd */
+ 189, /* (351) ecmd ::= SEMI */
+ 189, /* (352) ecmd ::= cmdx SEMI */
+ 189, /* (353) ecmd ::= explain cmdx SEMI */
+ 194, /* (354) trans_opt ::= */
+ 194, /* (355) trans_opt ::= TRANSACTION */
+ 194, /* (356) trans_opt ::= TRANSACTION nm */
+ 196, /* (357) savepoint_opt ::= SAVEPOINT */
+ 196, /* (358) savepoint_opt ::= */
+ 192, /* (359) cmd ::= create_table create_table_args */
+ 205, /* (360) table_option_set ::= table_option */
+ 203, /* (361) columnlist ::= columnlist COMMA columnname carglist */
+ 203, /* (362) columnlist ::= columnname carglist */
+ 195, /* (363) nm ::= ID|INDEXED|JOIN_KW */
+ 195, /* (364) nm ::= STRING */
+ 210, /* (365) typetoken ::= typename */
+ 211, /* (366) typename ::= ID|STRING */
+ 212, /* (367) signed ::= plus_num */
+ 212, /* (368) signed ::= minus_num */
+ 209, /* (369) carglist ::= carglist ccons */
+ 209, /* (370) carglist ::= */
+ 217, /* (371) ccons ::= NULL onconf */
+ 217, /* (372) ccons ::= GENERATED ALWAYS AS generated */
+ 217, /* (373) ccons ::= AS generated */
+ 204, /* (374) conslist_opt ::= COMMA conslist */
+ 230, /* (375) conslist ::= conslist tconscomma tcons */
+ 230, /* (376) conslist ::= tcons */
+ 231, /* (377) tconscomma ::= */
+ 235, /* (378) defer_subclause_opt ::= defer_subclause */
+ 237, /* (379) resolvetype ::= raisetype */
+ 241, /* (380) selectnowith ::= oneselect */
+ 242, /* (381) oneselect ::= values */
+ 257, /* (382) sclp ::= selcollist COMMA */
+ 258, /* (383) as ::= ID|STRING */
+ 267, /* (384) indexed_opt ::= indexed_by */
+ 275, /* (385) returning ::= */
+ 219, /* (386) expr ::= term */
+ 277, /* (387) likeop ::= LIKE_KW|MATCH */
+ 281, /* (388) case_operand ::= expr */
+ 264, /* (389) exprlist ::= nexprlist */
+ 287, /* (390) nmnum ::= plus_num */
+ 287, /* (391) nmnum ::= nm */
+ 287, /* (392) nmnum ::= ON */
+ 287, /* (393) nmnum ::= DELETE */
+ 287, /* (394) nmnum ::= DEFAULT */
+ 213, /* (395) plus_num ::= INTEGER|FLOAT */
+ 292, /* (396) foreach_clause ::= */
+ 292, /* (397) foreach_clause ::= FOR EACH ROW */
+ 295, /* (398) tridxby ::= */
+ 296, /* (399) database_kw_opt ::= DATABASE */
+ 296, /* (400) database_kw_opt ::= */
+ 299, /* (401) kwcolumn_opt ::= */
+ 299, /* (402) kwcolumn_opt ::= COLUMNKW */
+ 301, /* (403) vtabarglist ::= vtabarg */
+ 301, /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */
+ 302, /* (405) vtabarg ::= vtabarg vtabargtoken */
+ 305, /* (406) anylist ::= */
+ 305, /* (407) anylist ::= anylist LP anylist RP */
+ 305, /* (408) anylist ::= anylist ANY */
+ 269, /* (409) with ::= */
+ 309, /* (410) windowdefn_list ::= windowdefn */
+ 311, /* (411) window ::= frame_opt */
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
@@ -180876,8 +184215,8 @@ static const signed char yyRuleInfoNRhs[] = {
-3, /* (119) fullname ::= nm DOT nm */
-1, /* (120) xfullname ::= nm */
-3, /* (121) xfullname ::= nm DOT nm */
- -5, /* (122) xfullname ::= nm DOT nm AS nm */
- -3, /* (123) xfullname ::= nm AS nm */
+ -3, /* (122) xfullname ::= nm AS nm */
+ -5, /* (123) xfullname ::= nm DOT nm AS nm */
-1, /* (124) joinop ::= COMMA|JOIN */
-2, /* (125) joinop ::= JOIN_KW JOIN */
-3, /* (126) joinop ::= JOIN_KW nm JOIN */
@@ -181026,143 +184365,146 @@ static const signed char yyRuleInfoNRhs[] = {
-2, /* (269) when_clause ::= WHEN expr */
-3, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
-2, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */
- -3, /* (272) trnm ::= nm DOT nm */
- -3, /* (273) tridxby ::= INDEXED BY nm */
- -2, /* (274) tridxby ::= NOT INDEXED */
- -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
- -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- -6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- -3, /* (278) trigger_cmd ::= scanpt select scanpt */
- -4, /* (279) expr ::= RAISE LP IGNORE RP */
- -6, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
- -1, /* (281) raisetype ::= ROLLBACK */
- -1, /* (282) raisetype ::= ABORT */
- -1, /* (283) raisetype ::= FAIL */
- -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
- -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- -3, /* (286) cmd ::= DETACH database_kw_opt expr */
- 0, /* (287) key_opt ::= */
- -2, /* (288) key_opt ::= KEY expr */
- -1, /* (289) cmd ::= REINDEX */
- -3, /* (290) cmd ::= REINDEX nm dbnm */
- -1, /* (291) cmd ::= ANALYZE */
- -3, /* (292) cmd ::= ANALYZE nm dbnm */
- -6, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */
- -7, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ -3, /* (272) tridxby ::= INDEXED BY nm */
+ -2, /* (273) tridxby ::= NOT INDEXED */
+ -9, /* (274) trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */
+ -8, /* (275) trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */
+ -6, /* (276) trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */
+ -3, /* (277) trigger_cmd ::= scanpt select scanpt */
+ -4, /* (278) expr ::= RAISE LP IGNORE RP */
+ -6, /* (279) expr ::= RAISE LP raisetype COMMA expr RP */
+ -1, /* (280) raisetype ::= ROLLBACK */
+ -1, /* (281) raisetype ::= ABORT */
+ -1, /* (282) raisetype ::= FAIL */
+ -4, /* (283) cmd ::= DROP TRIGGER ifexists fullname */
+ -6, /* (284) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ -3, /* (285) cmd ::= DETACH database_kw_opt expr */
+ 0, /* (286) key_opt ::= */
+ -2, /* (287) key_opt ::= KEY expr */
+ -1, /* (288) cmd ::= REINDEX */
+ -3, /* (289) cmd ::= REINDEX nm dbnm */
+ -1, /* (290) cmd ::= ANALYZE */
+ -3, /* (291) cmd ::= ANALYZE nm dbnm */
+ -6, /* (292) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ -2, /* (293) cmd ::= alter_add carglist */
+ -7, /* (294) alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */
-6, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
- -1, /* (296) add_column_fullname ::= fullname */
- -8, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- -1, /* (298) cmd ::= create_vtab */
- -4, /* (299) cmd ::= create_vtab LP vtabarglist RP */
- -8, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 0, /* (301) vtabarg ::= */
- -1, /* (302) vtabargtoken ::= ANY */
- -3, /* (303) vtabargtoken ::= lp anylist RP */
- -1, /* (304) lp ::= LP */
- -2, /* (305) with ::= WITH wqlist */
- -3, /* (306) with ::= WITH RECURSIVE wqlist */
- -1, /* (307) wqas ::= AS */
- -2, /* (308) wqas ::= AS MATERIALIZED */
- -3, /* (309) wqas ::= AS NOT MATERIALIZED */
- -6, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */
- -1, /* (311) withnm ::= nm */
- -1, /* (312) wqlist ::= wqitem */
- -3, /* (313) wqlist ::= wqlist COMMA wqitem */
- -3, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */
- -5, /* (315) windowdefn ::= nm AS LP window RP */
- -5, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
- -6, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
- -4, /* (318) window ::= ORDER BY sortlist frame_opt */
- -5, /* (319) window ::= nm ORDER BY sortlist frame_opt */
- -2, /* (320) window ::= nm frame_opt */
- 0, /* (321) frame_opt ::= */
- -3, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
- -6, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
- -1, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */
- -1, /* (325) frame_bound_s ::= frame_bound */
- -2, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */
- -1, /* (327) frame_bound_e ::= frame_bound */
- -2, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */
- -2, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */
- -2, /* (330) frame_bound ::= CURRENT ROW */
- 0, /* (331) frame_exclude_opt ::= */
- -2, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */
- -2, /* (333) frame_exclude ::= NO OTHERS */
- -2, /* (334) frame_exclude ::= CURRENT ROW */
- -1, /* (335) frame_exclude ::= GROUP|TIES */
- -2, /* (336) window_clause ::= WINDOW windowdefn_list */
- -2, /* (337) filter_over ::= filter_clause over_clause */
- -1, /* (338) filter_over ::= over_clause */
- -1, /* (339) filter_over ::= filter_clause */
- -4, /* (340) over_clause ::= OVER LP window RP */
- -2, /* (341) over_clause ::= OVER nm */
- -5, /* (342) filter_clause ::= FILTER LP WHERE expr RP */
- -1, /* (343) term ::= QNUMBER */
- -1, /* (344) input ::= cmdlist */
- -2, /* (345) cmdlist ::= cmdlist ecmd */
- -1, /* (346) cmdlist ::= ecmd */
- -1, /* (347) ecmd ::= SEMI */
- -2, /* (348) ecmd ::= cmdx SEMI */
- -3, /* (349) ecmd ::= explain cmdx SEMI */
- 0, /* (350) trans_opt ::= */
- -1, /* (351) trans_opt ::= TRANSACTION */
- -2, /* (352) trans_opt ::= TRANSACTION nm */
- -1, /* (353) savepoint_opt ::= SAVEPOINT */
- 0, /* (354) savepoint_opt ::= */
- -2, /* (355) cmd ::= create_table create_table_args */
- -1, /* (356) table_option_set ::= table_option */
- -4, /* (357) columnlist ::= columnlist COMMA columnname carglist */
- -2, /* (358) columnlist ::= columnname carglist */
- -1, /* (359) nm ::= ID|INDEXED|JOIN_KW */
- -1, /* (360) nm ::= STRING */
- -1, /* (361) typetoken ::= typename */
- -1, /* (362) typename ::= ID|STRING */
- -1, /* (363) signed ::= plus_num */
- -1, /* (364) signed ::= minus_num */
- -2, /* (365) carglist ::= carglist ccons */
- 0, /* (366) carglist ::= */
- -2, /* (367) ccons ::= NULL onconf */
- -4, /* (368) ccons ::= GENERATED ALWAYS AS generated */
- -2, /* (369) ccons ::= AS generated */
- -2, /* (370) conslist_opt ::= COMMA conslist */
- -3, /* (371) conslist ::= conslist tconscomma tcons */
- -1, /* (372) conslist ::= tcons */
- 0, /* (373) tconscomma ::= */
- -1, /* (374) defer_subclause_opt ::= defer_subclause */
- -1, /* (375) resolvetype ::= raisetype */
- -1, /* (376) selectnowith ::= oneselect */
- -1, /* (377) oneselect ::= values */
- -2, /* (378) sclp ::= selcollist COMMA */
- -1, /* (379) as ::= ID|STRING */
- -1, /* (380) indexed_opt ::= indexed_by */
- 0, /* (381) returning ::= */
- -1, /* (382) expr ::= term */
- -1, /* (383) likeop ::= LIKE_KW|MATCH */
- -1, /* (384) case_operand ::= expr */
- -1, /* (385) exprlist ::= nexprlist */
- -1, /* (386) nmnum ::= plus_num */
- -1, /* (387) nmnum ::= nm */
- -1, /* (388) nmnum ::= ON */
- -1, /* (389) nmnum ::= DELETE */
- -1, /* (390) nmnum ::= DEFAULT */
- -1, /* (391) plus_num ::= INTEGER|FLOAT */
- 0, /* (392) foreach_clause ::= */
- -3, /* (393) foreach_clause ::= FOR EACH ROW */
- -1, /* (394) trnm ::= nm */
- 0, /* (395) tridxby ::= */
- -1, /* (396) database_kw_opt ::= DATABASE */
- 0, /* (397) database_kw_opt ::= */
- 0, /* (398) kwcolumn_opt ::= */
- -1, /* (399) kwcolumn_opt ::= COLUMNKW */
- -1, /* (400) vtabarglist ::= vtabarg */
- -3, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */
- -2, /* (402) vtabarg ::= vtabarg vtabargtoken */
- 0, /* (403) anylist ::= */
- -4, /* (404) anylist ::= anylist LP anylist RP */
- -2, /* (405) anylist ::= anylist ANY */
- 0, /* (406) with ::= */
- -1, /* (407) windowdefn_list ::= windowdefn */
- -1, /* (408) window ::= frame_opt */
+ -8, /* (296) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ -6, /* (297) cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */
+ -9, /* (298) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */
+ -10, /* (299) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */
+ -11, /* (300) cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */
+ -9, /* (301) cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */
+ -1, /* (302) cmd ::= create_vtab */
+ -4, /* (303) cmd ::= create_vtab LP vtabarglist RP */
+ -8, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 0, /* (305) vtabarg ::= */
+ -1, /* (306) vtabargtoken ::= ANY */
+ -3, /* (307) vtabargtoken ::= lp anylist RP */
+ -1, /* (308) lp ::= LP */
+ -2, /* (309) with ::= WITH wqlist */
+ -3, /* (310) with ::= WITH RECURSIVE wqlist */
+ -1, /* (311) wqas ::= AS */
+ -2, /* (312) wqas ::= AS MATERIALIZED */
+ -3, /* (313) wqas ::= AS NOT MATERIALIZED */
+ -6, /* (314) wqitem ::= withnm eidlist_opt wqas LP select RP */
+ -1, /* (315) withnm ::= nm */
+ -1, /* (316) wqlist ::= wqitem */
+ -3, /* (317) wqlist ::= wqlist COMMA wqitem */
+ -3, /* (318) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ -5, /* (319) windowdefn ::= nm AS LP window RP */
+ -5, /* (320) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ -6, /* (321) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ -4, /* (322) window ::= ORDER BY sortlist frame_opt */
+ -5, /* (323) window ::= nm ORDER BY sortlist frame_opt */
+ -2, /* (324) window ::= nm frame_opt */
+ 0, /* (325) frame_opt ::= */
+ -3, /* (326) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ -6, /* (327) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ -1, /* (328) range_or_rows ::= RANGE|ROWS|GROUPS */
+ -1, /* (329) frame_bound_s ::= frame_bound */
+ -2, /* (330) frame_bound_s ::= UNBOUNDED PRECEDING */
+ -1, /* (331) frame_bound_e ::= frame_bound */
+ -2, /* (332) frame_bound_e ::= UNBOUNDED FOLLOWING */
+ -2, /* (333) frame_bound ::= expr PRECEDING|FOLLOWING */
+ -2, /* (334) frame_bound ::= CURRENT ROW */
+ 0, /* (335) frame_exclude_opt ::= */
+ -2, /* (336) frame_exclude_opt ::= EXCLUDE frame_exclude */
+ -2, /* (337) frame_exclude ::= NO OTHERS */
+ -2, /* (338) frame_exclude ::= CURRENT ROW */
+ -1, /* (339) frame_exclude ::= GROUP|TIES */
+ -2, /* (340) window_clause ::= WINDOW windowdefn_list */
+ -2, /* (341) filter_over ::= filter_clause over_clause */
+ -1, /* (342) filter_over ::= over_clause */
+ -1, /* (343) filter_over ::= filter_clause */
+ -4, /* (344) over_clause ::= OVER LP window RP */
+ -2, /* (345) over_clause ::= OVER nm */
+ -5, /* (346) filter_clause ::= FILTER LP WHERE expr RP */
+ -1, /* (347) term ::= QNUMBER */
+ -1, /* (348) input ::= cmdlist */
+ -2, /* (349) cmdlist ::= cmdlist ecmd */
+ -1, /* (350) cmdlist ::= ecmd */
+ -1, /* (351) ecmd ::= SEMI */
+ -2, /* (352) ecmd ::= cmdx SEMI */
+ -3, /* (353) ecmd ::= explain cmdx SEMI */
+ 0, /* (354) trans_opt ::= */
+ -1, /* (355) trans_opt ::= TRANSACTION */
+ -2, /* (356) trans_opt ::= TRANSACTION nm */
+ -1, /* (357) savepoint_opt ::= SAVEPOINT */
+ 0, /* (358) savepoint_opt ::= */
+ -2, /* (359) cmd ::= create_table create_table_args */
+ -1, /* (360) table_option_set ::= table_option */
+ -4, /* (361) columnlist ::= columnlist COMMA columnname carglist */
+ -2, /* (362) columnlist ::= columnname carglist */
+ -1, /* (363) nm ::= ID|INDEXED|JOIN_KW */
+ -1, /* (364) nm ::= STRING */
+ -1, /* (365) typetoken ::= typename */
+ -1, /* (366) typename ::= ID|STRING */
+ -1, /* (367) signed ::= plus_num */
+ -1, /* (368) signed ::= minus_num */
+ -2, /* (369) carglist ::= carglist ccons */
+ 0, /* (370) carglist ::= */
+ -2, /* (371) ccons ::= NULL onconf */
+ -4, /* (372) ccons ::= GENERATED ALWAYS AS generated */
+ -2, /* (373) ccons ::= AS generated */
+ -2, /* (374) conslist_opt ::= COMMA conslist */
+ -3, /* (375) conslist ::= conslist tconscomma tcons */
+ -1, /* (376) conslist ::= tcons */
+ 0, /* (377) tconscomma ::= */
+ -1, /* (378) defer_subclause_opt ::= defer_subclause */
+ -1, /* (379) resolvetype ::= raisetype */
+ -1, /* (380) selectnowith ::= oneselect */
+ -1, /* (381) oneselect ::= values */
+ -2, /* (382) sclp ::= selcollist COMMA */
+ -1, /* (383) as ::= ID|STRING */
+ -1, /* (384) indexed_opt ::= indexed_by */
+ 0, /* (385) returning ::= */
+ -1, /* (386) expr ::= term */
+ -1, /* (387) likeop ::= LIKE_KW|MATCH */
+ -1, /* (388) case_operand ::= expr */
+ -1, /* (389) exprlist ::= nexprlist */
+ -1, /* (390) nmnum ::= plus_num */
+ -1, /* (391) nmnum ::= nm */
+ -1, /* (392) nmnum ::= ON */
+ -1, /* (393) nmnum ::= DELETE */
+ -1, /* (394) nmnum ::= DEFAULT */
+ -1, /* (395) plus_num ::= INTEGER|FLOAT */
+ 0, /* (396) foreach_clause ::= */
+ -3, /* (397) foreach_clause ::= FOR EACH ROW */
+ 0, /* (398) tridxby ::= */
+ -1, /* (399) database_kw_opt ::= DATABASE */
+ 0, /* (400) database_kw_opt ::= */
+ 0, /* (401) kwcolumn_opt ::= */
+ -1, /* (402) kwcolumn_opt ::= COLUMNKW */
+ -1, /* (403) vtabarglist ::= vtabarg */
+ -3, /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */
+ -2, /* (405) vtabarg ::= vtabarg vtabargtoken */
+ 0, /* (406) anylist ::= */
+ -4, /* (407) anylist ::= anylist LP anylist RP */
+ -2, /* (408) anylist ::= anylist ANY */
+ 0, /* (409) with ::= */
+ -1, /* (410) windowdefn_list ::= windowdefn */
+ -1, /* (411) window ::= frame_opt */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -181214,16 +184556,16 @@ static YYACTIONTYPE yy_reduce(
{ sqlite3FinishCoding(pParse); }
break;
case 3: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy144);}
break;
case 4: /* transtype ::= */
-{yymsp[1].minor.yy502 = TK_DEFERRED;}
+{yymsp[1].minor.yy144 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
- case 324: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==324);
-{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/}
+ case 328: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==328);
+{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 8: /* cmd ::= COMMIT|END trans_opt */
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
@@ -181246,7 +184588,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy144,0,0,yymsp[-2].minor.yy144);
}
break;
case 14: /* createkw ::= CREATE */
@@ -181262,38 +184604,38 @@ static YYACTIONTYPE yy_reduce(
case 81: /* ifexists ::= */ yytestcase(yyruleno==81);
case 100: /* distinct ::= */ yytestcase(yyruleno==100);
case 246: /* collate ::= */ yytestcase(yyruleno==246);
-{yymsp[1].minor.yy502 = 0;}
+{yymsp[1].minor.yy144 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
-{yymsp[-2].minor.yy502 = 1;}
+{yymsp[-2].minor.yy144 = 1;}
break;
case 17: /* temp ::= TEMP */
-{yymsp[0].minor.yy502 = pParse->db->init.busy==0;}
+{yymsp[0].minor.yy144 = pParse->db->init.busy==0;}
break;
case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */
{
- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy9,0);
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy391,0);
}
break;
case 20: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy637);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637);
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy555);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555);
}
break;
case 21: /* table_option_set ::= */
-{yymsp[1].minor.yy9 = 0;}
+{yymsp[1].minor.yy391 = 0;}
break;
case 22: /* table_option_set ::= table_option_set COMMA table_option */
-{yylhsminor.yy9 = yymsp[-2].minor.yy9|yymsp[0].minor.yy9;}
- yymsp[-2].minor.yy9 = yylhsminor.yy9;
+{yylhsminor.yy391 = yymsp[-2].minor.yy391|yymsp[0].minor.yy391;}
+ yymsp[-2].minor.yy391 = yylhsminor.yy391;
break;
case 23: /* table_option ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
- yymsp[-1].minor.yy9 = TF_WithoutRowid | TF_NoVisibleRowid;
+ yymsp[-1].minor.yy391 = TF_WithoutRowid | TF_NoVisibleRowid;
}else{
- yymsp[-1].minor.yy9 = 0;
+ yymsp[-1].minor.yy391 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
@@ -181301,13 +184643,13 @@ static YYACTIONTYPE yy_reduce(
case 24: /* table_option ::= nm */
{
if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){
- yylhsminor.yy9 = TF_Strict;
+ yylhsminor.yy391 = TF_Strict;
}else{
- yylhsminor.yy9 = 0;
+ yylhsminor.yy391 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
- yymsp[0].minor.yy9 = yylhsminor.yy9;
+ yymsp[0].minor.yy391 = yylhsminor.yy391;
break;
case 25: /* columnname ::= nm typetoken */
{sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);}
@@ -181333,7 +184675,7 @@ static YYACTIONTYPE yy_reduce(
case 30: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
- yymsp[1].minor.yy342 = yyLookaheadToken.z;
+ yymsp[1].minor.yy168 = yyLookaheadToken.z;
}
break;
case 31: /* scantok ::= */
@@ -181347,17 +184689,17 @@ static YYACTIONTYPE yy_reduce(
{ASSERT_IS_CREATE; pParse->u1.cr.constraintName = yymsp[0].minor.yy0;}
break;
case 33: /* ccons ::= DEFAULT scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 34: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
case 35: /* ccons ::= DEFAULT PLUS scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 36: /* ccons ::= DEFAULT MINUS scantok term */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy590, 0);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy454, 0);
sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);
}
break;
@@ -181372,133 +184714,133 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 38: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy144);}
break;
case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy144,yymsp[0].minor.yy144,yymsp[-2].minor.yy144);}
break;
case 40: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy144,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 41: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
break;
case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy402,yymsp[0].minor.yy502);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy144);}
break;
case 43: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy144);}
break;
case 44: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 45: /* generated ::= LP expr RP */
-{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy590,0);}
+{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy454,0);}
break;
case 46: /* generated ::= LP expr RP ID */
-{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy590,&yymsp[0].minor.yy0);}
+{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy454,&yymsp[0].minor.yy0);}
break;
case 48: /* autoinc ::= AUTOINCR */
-{yymsp[0].minor.yy502 = 1;}
+{yymsp[0].minor.yy144 = 1;}
break;
case 49: /* refargs ::= */
-{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */}
+{ yymsp[1].minor.yy144 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
case 50: /* refargs ::= refargs refarg */
-{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy481.mask) | yymsp[0].minor.yy481.value; }
+{ yymsp[-1].minor.yy144 = (yymsp[-1].minor.yy144 & ~yymsp[0].minor.yy383.mask) | yymsp[0].minor.yy383.value; }
break;
case 51: /* refarg ::= MATCH nm */
-{ yymsp[-1].minor.yy481.value = 0; yymsp[-1].minor.yy481.mask = 0x000000; }
+{ yymsp[-1].minor.yy383.value = 0; yymsp[-1].minor.yy383.mask = 0x000000; }
break;
case 52: /* refarg ::= ON INSERT refact */
-{ yymsp[-2].minor.yy481.value = 0; yymsp[-2].minor.yy481.mask = 0x000000; }
+{ yymsp[-2].minor.yy383.value = 0; yymsp[-2].minor.yy383.mask = 0x000000; }
break;
case 53: /* refarg ::= ON DELETE refact */
-{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy481.mask = 0x0000ff; }
+{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144; yymsp[-2].minor.yy383.mask = 0x0000ff; }
break;
case 54: /* refarg ::= ON UPDATE refact */
-{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy481.mask = 0x00ff00; }
+{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144<<8; yymsp[-2].minor.yy383.mask = 0x00ff00; }
break;
case 55: /* refact ::= SET NULL */
-{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy144 = OE_SetNull; /* EV: R-33326-45252 */}
break;
case 56: /* refact ::= SET DEFAULT */
-{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy144 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
case 57: /* refact ::= CASCADE */
-{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy144 = OE_Cascade; /* EV: R-33326-45252 */}
break;
case 58: /* refact ::= RESTRICT */
-{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy144 = OE_Restrict; /* EV: R-33326-45252 */}
break;
case 59: /* refact ::= NO ACTION */
-{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy144 = OE_None; /* EV: R-33326-45252 */}
break;
case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-{yymsp[-2].minor.yy502 = 0;}
+{yymsp[-2].minor.yy144 = 0;}
break;
case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76);
case 173: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==173);
-{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;}
+{yymsp[-1].minor.yy144 = yymsp[0].minor.yy144;}
break;
case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80);
case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219);
case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222);
case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247);
-{yymsp[-1].minor.yy502 = 1;}
+{yymsp[-1].minor.yy144 = 1;}
break;
case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-{yymsp[-1].minor.yy502 = 0;}
+{yymsp[-1].minor.yy144 = 0;}
break;
case 66: /* tconscomma ::= COMMA */
{ASSERT_IS_CREATE; pParse->u1.cr.constraintName.n = 0;}
break;
case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy144,yymsp[-2].minor.yy144,0);}
break;
case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy402,yymsp[0].minor.yy502,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy144,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 70: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy590,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy454,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
break;
case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy402, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy502);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy144);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy144);
}
break;
case 73: /* onconf ::= */
case 75: /* orconf ::= */ yytestcase(yyruleno==75);
-{yymsp[1].minor.yy502 = OE_Default;}
+{yymsp[1].minor.yy144 = OE_Default;}
break;
case 74: /* onconf ::= ON CONFLICT resolvetype */
-{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;}
+{yymsp[-2].minor.yy144 = yymsp[0].minor.yy144;}
break;
case 77: /* resolvetype ::= IGNORE */
-{yymsp[0].minor.yy502 = OE_Ignore;}
+{yymsp[0].minor.yy144 = OE_Ignore;}
break;
case 78: /* resolvetype ::= REPLACE */
case 174: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==174);
-{yymsp[0].minor.yy502 = OE_Replace;}
+{yymsp[0].minor.yy144 = OE_Replace;}
break;
case 79: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy563, 0, yymsp[-1].minor.yy502);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy203, 0, yymsp[-1].minor.yy144);
}
break;
case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[0].minor.yy637, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502);
+ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[0].minor.yy555, yymsp[-7].minor.yy144, yymsp[-5].minor.yy144);
}
break;
case 83: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy563, 1, yymsp[-1].minor.yy502);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy203, 1, yymsp[-1].minor.yy144);
}
break;
case 84: /* cmd ::= select */
@@ -181507,20 +184849,20 @@ static YYACTIONTYPE yy_reduce(
if( (pParse->db->mDbFlags & DBFLAG_EncodingFixed)!=0
|| sqlite3ReadSchema(pParse)==SQLITE_OK
){
- sqlite3Select(pParse, yymsp[0].minor.yy637, &dest);
+ sqlite3Select(pParse, yymsp[0].minor.yy555, &dest);
}
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555);
}
break;
case 85: /* select ::= WITH wqlist selectnowith */
-{yymsp[-2].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);}
+{yymsp[-2].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);}
break;
case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */
-{yymsp[-3].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);}
+{yymsp[-3].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);}
break;
case 87: /* select ::= selectnowith */
{
- Select *p = yymsp[0].minor.yy637;
+ Select *p = yymsp[0].minor.yy555;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
@@ -181528,8 +184870,8 @@ static YYACTIONTYPE yy_reduce(
break;
case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
- Select *pRhs = yymsp[0].minor.yy637;
- Select *pLhs = yymsp[-2].minor.yy637;
+ Select *pRhs = yymsp[0].minor.yy555;
+ Select *pLhs = yymsp[-2].minor.yy555;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
@@ -181539,60 +184881,60 @@ static YYACTIONTYPE yy_reduce(
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
- pRhs->op = (u8)yymsp[-1].minor.yy502;
+ pRhs->op = (u8)yymsp[-1].minor.yy144;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue;
pRhs->selFlags &= ~(u32)SF_MultiValue;
- if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1;
+ if( yymsp[-1].minor.yy144!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
}
- yymsp[-2].minor.yy637 = pRhs;
+ yymsp[-2].minor.yy555 = pRhs;
}
break;
case 89: /* multiselect_op ::= UNION */
case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91);
-{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/}
+{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-OP*/}
break;
case 90: /* multiselect_op ::= UNION ALL */
-{yymsp[-1].minor.yy502 = TK_ALL;}
+{yymsp[-1].minor.yy144 = TK_ALL;}
break;
case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yymsp[-8].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy402,yymsp[-5].minor.yy563,yymsp[-4].minor.yy590,yymsp[-3].minor.yy402,yymsp[-2].minor.yy590,yymsp[-1].minor.yy402,yymsp[-7].minor.yy502,yymsp[0].minor.yy590);
+ yymsp[-8].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy203,yymsp[-4].minor.yy454,yymsp[-3].minor.yy14,yymsp[-2].minor.yy454,yymsp[-1].minor.yy14,yymsp[-7].minor.yy144,yymsp[0].minor.yy454);
}
break;
case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
{
- yymsp[-9].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy402,yymsp[-6].minor.yy563,yymsp[-5].minor.yy590,yymsp[-4].minor.yy402,yymsp[-3].minor.yy590,yymsp[-1].minor.yy402,yymsp[-8].minor.yy502,yymsp[0].minor.yy590);
- if( yymsp[-9].minor.yy637 ){
- yymsp[-9].minor.yy637->pWinDefn = yymsp[-2].minor.yy483;
+ yymsp[-9].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy14,yymsp[-6].minor.yy203,yymsp[-5].minor.yy454,yymsp[-4].minor.yy14,yymsp[-3].minor.yy454,yymsp[-1].minor.yy14,yymsp[-8].minor.yy144,yymsp[0].minor.yy454);
+ if( yymsp[-9].minor.yy555 ){
+ yymsp[-9].minor.yy555->pWinDefn = yymsp[-2].minor.yy211;
}else{
- sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy483);
+ sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy211);
}
}
break;
case 94: /* values ::= VALUES LP nexprlist RP */
{
- yymsp[-3].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values,0);
+ yymsp[-3].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0);
}
break;
case 95: /* oneselect ::= mvalues */
{
- sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy637);
+ sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy555);
}
break;
case 96: /* mvalues ::= values COMMA LP nexprlist RP */
case 97: /* mvalues ::= mvalues COMMA LP nexprlist RP */ yytestcase(yyruleno==97);
{
- yymsp[-4].minor.yy637 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy637, yymsp[-1].minor.yy402);
+ yymsp[-4].minor.yy555 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy555, yymsp[-1].minor.yy14);
}
break;
case 98: /* distinct ::= DISTINCT */
-{yymsp[0].minor.yy502 = SF_Distinct;}
+{yymsp[0].minor.yy144 = SF_Distinct;}
break;
case 99: /* distinct ::= ALL */
-{yymsp[0].minor.yy502 = SF_All;}
+{yymsp[0].minor.yy144 = SF_All;}
break;
case 101: /* sclp ::= */
case 134: /* orderby_opt ::= */ yytestcase(yyruleno==134);
@@ -181600,20 +184942,20 @@ static YYACTIONTYPE yy_reduce(
case 234: /* exprlist ::= */ yytestcase(yyruleno==234);
case 237: /* paren_exprlist ::= */ yytestcase(yyruleno==237);
case 242: /* eidlist_opt ::= */ yytestcase(yyruleno==242);
-{yymsp[1].minor.yy402 = 0;}
+{yymsp[1].minor.yy14 = 0;}
break;
case 102: /* selcollist ::= sclp scanpt expr scanpt as */
{
- yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[-2].minor.yy590);
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[0].minor.yy0, 1);
- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy402,yymsp[-3].minor.yy342,yymsp[-1].minor.yy342);
+ yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[-2].minor.yy454);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy14,yymsp[-3].minor.yy168,yymsp[-1].minor.yy168);
}
break;
case 103: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail));
- yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy402, p);
+ yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, p);
}
break;
case 104: /* selcollist ::= sclp scanpt nm DOT STAR */
@@ -181623,7 +184965,7 @@ static YYACTIONTYPE yy_reduce(
sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail));
pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0);
pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, pDot);
+ yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, pDot);
}
break;
case 105: /* as ::= AS nm */
@@ -181634,52 +184976,53 @@ static YYACTIONTYPE yy_reduce(
break;
case 107: /* from ::= */
case 110: /* stl_prefix ::= */ yytestcase(yyruleno==110);
-{yymsp[1].minor.yy563 = 0;}
+{yymsp[1].minor.yy203 = 0;}
break;
case 108: /* from ::= FROM seltablist */
{
- yymsp[-1].minor.yy563 = yymsp[0].minor.yy563;
- sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy563);
+ yymsp[-1].minor.yy203 = yymsp[0].minor.yy203;
+ sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy203);
}
break;
case 109: /* stl_prefix ::= seltablist joinop */
{
- if( ALWAYS(yymsp[-1].minor.yy563 && yymsp[-1].minor.yy563->nSrc>0) ) yymsp[-1].minor.yy563->a[yymsp[-1].minor.yy563->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502;
+ if( ALWAYS(yymsp[-1].minor.yy203 && yymsp[-1].minor.yy203->nSrc>0) ) yymsp[-1].minor.yy203->a[yymsp[-1].minor.yy203->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy144;
}
break;
case 111: /* seltablist ::= stl_prefix nm dbnm as on_using */
{
- yymsp[-4].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy563,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421);
+ yymsp[-4].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy203,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269);
}
break;
case 112: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
{
- yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy421);
- sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-1].minor.yy0);
+ yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy269);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-1].minor.yy0);
}
break;
case 113: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
{
- yymsp[-7].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy563,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421);
- sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy563, yymsp[-3].minor.yy402);
+ yymsp[-7].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy203,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269);
+ sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy203, yymsp[-3].minor.yy14);
}
break;
case 114: /* seltablist ::= stl_prefix LP select RP as on_using */
{
- yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy637,&yymsp[0].minor.yy421);
+ yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy555,&yymsp[0].minor.yy269);
}
break;
case 115: /* seltablist ::= stl_prefix LP seltablist RP as on_using */
{
- if( yymsp[-5].minor.yy563==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy421.pOn==0 && yymsp[0].minor.yy421.pUsing==0 ){
- yymsp[-5].minor.yy563 = yymsp[-3].minor.yy563;
- }else if( ALWAYS(yymsp[-3].minor.yy563!=0) && yymsp[-3].minor.yy563->nSrc==1 ){
- yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421);
- if( yymsp[-5].minor.yy563 ){
- SrcItem *pNew = &yymsp[-5].minor.yy563->a[yymsp[-5].minor.yy563->nSrc-1];
- SrcItem *pOld = yymsp[-3].minor.yy563->a;
+ if( yymsp[-5].minor.yy203==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy269.pOn==0 && yymsp[0].minor.yy269.pUsing==0 ){
+ yymsp[-5].minor.yy203 = yymsp[-3].minor.yy203;
+ }else if( ALWAYS(yymsp[-3].minor.yy203!=0) && yymsp[-3].minor.yy203->nSrc==1 ){
+ yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269);
+ if( yymsp[-5].minor.yy203 ){
+ SrcItem *pNew = &yymsp[-5].minor.yy203->a[yymsp[-5].minor.yy203->nSrc-1];
+ SrcItem *pOld = yymsp[-3].minor.yy203->a;
assert( pOld->fg.fixedSchema==0 );
pNew->zName = pOld->zName;
+ pOld->zName = 0;
assert( pOld->fg.fixedSchema==0 );
if( pOld->fg.isSubquery ){
pNew->fg.isSubquery = 1;
@@ -181699,15 +185042,20 @@ static YYACTIONTYPE yy_reduce(
pOld->u1.pFuncArg = 0;
pOld->fg.isTabFunc = 0;
pNew->fg.isTabFunc = 1;
+ }else if( pOld->fg.isIndexedBy ){
+ pNew->u1.zIndexedBy = pOld->u1.zIndexedBy;
+ pOld->u1.zIndexedBy = 0;
+ pOld->fg.isIndexedBy = 0;
+ pNew->fg.isIndexedBy = 1;
}
- pOld->zName = 0;
+ pNew->fg.notIndexed = pOld->fg.notIndexed;
}
- sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy563);
+ sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy203);
}else{
Select *pSubquery;
- sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy563);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy563,0,0,0,0,SF_NestedFrom,0);
- yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy421);
+ sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy203);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy203,0,0,0,0,SF_NestedFrom,0);
+ yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy269);
}
}
break;
@@ -181716,57 +185064,67 @@ static YYACTIONTYPE yy_reduce(
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
case 118: /* fullname ::= nm */
+ case 120: /* xfullname ::= nm */ yytestcase(yyruleno==120);
{
- yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
- if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[0].minor.yy563 = yylhsminor.yy563;
+ yymsp[0].minor.yy203 = yylhsminor.yy203;
break;
case 119: /* fullname ::= nm DOT nm */
+ case 121: /* xfullname ::= nm DOT nm */ yytestcase(yyruleno==121);
{
- yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[-2].minor.yy563 = yylhsminor.yy563;
+ yymsp[-2].minor.yy203 = yylhsminor.yy203;
break;
- case 120: /* xfullname ::= nm */
-{yymsp[0].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
- break;
- case 121: /* xfullname ::= nm DOT nm */
-{yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
- break;
- case 122: /* xfullname ::= nm DOT nm AS nm */
+ case 122: /* xfullname ::= nm AS nm */
{
- yymsp[-4].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
- if( yymsp[-4].minor.yy563 ) yymsp[-4].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0);
+ if( yylhsminor.yy203 ){
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[-2].minor.yy0);
+ }else{
+ yylhsminor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ }
+ }
}
+ yymsp[-2].minor.yy203 = yylhsminor.yy203;
break;
- case 123: /* xfullname ::= nm AS nm */
+ case 123: /* xfullname ::= nm DOT nm AS nm */
{
- yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
- if( yymsp[-2].minor.yy563 ) yymsp[-2].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0);
+ if( yylhsminor.yy203 ){
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[-2].minor.yy0);
+ }else{
+ yylhsminor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ }
+ }
}
+ yymsp[-4].minor.yy203 = yylhsminor.yy203;
break;
case 124: /* joinop ::= COMMA|JOIN */
-{ yymsp[0].minor.yy502 = JT_INNER; }
+{ yymsp[0].minor.yy144 = JT_INNER; }
break;
case 125: /* joinop ::= JOIN_KW JOIN */
-{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
+{yymsp[-1].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
case 126: /* joinop ::= JOIN_KW nm JOIN */
-{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
+{yymsp[-2].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
case 127: /* joinop ::= JOIN_KW nm nm JOIN */
-{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
+{yymsp[-3].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
case 128: /* on_using ::= ON expr */
-{yymsp[-1].minor.yy421.pOn = yymsp[0].minor.yy590; yymsp[-1].minor.yy421.pUsing = 0;}
+{yymsp[-1].minor.yy269.pOn = yymsp[0].minor.yy454; yymsp[-1].minor.yy269.pUsing = 0;}
break;
case 129: /* on_using ::= USING LP idlist RP */
-{yymsp[-3].minor.yy421.pOn = 0; yymsp[-3].minor.yy421.pUsing = yymsp[-1].minor.yy204;}
+{yymsp[-3].minor.yy269.pOn = 0; yymsp[-3].minor.yy269.pUsing = yymsp[-1].minor.yy132;}
break;
case 130: /* on_using ::= */
-{yymsp[1].minor.yy421.pOn = 0; yymsp[1].minor.yy421.pUsing = 0;}
+{yymsp[1].minor.yy269.pOn = 0; yymsp[1].minor.yy269.pUsing = 0;}
break;
case 132: /* indexed_by ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
@@ -181776,35 +185134,35 @@ static YYACTIONTYPE yy_reduce(
break;
case 135: /* orderby_opt ::= ORDER BY sortlist */
case 145: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==145);
-{yymsp[-2].minor.yy402 = yymsp[0].minor.yy402;}
+{yymsp[-2].minor.yy14 = yymsp[0].minor.yy14;}
break;
case 136: /* sortlist ::= sortlist COMMA expr sortorder nulls */
{
- yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402,yymsp[-2].minor.yy590);
- sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502);
+ yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14,yymsp[-2].minor.yy454);
+ sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144);
}
break;
case 137: /* sortlist ::= expr sortorder nulls */
{
- yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy590); /*A-overwrites-Y*/
- sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502);
+ yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy454); /*A-overwrites-Y*/
+ sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144);
}
break;
case 138: /* sortorder ::= ASC */
-{yymsp[0].minor.yy502 = SQLITE_SO_ASC;}
+{yymsp[0].minor.yy144 = SQLITE_SO_ASC;}
break;
case 139: /* sortorder ::= DESC */
-{yymsp[0].minor.yy502 = SQLITE_SO_DESC;}
+{yymsp[0].minor.yy144 = SQLITE_SO_DESC;}
break;
case 140: /* sortorder ::= */
case 143: /* nulls ::= */ yytestcase(yyruleno==143);
-{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;}
+{yymsp[1].minor.yy144 = SQLITE_SO_UNDEFINED;}
break;
case 141: /* nulls ::= NULLS FIRST */
-{yymsp[-1].minor.yy502 = SQLITE_SO_ASC;}
+{yymsp[-1].minor.yy144 = SQLITE_SO_ASC;}
break;
case 142: /* nulls ::= NULLS LAST */
-{yymsp[-1].minor.yy502 = SQLITE_SO_DESC;}
+{yymsp[-1].minor.yy144 = SQLITE_SO_DESC;}
break;
case 146: /* having_opt ::= */
case 148: /* limit_opt ::= */ yytestcase(yyruleno==148);
@@ -181813,48 +185171,48 @@ static YYACTIONTYPE yy_reduce(
case 232: /* case_else ::= */ yytestcase(yyruleno==232);
case 233: /* case_operand ::= */ yytestcase(yyruleno==233);
case 252: /* vinto ::= */ yytestcase(yyruleno==252);
-{yymsp[1].minor.yy590 = 0;}
+{yymsp[1].minor.yy454 = 0;}
break;
case 147: /* having_opt ::= HAVING expr */
case 154: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==154);
case 156: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==156);
case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231);
case 251: /* vinto ::= INTO expr */ yytestcase(yyruleno==251);
-{yymsp[-1].minor.yy590 = yymsp[0].minor.yy590;}
+{yymsp[-1].minor.yy454 = yymsp[0].minor.yy454;}
break;
case 149: /* limit_opt ::= LIMIT expr */
-{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,0);}
+{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,0);}
break;
case 150: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);}
+{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);}
break;
case 151: /* limit_opt ::= LIMIT expr COMMA expr */
-{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,yymsp[-2].minor.yy590);}
+{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,yymsp[-2].minor.yy454);}
break;
case 152: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret orderby_opt limit_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy563, &yymsp[-3].minor.yy0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy203, &yymsp[-3].minor.yy0);
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- if( yymsp[-1].minor.yy402 || yymsp[0].minor.yy590 ){
- updateDeleteLimitError(pParse,yymsp[-1].minor.yy402,yymsp[0].minor.yy590);
- yymsp[-1].minor.yy402 = 0;
- yymsp[0].minor.yy590 = 0;
+ if( yymsp[-1].minor.yy14 || yymsp[0].minor.yy454 ){
+ updateDeleteLimitError(pParse,yymsp[-1].minor.yy14,yymsp[0].minor.yy454);
+ yymsp[-1].minor.yy14 = 0;
+ yymsp[0].minor.yy454 = 0;
}
#endif
- sqlite3DeleteFrom(pParse,yymsp[-4].minor.yy563,yymsp[-2].minor.yy590,yymsp[-1].minor.yy402,yymsp[0].minor.yy590);
+ sqlite3DeleteFrom(pParse,yymsp[-4].minor.yy203,yymsp[-2].minor.yy454,yymsp[-1].minor.yy14,yymsp[0].minor.yy454);
}
break;
case 157: /* where_opt_ret ::= RETURNING selcollist */
-{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-1].minor.yy590 = 0;}
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-1].minor.yy454 = 0;}
break;
case 158: /* where_opt_ret ::= WHERE expr RETURNING selcollist */
-{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-3].minor.yy590 = yymsp[-2].minor.yy590;}
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-3].minor.yy454 = yymsp[-2].minor.yy454;}
break;
case 159: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret orderby_opt limit_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-7].minor.yy563, &yymsp[-6].minor.yy0);
- if( yymsp[-3].minor.yy563 ){
- SrcList *pFromClause = yymsp[-3].minor.yy563;
+ sqlite3SrcListIndexedBy(pParse, yymsp[-7].minor.yy203, &yymsp[-6].minor.yy0);
+ if( yymsp[-3].minor.yy203 ){
+ SrcList *pFromClause = yymsp[-3].minor.yy203;
if( pFromClause->nSrc>1 ){
Select *pSubquery;
Token as;
@@ -181863,98 +185221,98 @@ static YYACTIONTYPE yy_reduce(
as.z = 0;
pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
}
- yymsp[-7].minor.yy563 = sqlite3SrcListAppendList(pParse, yymsp[-7].minor.yy563, pFromClause);
+ yymsp[-7].minor.yy203 = sqlite3SrcListAppendList(pParse, yymsp[-7].minor.yy203, pFromClause);
}
- sqlite3ExprListCheckLength(pParse,yymsp[-4].minor.yy402,"set list");
+ sqlite3ExprListCheckLength(pParse,yymsp[-4].minor.yy14,"set list");
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- if( yymsp[-1].minor.yy402 || yymsp[0].minor.yy590 ){
- updateDeleteLimitError(pParse,yymsp[-1].minor.yy402,yymsp[0].minor.yy590);
- yymsp[-1].minor.yy402 = 0;
- yymsp[0].minor.yy590 = 0;
+ if( yymsp[-1].minor.yy14 || yymsp[0].minor.yy454 ){
+ updateDeleteLimitError(pParse,yymsp[-1].minor.yy14,yymsp[0].minor.yy454);
+ yymsp[-1].minor.yy14 = 0;
+ yymsp[0].minor.yy454 = 0;
}
#endif
- sqlite3Update(pParse,yymsp[-7].minor.yy563,yymsp[-4].minor.yy402,yymsp[-2].minor.yy590,yymsp[-8].minor.yy502,yymsp[-1].minor.yy402,yymsp[0].minor.yy590,0);
+ sqlite3Update(pParse,yymsp[-7].minor.yy203,yymsp[-4].minor.yy14,yymsp[-2].minor.yy454,yymsp[-8].minor.yy144,yymsp[-1].minor.yy14,yymsp[0].minor.yy454,0);
}
break;
case 160: /* setlist ::= setlist COMMA nm EQ expr */
{
- yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[0].minor.yy590);
- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, 1);
+ yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy454);
+ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, 1);
}
break;
case 161: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
- yymsp[-6].minor.yy402 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy402, yymsp[-3].minor.yy204, yymsp[0].minor.yy590);
+ yymsp[-6].minor.yy14 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy14, yymsp[-3].minor.yy132, yymsp[0].minor.yy454);
}
break;
case 162: /* setlist ::= nm EQ expr */
{
- yylhsminor.yy402 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy590);
- sqlite3ExprListSetName(pParse, yylhsminor.yy402, &yymsp[-2].minor.yy0, 1);
+ yylhsminor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy454);
+ sqlite3ExprListSetName(pParse, yylhsminor.yy14, &yymsp[-2].minor.yy0, 1);
}
- yymsp[-2].minor.yy402 = yylhsminor.yy402;
+ yymsp[-2].minor.yy14 = yylhsminor.yy14;
break;
case 163: /* setlist ::= LP idlist RP EQ expr */
{
- yymsp[-4].minor.yy402 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy204, yymsp[0].minor.yy590);
+ yymsp[-4].minor.yy14 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy132, yymsp[0].minor.yy454);
}
break;
case 164: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy563, yymsp[-1].minor.yy637, yymsp[-2].minor.yy204, yymsp[-5].minor.yy502, yymsp[0].minor.yy403);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy555, yymsp[-2].minor.yy132, yymsp[-5].minor.yy144, yymsp[0].minor.yy122);
}
break;
case 165: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
{
- sqlite3Insert(pParse, yymsp[-4].minor.yy563, 0, yymsp[-3].minor.yy204, yymsp[-6].minor.yy502, 0);
+ sqlite3Insert(pParse, yymsp[-4].minor.yy203, 0, yymsp[-3].minor.yy132, yymsp[-6].minor.yy144, 0);
}
break;
case 166: /* upsert ::= */
-{ yymsp[1].minor.yy403 = 0; }
+{ yymsp[1].minor.yy122 = 0; }
break;
case 167: /* upsert ::= RETURNING selcollist */
-{ yymsp[-1].minor.yy403 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy402); }
+{ yymsp[-1].minor.yy122 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy14); }
break;
case 168: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
-{ yymsp[-11].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy402,yymsp[-6].minor.yy590,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,yymsp[0].minor.yy403);}
+{ yymsp[-11].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy14,yymsp[-6].minor.yy454,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,yymsp[0].minor.yy122);}
break;
case 169: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
-{ yymsp[-8].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy402,yymsp[-3].minor.yy590,0,0,yymsp[0].minor.yy403); }
+{ yymsp[-8].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy14,yymsp[-3].minor.yy454,0,0,yymsp[0].minor.yy122); }
break;
case 170: /* upsert ::= ON CONFLICT DO NOTHING returning */
-{ yymsp[-4].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
+{ yymsp[-4].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
break;
case 171: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
-{ yymsp[-7].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,0);}
+{ yymsp[-7].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,0);}
break;
case 172: /* returning ::= RETURNING selcollist */
-{sqlite3AddReturning(pParse,yymsp[0].minor.yy402);}
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy14);}
break;
case 175: /* idlist_opt ::= */
-{yymsp[1].minor.yy204 = 0;}
+{yymsp[1].minor.yy132 = 0;}
break;
case 176: /* idlist_opt ::= LP idlist RP */
-{yymsp[-2].minor.yy204 = yymsp[-1].minor.yy204;}
+{yymsp[-2].minor.yy132 = yymsp[-1].minor.yy132;}
break;
case 177: /* idlist ::= idlist COMMA nm */
-{yymsp[-2].minor.yy204 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy204,&yymsp[0].minor.yy0);}
+{yymsp[-2].minor.yy132 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy132,&yymsp[0].minor.yy0);}
break;
case 178: /* idlist ::= nm */
-{yymsp[0].minor.yy204 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+{yymsp[0].minor.yy132 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
case 179: /* expr ::= LP expr RP */
-{yymsp[-2].minor.yy590 = yymsp[-1].minor.yy590;}
+{yymsp[-2].minor.yy454 = yymsp[-1].minor.yy454;}
break;
case 180: /* expr ::= ID|INDEXED|JOIN_KW */
-{yymsp[0].minor.yy590=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy454=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 181: /* expr ::= nm DOT nm */
{
Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0);
Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0);
- yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
+ yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
- yymsp[-2].minor.yy590 = yylhsminor.yy590;
+ yymsp[-2].minor.yy454 = yylhsminor.yy454;
break;
case 182: /* expr ::= nm DOT nm DOT nm */
{
@@ -181965,27 +185323,32 @@ static YYACTIONTYPE yy_reduce(
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, 0, temp1);
}
- yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
+ yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
- yymsp[-4].minor.yy590 = yylhsminor.yy590;
+ yymsp[-4].minor.yy454 = yylhsminor.yy454;
break;
case 183: /* term ::= NULL|FLOAT|BLOB */
case 184: /* term ::= STRING */ yytestcase(yyruleno==184);
-{yymsp[0].minor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 185: /* term ::= INTEGER */
{
- yylhsminor.yy590 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
- if( yylhsminor.yy590 ) yylhsminor.yy590->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail);
+ int iValue;
+ if( sqlite3GetInt32(yymsp[0].minor.yy0.z, &iValue)==0 ){
+ yylhsminor.yy454 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 0);
+ }else{
+ yylhsminor.yy454 = sqlite3ExprInt32(pParse->db, iValue);
+ }
+ if( yylhsminor.yy454 ) yylhsminor.yy454->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail);
}
- yymsp[0].minor.yy590 = yylhsminor.yy590;
+ yymsp[0].minor.yy454 = yylhsminor.yy454;
break;
case 186: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
- yymsp[0].minor.yy590 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy590, n);
+ yymsp[0].minor.yy454 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy454, 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
@@ -181994,80 +185357,82 @@ static YYACTIONTYPE yy_reduce(
assert( t.n>=2 );
if( pParse->nested==0 ){
parserSyntaxError(pParse, &t);
- yymsp[0].minor.yy590 = 0;
+ yymsp[0].minor.yy454 = 0;
}else{
- yymsp[0].minor.yy590 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( yymsp[0].minor.yy590 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy590->iTable);
+ yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
+ if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable);
}
}
}
break;
case 187: /* expr ::= expr COLLATE ID|STRING */
{
- yymsp[-2].minor.yy590 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy590, &yymsp[0].minor.yy0, 1);
+ yymsp[-2].minor.yy454 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy454, &yymsp[0].minor.yy0, 1);
}
break;
case 188: /* expr ::= CAST LP expr AS typetoken RP */
{
- yymsp[-5].minor.yy590 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy590, yymsp[-3].minor.yy590, 0);
+ yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy454, yymsp[-3].minor.yy454, 0);
}
break;
case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */
{
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy502);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy144);
}
- yymsp[-4].minor.yy590 = yylhsminor.yy590;
+ yymsp[-4].minor.yy454 = yylhsminor.yy454;
break;
case 190: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */
{
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy402, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy502);
- sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-1].minor.yy402);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy14, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy144);
+ sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-1].minor.yy14);
}
- yymsp[-7].minor.yy590 = yylhsminor.yy590;
+ yymsp[-7].minor.yy454 = yylhsminor.yy454;
break;
case 191: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */
{
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
}
- yymsp[-3].minor.yy590 = yylhsminor.yy590;
+ yymsp[-3].minor.yy454 = yylhsminor.yy454;
break;
case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */
{
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy402, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy502);
- sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy14, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy144);
+ sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211);
}
- yymsp[-5].minor.yy590 = yylhsminor.yy590;
+ yymsp[-5].minor.yy454 = yylhsminor.yy454;
break;
case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */
{
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy402, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy502);
- sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483);
- sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-2].minor.yy402);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy14, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy144);
+ sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211);
+ sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-2].minor.yy14);
}
- yymsp[-8].minor.yy590 = yylhsminor.yy590;
+ yymsp[-8].minor.yy454 = yylhsminor.yy454;
break;
case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */
{
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
- sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
+ sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211);
}
- yymsp[-4].minor.yy590 = yylhsminor.yy590;
+ yymsp[-4].minor.yy454 = yylhsminor.yy454;
break;
case 195: /* term ::= CTIME_KW */
{
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
- yymsp[0].minor.yy590 = yylhsminor.yy590;
+ yymsp[0].minor.yy454 = yylhsminor.yy454;
break;
case 196: /* expr ::= LP nexprlist COMMA expr RP */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590);
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( yymsp[-4].minor.yy590 ){
- yymsp[-4].minor.yy590->x.pList = pList;
- if( ALWAYS(pList->nExpr) ){
- yymsp[-4].minor.yy590->flags |= pList->a[0].pExpr->flags & EP_Propagate;
+ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( yymsp[-4].minor.yy454 ){
+ int i;
+ yymsp[-4].minor.yy454->x.pList = pList;
+ for(i=0; inExpr; i++){
+ assert( pList->a[i].pExpr!=0 );
+ yymsp[-4].minor.yy454->flags |= pList->a[i].pExpr->flags & EP_Propagate;
}
}else{
sqlite3ExprListDelete(pParse->db, pList);
@@ -182075,7 +185440,7 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 197: /* expr ::= expr AND expr */
-{yymsp[-2].minor.yy590=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);}
+{yymsp[-2].minor.yy454=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);}
break;
case 198: /* expr ::= expr OR expr */
case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199);
@@ -182084,7 +185449,7 @@ static YYACTIONTYPE yy_reduce(
case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202);
case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203);
case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204);
-{yymsp[-2].minor.yy590=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);}
+{yymsp[-2].minor.yy454=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);}
break;
case 205: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
@@ -182094,11 +185459,11 @@ static YYACTIONTYPE yy_reduce(
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy590);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy590);
- yymsp[-2].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
- if( bNot ) yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy590, 0);
- if( yymsp[-2].minor.yy590 ) yymsp[-2].minor.yy590->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy454);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy454);
+ yymsp[-2].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ if( bNot ) yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy454, 0);
+ if( yymsp[-2].minor.yy454 ) yymsp[-2].minor.yy454->flags |= EP_InfixFunc;
}
break;
case 207: /* expr ::= expr likeop expr ESCAPE expr */
@@ -182106,91 +185471,88 @@ static YYACTIONTYPE yy_reduce(
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy590);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590);
- yymsp[-4].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
- if( bNot ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
- if( yymsp[-4].minor.yy590 ) yymsp[-4].minor.yy590->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy454);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454);
+ yymsp[-4].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
+ if( bNot ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
+ if( yymsp[-4].minor.yy454 ) yymsp[-4].minor.yy454->flags |= EP_InfixFunc;
}
break;
case 208: /* expr ::= expr ISNULL|NOTNULL */
-{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy590,0);}
+{yymsp[-1].minor.yy454 = sqlite3PExprIsNull(pParse,yymsp[0].major,yymsp[-1].minor.yy454);}
break;
case 209: /* expr ::= expr NOT NULL */
-{yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy590,0);}
+{yymsp[-2].minor.yy454 = sqlite3PExprIsNull(pParse,TK_NOTNULL,yymsp[-2].minor.yy454);}
break;
case 210: /* expr ::= expr IS expr */
{
- yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-2].minor.yy590, TK_ISNULL);
+ yymsp[-2].minor.yy454 = sqlite3PExprIs(pParse, TK_IS, yymsp[-2].minor.yy454, yymsp[0].minor.yy454);
}
break;
case 211: /* expr ::= expr IS NOT expr */
{
- yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy590,yymsp[0].minor.yy590);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-3].minor.yy590, TK_NOTNULL);
+ yymsp[-3].minor.yy454 = sqlite3PExprIs(pParse, TK_ISNOT, yymsp[-3].minor.yy454, yymsp[0].minor.yy454);
}
break;
case 212: /* expr ::= expr IS NOT DISTINCT FROM expr */
{
- yymsp[-5].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy590,yymsp[0].minor.yy590);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-5].minor.yy590, TK_ISNULL);
+ yymsp[-5].minor.yy454 = sqlite3PExprIs(pParse, TK_IS, yymsp[-5].minor.yy454, yymsp[0].minor.yy454);
}
break;
case 213: /* expr ::= expr IS DISTINCT FROM expr */
{
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy590,yymsp[0].minor.yy590);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-4].minor.yy590, TK_NOTNULL);
+ yymsp[-4].minor.yy454 = sqlite3PExprIs(pParse, TK_ISNOT, yymsp[-4].minor.yy454, yymsp[0].minor.yy454);
}
break;
case 214: /* expr ::= NOT expr */
case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215);
-{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy590, 0);/*A-overwrites-B*/}
+{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/}
break;
case 216: /* expr ::= PLUS|MINUS expr */
{
- Expr *p = yymsp[0].minor.yy590;
+ Expr *p = yymsp[0].minor.yy454;
u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS);
assert( TK_UPLUS>TK_PLUS );
assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) );
if( p && p->op==TK_UPLUS ){
p->op = op;
- yymsp[-1].minor.yy590 = p;
+ yymsp[-1].minor.yy454 = p;
}else{
- yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, op, p, 0);
+ yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, op, p, 0);
/*A-overwrites-B*/
}
}
break;
case 217: /* expr ::= expr PTR expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy590);
- pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy590);
- yylhsminor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454);
+ pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy454);
+ yylhsminor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
}
- yymsp[-2].minor.yy590 = yylhsminor.yy590;
+ yymsp[-2].minor.yy454 = yylhsminor.yy454;
break;
case 218: /* between_op ::= BETWEEN */
case 221: /* in_op ::= IN */ yytestcase(yyruleno==221);
-{yymsp[0].minor.yy502 = 0;}
+{yymsp[0].minor.yy144 = 0;}
break;
case 220: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590);
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy590, 0);
- if( yymsp[-4].minor.yy590 ){
- yymsp[-4].minor.yy590->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0);
+ if( yymsp[-4].minor.yy454 ){
+ yymsp[-4].minor.yy454->x.pList = pList;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454);
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
+ if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
}
break;
case 223: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy402==0 ){
+ if( yymsp[-1].minor.yy14==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -182203,145 +185565,149 @@ static YYACTIONTYPE yy_reduce(
** it is or not) and if it is an aggregate, that could change the meaning
** of the whole query.
*/
- Expr *pB = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy502 ? "true" : "false");
+ Expr *pB = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy144 ? "true" : "false");
if( pB ) sqlite3ExprIdToTrueFalse(pB);
- if( !ExprHasProperty(yymsp[-4].minor.yy590, EP_HasFunc) ){
- sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy590);
- yymsp[-4].minor.yy590 = pB;
+ if( !ExprHasProperty(yymsp[-4].minor.yy454, EP_HasFunc) ){
+ sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy454);
+ yymsp[-4].minor.yy454 = pB;
}else{
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, yymsp[-3].minor.yy502 ? TK_OR : TK_AND, pB, yymsp[-4].minor.yy590);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, yymsp[-3].minor.yy144 ? TK_OR : TK_AND, pB, yymsp[-4].minor.yy454);
}
}else{
- Expr *pRHS = yymsp[-1].minor.yy402->a[0].pExpr;
- if( yymsp[-1].minor.yy402->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy590->op!=TK_VECTOR ){
- yymsp[-1].minor.yy402->a[0].pExpr = 0;
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402);
+ Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr;
+ if( yymsp[-1].minor.yy14->nExpr==1
+ && sqlite3ExprIsConstant(pParse,pRHS)
+ && pRHS->op!=TK_COLLATE
+ && yymsp[-4].minor.yy454->op!=TK_VECTOR
+ ){
+ yymsp[-1].minor.yy14->a[0].pExpr = 0;
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy590, pRHS);
- }else if( yymsp[-1].minor.yy402->nExpr==1 && pRHS->op==TK_SELECT ){
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pRHS->x.pSelect);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy454, pRHS);
+ }else if( yymsp[-1].minor.yy14->nExpr==1 && pRHS->op==TK_SELECT ){
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pRHS->x.pSelect);
pRHS->x.pSelect = 0;
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
}else{
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0);
- if( yymsp[-4].minor.yy590==0 ){
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402);
- }else if( yymsp[-4].minor.yy590->pLeft->op==TK_VECTOR ){
- int nExpr = yymsp[-4].minor.yy590->pLeft->x.pList->nExpr;
- Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy402);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
+ if( yymsp[-4].minor.yy454==0 ){
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
+ }else if( yymsp[-4].minor.yy454->pLeft->op==TK_VECTOR ){
+ int nExpr = yymsp[-4].minor.yy454->pLeft->x.pList->nExpr;
+ Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy14);
if( pSelectRHS ){
parserDoubleLinkSelect(pParse, pSelectRHS);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelectRHS);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelectRHS);
}
}else{
- yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy402;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590);
+ yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy14;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454);
}
}
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
+ if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
}
}
break;
case 224: /* expr ::= LP select RP */
{
- yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy590, yymsp[-1].minor.yy637);
+ yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy454, yymsp[-1].minor.yy555);
}
break;
case 225: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, yymsp[-1].minor.yy637);
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, yymsp[-1].minor.yy555);
+ if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
}
break;
case 226: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
- if( yymsp[0].minor.yy402 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy402);
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelect);
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
+ if( yymsp[0].minor.yy14 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy14);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelect);
+ if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
}
break;
case 227: /* expr ::= EXISTS LP select RP */
{
Expr *p;
- p = yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy637);
+ p = yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
+ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy555);
}
break;
case 228: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy590, 0);
- if( yymsp[-4].minor.yy590 ){
- yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy590 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590) : yymsp[-2].minor.yy402;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590);
+ yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy454, 0);
+ if( yymsp[-4].minor.yy454 ){
+ yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy454 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454) : yymsp[-2].minor.yy14;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy402);
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454);
}
}
break;
case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[-2].minor.yy590);
- yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[0].minor.yy590);
+ yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy454);
+ yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[0].minor.yy454);
}
break;
case 230: /* case_exprlist ::= WHEN expr THEN expr */
{
- yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590);
- yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402, yymsp[0].minor.yy590);
+ yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
+ yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, yymsp[0].minor.yy454);
}
break;
case 235: /* nexprlist ::= nexprlist COMMA expr */
-{yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[0].minor.yy590);}
+{yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy454);}
break;
case 236: /* nexprlist ::= expr */
-{yymsp[0].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy590); /*A-overwrites-Y*/}
+{yymsp[0].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy454); /*A-overwrites-Y*/}
break;
case 238: /* paren_exprlist ::= LP exprlist RP */
case 243: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==243);
-{yymsp[-2].minor.yy402 = yymsp[-1].minor.yy402;}
+{yymsp[-2].minor.yy14 = yymsp[-1].minor.yy14;}
break;
case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
- sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy402, yymsp[-10].minor.yy502,
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy590, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF);
+ sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy144,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy454, SQLITE_SO_ASC, yymsp[-8].minor.yy144, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
}
break;
case 240: /* uniqueflag ::= UNIQUE */
- case 282: /* raisetype ::= ABORT */ yytestcase(yyruleno==282);
-{yymsp[0].minor.yy502 = OE_Abort;}
+ case 281: /* raisetype ::= ABORT */ yytestcase(yyruleno==281);
+{yymsp[0].minor.yy144 = OE_Abort;}
break;
case 241: /* uniqueflag ::= */
-{yymsp[1].minor.yy502 = OE_None;}
+{yymsp[1].minor.yy144 = OE_None;}
break;
case 244: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
- yymsp[-4].minor.yy402 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502);
+ yymsp[-4].minor.yy14 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144);
}
break;
case 245: /* eidlist ::= nm collate sortorder */
{
- yymsp[-2].minor.yy402 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/
+ yymsp[-2].minor.yy14 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); /*A-overwrites-Y*/
}
break;
case 248: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy563, yymsp[-1].minor.yy502);}
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy203, yymsp[-1].minor.yy144);}
break;
case 249: /* cmd ::= VACUUM vinto */
-{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy590);}
+{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy454);}
break;
case 250: /* cmd ::= VACUUM nm vinto */
-{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy590);}
+{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy454);}
break;
case 253: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
@@ -182363,12 +185729,12 @@ static YYACTIONTYPE yy_reduce(
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy319, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all);
}
break;
case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy28.a, yymsp[-4].minor.yy28.b, yymsp[-2].minor.yy563, yymsp[0].minor.yy590, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy144, yymsp[-4].minor.yy286.a, yymsp[-4].minor.yy286.b, yymsp[-2].minor.yy203, yymsp[0].minor.yy454, yymsp[-10].minor.yy144, yymsp[-8].minor.yy144);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
#ifdef SQLITE_DEBUG
assert( pParse->isCreate ); /* Set by createkw reduce action */
@@ -182377,421 +185743,437 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 262: /* trigger_time ::= BEFORE|AFTER */
-{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ }
+{ yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/ }
break;
case 263: /* trigger_time ::= INSTEAD OF */
-{ yymsp[-1].minor.yy502 = TK_INSTEAD;}
+{ yymsp[-1].minor.yy144 = TK_INSTEAD;}
break;
case 264: /* trigger_time ::= */
-{ yymsp[1].minor.yy502 = TK_BEFORE; }
+{ yymsp[1].minor.yy144 = TK_BEFORE; }
break;
case 265: /* trigger_event ::= DELETE|INSERT */
case 266: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==266);
-{yymsp[0].minor.yy28.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy28.b = 0;}
+{yymsp[0].minor.yy286.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy286.b = 0;}
break;
case 267: /* trigger_event ::= UPDATE OF idlist */
-{yymsp[-2].minor.yy28.a = TK_UPDATE; yymsp[-2].minor.yy28.b = yymsp[0].minor.yy204;}
+{yymsp[-2].minor.yy286.a = TK_UPDATE; yymsp[-2].minor.yy286.b = yymsp[0].minor.yy132;}
break;
case 268: /* when_clause ::= */
- case 287: /* key_opt ::= */ yytestcase(yyruleno==287);
-{ yymsp[1].minor.yy590 = 0; }
+ case 286: /* key_opt ::= */ yytestcase(yyruleno==286);
+{ yymsp[1].minor.yy454 = 0; }
break;
case 269: /* when_clause ::= WHEN expr */
- case 288: /* key_opt ::= KEY expr */ yytestcase(yyruleno==288);
-{ yymsp[-1].minor.yy590 = yymsp[0].minor.yy590; }
+ case 287: /* key_opt ::= KEY expr */ yytestcase(yyruleno==287);
+{ yymsp[-1].minor.yy454 = yymsp[0].minor.yy454; }
break;
case 270: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy319!=0 );
- yymsp[-2].minor.yy319->pLast->pNext = yymsp[-1].minor.yy319;
- yymsp[-2].minor.yy319->pLast = yymsp[-1].minor.yy319;
+ yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427;
+ yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427;
}
break;
case 271: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy319!=0 );
- yymsp[-1].minor.yy319->pLast = yymsp[-1].minor.yy319;
+ yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427;
}
break;
- case 272: /* trnm ::= nm DOT nm */
-{
- yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
- sqlite3ErrorMsg(pParse,
- "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
- "statements within triggers");
-}
- break;
- case 273: /* tridxby ::= INDEXED BY nm */
+ case 272: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 274: /* tridxby ::= NOT INDEXED */
+ case 273: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 275: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
-{yylhsminor.yy319 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy563, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590, yymsp[-7].minor.yy502, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy342);}
- yymsp[-8].minor.yy319 = yylhsminor.yy319;
+ case 274: /* trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */
+{yylhsminor.yy427 = sqlite3TriggerUpdateStep(pParse, yymsp[-6].minor.yy203, yymsp[-2].minor.yy203, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454, yymsp[-7].minor.yy144, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy168);}
+ yymsp[-8].minor.yy427 = yylhsminor.yy427;
break;
- case 276: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ case 275: /* trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */
{
- yylhsminor.yy319 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy204,yymsp[-2].minor.yy637,yymsp[-6].minor.yy502,yymsp[-1].minor.yy403,yymsp[-7].minor.yy342,yymsp[0].minor.yy342);/*yylhsminor.yy319-overwrites-yymsp[-6].minor.yy502*/
+ yylhsminor.yy427 = sqlite3TriggerInsertStep(pParse,yymsp[-4].minor.yy203,yymsp[-3].minor.yy132,yymsp[-2].minor.yy555,yymsp[-6].minor.yy144,yymsp[-1].minor.yy122,yymsp[-7].minor.yy168,yymsp[0].minor.yy168);/*yylhsminor.yy427-overwrites-yymsp[-6].minor.yy144*/
}
- yymsp[-7].minor.yy319 = yylhsminor.yy319;
+ yymsp[-7].minor.yy427 = yylhsminor.yy427;
break;
- case 277: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-{yylhsminor.yy319 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy590, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy342);}
- yymsp[-5].minor.yy319 = yylhsminor.yy319;
+ case 276: /* trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */
+{yylhsminor.yy427 = sqlite3TriggerDeleteStep(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy454, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy168);}
+ yymsp[-5].minor.yy427 = yylhsminor.yy427;
break;
- case 278: /* trigger_cmd ::= scanpt select scanpt */
-{yylhsminor.yy319 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy637, yymsp[-2].minor.yy342, yymsp[0].minor.yy342); /*yylhsminor.yy319-overwrites-yymsp[-1].minor.yy637*/}
- yymsp[-2].minor.yy319 = yylhsminor.yy319;
+ case 277: /* trigger_cmd ::= scanpt select scanpt */
+{yylhsminor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy555, yymsp[-2].minor.yy168, yymsp[0].minor.yy168); /*yylhsminor.yy427-overwrites-yymsp[-1].minor.yy555*/}
+ yymsp[-2].minor.yy427 = yylhsminor.yy427;
break;
- case 279: /* expr ::= RAISE LP IGNORE RP */
+ case 278: /* expr ::= RAISE LP IGNORE RP */
{
- yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( yymsp[-3].minor.yy590 ){
- yymsp[-3].minor.yy590->affExpr = OE_Ignore;
+ yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
+ if( yymsp[-3].minor.yy454 ){
+ yymsp[-3].minor.yy454->affExpr = OE_Ignore;
}
}
break;
- case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */
+ case 279: /* expr ::= RAISE LP raisetype COMMA expr RP */
{
- yymsp[-5].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy590, 0);
- if( yymsp[-5].minor.yy590 ) {
- yymsp[-5].minor.yy590->affExpr = (char)yymsp[-3].minor.yy502;
+ yymsp[-5].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy454, 0);
+ if( yymsp[-5].minor.yy454 ) {
+ yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144;
}
}
break;
- case 281: /* raisetype ::= ROLLBACK */
-{yymsp[0].minor.yy502 = OE_Rollback;}
+ case 280: /* raisetype ::= ROLLBACK */
+{yymsp[0].minor.yy144 = OE_Rollback;}
break;
- case 283: /* raisetype ::= FAIL */
-{yymsp[0].minor.yy502 = OE_Fail;}
+ case 282: /* raisetype ::= FAIL */
+{yymsp[0].minor.yy144 = OE_Fail;}
break;
- case 284: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 283: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy563,yymsp[-1].minor.yy502);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy203,yymsp[-1].minor.yy144);
}
break;
- case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 284: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy590, yymsp[-1].minor.yy590, yymsp[0].minor.yy590);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, yymsp[0].minor.yy454);
}
break;
- case 286: /* cmd ::= DETACH database_kw_opt expr */
+ case 285: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy590);
+ sqlite3Detach(pParse, yymsp[0].minor.yy454);
}
break;
- case 289: /* cmd ::= REINDEX */
+ case 288: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 290: /* cmd ::= REINDEX nm dbnm */
+ case 289: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 291: /* cmd ::= ANALYZE */
+ case 290: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 292: /* cmd ::= ANALYZE nm dbnm */
+ case 291: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 293: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 292: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy563,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy203,&yymsp[0].minor.yy0);
}
break;
- case 294: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 293: /* cmd ::= alter_add carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
+}
+ break;
+ case 294: /* alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */
+{
+ disableLookaside(pParse);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[-4].minor.yy203);
+ sqlite3AddColumn(pParse, yymsp[-1].minor.yy0, yymsp[0].minor.yy0);
+ yymsp[-6].minor.yy0 = yymsp[-1].minor.yy0;
}
break;
case 295: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
{
- sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy563, &yymsp[0].minor.yy0);
+ sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0);
}
break;
- case 296: /* add_column_fullname ::= fullname */
+ case 296: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
- disableLookaside(pParse);
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy563);
+ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy203, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
+}
+ break;
+ case 297: /* cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */
+{
+ sqlite3AlterDropConstraint(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0, 0);
+}
+ break;
+ case 298: /* cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */
+{
+ sqlite3AlterDropConstraint(pParse, yymsp[-6].minor.yy203, 0, &yymsp[-3].minor.yy0);
}
break;
- case 297: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ case 299: /* cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */
{
- sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy563, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
+ sqlite3AlterSetNotNull(pParse, yymsp[-7].minor.yy203, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0);
}
break;
- case 298: /* cmd ::= create_vtab */
+ case 300: /* cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */
+{
+ sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
+}
+ break;
+ case 301: /* cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */
+{
+ sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
+}
+ break;
+ case 302: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 299: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 303: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 300: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 304: /* 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.yy502);
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy144);
}
break;
- case 301: /* vtabarg ::= */
+ case 305: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 302: /* vtabargtoken ::= ANY */
- case 303: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==303);
- case 304: /* lp ::= LP */ yytestcase(yyruleno==304);
+ case 306: /* vtabargtoken ::= ANY */
+ case 307: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==307);
+ case 308: /* lp ::= LP */ yytestcase(yyruleno==308);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 305: /* with ::= WITH wqlist */
- case 306: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==306);
-{ sqlite3WithPush(pParse, yymsp[0].minor.yy125, 1); }
+ case 309: /* with ::= WITH wqlist */
+ case 310: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==310);
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy59, 1); }
break;
- case 307: /* wqas ::= AS */
-{yymsp[0].minor.yy444 = M10d_Any;}
+ case 311: /* wqas ::= AS */
+{yymsp[0].minor.yy462 = M10d_Any;}
break;
- case 308: /* wqas ::= AS MATERIALIZED */
-{yymsp[-1].minor.yy444 = M10d_Yes;}
+ case 312: /* wqas ::= AS MATERIALIZED */
+{yymsp[-1].minor.yy462 = M10d_Yes;}
break;
- case 309: /* wqas ::= AS NOT MATERIALIZED */
-{yymsp[-2].minor.yy444 = M10d_No;}
+ case 313: /* wqas ::= AS NOT MATERIALIZED */
+{yymsp[-2].minor.yy462 = M10d_No;}
break;
- case 310: /* wqitem ::= withnm eidlist_opt wqas LP select RP */
+ case 314: /* wqitem ::= withnm eidlist_opt wqas LP select RP */
{
- yymsp[-5].minor.yy361 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy637, yymsp[-3].minor.yy444); /*A-overwrites-X*/
+ yymsp[-5].minor.yy67 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy555, yymsp[-3].minor.yy462); /*A-overwrites-X*/
}
break;
- case 311: /* withnm ::= nm */
+ case 315: /* withnm ::= nm */
{pParse->bHasWith = 1;}
break;
- case 312: /* wqlist ::= wqitem */
+ case 316: /* wqlist ::= wqitem */
{
- yymsp[0].minor.yy125 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy361); /*A-overwrites-X*/
+ yymsp[0].minor.yy59 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy67); /*A-overwrites-X*/
}
break;
- case 313: /* wqlist ::= wqlist COMMA wqitem */
+ case 317: /* wqlist ::= wqlist COMMA wqitem */
{
- yymsp[-2].minor.yy125 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy125, yymsp[0].minor.yy361);
+ yymsp[-2].minor.yy59 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy59, yymsp[0].minor.yy67);
}
break;
- case 314: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ case 318: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
{
- assert( yymsp[0].minor.yy483!=0 );
- sqlite3WindowChain(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy483);
- yymsp[0].minor.yy483->pNextWin = yymsp[-2].minor.yy483;
- yylhsminor.yy483 = yymsp[0].minor.yy483;
+ assert( yymsp[0].minor.yy211!=0 );
+ sqlite3WindowChain(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy211);
+ yymsp[0].minor.yy211->pNextWin = yymsp[-2].minor.yy211;
+ yylhsminor.yy211 = yymsp[0].minor.yy211;
}
- yymsp[-2].minor.yy483 = yylhsminor.yy483;
+ yymsp[-2].minor.yy211 = yylhsminor.yy211;
break;
- case 315: /* windowdefn ::= nm AS LP window RP */
+ case 319: /* windowdefn ::= nm AS LP window RP */
{
- if( ALWAYS(yymsp[-1].minor.yy483) ){
- yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
+ if( ALWAYS(yymsp[-1].minor.yy211) ){
+ yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
}
- yylhsminor.yy483 = yymsp[-1].minor.yy483;
+ yylhsminor.yy211 = yymsp[-1].minor.yy211;
}
- yymsp[-4].minor.yy483 = yylhsminor.yy483;
+ yymsp[-4].minor.yy211 = yylhsminor.yy211;
break;
- case 316: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ case 320: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
{
- yymsp[-4].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, 0);
+ yymsp[-4].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, 0);
}
break;
- case 317: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ case 321: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
{
- yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, &yymsp[-5].minor.yy0);
+ yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, &yymsp[-5].minor.yy0);
}
- yymsp[-5].minor.yy483 = yylhsminor.yy483;
+ yymsp[-5].minor.yy211 = yylhsminor.yy211;
break;
- case 318: /* window ::= ORDER BY sortlist frame_opt */
+ case 322: /* window ::= ORDER BY sortlist frame_opt */
{
- yymsp[-3].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, 0);
+ yymsp[-3].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, 0);
}
break;
- case 319: /* window ::= nm ORDER BY sortlist frame_opt */
+ case 323: /* window ::= nm ORDER BY sortlist frame_opt */
{
- yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0);
+ yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0);
}
- yymsp[-4].minor.yy483 = yylhsminor.yy483;
+ yymsp[-4].minor.yy211 = yylhsminor.yy211;
break;
- case 320: /* window ::= nm frame_opt */
+ case 324: /* window ::= nm frame_opt */
{
- yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, 0, &yymsp[-1].minor.yy0);
+ yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, 0, &yymsp[-1].minor.yy0);
}
- yymsp[-1].minor.yy483 = yylhsminor.yy483;
+ yymsp[-1].minor.yy211 = yylhsminor.yy211;
break;
- case 321: /* frame_opt ::= */
+ case 325: /* frame_opt ::= */
{
- yymsp[1].minor.yy483 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
+ yymsp[1].minor.yy211 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
}
break;
- case 322: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ case 326: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
{
- yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy502, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy444);
+ yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy144, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy462);
}
- yymsp[-2].minor.yy483 = yylhsminor.yy483;
+ yymsp[-2].minor.yy211 = yylhsminor.yy211;
break;
- case 323: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ case 327: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
{
- yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy502, yymsp[-3].minor.yy205.eType, yymsp[-3].minor.yy205.pExpr, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, yymsp[0].minor.yy444);
+ yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy144, yymsp[-3].minor.yy509.eType, yymsp[-3].minor.yy509.pExpr, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, yymsp[0].minor.yy462);
}
- yymsp[-5].minor.yy483 = yylhsminor.yy483;
+ yymsp[-5].minor.yy211 = yylhsminor.yy211;
break;
- case 325: /* frame_bound_s ::= frame_bound */
- case 327: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==327);
-{yylhsminor.yy205 = yymsp[0].minor.yy205;}
- yymsp[0].minor.yy205 = yylhsminor.yy205;
+ case 329: /* frame_bound_s ::= frame_bound */
+ case 331: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==331);
+{yylhsminor.yy509 = yymsp[0].minor.yy509;}
+ yymsp[0].minor.yy509 = yylhsminor.yy509;
break;
- case 326: /* frame_bound_s ::= UNBOUNDED PRECEDING */
- case 328: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==328);
- case 330: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==330);
-{yylhsminor.yy205.eType = yymsp[-1].major; yylhsminor.yy205.pExpr = 0;}
- yymsp[-1].minor.yy205 = yylhsminor.yy205;
+ case 330: /* frame_bound_s ::= UNBOUNDED PRECEDING */
+ case 332: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==332);
+ case 334: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==334);
+{yylhsminor.yy509.eType = yymsp[-1].major; yylhsminor.yy509.pExpr = 0;}
+ yymsp[-1].minor.yy509 = yylhsminor.yy509;
break;
- case 329: /* frame_bound ::= expr PRECEDING|FOLLOWING */
-{yylhsminor.yy205.eType = yymsp[0].major; yylhsminor.yy205.pExpr = yymsp[-1].minor.yy590;}
- yymsp[-1].minor.yy205 = yylhsminor.yy205;
+ case 333: /* frame_bound ::= expr PRECEDING|FOLLOWING */
+{yylhsminor.yy509.eType = yymsp[0].major; yylhsminor.yy509.pExpr = yymsp[-1].minor.yy454;}
+ yymsp[-1].minor.yy509 = yylhsminor.yy509;
break;
- case 331: /* frame_exclude_opt ::= */
-{yymsp[1].minor.yy444 = 0;}
+ case 335: /* frame_exclude_opt ::= */
+{yymsp[1].minor.yy462 = 0;}
break;
- case 332: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
-{yymsp[-1].minor.yy444 = yymsp[0].minor.yy444;}
+ case 336: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
+{yymsp[-1].minor.yy462 = yymsp[0].minor.yy462;}
break;
- case 333: /* frame_exclude ::= NO OTHERS */
- case 334: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==334);
-{yymsp[-1].minor.yy444 = yymsp[-1].major; /*A-overwrites-X*/}
+ case 337: /* frame_exclude ::= NO OTHERS */
+ case 338: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==338);
+{yymsp[-1].minor.yy462 = yymsp[-1].major; /*A-overwrites-X*/}
break;
- case 335: /* frame_exclude ::= GROUP|TIES */
-{yymsp[0].minor.yy444 = yymsp[0].major; /*A-overwrites-X*/}
+ case 339: /* frame_exclude ::= GROUP|TIES */
+{yymsp[0].minor.yy462 = yymsp[0].major; /*A-overwrites-X*/}
break;
- case 336: /* window_clause ::= WINDOW windowdefn_list */
-{ yymsp[-1].minor.yy483 = yymsp[0].minor.yy483; }
+ case 340: /* window_clause ::= WINDOW windowdefn_list */
+{ yymsp[-1].minor.yy211 = yymsp[0].minor.yy211; }
break;
- case 337: /* filter_over ::= filter_clause over_clause */
+ case 341: /* filter_over ::= filter_clause over_clause */
{
- if( yymsp[0].minor.yy483 ){
- yymsp[0].minor.yy483->pFilter = yymsp[-1].minor.yy590;
+ if( yymsp[0].minor.yy211 ){
+ yymsp[0].minor.yy211->pFilter = yymsp[-1].minor.yy454;
}else{
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454);
}
- yylhsminor.yy483 = yymsp[0].minor.yy483;
+ yylhsminor.yy211 = yymsp[0].minor.yy211;
}
- yymsp[-1].minor.yy483 = yylhsminor.yy483;
+ yymsp[-1].minor.yy211 = yylhsminor.yy211;
break;
- case 338: /* filter_over ::= over_clause */
+ case 342: /* filter_over ::= over_clause */
{
- yylhsminor.yy483 = yymsp[0].minor.yy483;
+ yylhsminor.yy211 = yymsp[0].minor.yy211;
}
- yymsp[0].minor.yy483 = yylhsminor.yy483;
+ yymsp[0].minor.yy211 = yylhsminor.yy211;
break;
- case 339: /* filter_over ::= filter_clause */
+ case 343: /* filter_over ::= filter_clause */
{
- yylhsminor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yylhsminor.yy483 ){
- yylhsminor.yy483->eFrmType = TK_FILTER;
- yylhsminor.yy483->pFilter = yymsp[0].minor.yy590;
+ yylhsminor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yylhsminor.yy211 ){
+ yylhsminor.yy211->eFrmType = TK_FILTER;
+ yylhsminor.yy211->pFilter = yymsp[0].minor.yy454;
}else{
- sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy590);
+ sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy454);
}
}
- yymsp[0].minor.yy483 = yylhsminor.yy483;
+ yymsp[0].minor.yy211 = yylhsminor.yy211;
break;
- case 340: /* over_clause ::= OVER LP window RP */
+ case 344: /* over_clause ::= OVER LP window RP */
{
- yymsp[-3].minor.yy483 = yymsp[-1].minor.yy483;
- assert( yymsp[-3].minor.yy483!=0 );
+ yymsp[-3].minor.yy211 = yymsp[-1].minor.yy211;
+ assert( yymsp[-3].minor.yy211!=0 );
}
break;
- case 341: /* over_clause ::= OVER nm */
+ case 345: /* over_clause ::= OVER nm */
{
- yymsp[-1].minor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yymsp[-1].minor.yy483 ){
- yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
+ yymsp[-1].minor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yymsp[-1].minor.yy211 ){
+ yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
}
}
break;
- case 342: /* filter_clause ::= FILTER LP WHERE expr RP */
-{ yymsp[-4].minor.yy590 = yymsp[-1].minor.yy590; }
+ case 346: /* filter_clause ::= FILTER LP WHERE expr RP */
+{ yymsp[-4].minor.yy454 = yymsp[-1].minor.yy454; }
break;
- case 343: /* term ::= QNUMBER */
+ case 347: /* term ::= QNUMBER */
{
- yylhsminor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0);
- sqlite3DequoteNumber(pParse, yylhsminor.yy590);
+ yylhsminor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0);
+ sqlite3DequoteNumber(pParse, yylhsminor.yy454);
}
- yymsp[0].minor.yy590 = yylhsminor.yy590;
+ yymsp[0].minor.yy454 = yylhsminor.yy454;
break;
default:
- /* (344) input ::= cmdlist */ yytestcase(yyruleno==344);
- /* (345) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==345);
- /* (346) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=346);
- /* (347) ecmd ::= SEMI */ yytestcase(yyruleno==347);
- /* (348) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==348);
- /* (349) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=349);
- /* (350) trans_opt ::= */ yytestcase(yyruleno==350);
- /* (351) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==351);
- /* (352) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==352);
- /* (353) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==353);
- /* (354) savepoint_opt ::= */ yytestcase(yyruleno==354);
- /* (355) cmd ::= create_table create_table_args */ yytestcase(yyruleno==355);
- /* (356) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=356);
- /* (357) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==357);
- /* (358) columnlist ::= columnname carglist */ yytestcase(yyruleno==358);
- /* (359) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==359);
- /* (360) nm ::= STRING */ yytestcase(yyruleno==360);
- /* (361) typetoken ::= typename */ yytestcase(yyruleno==361);
- /* (362) typename ::= ID|STRING */ yytestcase(yyruleno==362);
- /* (363) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=363);
- /* (364) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=364);
- /* (365) carglist ::= carglist ccons */ yytestcase(yyruleno==365);
- /* (366) carglist ::= */ yytestcase(yyruleno==366);
- /* (367) ccons ::= NULL onconf */ yytestcase(yyruleno==367);
- /* (368) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==368);
- /* (369) ccons ::= AS generated */ yytestcase(yyruleno==369);
- /* (370) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==370);
- /* (371) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==371);
- /* (372) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=372);
- /* (373) tconscomma ::= */ yytestcase(yyruleno==373);
- /* (374) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=374);
- /* (375) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=375);
- /* (376) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=376);
- /* (377) oneselect ::= values */ yytestcase(yyruleno==377);
- /* (378) sclp ::= selcollist COMMA */ yytestcase(yyruleno==378);
- /* (379) as ::= ID|STRING */ yytestcase(yyruleno==379);
- /* (380) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=380);
- /* (381) returning ::= */ yytestcase(yyruleno==381);
- /* (382) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=382);
- /* (383) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==383);
- /* (384) case_operand ::= expr */ yytestcase(yyruleno==384);
- /* (385) exprlist ::= nexprlist */ yytestcase(yyruleno==385);
- /* (386) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=386);
- /* (387) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=387);
- /* (388) nmnum ::= ON */ yytestcase(yyruleno==388);
- /* (389) nmnum ::= DELETE */ yytestcase(yyruleno==389);
- /* (390) nmnum ::= DEFAULT */ yytestcase(yyruleno==390);
- /* (391) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==391);
- /* (392) foreach_clause ::= */ yytestcase(yyruleno==392);
- /* (393) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==393);
- /* (394) trnm ::= nm */ yytestcase(yyruleno==394);
- /* (395) tridxby ::= */ yytestcase(yyruleno==395);
- /* (396) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==396);
- /* (397) database_kw_opt ::= */ yytestcase(yyruleno==397);
- /* (398) kwcolumn_opt ::= */ yytestcase(yyruleno==398);
- /* (399) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==399);
- /* (400) vtabarglist ::= vtabarg */ yytestcase(yyruleno==400);
- /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==401);
- /* (402) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==402);
- /* (403) anylist ::= */ yytestcase(yyruleno==403);
- /* (404) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==404);
- /* (405) anylist ::= anylist ANY */ yytestcase(yyruleno==405);
- /* (406) with ::= */ yytestcase(yyruleno==406);
- /* (407) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=407);
- /* (408) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=408);
+ /* (348) input ::= cmdlist */ yytestcase(yyruleno==348);
+ /* (349) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==349);
+ /* (350) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=350);
+ /* (351) ecmd ::= SEMI */ yytestcase(yyruleno==351);
+ /* (352) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==352);
+ /* (353) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=353);
+ /* (354) trans_opt ::= */ yytestcase(yyruleno==354);
+ /* (355) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==355);
+ /* (356) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==356);
+ /* (357) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==357);
+ /* (358) savepoint_opt ::= */ yytestcase(yyruleno==358);
+ /* (359) cmd ::= create_table create_table_args */ yytestcase(yyruleno==359);
+ /* (360) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=360);
+ /* (361) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==361);
+ /* (362) columnlist ::= columnname carglist */ yytestcase(yyruleno==362);
+ /* (363) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==363);
+ /* (364) nm ::= STRING */ yytestcase(yyruleno==364);
+ /* (365) typetoken ::= typename */ yytestcase(yyruleno==365);
+ /* (366) typename ::= ID|STRING */ yytestcase(yyruleno==366);
+ /* (367) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=367);
+ /* (368) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=368);
+ /* (369) carglist ::= carglist ccons */ yytestcase(yyruleno==369);
+ /* (370) carglist ::= */ yytestcase(yyruleno==370);
+ /* (371) ccons ::= NULL onconf */ yytestcase(yyruleno==371);
+ /* (372) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==372);
+ /* (373) ccons ::= AS generated */ yytestcase(yyruleno==373);
+ /* (374) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==374);
+ /* (375) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==375);
+ /* (376) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=376);
+ /* (377) tconscomma ::= */ yytestcase(yyruleno==377);
+ /* (378) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=378);
+ /* (379) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=379);
+ /* (380) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=380);
+ /* (381) oneselect ::= values */ yytestcase(yyruleno==381);
+ /* (382) sclp ::= selcollist COMMA */ yytestcase(yyruleno==382);
+ /* (383) as ::= ID|STRING */ yytestcase(yyruleno==383);
+ /* (384) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=384);
+ /* (385) returning ::= */ yytestcase(yyruleno==385);
+ /* (386) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=386);
+ /* (387) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==387);
+ /* (388) case_operand ::= expr */ yytestcase(yyruleno==388);
+ /* (389) exprlist ::= nexprlist */ yytestcase(yyruleno==389);
+ /* (390) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=390);
+ /* (391) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=391);
+ /* (392) nmnum ::= ON */ yytestcase(yyruleno==392);
+ /* (393) nmnum ::= DELETE */ yytestcase(yyruleno==393);
+ /* (394) nmnum ::= DEFAULT */ yytestcase(yyruleno==394);
+ /* (395) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==395);
+ /* (396) foreach_clause ::= */ yytestcase(yyruleno==396);
+ /* (397) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==397);
+ /* (398) tridxby ::= */ yytestcase(yyruleno==398);
+ /* (399) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==399);
+ /* (400) database_kw_opt ::= */ yytestcase(yyruleno==400);
+ /* (401) kwcolumn_opt ::= */ yytestcase(yyruleno==401);
+ /* (402) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==402);
+ /* (403) vtabarglist ::= vtabarg */ yytestcase(yyruleno==403);
+ /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==404);
+ /* (405) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==405);
+ /* (406) anylist ::= */ yytestcase(yyruleno==406);
+ /* (407) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==407);
+ /* (408) anylist ::= anylist ANY */ yytestcase(yyruleno==408);
+ /* (409) with ::= */ yytestcase(yyruleno==409);
+ /* (410) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=410);
+ /* (411) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=411);
break;
/********** End reduce actions ************************************************/
};
@@ -183570,8 +186952,8 @@ static const unsigned char aKWCode[148] = {0,
/* Check to see if z[0..n-1] is a keyword. If it is, write the
** parser symbol code for that keyword into *pType. Always
** return the integer n (the length of the token). */
-static int keywordCode(const char *z, int n, int *pType){
- int i, j;
+static i64 keywordCode(const char *z, i64 n, int *pType){
+ i64 i, j;
const char *zKW;
assert( n>=2 );
i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127;
@@ -184125,7 +187507,7 @@ SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *z, int *tokenType){
}
case CC_DOLLAR:
case CC_VARALPHA: {
- int n = 0;
+ i64 n = 0;
testcase( z[0]=='$' ); testcase( z[0]=='@' );
testcase( z[0]==':' ); testcase( z[0]=='#' );
*tokenType = TK_VARIABLE;
@@ -184221,7 +187603,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){
int tokenType; /* type of the next token */
int lastTokenParsed = -1; /* type of the previous token */
sqlite3 *db = pParse->db; /* The database connection */
- int mxSqlLen; /* Max length of an SQL string */
+ i64 mxSqlLen; /* Max length of an SQL string */
Parse *pParentParse = 0; /* Outer parse context, if any */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
yyParser sEngine; /* Space to hold the Lemon-generated Parser object */
@@ -184351,7 +187733,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){
}
if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
if( pParse->zErrMsg==0 ){
- pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
+ pParse->zErrMsg = sqlite3DbStrDup(db, sqlite3ErrStr(pParse->rc));
}
if( (pParse->prepFlags & SQLITE_PREPARE_DONT_LOG)==0 ){
sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
@@ -184432,7 +187814,7 @@ SQLITE_PRIVATE char *sqlite3Normalize(
sqlite3_str_append(pStr, " NULL", 5);
break;
}
- /* Fall through */
+ /* no break */ deliberate_fall_through
}
case TK_STRING:
case TK_INTEGER:
@@ -184496,7 +187878,7 @@ SQLITE_PRIVATE char *sqlite3Normalize(
}
case TK_SELECT: {
iStartIN = 0;
- /* fall through */
+ /* no break */ deliberate_fall_through
}
default: {
if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr);
@@ -184568,15 +187950,55 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[];
#endif
/*
-** Return TRUE if the given SQL string ends in a semicolon.
+** Return zero if the given SQL string is complete - if all comments,
+** string and blob literals, and quoted identifiers have been closed and
+** if the entire string ends with ";" and possibly with ";END;" if the
+** string is a CREATE TRIGGER statement. A non-zero return indicates
+** that the string is empty or incomplete. Bits of the return value
+** indicate what is missing and is needed to close out the statement.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
+** Let the return code be a value R. R is split up into various
+** subfields, at byte boundaries:
+**
+** R = 0xwwwwwwww00xxyyzz
+**
+** In other words, zz is the least significant byte, yy is the next
+** most significant byte, xx is the third byte, wwwwwwww is the upper
+** four bytes of the return value.
+**
+** zz == SQLITE_OK Input is complete
+** zz == SQLITE_ERROR Input is incomplete
+** zz == SQLITE_EMPTY Input contains only whitespace
+** zz == SQLITE_MISUSE Input is a NULL pointer
+** zz != 0 New values for zz may be added in the future
+**
+** yy == 0x01 Need a semicolon at the end
+** yy == 0x02 Need "END" and a semicolon
+** yy == 0x03 Need semicolon, "END", and semicolon
+** yy != 0 New values for yy may be added in the future
+**
+** xx == '\'' Incomplete string or blob literal
+** xx == '"' Incomplete quoted identifier
+** xx == '`' Incompelte MySQL-style quoted identifier
+** xx == ']' Incomplete SQLServer-style quoted identifer
+** xx == '-' Incomplete SQL-style comment
+** xx == '/' Incomplete C-style comment
+** xx != 0 New values of xx may be added in the future
+**
+** wwwwwwww Interpret as a signed integer, the number
+** of unmatched "(". Negative means there are
+** more ")" and "(".
+**
+** ((R>>24)&0xff)!=0 New uses for the 4th byte may be added
+** in the future
+**
** This implementation uses a state machine with 8 states:
**
-** (0) INVALID We have not yet seen a non-whitespace character.
+** (0) NOTHING We have not yet seen a non-whitespace character.
**
** (1) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
@@ -184620,9 +188042,11 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[];
** to recognize the end of a trigger can be omitted. All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
-SQLITE_API int sqlite3_complete(const char *zSql){
+SQLITE_API sqlite3_int64 sqlite3_incomplete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
+ u8 pending = 0; /* unmatched structure character */
+ int nParen = 0; /* Nested parentheses */
#ifndef SQLITE_OMIT_TRIGGER
/* A complex statement machine used to detect the end of a CREATE TRIGGER
@@ -184631,7 +188055,7 @@ SQLITE_API int sqlite3_complete(const char *zSql){
static const u8 trans[8][8] = {
/* Token: */
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
- /* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
+ /* 0 NOTHING: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
/* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, },
/* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, },
/* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, },
@@ -184647,16 +188071,26 @@ SQLITE_API int sqlite3_complete(const char *zSql){
static const u8 trans[3][3] = {
/* Token: */
/* State: ** SEMI WS OTHER */
- /* 0 INVALID: */ { 1, 0, 2, },
+ /* 0 NOTHING: */ { 1, 0, 2, },
/* 1 START: */ { 1, 1, 2, },
/* 2 NORMAL: */ { 1, 2, 2, },
};
#endif /* SQLITE_OMIT_TRIGGER */
+ /* Mapping state number to yy value for the return */
+ static const u8 statemap[8] = {
+ /* 0 NOTHING */ 0,
+ /* 1 START */ 0,
+ /* 2 NORMAL */ 1,
+ /* 3 EXPLAIN */ 1,
+ /* 4 CREATE */ 1,
+ /* 5 TRIGGER */ 3,
+ /* 6 SEMI */ 2,
+ /* 7 END */ 1,
+ };
#ifdef SQLITE_ENABLE_API_ARMOR
if( zSql==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
+ return SQLITE_MISUSE_BKPT;
}
#endif
@@ -184681,7 +188115,10 @@ SQLITE_API int sqlite3_complete(const char *zSql){
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
- if( zSql[0]==0 ) return 0;
+ if( zSql[0]==0 ){
+ pending = '/';
+ goto incomplete_finish;
+ }
zSql++;
token = tkWS;
break;
@@ -184692,14 +188129,20 @@ SQLITE_API int sqlite3_complete(const char *zSql){
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
- if( *zSql==0 ) return state==1;
+ if( *zSql==0 ){
+ pending = '-';
+ goto incomplete_finish;
+ }
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
- if( *zSql==0 ) return 0;
+ if( *zSql==0 ){
+ pending = ']';
+ goto incomplete_finish;
+ }
token = tkOTHER;
break;
}
@@ -184709,7 +188152,20 @@ SQLITE_API int sqlite3_complete(const char *zSql){
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
- if( *zSql==0 ) return 0;
+ if( *zSql==0 ){
+ pending = c;
+ goto incomplete_finish;
+ }
+ token = tkOTHER;
+ break;
+ }
+ case '(': {
+ nParen++;
+ token = tkOTHER;
+ break;
+ }
+ case ')': {
+ nParen--;
token = tkOTHER;
break;
}
@@ -184776,7 +188232,16 @@ SQLITE_API int sqlite3_complete(const char *zSql){
state = trans[state][token];
zSql++;
}
- return state==1;
+incomplete_finish:
+ if( state==0 && pending==0 ) return SQLITE_EMPTY;
+ if( state==1 ) nParen = 0;
+ return (i64)((((u64)nParen)<<32) |
+ ((u64)pending<<16) |
+ ((u64)statemap[state]<<8) |
+ (state>1 || pending!=0));
+}
+SQLITE_API int sqlite3_complete(const char *zSql){
+ return sqlite3_incomplete(zSql)==0;
}
#ifndef SQLITE_OMIT_UTF16
@@ -184798,7 +188263,7 @@ SQLITE_API int sqlite3_complete16(const void *zSql){
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zSql8 ){
- rc = sqlite3_complete(zSql8);
+ rc = sqlite3_incomplete(zSql8)==0;
}else{
rc = SQLITE_NOMEM_BKPT;
}
@@ -185065,17 +188530,29 @@ SQLITE_API char *sqlite3_data_directory = 0;
/*
** Initialize SQLite.
**
-** This routine must be called to initialize the memory allocation,
-** VFS, and mutex subsystems prior to doing any serious work with
-** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
+** The sqlite3_initialize() routine must be called to initialize the
+** memory allocation, VFS, and mutex subsystems prior to doing any
+** serious work. As long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite3_open().
**
** This routine is a no-op except on its very first call for the process,
-** or for the first call after a call to sqlite3_shutdown.
+** or for the first call after a call to sqlite3_shutdown. Most calls
+** to sqlite3_initialize() are, in fact, no-ops. For that reason, the
+** routine is broken into two pieces:
+**
+** sqlite3Initialize() Does the actual work of initialization
**
-** The first thread to call this routine runs the initialization to
-** completion. If subsequent threads call this routine before the first
+** sqlite3_initialize() Checks to see if initialization is needed
+** and invokes sqlite3Initialize() if it is.
+**
+** The sqlite3_initialize() interface is called frequently, but
+** sqlite3Initialize() runs rarely. The function is broken up this way
+** to avoid wasting CPU cycles with unnecessary stack setup for local
+** variables in cases where it is not needed.
+**
+** The first thread to call sqlite3_initialize() runs the initialization to
+** completion. If subsequent threads call sqlite3_initialize() before the first
** thread has finished the initialization process, then the subsequent
** threads must block until the first thread finishes with the initialization.
**
@@ -185083,44 +188560,29 @@ SQLITE_API char *sqlite3_data_directory = 0;
** calls to this routine should not block, of course. Otherwise the
** initialization process would never complete.
**
-** Let X be the first thread to enter this routine. Let Y be some other
-** thread. Then while the initial invocation of this routine by X is
-** incomplete, it is required that:
+** Let X be the first thread to enter sqlite3_initialize(). Let Y be some
+** other thread. While the initial invocation of sqlite3_initialize() by X
+** is incomplete, it is required that:
**
-** * Calls to this routine from Y must block until the outer-most
+** * Calls to sqlite3_initialize() from Y must block until the outer-most
** call by X completes.
**
-** * Recursive calls to this routine from thread X return immediately
-** without blocking.
+** * Recursive calls to sqlite3_initialize() from thread X return
+** immediately without blocking.
*/
-SQLITE_API int sqlite3_initialize(void){
- MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */
- int rc; /* Result code */
+static SQLITE_NOINLINE int sqlite3Initialize(void){
+ MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */
+ int rc; /* Result code */
#ifdef SQLITE_EXTRA_INIT
- int bRunExtraInit = 0; /* Extra initialization needed */
-#endif
-
-#ifdef SQLITE_OMIT_WSD
- rc = sqlite3_wsd_init(4096, 24);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ int bRunExtraInit = 0; /* Extra initialization needed */
#endif
/* If the following assert() fails on some obscure processor/compiler
- ** combination, the work-around is to set the correct pointer
- ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */
- assert( SQLITE_PTRSIZE==sizeof(char*) );
-
- /* If SQLite is already completely initialized, then this call
- ** to sqlite3_initialize() should be a no-op. But the initialization
- ** must be complete. So isInit must not be set until the very end
- ** of this routine.
+ ** combination to warn that SQLite has been mis-compiled. If you hit
+ ** this assert(), that means you need to recompile with the
+ ** -DSQLITE_PTRSIZE=n compile-time option to set the correct pointer size.
*/
- if( sqlite3GlobalConfig.isInit ){
- sqlite3MemoryBarrier();
- return SQLITE_OK;
- }
+ assert( SQLITE_PTRSIZE==sizeof(char*) );
/* Make sure the mutex subsystem is initialized. If unable to
** initialize the mutex subsystem, return early with the error.
@@ -185266,6 +188728,26 @@ SQLITE_API int sqlite3_initialize(void){
#endif
return rc;
}
+SQLITE_API int sqlite3_initialize(void){
+ /* If this build does not support writable static data (WSD) natively
+ ** then we have to invoke the (application-supplied) WSD initialization
+ ** routine before doing anything else. */
+#ifdef SQLITE_OMIT_WSD
+ int rc = sqlite3_wsd_init(4096, 24);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+#endif
+
+ if( sqlite3GlobalConfig.isInit ){
+ /* SQLite has already been initialized. Fast early-out. */
+ sqlite3MemoryBarrier();
+ return SQLITE_OK;
+ }else{
+ /* Invoke sqlite3Initialize() to do the actual work. */
+ return sqlite3Initialize();
+ }
+}
/*
** Undo the effects of sqlite3_initialize(). Must not be called while
@@ -185424,7 +188906,7 @@ SQLITE_API int sqlite3_config(int op, ...){
break;
}
case SQLITE_CONFIG_SMALL_MALLOC: {
- sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int);
+ sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int)!=0;
break;
}
case SQLITE_CONFIG_PAGECACHE: {
@@ -185877,6 +189359,14 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
rc = setupLookaside(db, pBuf, sz, cnt);
break;
}
+ case SQLITE_DBCONFIG_FP_DIGITS: {
+ int nIn = va_arg(ap, int);
+ int *pOut = va_arg(ap, int*);
+ if( nIn>3 && nIn<24 ) db->nFpDigit = (u8)nIn;
+ if( pOut ) *pOut = db->nFpDigit;
+ rc = SQLITE_OK;
+ break;
+ }
default: {
static const struct {
int op; /* The opcode */
@@ -185939,7 +189429,7 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
** This is the default collating function named "BINARY" which is always
** available.
*/
-static int binCollFunc(
+SQLITE_PRIVATE int sqlite3BinaryCompare(
void *NotUsed,
int nKey1, const void *pKey1,
int nKey2, const void *pKey2
@@ -185971,16 +189461,19 @@ static int rtrimCollFunc(
const u8 *pK2 = (const u8*)pKey2;
while( nKey1 && pK1[nKey1-1]==' ' ) nKey1--;
while( nKey2 && pK2[nKey2-1]==' ' ) nKey2--;
- return binCollFunc(pUser, nKey1, pKey1, nKey2, pKey2);
+ return sqlite3BinaryCompare(pUser, nKey1, pKey1, nKey2, pKey2);
}
/*
** Return true if CollSeq is the default built-in BINARY.
*/
+#if !SQLITE_USES_INLINE
SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq *p){
- assert( p==0 || p->xCmp!=binCollFunc || strcmp(p->zName,"BINARY")==0 );
- return p==0 || p->xCmp==binCollFunc;
+ assert( p==0 || p->xCmp!=sqlite3BinaryCompare
+ || strcmp(p->zName,"BINARY")==0 );
+ return p==0 || p->xCmp==sqlite3BinaryCompare;
}
+#endif
/*
** Another built-in collating sequence: NOCASE.
@@ -186009,13 +189502,17 @@ static int nocaseCollatingFunc(
** Return the ROWID of the most recent insert
*/
SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
+ i64 iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->lastRowid;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->lastRowid;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
/*
@@ -186034,16 +189531,21 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid)
}
/*
-** Return the number of changes in the most recent call to sqlite3_exec().
+** Return the number of changes in the most recently executed DML
+** statement.
*/
SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){
+ i64 iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->nChange;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->nChange;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_changes(sqlite3 *db){
return (int)sqlite3_changes64(db);
@@ -186053,13 +189555,17 @@ SQLITE_API int sqlite3_changes(sqlite3 *db){
** Return the number of changes since the database handle was opened.
*/
SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
+ i64 iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->nTotalChange;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->nTotalChange;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_total_changes(sqlite3 *db){
return (int)sqlite3_total_changes64(db);
@@ -186742,6 +190248,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
+ sqlite3_mutex_enter(db->mutex);
if( ms>0 ){
sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
(void*)db);
@@ -186752,6 +190259,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
}else{
sqlite3_busy_handler(db, 0, 0);
}
+ sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -186917,7 +190425,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
if( db->nVdbeActive ){
sqlite3ErrorWithMsg(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
- assert( !db->mallocFailed );
+ assert( !db->mallocFailed || db->nVdbeExec>0 );
return SQLITE_BUSY;
}else{
sqlite3ExpirePreparedStatements(db, 0);
@@ -187432,6 +190940,9 @@ SQLITE_API void *sqlite3_wal_hook(
sqlite3_mutex_leave(db->mutex);
return pRet;
#else
+ UNUSED_PARAMETER(db);
+ UNUSED_PARAMETER(xCallback);
+ UNUSED_PARAMETER(pArg);
return 0;
#endif
}
@@ -187447,6 +190958,11 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
int *pnCkpt /* OUT: Total number of frames checkpointed */
){
#ifdef SQLITE_OMIT_WAL
+ UNUSED_PARAMETER(db);
+ UNUSED_PARAMETER(zDb);
+ UNUSED_PARAMETER(eMode);
+ UNUSED_PARAMETER(pnLog);
+ UNUSED_PARAMETER(pnCkpt);
return SQLITE_OK;
#else
int rc; /* Return code */
@@ -187460,11 +190976,12 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
if( pnLog ) *pnLog = -1;
if( pnCkpt ) *pnCkpt = -1;
+ assert( SQLITE_CHECKPOINT_NOOP==-1 );
assert( SQLITE_CHECKPOINT_PASSIVE==0 );
assert( SQLITE_CHECKPOINT_FULL==1 );
assert( SQLITE_CHECKPOINT_RESTART==2 );
assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
- if( eModeSQLITE_CHECKPOINT_TRUNCATE ){
+ if( eModeSQLITE_CHECKPOINT_TRUNCATE ){
/* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint
** mode: */
return SQLITE_MISUSE_BKPT;
@@ -187648,9 +191165,11 @@ SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zMsg){
*/
SQLITE_API int sqlite3_error_offset(sqlite3 *db){
int iOffset = -1;
- if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
+ if( db && sqlite3SafetyCheckSickOrOk(db) ){
sqlite3_mutex_enter(db->mutex);
- iOffset = db->errByteOffset;
+ if( db->errCode ){
+ iOffset = db->errByteOffset;
+ }
sqlite3_mutex_leave(db->mutex);
}
return iOffset;
@@ -187704,25 +191223,43 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
** passed to this function, we assume a malloc() failed during sqlite3_open().
*/
SQLITE_API int sqlite3_errcode(sqlite3 *db){
- if( db && !sqlite3SafetyCheckSickOrOk(db) ){
+ int iRet;
+ if( !db ) return SQLITE_NOMEM_BKPT;
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
- if( !db || db->mallocFailed ){
- return SQLITE_NOMEM_BKPT;
+ sqlite3_mutex_enter(db->mutex);
+ if( db->mallocFailed ){
+ iRet = SQLITE_NOMEM_BKPT;
+ }else{
+ iRet = db->errCode & db->errMask;
}
- return db->errCode & db->errMask;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
- if( db && !sqlite3SafetyCheckSickOrOk(db) ){
+ int iRet;
+ if( !db ) return SQLITE_NOMEM_BKPT;
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
- if( !db || db->mallocFailed ){
- return SQLITE_NOMEM_BKPT;
+ sqlite3_mutex_enter(db->mutex);
+ if( db->mallocFailed ){
+ iRet = SQLITE_NOMEM_BKPT;
+ }else{
+ iRet = db->errCode;
}
- return db->errCode;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_system_errno(sqlite3 *db){
- return db ? db->iSysErrno : 0;
+ int iRet = 0;
+ if( db ){
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->iSysErrno;
+ sqlite3_mutex_leave(db->mutex);
+ }
+ return iRet;
}
/*
@@ -187828,6 +191365,9 @@ static const int aHardLimit[] = {
SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */
SQLITE_MAX_TRIGGER_DEPTH,
SQLITE_MAX_WORKER_THREADS,
+ SQLITE_MAX_PARSER_DEPTH,
+ SQLITE_MAX_SCHEMA,
+ SQLITE_MAX_TRIGGER_STEPS,
};
/*
@@ -187842,6 +191382,9 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH
# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH
#endif
+#if SQLITE_MAX_SQL_LENGTH>2147482624 /* 1024 less than 2^31 */
+# error SQLITE_MAX_SQL_LENGTH must not be greater than 2147482624
+#endif
#if SQLITE_MAX_COMPOUND_SELECT<2
# error SQLITE_MAX_COMPOUND_SELECT must be at least 2
#endif
@@ -187866,6 +191409,9 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_WORKER_THREADS<0 || SQLITE_MAX_WORKER_THREADS>50
# error SQLITE_MAX_WORKER_THREADS must be between 0 and 50
#endif
+#if SQLITE_MAX_TRIGGER_STEPS<0 || SQLITE_MAX_TRIGGER_STEPS>65535
+# error SQLITE_MAX_TRIGGER_STEPS must be between 0 and 65535
+#endif
/*
@@ -187897,6 +191443,7 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH );
assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN );
assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH );
+ assert( aHardLimit[SQLITE_LIMIT_PARSER_DEPTH]==SQLITE_MAX_PARSER_DEPTH );
assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT);
assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP );
assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG );
@@ -187906,12 +191453,15 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER);
assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH );
assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS );
- assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) );
+ assert( aHardLimit[SQLITE_LIMIT_SCHEMA]==SQLITE_MAX_SCHEMA );
+ assert( aHardLimit[SQLITE_LIMIT_TRIGGER_STEPS]==SQLITE_MAX_TRIGGER_STEPS );
+ assert( SQLITE_LIMIT_TRIGGER_STEPS==(SQLITE_N_LIMIT-1) );
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
return -1;
}
+ sqlite3_mutex_enter(db->mutex);
oldLimit = db->aLimit[limitId];
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
@@ -187921,6 +191471,7 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
}
db->aLimit[limitId] = newLimit;
}
+ sqlite3_mutex_leave(db->mutex);
return oldLimit; /* IMP: R-53341-35419 */
}
@@ -187963,7 +191514,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
const char *zVfs = zDefaultVfs;
char *zFile;
char c;
- int nUri = sqlite3Strlen30(zUri);
+ i64 nUri = strlen(zUri);
assert( *pzErrMsg==0 );
@@ -187973,8 +191524,8 @@ SQLITE_PRIVATE int sqlite3ParseUri(
){
char *zOpt;
int eState; /* Parser state when parsing URI */
- int iIn; /* Input character index */
- int iOut = 0; /* Output character index */
+ i64 iIn; /* Input character index */
+ i64 iOut = 0; /* Output character index */
u64 nByte = nUri+8; /* Bytes of space to allocate */
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
@@ -188008,7 +191559,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
- iIn-7, &zUri[7]);
+ (int)(iIn-7), &zUri[7]);
rc = SQLITE_ERROR;
goto parse_uri_out;
}
@@ -188083,11 +191634,11 @@ SQLITE_PRIVATE int sqlite3ParseUri(
** here. Options that are interpreted here include "vfs" and those that
** correspond to flags that may be passed to the sqlite3_open_v2()
** method. */
- zOpt = &zFile[sqlite3Strlen30(zFile)+1];
+ zOpt = &zFile[strlen(zFile)+1];
while( zOpt[0] ){
- int nOpt = sqlite3Strlen30(zOpt);
+ i64 nOpt = strlen(zOpt);
char *zVal = &zOpt[nOpt+1];
- int nVal = sqlite3Strlen30(zVal);
+ i64 nVal = strlen(zVal);
if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
zVfs = zVal;
@@ -188133,7 +191684,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
int mode = 0;
for(i=0; aMode[i].z; i++){
const char *z = aMode[i].z;
- if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
+ if( nVal==(i64)strlen(z) && 0==memcmp(zVal, z, nVal) ){
mode = aMode[i].mode;
break;
}
@@ -188270,7 +191821,7 @@ static int openDatabase(
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
if( isThreadsafe
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+#if defined(SQLITE_THREAD_MISUSE_WARNINGS)
|| sqlite3GlobalConfig.bCoreMutex
#endif
){
@@ -188291,6 +191842,7 @@ static int openDatabase(
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
+ db->nFpDigit = 17;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
@@ -188395,9 +191947,12 @@ static int openDatabase(
** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating
** functions:
*/
- createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0);
- createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0);
- createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0);
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0,
+ sqlite3BinaryCompare, 0);
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0,
+ sqlite3BinaryCompare, 0);
+ createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0,
+ sqlite3BinaryCompare, 0);
createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
createCollation(db, "RTRIM", SQLITE_UTF8, 0, rtrimCollFunc, 0);
if( db->mallocFailed ){
@@ -188736,6 +192291,12 @@ SQLITE_API int sqlite3_collation_needed16(
*/
SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){
DbClientData *p;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !zName || !sqlite3SafetyCheckOk(db) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return 0;
+ }
+#endif
sqlite3_mutex_enter(db->mutex);
for(p=db->pDbData; p; p=p->pNext){
if( strcmp(p->zName, zName)==0 ){
@@ -188811,13 +192372,17 @@ SQLITE_API int sqlite3_global_recover(void){
** by the next COMMIT or ROLLBACK.
*/
SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
+ int iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->autoCommit;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->autoCommit;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
/*
@@ -189593,6 +193158,17 @@ SQLITE_API int sqlite3_test_control(int op, ...){
break;
}
+ /* sqlite3_test_control(SQLITE_TESTCTRL_ATOF, const char *z, double *p);
+ **
+ ** Test access to the sqlite3AtoF() routine.
+ */
+ case SQLITE_TESTCTRL_ATOF: {
+ const char *z = va_arg(ap,const char*);
+ double *pR = va_arg(ap,double*);
+ rc = sqlite3AtoF(z,pR);
+ break;
+ }
+
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
**
@@ -189809,6 +193385,7 @@ SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){
}
SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){
#ifdef SQLITE_OMIT_WAL
+ UNUSED_PARAMETER(zFilename);
return 0;
#else
zFilename = sqlite3_filename_journal(zFilename);
@@ -189830,17 +193407,19 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
** of range.
*/
SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N){
+ const char *zRet = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- if( N<0 || N>=db->nDb ){
- return 0;
- }else{
- return db->aDb[N].zDbSName;
+ sqlite3_mutex_enter(db->mutex);
+ if( N>=0 && NnDb ){
+ zRet = db->aDb[N].zDbSName;
}
+ sqlite3_mutex_leave(db->mutex);
+ return zRet;
}
/*
@@ -191182,7 +194761,16 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
-#define deliberate_fall_through
+#if !defined(deliberate_fall_through)
+# if defined(__has_attribute)
+# if __has_attribute(fallthrough)
+# define deliberate_fall_through __attribute__((fallthrough));
+# endif
+# endif
+#endif
+#if !defined(deliberate_fall_through)
+# define deliberate_fall_through
+#endif
/*
** Macros needed to provide flexible arrays in a portable way
@@ -191580,6 +195168,15 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
(*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
)
+SQLITE_PRIVATE int sqlite3Fts3PrepareStmt(
+ Fts3Table *p, /* Prepare for this connection */
+ const char *zSql, /* SQL to prepare */
+ int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */
+ int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */
+ sqlite3_stmt **pp /* OUT: Prepared statement */
+);
+
+
/* fts3.c */
SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
@@ -191673,6 +195270,12 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
SQLITE_EXTENSION_INIT1
#endif
+
+/*
+** Assume any b-tree layer with more levels than this is corrupt.
+*/
+#define FTS3_MAX_BTREE_HEIGHT 48
+
typedef struct Fts3HashWrapper Fts3HashWrapper;
struct Fts3HashWrapper {
Fts3Hash hash; /* Hash table */
@@ -192495,7 +196098,10 @@ static int fts3ContentColumns(
** nul-terminator byte. */
nCol = sqlite3_column_count(pStmt);
for(i=0; izReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
p->bLock++;
- rc = sqlite3_prepare_v3(
- p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
- );
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt);
p->bLock--;
sqlite3_free(zSql);
}
@@ -193391,7 +196996,11 @@ static int fts3SelectLeaf(
assert( piLeaf || piLeaf2 );
fts3GetVarint32(zNode, &iHeight);
- rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
+ if( iHeight>FTS3_MAX_BTREE_HEIGHT ){
+ rc = FTS_CORRUPT_VTAB;
+ }else{
+ rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
+ }
assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
if( rc==SQLITE_OK && iHeight>1 ){
@@ -193436,8 +197045,13 @@ static void fts3PutDeltaVarint(
sqlite3_int64 iVal /* Write this value to the list */
){
assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
- *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
- *piPrev = iVal;
+ if( iVal-(*piPrev)>=0 ){
+ /* Refuse to write a negative delta integer. This only happens with a
+ ** corrupt db (see the assert above) and can cause buffer overwrites
+ ** in some cases. */
+ *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
+ *piPrev = iVal;
+ }
}
/*
@@ -194764,9 +198378,7 @@ static int fts3FilterMethod(
}
if( zSql ){
p->bLock++;
- rc = sqlite3_prepare_v3(
- p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
- );
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt);
p->bLock--;
sqlite3_free(zSql);
}else{
@@ -195079,12 +198691,13 @@ static void fts3SnippetFunc(
int nVal, /* Size of apVal[] array */
sqlite3_value **apVal /* Array of arguments */
){
+ Fts3Table *pTab = 0;
Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
const char *zStart = "";
const char *zEnd = "";
const char *zEllipsis = "...";
- int iCol = -1;
- int nToken = 15; /* Default number of tokens in snippet */
+ i64 iCol = -1;
+ i64 nToken = 15; /* Default number of tokens in snippet */
/* There must be at least one argument passed to this function (otherwise
** the non-overloaded version would have been called instead of this one).
@@ -195097,11 +198710,12 @@ static void fts3SnippetFunc(
return;
}
if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;
+ pTab = (Fts3Table *)pCsr->base.pVtab;
switch( nVal ){
- case 6: nToken = sqlite3_value_int(apVal[5]);
+ case 6: nToken = sqlite3_value_int64(apVal[5]);
/* no break */ deliberate_fall_through
- case 5: iCol = sqlite3_value_int(apVal[4]);
+ case 5: iCol = sqlite3_value_int64(apVal[4]);
/* no break */ deliberate_fall_through
case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
/* no break */ deliberate_fall_through
@@ -195111,9 +198725,12 @@ static void fts3SnippetFunc(
}
if( !zEllipsis || !zEnd || !zStart ){
sqlite3_result_error_nomem(pContext);
- }else if( nToken==0 ){
+ }else if( nToken==0 || iCol>=pTab->nColumn ){
sqlite3_result_text(pContext, "", -1, SQLITE_STATIC);
}else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
+ if( iCol<0 ) iCol = -1;
+ if( nToken<-64 ) nToken = -64;
+ if( nToken>64 ) nToken = 64;
sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
}
}
@@ -195389,6 +199006,7 @@ static int fts3IntegrityMethod(
UNUSED_PARAMETER(isQuick);
rc = sqlite3Fts3IntegrityCheck(p, &bOk);
+ assert( pVtab->zErrMsg==0 || rc!=SQLITE_OK );
assert( rc!=SQLITE_CORRUPT_VTAB );
if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
@@ -195792,6 +199410,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
char *p1;
char *p2;
char *aOut;
+ i64 nAlloc = (i64)nPoslist*2 + FTS3_BUFFER_PADDING;
if( nMaxUndeferred>iPrev ){
p1 = aPoslist;
@@ -195803,7 +199422,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
nDistance = iPrev - nMaxUndeferred;
}
- aOut = (char *)sqlite3Fts3MallocZero(((i64)nPoslist)+FTS3_BUFFER_PADDING);
+ aOut = (char *)sqlite3Fts3MallocZero(nAlloc);
if( !aOut ){
sqlite3_free(aPoslist);
return SQLITE_NOMEM;
@@ -197723,6 +201342,14 @@ static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){
#define FTS4AUX_GE_CONSTRAINT 2
#define FTS4AUX_LE_CONSTRAINT 4
+/*
+** Return true if constraint iCons of pInfo uses the "binary" collation
+** sequence. Or false it it uses anything else.
+*/
+static int fts3auxIsBinary(sqlite3_index_info *pInfo, int iCons){
+ return 0==sqlite3_stricmp("binary", sqlite3_vtab_collation(pInfo, iCons));
+}
+
/*
** xBestIndex - Analyze a WHERE and ORDER BY clause.
*/
@@ -197750,7 +201377,7 @@ static int fts3auxBestIndexMethod(
/* Search for equality and range constraints on the "term" column.
** And equality constraints on the hidden "languageid" column. */
for(i=0; inConstraint; i++){
- if( pInfo->aConstraint[i].usable ){
+ if( pInfo->aConstraint[i].usable && fts3auxIsBinary(pInfo, i) ){
int op = pInfo->aConstraint[i].op;
int iCol = pInfo->aConstraint[i].iColumn;
@@ -197905,7 +201532,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->aStat[1].nDoc++;
}
eState = 2;
- /* fall through */
+ /* no break */ deliberate_fall_through
case 2:
if( v==0 ){ /* 0x00. Next integer will be a docid. */
@@ -197921,7 +201548,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
/* State 3. The integer just read is a column number. */
default: assert( eState==3 );
iCol = (int)v;
- if( iCol<1 ){
+ if( iCol<1 || iCol>32767 ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
@@ -197996,7 +201623,7 @@ static int fts3auxFilterMethod(
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
- if( iEq>=0 || iGe>=0 ){
+ if( (iEq>=0 || iGe>=0) && sqlite3_value_type(apVal[0])==SQLITE_TEXT ){
const unsigned char *zStr = sqlite3_value_text(apVal[0]);
assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
if( zStr ){
@@ -198006,7 +201633,7 @@ static int fts3auxFilterMethod(
}
}
- if( iLe>=0 ){
+ if( iLe>=0 && sqlite3_value_type(apVal[0])==SQLITE_TEXT ){
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
pCsr->nStop = (int)strlen(pCsr->zStop);
@@ -198611,6 +202238,7 @@ static int getNextNode(
assert( nKey==4 );
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
+ if( nNear>=1000000000 ) nNear = 1000000000;
}
}
@@ -198688,7 +202316,7 @@ static int getNextNode(
iColLen = 0;
for(ii=0; iinCol; ii++){
const char *zStr = pParse->azCol[ii];
- int nStr = (int)strlen(zStr);
+ int nStr = zStr ? (int)strlen(zStr) : 0;
if( nInput>nStr && zInput[nStr]==':'
&& sqlite3_strnicmp(zStr, zInput, nStr)==0
){
@@ -199403,7 +203031,9 @@ static void fts3ExprTestCommon(
);
}
- if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
+ if( rc==SQLITE_OK && fts3ExprCheckDepth(pExpr, SQLITE_FTS3_MAX_EXPR_DEPTH) ){
+ sqlite3_result_error(context, "Expression nested too deep", -1);
+ }else if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
sqlite3_result_error(context, "Error parsing expression", -1);
}else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
sqlite3_result_error_nomem(context);
@@ -200464,10 +204094,11 @@ static int porterNext(
if( c->iOffset>iStartOffset ){
int n = c->iOffset-iStartOffset;
if( n>c->nAllocated ){
+ i64 nNew = n + 20;
char *pNew;
- c->nAllocated = n+20;
- pNew = sqlite3_realloc64(c->zToken, c->nAllocated);
+ pNew = sqlite3_realloc64(c->zToken, nNew);
if( !pNew ) return SQLITE_NOMEM;
+ c->nAllocated = (int)nNew;
c->zToken = pNew;
}
porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
@@ -201826,9 +205457,9 @@ typedef struct SegmentWriter SegmentWriter;
** incrementally. See function fts3PendingListAppend() for details.
*/
struct PendingList {
- int nData;
+ sqlite3_int64 nData;
char *aData;
- int nSpace;
+ sqlite3_int64 nSpace;
sqlite3_int64 iLastDocid;
sqlite3_int64 iLastCol;
sqlite3_int64 iLastPos;
@@ -202001,6 +205632,24 @@ struct SegmentNode {
#define SQL_UPDATE_LEVEL_IDX 38
#define SQL_UPDATE_LEVEL 39
+/*
+** Wrapper around sqlite3_prepare_v3() to ensure that SQLITE_PREPARE_FROM_DDL
+** is always set.
+*/
+SQLITE_PRIVATE int sqlite3Fts3PrepareStmt(
+ Fts3Table *p, /* Prepare for this connection */
+ const char *zSql, /* SQL to prepare */
+ int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */
+ int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */
+ sqlite3_stmt **pp /* OUT: Prepared statement */
+){
+ int f = SQLITE_PREPARE_FROM_DDL
+ |((bAllowVtab==0) ? SQLITE_PREPARE_NO_VTAB : 0)
+ |(bPersist ? SQLITE_PREPARE_PERSISTENT : 0);
+
+ return sqlite3_prepare_v3(p->db, zSql, -1, f, pp, NULL);
+}
+
/*
** This function is used to obtain an SQLite prepared statement handle
** for the statement identified by the second argument. If successful,
@@ -202126,12 +205775,12 @@ static int fts3SqlStmt(
pStmt = p->aStmt[eStmt];
if( !pStmt ){
- int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
+ int bAllowVtab = 0;
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;
+ bAllowVtab = 1;
zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
}else{
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
@@ -202139,7 +205788,7 @@ static int fts3SqlStmt(
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
- rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 1, bAllowVtab, &pStmt);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pStmt==0 );
p->aStmt[eStmt] = pStmt;
@@ -202488,7 +206137,9 @@ static int fts3PendingTermsAddOne(
pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
if( pList ){
- p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
+ assert( (i64)pList->nData+(i64)nToken+(i64)sizeof(Fts3HashElem)
+ <= (i64)p->nPendingData );
+ p->nPendingData -= (int)(pList->nData + nToken + sizeof(Fts3HashElem));
}
if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
@@ -202501,7 +206152,9 @@ static int fts3PendingTermsAddOne(
}
}
if( rc==SQLITE_OK ){
- p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
+ assert( (i64)p->nPendingData + pList->nData + nToken
+ + sizeof(Fts3HashElem) <= 0x3fffffff );
+ p->nPendingData += (int)(pList->nData + nToken + sizeof(Fts3HashElem));
}
return rc;
}
@@ -204835,6 +208488,10 @@ static void fts3ReadEndBlockField(
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
+
+ /* This if() clause is just to avoid an integer overflow. The record is
+ ** corrupt in this case. */
+ if( (i64)iVal==SMALLEST_INT64 ) iMul = 1;
*pnByte = ((i64)iVal * (i64)iMul);
}
}
@@ -205302,7 +208959,7 @@ static int fts3DoRebuild(Fts3Table *p){
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt);
sqlite3_free(zSql);
}
@@ -206061,7 +209718,7 @@ static int fts3IncrmergeLoad(
return FTS_CORRUPT_VTAB;
}
- pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
+ pWriter->nLeafEst = (int)(((iEnd - iStart)+1)/FTS_MAX_APPENDABLE_HEIGHT);
pWriter->iStart = iStart;
pWriter->iEnd = iEnd;
pWriter->iAbsLevel = iAbsLevel;
@@ -206969,38 +210626,42 @@ static u64 fts3ChecksumIndex(
rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
}
- if( rc==SQLITE_OK ){
- while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){
- char *pCsr = csr.aDoclist;
- char *pEnd = &pCsr[csr.nDoclist];
+ while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p,&csr)) ){
+ char *pCsr = csr.aDoclist;
+ char *pEnd = &pCsr[csr.nDoclist];
- i64 iDocid = 0;
- i64 iCol = 0;
- u64 iPos = 0;
+ i64 iDocid = 0;
+ int iCol = 0;
+ u64 iPos = 0;
- pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
- while( pCsrbDescIdx ){
+ iDocid = (i64)((u64)iDocid - iVal);
}else{
- pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
- if( p->bDescIdx ){
- iDocid = (i64)((u64)iDocid - iVal);
- }else{
- iDocid = (i64)((u64)iDocid + iVal);
- }
+ iDocid = (i64)((u64)iDocid + iVal);
}
+ }
+ }else{
+ iPos += (iVal - 2);
+ if( iPos>0x7FFFFFFF ){
+ rc = SQLITE_CORRUPT_VTAB;
+ break;
}else{
- iPos += (iVal - 2);
cksum = cksum ^ fts3ChecksumEntry(
csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid,
- (int)iCol, (int)iPos
+ iCol, (int)iPos
);
}
}
@@ -207027,6 +210688,7 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
u64 cksum1 = 0; /* Checksum based on FTS index contents */
u64 cksum2 = 0; /* Checksum based on %_content contents */
sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */
+ int bContentless = (p->zContentTbl && p->zContentTbl[0]=='\0');
/* This block calculates the checksum according to the FTS index. */
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
@@ -207046,7 +210708,7 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
}
/* This block calculates the checksum according to the %_content table */
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && !bContentless ){
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
sqlite3_stmt *pStmt = 0;
char *zSql;
@@ -207055,7 +210717,7 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt);
sqlite3_free(zSql);
}
@@ -207104,7 +210766,7 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
rc = SQLITE_OK;
*pbOk = 0;
}else{
- *pbOk = (rc==SQLITE_OK && cksum1==cksum2);
+ *pbOk = (rc==SQLITE_OK && (bContentless || cksum1==cksum2));
}
return rc;
}
@@ -207185,7 +210847,7 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
v = atoi(&zVal[9]);
if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v;
rc = SQLITE_OK;
- }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
+ }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 11) ){
v = atoi(&zVal[11]);
if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v;
rc = SQLITE_OK;
@@ -207697,10 +211359,9 @@ struct StrBuffer {
/*
** Allocate a two-slot MatchinfoBuffer object.
*/
-static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
+static MatchinfoBuffer *fts3MIBufferNew(i64 nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
- sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
- + SZ_MATCHINFOBUFFER(1);
+ sqlite3_int64 nByte = sizeof(u32) * (2*(i64)nElem+1) + SZ_MATCHINFOBUFFER(1);
sqlite3_int64 nStr = strlen(zMatchinfo);
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
@@ -208094,6 +211755,7 @@ static int fts3BestSnippet(
sqlite3_int64 nByte; /* Number of bytes of space to allocate */
int iBestScore = -1; /* Best snippet score found so far */
int i; /* Loop counter */
+ Fts3Expr *pExpr = pCsr->pExpr;
memset(&sIter, 0, sizeof(sIter));
@@ -208122,9 +211784,12 @@ static int fts3BestSnippet(
sIter.nSnippet = nSnippet;
sIter.nPhrase = nList;
sIter.iCurrent = -1;
- rc = sqlite3Fts3ExprIterate(
- pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter
- );
+ rc = sqlite3Fts3ExprIterate(pExpr, fts3SnippetFindPositions, (void*)&sIter);
+ if( rc==SQLITE_OK ){
+ /* Iterate through the expression twice, in case pointers garnered during
+ ** the first iteration are invalidated by a call to fts5EvalRestart(). */
+ rc = sqlite3Fts3ExprIterate(pExpr, fts3SnippetFindPositions, (void*)&sIter);
+ }
if( rc==SQLITE_OK ){
/* Set the *pmSeen output variable. */
@@ -208179,8 +211844,8 @@ static int fts3StringAppend(
** to grow the buffer until so that it is big enough to accommodate the
** appended data.
*/
- if( pStr->n+nAppend+1>=pStr->nAlloc ){
- sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
+ if( (i64)pStr->n+(i64)nAppend+1>=(i64)pStr->nAlloc ){
+ i64 nAlloc = pStr->nAlloc+(i64)nAppend+100;
char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
if( !zNew ){
return SQLITE_NOMEM;
@@ -208452,7 +212117,7 @@ static int fts3ExprLHits(
if( p->flag==FTS3_MATCHINFO_LHITS ){
p->aMatchinfo[iStart + iCol] = (u32)nHit;
}else if( nHit ){
- p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
+ p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
}
}
assert( *pIter==0x00 || *pIter==0x01 );
@@ -208571,8 +212236,8 @@ static int fts3MatchinfoCheck(
return SQLITE_ERROR;
}
-static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
- size_t nVal; /* Number of integers output by cArg */
+static i64 fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
+ i64 nVal; /* Number of integers output by cArg */
switch( cArg ){
case FTS3_MATCHINFO_NDOC:
@@ -208588,16 +212253,16 @@ static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
break;
case FTS3_MATCHINFO_LHITS:
- nVal = (size_t)pInfo->nCol * pInfo->nPhrase;
+ nVal = (i64)pInfo->nCol * pInfo->nPhrase;
break;
case FTS3_MATCHINFO_LHITS_BM:
- nVal = (size_t)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
+ nVal = (i64)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
break;
default:
assert( cArg==FTS3_MATCHINFO_HITS );
- nVal = (size_t)pInfo->nCol * pInfo->nPhrase * 3;
+ nVal = (i64)pInfo->nCol * pInfo->nPhrase * 3;
break;
}
@@ -208879,7 +212544,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_LHITS_BM:
case FTS3_MATCHINFO_LHITS: {
- size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
+ i64 nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
break;
@@ -208948,7 +212613,7 @@ static void fts3GetMatchinfo(
** initialize those elements that are constant for every row.
*/
if( pCsr->pMIBuffer==0 ){
- size_t nMatchinfo = 0; /* Number of u32 elements in match-info */
+ i64 nMatchinfo = 0; /* Number of u32 elements in match-info */
int i; /* Used to iterate through zArg */
/* Determine the number of phrases in the query */
@@ -209033,9 +212698,8 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet(
return;
}
- /* Limit the snippet length to 64 tokens. */
- if( nToken<-64 ) nToken = -64;
- if( nToken>+64 ) nToken = +64;
+ /* The snippet length should already have been limited to 64 tokens. */
+ assert( nToken>=-64 && nToken<=64 );
for(nSnippet=1; 1; nSnippet++){
@@ -209372,13 +213036,11 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo(
/* #include "fts3_tokenizer.h" */
/*
-** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
-** from the sqlite3 source file utf.c. If this file is compiled as part
-** of the amalgamation, they are not required.
+** The following two macros - FTS3_READ_UTF8 and FTS3_WRITE_UTF8 - have
+** been copied from the sqlite3 source file utf.c.
*/
-#ifndef SQLITE_AMALGAMATION
-static const unsigned char sqlite3Utf8Trans1[] = {
+static const unsigned char fts3Utf8Trans1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -209389,10 +213051,10 @@ static const unsigned char sqlite3Utf8Trans1[] = {
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
};
-#define READ_UTF8(zIn, zTerm, c) \
+#define FTS3_READ_UTF8(zIn, zTerm, c) \
c = *(zIn++); \
if( c>=0xc0 ){ \
- c = sqlite3Utf8Trans1[c-0xc0]; \
+ c = fts3Utf8Trans1[c-0xc0]; \
while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
@@ -209401,28 +213063,26 @@ static const unsigned char sqlite3Utf8Trans1[] = {
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
}
-#define WRITE_UTF8(zOut, c) { \
- if( c<0x00080 ){ \
- *zOut++ = (u8)(c&0xFF); \
- } \
- else if( c<0x00800 ){ \
- *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- } \
- else if( c<0x10000 ){ \
- *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- }else{ \
- *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
- *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (u8)(c & 0x3F); \
- } \
+#define FTS3_WRITE_UTF8(zOut, c) { \
+ if( c<0x00080 ){ \
+ *zOut++ = (u8)(c&0xFF); \
+ } \
+ else if( c<0x00800 ){ \
+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ } \
+ else if( c<0x10000 ){ \
+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ }else{ \
+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ } \
}
-#endif /* ifndef SQLITE_AMALGAMATION */
-
typedef struct unicode_tokenizer unicode_tokenizer;
typedef struct unicode_cursor unicode_cursor;
@@ -209488,7 +213148,7 @@ static int unicodeAddExceptions(
assert( bAlnum==0 || bAlnum==1 );
while( zeRemoveDiacritic);
if( iOut ){
- WRITE_UTF8(zOut, iOut);
+ FTS3_WRITE_UTF8(zOut, iOut);
}
/* If the cursor is not at EOF, read the next character */
if( z>=zTerm ) break;
- READ_UTF8(z, zTerm, iCode);
+ FTS3_READ_UTF8(z, zTerm, iCode);
}while( unicodeIsAlnum(p, (int)iCode)
|| sqlite3FtsUnicodeIsdiacritic((int)iCode)
);
@@ -210445,7 +214105,8 @@ struct JsonString {
/* Allowed values for JsonString.eErr */
#define JSTRING_OOM 0x01 /* Out of memory */
#define JSTRING_MALFORMED 0x02 /* Malformed JSONB */
-#define JSTRING_ERR 0x04 /* Error already sent to sqlite3_result */
+#define JSTRING_TOODEEP 0x04 /* JSON nested too deep */
+#define JSTRING_ERR 0x08 /* Error already sent to sqlite3_result */
/* The "subtype" set for text JSON values passed through using
** sqlite3_result_subtype() and sqlite3_value_subtype().
@@ -210460,7 +214121,10 @@ struct JsonString {
#define JSON_SQL 0x02 /* Result is always SQL */
#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
#define JSON_ISSET 0x04 /* json_set(), not json_insert() */
-#define JSON_BLOB 0x08 /* Use the BLOB output format */
+#define JSON_AINS 0x08 /* json_array_insert(), not json_insert() */
+#define JSON_BLOB 0x10 /* Use the BLOB output format */
+
+#define JSON_INSERT_TYPE(X) (((X)&0xC)>>2)
/* A parsed JSON value. Lifecycle:
@@ -210506,6 +214170,7 @@ struct JsonParse {
#define JEDIT_REPL 2 /* Overwrite if exists */
#define JEDIT_INS 3 /* Insert if not exists */
#define JEDIT_SET 4 /* Insert or overwrite */
+#define JEDIT_AINS 5 /* array_insert() */
/*
** Maximum nesting depth of JSON for this implementation.
@@ -210525,13 +214190,14 @@ struct JsonParse {
*/
#define JSON_EDITABLE 0x01 /* Generate a writable JsonParse object */
#define JSON_KEEPERROR 0x02 /* Return non-NULL even if there is an error */
+#define JSON_NOCACHE 0x04 /* Do not use the JSON cache */
/**************************************************************************
** Forward references
**************************************************************************/
static void jsonReturnStringAsBlob(JsonString*);
static int jsonArgIsJsonb(sqlite3_value *pJson, JsonParse *p);
-static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*);
+static u32 jsonTranslateBlobToText(JsonParse*,u32,JsonString*);
static void jsonReturnParse(sqlite3_context*,JsonParse*);
static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
static void jsonParseFree(JsonParse*);
@@ -210689,6 +214355,15 @@ static void jsonStringOom(JsonString *p){
jsonStringReset(p);
}
+/* Report JSON nested too deep
+*/
+static void jsonStringTooDeep(JsonString *p){
+ p->eErr |= JSTRING_TOODEEP;
+ assert( p->pCtx!=0 );
+ sqlite3_result_error(p->pCtx, "JSON nested too deep", -1);
+ jsonStringReset(p);
+}
+
/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
** Return zero on success. Return non-zero on an OOM error
*/
@@ -210928,7 +214603,7 @@ static void jsonAppendSqlValue(
break;
}
case SQLITE_FLOAT: {
- jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
+ jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
break;
}
case SQLITE_INTEGER: {
@@ -210978,6 +214653,7 @@ static void jsonReturnString(
){
assert( (pParse!=0)==(ctx!=0) );
assert( ctx==0 || ctx==p->pCtx );
+ jsonStringTerminate(p);
if( p->eErr==0 ){
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(p->pCtx));
if( flags & JSON_BLOB ){
@@ -210985,7 +214661,7 @@ static void jsonReturnString(
}else if( p->bStatic ){
sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
SQLITE_TRANSIENT, SQLITE_UTF8);
- }else if( jsonStringTerminate(p) ){
+ }else{
if( pParse && pParse->bJsonIsRCStr==0 && pParse->nBlobAlloc>0 ){
int rc;
pParse->zJson = sqlite3RCStrRef(p->zBuf);
@@ -211001,11 +214677,11 @@ static void jsonReturnString(
sqlite3_result_text64(p->pCtx, sqlite3RCStrRef(p->zBuf), p->nUsed,
sqlite3RCStrUnref,
SQLITE_UTF8);
- }else{
- sqlite3_result_error_nomem(p->pCtx);
}
}else if( p->eErr & JSTRING_OOM ){
sqlite3_result_error_nomem(p->pCtx);
+ }else if( p->eErr & JSTRING_TOODEEP ){
+ /* error already in p->pCtx */
}else if( p->eErr & JSTRING_MALFORMED ){
sqlite3_result_error(p->pCtx, "malformed JSON", -1);
}
@@ -211267,7 +214943,7 @@ static void jsonWrongNumArgs(
**
** Return the number of errors.
*/
-static int jsonBlobExpand(JsonParse *pParse, u32 N){
+static int jsonBlobExpand(JsonParse *pParse, u64 N){
u8 *aNew;
u64 t;
assert( N>pParse->nBlobAlloc );
@@ -211295,7 +214971,7 @@ static int jsonBlobExpand(JsonParse *pParse, u32 N){
*/
static int jsonBlobMakeEditable(JsonParse *pParse, u32 nExtra){
u8 *aOld;
- u32 nSize;
+ u64 nSize;
assert( !pParse->bReadOnly );
if( pParse->oom ) return 0;
if( pParse->nBlobAlloc>0 ) return 1;
@@ -211316,7 +214992,7 @@ static SQLITE_NOINLINE void jsonBlobExpandAndAppendOneByte(
JsonParse *pParse,
u8 c
){
- jsonBlobExpand(pParse, pParse->nBlob+1);
+ jsonBlobExpand(pParse, (u64)pParse->nBlob+1);
if( pParse->oom==0 ){
assert( pParse->nBlob+1<=pParse->nBlobAlloc );
pParse->aBlob[pParse->nBlob++] = c;
@@ -211336,14 +215012,14 @@ static void jsonBlobAppendOneByte(JsonParse *pParse, u8 c){
/* Slow version of jsonBlobAppendNode() that first resizes the
** pParse->aBlob structure.
*/
-static void jsonBlobAppendNode(JsonParse*,u8,u32,const void*);
+static void jsonBlobAppendNode(JsonParse*,u8,u64,const void*);
static SQLITE_NOINLINE void jsonBlobExpandAndAppendNode(
JsonParse *pParse,
u8 eType,
- u32 szPayload,
+ u64 szPayload,
const void *aPayload
){
- if( jsonBlobExpand(pParse, pParse->nBlob+szPayload+9) ) return;
+ if( jsonBlobExpand(pParse, (u64)pParse->nBlob+(u64)szPayload+9) ) return;
jsonBlobAppendNode(pParse, eType, szPayload, aPayload);
}
@@ -211360,7 +215036,7 @@ static SQLITE_NOINLINE void jsonBlobExpandAndAppendNode(
static void jsonBlobAppendNode(
JsonParse *pParse, /* The JsonParse object under construction */
u8 eType, /* Node type. One of JSONB_* */
- u32 szPayload, /* Number of bytes of payload */
+ u64 szPayload, /* Number of bytes of payload */
const void *aPayload /* The payload. Might be NULL */
){
u8 *a;
@@ -211433,7 +215109,7 @@ static int jsonBlobChangePayloadSize(
}
delta = nNeeded - nExtra;
if( delta ){
- u32 newSize = pParse->nBlob + delta;
+ u64 newSize = (u64)pParse->nBlob + delta;
if( delta>0 ){
if( newSize>pParse->nBlobAlloc && jsonBlobExpand(pParse, newSize) ){
return 0; /* OOM error. Error state recorded in pParse->oom. */
@@ -212216,12 +215892,8 @@ static int jsonConvertTextToBlob(
*/
static void jsonReturnStringAsBlob(JsonString *pStr){
JsonParse px;
+ assert( pStr->eErr==0 );
memset(&px, 0, sizeof(px));
- jsonStringTerminate(pStr);
- if( pStr->eErr ){
- sqlite3_result_error_nomem(pStr->pCtx);
- return;
- }
px.zJson = pStr->zBuf;
px.nJson = pStr->nUsed;
px.db = sqlite3_context_db_handle(pStr->pCtx);
@@ -212236,18 +215908,132 @@ static void jsonReturnStringAsBlob(JsonString *pStr){
}
}
-/* The byte at index i is a node type-code. This routine
+/*
+** This a helper routine for jsonbPayloadSize() and
+** jsonbPayloadSizeSemiInline(). This routine is called using tail
+** recursion to handle the (relatively uncommon) cases where the
+** the payload size is a 2, 4, or 8 byte integer.
+*/
+static u32 jsonbPayloadSizeWide(
+ const JsonParse *pParse, /* JSON parsing context */
+ u32 i, /* Index of the node type-code */
+ u32 *pSz, /* Write payload size here */
+ u8 x /* pParse->aBlob[i]>>4 */
+){
+ u32 sz;
+ u32 n;
+ assert( inBlob );
+ assert( x==(pParse->aBlob[i]>>4) );
+ assert( x>=13 );
+ if( x==13 ){
+ if( i+2>=pParse->nBlob ){
+ *pSz = 0;
+ return 0;
+ }
+ sz = (pParse->aBlob[i+1]<<8) + pParse->aBlob[i+2];
+ n = 3;
+ }else if( x==14 ){
+ if( i+4>=pParse->nBlob ){
+ *pSz = 0;
+ return 0;
+ }
+ sz = ((u32)pParse->aBlob[i+1]<<24) + (pParse->aBlob[i+2]<<16) +
+ (pParse->aBlob[i+3]<<8) + pParse->aBlob[i+4];
+ n = 5;
+ }else{
+ if( i+8>=pParse->nBlob
+ || pParse->aBlob[i+1]!=0
+ || pParse->aBlob[i+2]!=0
+ || pParse->aBlob[i+3]!=0
+ || pParse->aBlob[i+4]!=0
+ ){
+ *pSz = 0;
+ return 0;
+ }
+ sz = ((u32)pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
+ (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
+ n = 9;
+ }
+ testcase( (i64)i+sz+n > pParse->nBlob );
+ testcase( (i64)i+sz+n > pParse->nBlob-pParse->delta
+ && (i64)i+sz+n > pParse->nBlob );
+ testcase( pParse->delta>0 );
+ testcase( pParse->delta<0 );
+ /* Quirks with -Os and gcov cause the NO_TEST line below to show up as
+ ** false-positive coverage miss. The testcases() macros above are
+ ** sufficient to prove that the branch is in fact covered */
+ if( (i64)i+sz+n > pParse->nBlob
+ && (i64)i+sz+n > pParse->nBlob-pParse->delta /*NO_TEST*/
+ ){
+ *pSz = 0;
+ return 0;
+ }
+ *pSz = sz;
+ return n;
+}
+
+/*
+** This is the main routine for determining the size of a node in JSONB.
+** The jsonbPayloadSizeWide() above is a helper. The two routines
+** jsonbPayloadSizeInline() and jsonbPayloadSizeSemiInline() below are
+** optional optimizations. It is important to keep all these routines in
+** sync. Agents reading this code: Help us humans to remember that!
+**
+** The byte at index i is a node type-code. This routine
** determines the payload size for that node and writes that
** payload size in to *pSz. It returns the offset from i to the
** beginning of the payload. Return 0 on error.
*/
-static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
+static u32 jsonbPayloadSize(
+ const JsonParse *pParse, /* JSON parsing context */
+ u32 i, /* Index of the node type-code */
+ u32 *pSz /* Write payload size here */
+){
+ u8 x;
+ u32 sz;
+ u32 n;
+ if( i>=pParse->nBlob ){
+ *pSz = 0;
+ return 0;
+ }else if( (x = pParse->aBlob[i]>>4)<=11 ){
+ sz = x;
+ n = 1;
+ }else if( x==12 ){
+ if( i+1>=pParse->nBlob ){
+ *pSz = 0;
+ return 0;
+ }
+ sz = pParse->aBlob[i+1];
+ n = 2;
+ }else{
+ return jsonbPayloadSizeWide(pParse, i, pSz, x);
+ }
+ if( (i64)i+sz+n > pParse->nBlob
+ && (i64)i+sz+n > pParse->nBlob-pParse->delta
+ ){
+ *pSz = 0;
+ return 0;
+ }
+ *pSz = sz;
+ return n;
+}
+
+#if SQLITE_USES_INLINE
+/* A separate inline version of jsonbPayloadSize(), used in one particulary
+** performance-critical place.
+*/
+static SQLITE_INLINE u32 jsonbPayloadSizeInline(
+ const JsonParse *pParse, /* JSON parsing context */
+ u32 i, /* Index of the node type-code */
+ u32 *pSz /* Write payload size here */
+){
u8 x;
u32 sz;
u32 n;
- assert( i<=pParse->nBlob );
- x = pParse->aBlob[i]>>4;
- if( x<=11 ){
+ if( i>=pParse->nBlob ){
+ *pSz = 0;
+ return 0;
+ }else if( (x = pParse->aBlob[i]>>4)<=11 ){
sz = x;
n = 1;
}else if( x==12 ){
@@ -212295,8 +216081,62 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
*pSz = sz;
return n;
}
+#else /* if !SQLITE_USES_INLINE */
+ /* On compilers that do not support in-lining, just call the original
+ ** jsonbPayloadSize(). It's slower, but it gets the right answer. */
+# define jsonbPayloadSizeInline(a,b,c) jsonbPayloadSize(a,b,c)
+#endif
+#if SQLITE_USES_INLINE
+/* A separate inline version of jsonbPayloadSize() that implements the more
+** common paths inline but then calls out to a subroutine for the uncommon
+** paths.
+**
+** * It is guaranteed that the i parameter is a valid index for
+** pParse->aBlob[]. There is no possibility of running of the end
+** of the allocation.
+**
+** * Large sizes (greater than 255) are uncommon and are handled
+** by a subroutine call to the jsonbPayloadSizeWide().
+*/
+static SQLITE_INLINE u32 jsonbPayloadSizeSemiInline(
+ const JsonParse *pParse, /* JSON parsing context */
+ u32 i, /* Index of the node type-code */
+ u32 *pSz /* Write payload size here */
+){
+ u8 x;
+ u32 sz;
+ u32 n;
+ assert( inBlob );
+ if( (x = pParse->aBlob[i]>>4)<=11 ){
+ sz = x;
+ n = 1;
+ }else if( x==12 ){
+ if( i+1>=pParse->nBlob ){
+ *pSz = 0;
+ return 0;
+ }
+ sz = pParse->aBlob[i+1];
+ n = 2;
+ }else{
+ return jsonbPayloadSizeWide(pParse,i,pSz,x);
+ }
+ if( (i64)i+sz+n > pParse->nBlob
+ && (i64)i+sz+n > pParse->nBlob-pParse->delta
+ ){
+ *pSz = 0;
+ return 0;
+ }
+ *pSz = sz;
+ return n;
+}
+#else /* if !SQLITE_USES_INLINE */
+ /* On compilers that do not support in-lining, just call the original
+ ** jsonbPayloadSize(). It's slower, but it gets the right answer. */
+# define jsonbPayloadSizeSemiInline(a,b,c) jsonbPayloadSize(a,b,c)
+#endif
+
/*
** Translate the binary JSONB representation of JSON beginning at
** pParse->aBlob[i] into a JSON text string. Append the JSON
@@ -212311,13 +216151,13 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
** The pOut->eErr JSTRING_OOM flag is set on a OOM.
*/
static u32 jsonTranslateBlobToText(
- const JsonParse *pParse, /* the complete parse of the JSON */
+ JsonParse *pParse, /* the complete parse of the JSON */
u32 i, /* Start rendering at this index */
JsonString *pOut /* Write JSON here */
){
u32 sz, n, j, iEnd;
- n = jsonbPayloadSize(pParse, i, &sz);
+ n = jsonbPayloadSizeInline(pParse, i, &sz);
if( n==0 ){
pOut->eErr |= JSTRING_MALFORMED;
return pParse->nBlob+1;
@@ -212372,7 +216212,8 @@ static u32 jsonTranslateBlobToText(
if( sz==0 ) goto malformed_jsonb;
if( zIn[0]=='-' ){
jsonAppendChar(pOut, '-');
- k++;
+ if( sz<=1 ) goto malformed_jsonb;
+ k = 1;
}
if( zIn[k]=='.' ){
jsonAppendChar(pOut, '0');
@@ -212461,7 +216302,7 @@ static u32 jsonTranslateBlobToText(
break;
case 0xe2:
/* '\' followed by either U+2028 or U+2029 is ignored as
- ** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29.
+ ** whitespace. Note that in UTF8, U+2028 is 0xe2 0x80 0x29.
** U+2029 is the same except for the last byte */
if( sz2<4
|| 0x80!=(u8)zIn[2]
@@ -212493,10 +216334,14 @@ static u32 jsonTranslateBlobToText(
jsonAppendChar(pOut, '[');
j = i+n;
iEnd = j+sz;
+ if( ++pParse->iDepth > JSON_MAX_DEPTH ){
+ jsonStringTooDeep(pOut);
+ }
while( jeErr==0 ){
j = jsonTranslateBlobToText(pParse, j, pOut);
jsonAppendChar(pOut, ',');
}
+ pParse->iDepth--;
if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
if( sz>0 ) jsonStringTrimOneChar(pOut);
jsonAppendChar(pOut, ']');
@@ -212507,10 +216352,14 @@ static u32 jsonTranslateBlobToText(
jsonAppendChar(pOut, '{');
j = i+n;
iEnd = j+sz;
+ if( ++pParse->iDepth > JSON_MAX_DEPTH ){
+ jsonStringTooDeep(pOut);
+ }
while( jeErr==0 ){
j = jsonTranslateBlobToText(pParse, j, pOut);
jsonAppendChar(pOut, (x++ & 1) ? ',' : ':');
}
+ pParse->iDepth--;
if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
if( sz>0 ) jsonStringTrimOneChar(pOut);
jsonAppendChar(pOut, '}');
@@ -212567,7 +216416,7 @@ static u32 jsonTranslateBlobToPrettyText(
u32 i /* Start rendering at this index */
){
u32 sz, n, j, iEnd;
- const JsonParse *pParse = pPretty->pParse;
+ JsonParse *pParse = pPretty->pParse;
JsonString *pOut = pPretty->pOut;
n = jsonbPayloadSize(pParse, i, &sz);
if( n==0 ){
@@ -212582,10 +216431,16 @@ static u32 jsonTranslateBlobToPrettyText(
if( jnIndent++;
+ if( pPretty->nIndent >= JSON_MAX_DEPTH ){
+ jsonStringTooDeep(pOut);
+ }
while( pOut->eErr==0 ){
jsonPrettyIndent(pPretty);
j = jsonTranslateBlobToPrettyText(pPretty, j);
- if( j>=iEnd ) break;
+ if( j>=iEnd ){
+ if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
+ break;
+ }
jsonAppendRawNZ(pOut, ",\n", 2);
}
jsonAppendChar(pOut, '\n');
@@ -212603,6 +216458,10 @@ static u32 jsonTranslateBlobToPrettyText(
if( jnIndent++;
+ if( pPretty->nIndent >= JSON_MAX_DEPTH ){
+ jsonStringTooDeep(pOut);
+ }
+ pParse->iDepth = pPretty->nIndent;
while( pOut->eErr==0 ){
jsonPrettyIndent(pPretty);
j = jsonTranslateBlobToText(pParse, j, pOut);
@@ -212641,7 +216500,7 @@ static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){
n = jsonbPayloadSize(pParse, iRoot, &sz);
iEnd = iRoot+n+sz;
for(i=iRoot+n; n>0 && inBlob >= (u64)iDel + (u64)nDel );
if( d<0 && d>=(-8) && aIns!=0
&& jsonBlobOverwrite(&pParse->aBlob[iDel], aIns, nIns, (int)-d)
){
@@ -212767,7 +216627,7 @@ static void jsonBlobEdit(
}
if( d!=0 ){
if( pParse->nBlob + d > pParse->nBlobAlloc ){
- jsonBlobExpand(pParse, pParse->nBlob+d);
+ jsonBlobExpand(pParse, (u64)pParse->nBlob+d);
if( pParse->oom ) return;
}
memmove(&pParse->aBlob[iDel+nIns],
@@ -213002,7 +216862,9 @@ static int jsonLabelCompare(
*/
#define JSON_LOOKUP_ERROR 0xffffffff
#define JSON_LOOKUP_NOTFOUND 0xfffffffe
-#define JSON_LOOKUP_PATHERROR 0xfffffffd
+#define JSON_LOOKUP_NOTARRAY 0xfffffffd
+#define JSON_LOOKUP_TOODEEP 0xfffffffc
+#define JSON_LOOKUP_PATHERROR 0xfffffffb
#define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR)
/* Forward declaration */
@@ -213031,7 +216893,7 @@ static u32 jsonLookupStep(JsonParse*,u32,const char*,u32);
static u32 jsonCreateEditSubstructure(
JsonParse *pParse, /* The original JSONB that is being edited */
JsonParse *pIns, /* Populate this with the blob data to insert */
- const char *zTail /* Tail of the path that determins substructure */
+ const char *zTail /* Tail of the path that determines substructure */
){
static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
int rc;
@@ -213049,7 +216911,12 @@ static u32 jsonCreateEditSubstructure(
pIns->eEdit = pParse->eEdit;
pIns->nIns = pParse->nIns;
pIns->aIns = pParse->aIns;
+ pIns->iDepth = pParse->iDepth+1;
+ if( pIns->iDepth >= JSON_MAX_DEPTH ){
+ return JSON_LOOKUP_TOODEEP;
+ }
rc = jsonLookupStep(pIns, 0, zTail, 0);
+ pParse->iDepth--;
pParse->oom |= pIns->oom;
}
return rc; /* Error code only */
@@ -213066,9 +216933,9 @@ static u32 jsonCreateEditSubstructure(
** Return one of the JSON_LOOKUP error codes if problems are seen.
**
** This routine will also modify the blob. If pParse->eEdit is one of
-** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be
-** made to the selected value. If an edit is performed, then the return
-** value does not necessarily point to the select element. If an edit
+** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, JEDIT_SET, or JEDIT_AINS, then changes
+** might be made to the selected value. If an edit is performed, then the
+** return value does not necessarily point to the select element. If an edit
** is performed, the return value is only useful for detecting error
** conditions.
*/
@@ -213094,6 +216961,13 @@ static u32 jsonLookupStep(
jsonBlobEdit(pParse, iRoot, sz, 0, 0);
}else if( pParse->eEdit==JEDIT_INS ){
/* Already exists, so json_insert() is a no-op */
+ }else if( pParse->eEdit==JEDIT_AINS ){
+ /* json_array_insert() */
+ if( zPath[-1]!=']' ){
+ return JSON_LOOKUP_NOTARRAY;
+ }else{
+ jsonBlobEdit(pParse, iRoot, 0, pParse->aIns, pParse->nIns);
+ }
}else{
/* json_set() or json_replace() */
jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns);
@@ -213136,7 +217010,7 @@ static u32 jsonLookupStep(
const char *zLabel;
x = pParse->aBlob[j] & 0x0f;
if( xJSONB_TEXTRAW ) return JSON_LOOKUP_ERROR;
- n = jsonbPayloadSize(pParse, j, &sz);
+ n = jsonbPayloadSizeSemiInline(pParse, j, &sz);
if( n==0 ) return JSON_LOOKUP_ERROR;
k = j+n; /* k is the index of the label text */
if( k+sz>=iEnd ) return JSON_LOOKUP_ERROR;
@@ -213148,13 +217022,17 @@ static u32 jsonLookupStep(
n = jsonbPayloadSize(pParse, v, &sz);
if( n==0 || v+n+sz>iEnd ) return JSON_LOOKUP_ERROR;
assert( j>0 );
+ if( ++pParse->iDepth >= JSON_MAX_DEPTH ){
+ return JSON_LOOKUP_TOODEEP;
+ }
rc = jsonLookupStep(pParse, v, &zPath[i], j);
+ pParse->iDepth--;
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
return rc;
}
j = k+sz;
if( ((pParse->aBlob[j])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR;
- n = jsonbPayloadSize(pParse, j, &sz);
+ n = jsonbPayloadSizeSemiInline(pParse, j, &sz);
if( n==0 ) return JSON_LOOKUP_ERROR;
j += n+sz;
}
@@ -213165,6 +217043,10 @@ static u32 jsonLookupStep(
JsonParse ix; /* Header of the label to be inserted */
testcase( pParse->eEdit==JEDIT_INS );
testcase( pParse->eEdit==JEDIT_SET );
+ testcase( pParse->eEdit==JEDIT_AINS );
+ if( pParse->eEdit==JEDIT_AINS && sqlite3_strglob("*]",&zPath[i])!=0 ){
+ return JSON_LOOKUP_NOTARRAY;
+ }
memset(&ix, 0, sizeof(ix));
ix.db = pParse->db;
jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0);
@@ -213192,28 +217074,32 @@ static u32 jsonLookupStep(
return rc;
}
}else if( zPath[0]=='[' ){
+ u64 kk = 0;
x = pParse->aBlob[iRoot] & 0x0f;
if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND;
n = jsonbPayloadSize(pParse, iRoot, &sz);
- k = 0;
i = 1;
while( sqlite3Isdigit(zPath[i]) ){
- k = k*10 + zPath[i] - '0';
+ if( kk<0xffffffff ) kk = kk*10 + zPath[i] - '0';
+ /* ^^^^^^^^^^--- Allow kk to be bigger than any JSON array so that
+ ** we get NOTFOUND instead of PATHERROR, without overflowing kk. */
i++;
}
if( i<2 || zPath[i]!=']' ){
if( zPath[1]=='#' ){
- k = jsonbArrayCount(pParse, iRoot);
+ kk = jsonbArrayCount(pParse, iRoot);
i = 2;
if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
- unsigned int nn = 0;
+ u64 nn = 0;
i = 3;
do{
- nn = nn*10 + zPath[i] - '0';
+ if( nn<0xffffffff ) nn = nn*10 + zPath[i] - '0';
+ /* ^^^^^^^^^^--- Allow nn to be bigger than any JSON array to
+ ** get NOTFOUND instead of PATHERROR, without overflowing nn. */
i++;
}while( sqlite3Isdigit(zPath[i]) );
- if( nn>k ) return JSON_LOOKUP_NOTFOUND;
- k -= nn;
+ if( nn>kk ) return JSON_LOOKUP_NOTFOUND;
+ kk -= nn;
}
if( zPath[i]!=']' ){
return JSON_LOOKUP_PATHERROR;
@@ -213225,21 +217111,26 @@ static u32 jsonLookupStep(
j = iRoot+n;
iEnd = j+sz;
while( jiDepth >= JSON_MAX_DEPTH ){
+ return JSON_LOOKUP_TOODEEP;
+ }
rc = jsonLookupStep(pParse, j, &zPath[i+1], 0);
+ pParse->iDepth--;
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
return rc;
}
- k--;
- n = jsonbPayloadSize(pParse, j, &sz);
+ kk--;
+ n = jsonbPayloadSizeSemiInline(pParse, j, &sz);
if( n==0 ) return JSON_LOOKUP_ERROR;
j += n+sz;
}
if( j>iEnd ) return JSON_LOOKUP_ERROR;
- if( k>0 ) return JSON_LOOKUP_NOTFOUND;
+ if( kk>0 ) return JSON_LOOKUP_NOTFOUND;
if( pParse->eEdit>=JEDIT_INS ){
JsonParse v;
testcase( pParse->eEdit==JEDIT_INS );
+ testcase( pParse->eEdit==JEDIT_AINS );
testcase( pParse->eEdit==JEDIT_SET );
rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]);
if( !JSON_LOOKUP_ISERROR(rc)
@@ -213377,7 +217268,7 @@ static void jsonReturnFromBlob(
to_double:
z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz);
if( z==0 ) goto returnfromblob_oom;
- rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
+ rc = sqlite3AtoF(z, &r);
sqlite3DbFree(db, z);
if( rc<=0 ) goto returnfromblob_malformed;
sqlite3_result_double(pCtx, r);
@@ -213523,8 +217414,7 @@ static int jsonFunctionArgToBlob(
break;
}
case SQLITE_FLOAT: {
- double r = sqlite3_value_double(pArg);
- if( NEVER(sqlite3IsNaN(r)) ){
+ if( NEVER(sqlite3IsNaN(sqlite3_value_double(pArg))) ){
jsonBlobAppendNode(pParse, JSONB_NULL, 0, 0);
}else{
int n = sqlite3_value_bytes(pArg);
@@ -213557,16 +217447,35 @@ static int jsonFunctionArgToBlob(
}
/*
-** Generate a bad path error.
+** Generate a path error.
+**
+** The specifics of the error are determined by the rc argument.
+**
+** rc error
+** ----------------- ----------------------
+** JSON_LOOKUP_ARRAY "not an array"
+** JSON_LOOKUP_TOODEEP "JSON nested too deep"
+** JSON_LOOKUP_ERROR "malformed JSON"
+** otherwise... "bad JSON path"
**
** If ctx is not NULL then push the error message into ctx and return NULL.
** If ctx is NULL, then return the text of the error message.
*/
static char *jsonBadPathError(
sqlite3_context *ctx, /* The function call containing the error */
- const char *zPath /* The path with the problem */
+ const char *zPath, /* The path with the problem */
+ int rc /* Maybe JSON_LOOKUP_NOTARRAY */
){
- char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath);
+ char *zMsg;
+ if( rc==(int)JSON_LOOKUP_NOTARRAY ){
+ zMsg = sqlite3_mprintf("not an array element: %Q", zPath);
+ }else if( rc==(int)JSON_LOOKUP_ERROR ){
+ zMsg = sqlite3_mprintf("malformed JSON");
+ }else if( rc==(int)JSON_LOOKUP_TOODEEP ){
+ zMsg = sqlite3_mprintf("JSON path too deep");
+ }else{
+ zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath);
+ }
if( ctx==0 ) return zMsg;
if( zMsg ){
sqlite3_result_error(ctx, zMsg, -1);
@@ -213583,13 +217492,13 @@ static char *jsonBadPathError(
** and return the result.
**
** The specific operation is determined by eEdit, which can be one
-** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET.
+** of JEDIT_INS, JEDIT_REPL, JEDIT_SET, or JEDIT_AINS.
*/
static void jsonInsertIntoBlob(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv,
- int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */
+ int eEdit /* JEDIT_INS, JEDIT_REPL, JEDIT_SET, JEDIT_AINS */
){
int i;
u32 rc = 0;
@@ -213626,6 +217535,7 @@ static void jsonInsertIntoBlob(
p->nIns = ax.nBlob;
p->aIns = ax.aBlob;
p->delta = 0;
+ p->iDepth = 0;
rc = jsonLookupStep(p, 0, zPath+1, 0);
}
jsonParseReset(&ax);
@@ -213638,11 +217548,7 @@ static void jsonInsertIntoBlob(
jsonInsertIntoBlob_patherror:
jsonParseFree(p);
- if( rc==JSON_LOOKUP_ERROR ){
- sqlite3_result_error(ctx, "malformed JSON", -1);
- }else{
- jsonBadPathError(ctx, zPath);
- }
+ jsonBadPathError(ctx, zPath, rc);
return;
}
@@ -213728,7 +217634,9 @@ static JsonParse *jsonParseFuncArg(
if( eType==SQLITE_NULL ){
return 0;
}
- pFromCache = jsonCacheSearch(ctx, pArg);
+ if( (flgs & JSON_NOCACHE)==0 ){
+ pFromCache = jsonCacheSearch(ctx, pArg);
+ }
if( pFromCache ){
pFromCache->nJPRef++;
if( (flgs & JSON_EDITABLE)==0 ){
@@ -214082,10 +217990,8 @@ static void jsonArrayLengthFunc(
if( JSON_LOOKUP_ISERROR(i) ){
if( i==JSON_LOOKUP_NOTFOUND ){
/* no-op */
- }else if( i==JSON_LOOKUP_PATHERROR ){
- jsonBadPathError(ctx, zPath);
}else{
- sqlite3_result_error(ctx, "malformed JSON", -1);
+ jsonBadPathError(ctx, zPath, i);
}
eErr = 1;
i = 0;
@@ -214188,7 +218094,7 @@ static void jsonExtractFunc(
j = jsonLookupStep(p, 0, jx.zBuf, 0);
jsonStringReset(&jx);
}else{
- jsonBadPathError(ctx, zPath);
+ jsonBadPathError(ctx, zPath, 0);
goto json_extract_error;
}
if( jnBlob ){
@@ -214219,11 +218125,8 @@ static void jsonExtractFunc(
jsonAppendSeparator(&jx);
jsonAppendRawNZ(&jx, "null", 4);
}
- }else if( j==JSON_LOOKUP_ERROR ){
- sqlite3_result_error(ctx, "malformed JSON", -1);
- goto json_extract_error;
}else{
- jsonBadPathError(ctx, zPath);
+ jsonBadPathError(ctx, zPath, j);
goto json_extract_error;
}
}
@@ -214247,6 +218150,7 @@ static void jsonExtractFunc(
#define JSON_MERGE_BADTARGET 1 /* Malformed TARGET blob */
#define JSON_MERGE_BADPATCH 2 /* Malformed PATCH blob */
#define JSON_MERGE_OOM 3 /* Out-of-memory condition */
+#define JSON_MERGE_TOODEEP 4 /* Nested too deep */
/*
** RFC-7396 MergePatch for two JSONB blobs.
@@ -214298,7 +218202,8 @@ static int jsonMergePatch(
JsonParse *pTarget, /* The JSON parser that contains the TARGET */
u32 iTarget, /* Index of TARGET in pTarget->aBlob[] */
const JsonParse *pPatch, /* The PATCH */
- u32 iPatch /* Index of PATCH in pPatch->aBlob[] */
+ u32 iPatch, /* Index of PATCH in pPatch->aBlob[] */
+ u32 iDepth /* Nesting depth */
){
u8 x; /* Type of a single node */
u32 n, sz=0; /* Return values from jsonbPayloadSize() */
@@ -214407,7 +218312,8 @@ static int jsonMergePatch(
/* Algorithm line 12 */
int rc, savedDelta = pTarget->delta;
pTarget->delta = 0;
- rc = jsonMergePatch(pTarget, iTValue, pPatch, iPValue);
+ if( iDepth>=JSON_MAX_DEPTH ) return JSON_MERGE_TOODEEP;
+ rc = jsonMergePatch(pTarget, iTValue, pPatch, iPValue, iDepth+1);
if( rc ) return rc;
pTarget->delta += savedDelta;
}
@@ -214428,7 +218334,8 @@ static int jsonMergePatch(
pTarget->aBlob[iTEnd+szNew] = 0x00;
savedDelta = pTarget->delta;
pTarget->delta = 0;
- rc = jsonMergePatch(pTarget, iTEnd+szNew,pPatch,iPValue);
+ if( iDepth>=JSON_MAX_DEPTH ) return JSON_MERGE_TOODEEP;
+ rc = jsonMergePatch(pTarget, iTEnd+szNew,pPatch,iPValue,iDepth+1);
if( rc ) return rc;
pTarget->delta += savedDelta;
}
@@ -214459,11 +218366,13 @@ static void jsonPatchFunc(
if( pTarget==0 ) return;
pPatch = jsonParseFuncArg(ctx, argv[1], 0);
if( pPatch ){
- rc = jsonMergePatch(pTarget, 0, pPatch, 0);
+ rc = jsonMergePatch(pTarget, 0, pPatch, 0, 0);
if( rc==JSON_MERGE_OK ){
jsonReturnParse(ctx, pTarget);
}else if( rc==JSON_MERGE_OOM ){
sqlite3_result_error_nomem(ctx);
+ }else if( rc==JSON_MERGE_TOODEEP ){
+ sqlite3_result_error(ctx, "JSON nested too deep", -1);
}else{
sqlite3_result_error(ctx, "malformed JSON", -1);
}
@@ -214551,10 +218460,8 @@ static void jsonRemoveFunc(
if( JSON_LOOKUP_ISERROR(rc) ){
if( rc==JSON_LOOKUP_NOTFOUND ){
continue; /* No-op */
- }else if( rc==JSON_LOOKUP_PATHERROR ){
- jsonBadPathError(ctx, zPath);
}else{
- sqlite3_result_error(ctx, "malformed JSON", -1);
+ jsonBadPathError(ctx, zPath, rc);
}
goto json_remove_done;
}
@@ -214564,7 +218471,7 @@ static void jsonRemoveFunc(
return;
json_remove_patherror:
- jsonBadPathError(ctx, zPath);
+ jsonBadPathError(ctx, zPath, 0);
json_remove_done:
jsonParseFree(p);
@@ -214608,16 +218515,18 @@ static void jsonSetFunc(
int argc,
sqlite3_value **argv
){
-
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
- int bIsSet = (flags&JSON_ISSET)!=0;
+ int eInsType = JSON_INSERT_TYPE(flags);
+ static const char *azInsType[] = { "insert", "set", "array_insert" };
+ static const u8 aEditType[] = { JEDIT_INS, JEDIT_SET, JEDIT_AINS };
if( argc<1 ) return;
+ assert( eInsType>=0 && eInsType<=2 );
if( (argc&1)==0 ) {
- jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
+ jsonWrongNumArgs(ctx, azInsType[eInsType]);
return;
}
- jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS);
+ jsonInsertIntoBlob(ctx, argc, argv, aEditType[eInsType]);
}
/*
@@ -214642,17 +218551,15 @@ static void jsonTypeFunc(
zPath = (const char*)sqlite3_value_text(argv[1]);
if( zPath==0 ) goto json_type_done;
if( zPath[0]!='$' ){
- jsonBadPathError(ctx, zPath);
+ jsonBadPathError(ctx, zPath, 0);
goto json_type_done;
}
i = jsonLookupStep(p, 0, zPath+1, 0);
if( JSON_LOOKUP_ISERROR(i) ){
if( i==JSON_LOOKUP_NOTFOUND ){
/* no-op */
- }else if( i==JSON_LOOKUP_PATHERROR ){
- jsonBadPathError(ctx, zPath);
}else{
- sqlite3_result_error(ctx, "malformed JSON", -1);
+ jsonBadPathError(ctx, zPath, i);
}
goto json_type_done;
}
@@ -214804,7 +218711,7 @@ static void jsonValidFunc(
if( (flags & 0x3)==0 ) break;
memset(&px, 0, sizeof(px));
- p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR);
+ p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR|JSON_NOCACHE);
if( p ){
if( p->oom ){
sqlite3_result_error_nomem(ctx);
@@ -214906,12 +218813,12 @@ static void jsonArrayStep(
}
static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
JsonString *pStr;
+ int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
- int flags;
pStr->pCtx = ctx;
- jsonAppendChar(pStr, ']');
- flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
+ jsonAppendRawNZ(pStr, "]", 2);
+ jsonStringTrimOneChar(pStr);
if( pStr->eErr ){
jsonReturnString(pStr, 0, 0);
return;
@@ -214932,6 +218839,9 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
jsonStringTrimOneChar(pStr);
}
+ }else if( flags & JSON_BLOB ){
+ static const u8 emptyArray = 0x0b;
+ sqlite3_result_blob(ctx, &emptyArray, 1, SQLITE_STATIC);
}else{
sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
}
@@ -214965,11 +218875,9 @@ static void jsonGroupInverse(
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
-#ifdef NEVER
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
** always have been called to initialize it */
if( NEVER(!pStr) ) return;
-#endif
z = pStr->zBuf;
for(i=1; inUsed && ((c = z[i])!=',' || inStr || nNest); i++){
if( c=='"' ){
@@ -214998,6 +218906,13 @@ static void jsonGroupInverse(
** json_group_obj(NAME,VALUE)
**
** Return a JSON object composed of all names and values in the aggregate.
+**
+** Rows for which NAME is NULL do not result in a new entry. However, we
+** do initially insert a "@" entry into the growing string for each null entry
+** and change the first character of the string to "@" to signal that the
+** string contains null entries. The "@" markers are needed in order to
+** correctly process xInverse() requests. The initial "@" is converted
+** back into "{" and the "@" null values are removed by jsonObjectCompute().
*/
static void jsonObjectStep(
sqlite3_context *ctx,
@@ -215015,7 +218930,7 @@ static void jsonObjectStep(
if( pStr->zBuf==0 ){
jsonStringInit(pStr, ctx);
jsonAppendChar(pStr, '{');
- }else if( pStr->nUsed>1 && z!=0 ){
+ }else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
@@ -215023,28 +218938,75 @@ static void jsonObjectStep(
jsonAppendString(pStr, z, n);
jsonAppendChar(pStr, ':');
jsonAppendSqlValue(pStr, argv[1]);
+ }else{
+ pStr->zBuf[0] = '@';
+ jsonAppendRawNZ(pStr, "@", 1);
}
}
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
JsonString *pStr;
+ int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
- int flags;
- jsonAppendChar(pStr, '}');
+ JsonString *pOgStr = pStr;
+ JsonString tmpStr;
+ jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
+ jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
pStr->pCtx = ctx;
- flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
if( pStr->eErr ){
jsonReturnString(pStr, 0, 0);
return;
- }else if( flags & JSON_BLOB ){
+ }
+ if( pStr->zBuf[0]!='{' ){
+ /* The string contains null entries that need to be removed */
+ u64 i, j;
+ int inStr = 0;
+ if( !isFinal ){
+ /* Work with a temporary copy of the string if this is not the
+ ** final result */
+ jsonStringInit(&tmpStr, ctx);
+ jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
+ pStr = &tmpStr;
+ if( pStr->eErr ){
+ jsonReturnString(pStr, 0, 0);
+ return;
+ }
+ jsonStringTrimOneChar(pStr); /* Remove zero terminator */
+ }
+ /* Fix up the string by changing the initial "@" flag back to
+ ** to "{" and removing all subsequence "@" entries, with their
+ ** associated comma delimeters. */
+ pStr->zBuf[0] = '{';
+ for(i=j=1; inUsed; i++){
+ char c = pStr->zBuf[i];
+ if( c=='"' ){
+ inStr = !inStr;
+ pStr->zBuf[j++] = '"';
+ }else if( c=='\\' ){
+ pStr->zBuf[j++] = '\\';
+ pStr->zBuf[j++] = pStr->zBuf[++i];
+ }else if( c=='@' && !inStr ){
+ assert( i+1nUsed );
+ if( pStr->zBuf[i+1]==',' ){
+ i++;
+ }else if( pStr->zBuf[j-1]==',' ){
+ j--;
+ }
+ }else{
+ pStr->zBuf[j++] = c;
+ }
+ }
+ pStr->zBuf[j] = 0; /* Restore zero terminator */
+ pStr->nUsed = j; /* Truncate the string */
+ }
+ if( flags & JSON_BLOB ){
jsonReturnStringAsBlob(pStr);
if( isFinal ){
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
}else{
- jsonStringTrimOneChar(pStr);
+ jsonStringTrimOneChar(pOgStr);
}
- return;
}else if( isFinal ){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
pStr->bStatic ? SQLITE_TRANSIENT :
@@ -215052,8 +219014,12 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
pStr->bStatic = 1;
}else{
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
- jsonStringTrimOneChar(pStr);
+ jsonStringTrimOneChar(pOgStr);
}
+ if( pStr!=pOgStr ) jsonStringReset(pStr);
+ }else if( flags & JSON_BLOB ){
+ static const unsigned char emptyObject = 0x0c;
+ sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
}else{
sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
}
@@ -215215,7 +219181,9 @@ static int jsonSkipLabel(JsonEachCursor *p){
if( p->eType==JSONB_OBJECT ){
u32 sz = 0;
u32 n = jsonbPayloadSize(&p->sParse, p->i, &sz);
- return p->i + n + sz;
+ sz += p->i + n;
+ if( sz >= p->sParse.nBlob ) sz = p->i;
+ return sz;
}else{
return p->i;
}
@@ -215254,6 +219222,15 @@ static void jsonAppendPathName(JsonEachCursor *p){
}
}
+/* Report a "malformed JSON" or OOM error against the cursor.
+*/
+static int jsonEachMalformedInput(sqlite3_vtab_cursor *cur){
+ sqlite3_free(cur->pVtab->zErrMsg);
+ cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
+ jsonEachCursorReset((JsonEachCursor*)cur);
+ return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
+}
+
/* Advance the cursor to the next element for json_tree() */
static int jsonEachNext(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
@@ -215265,6 +219242,7 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
u32 i = jsonSkipLabel(p);
x = p->sParse.aBlob[i] & 0x0f;
n = jsonbPayloadSize(&p->sParse, i, &sz);
+ if( n==0 )return jsonEachMalformedInput(cur);
if( x==JSONB_OBJECT || x==JSONB_ARRAY ){
JsonParent *pParent;
if( p->nParent>=p->nParentAlloc ){
@@ -215310,6 +219288,7 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
u32 n, sz = 0;
u32 i = jsonSkipLabel(p);
n = jsonbPayloadSize(&p->sParse, i, &sz);
+ if( n==0 )return jsonEachMalformedInput(cur);
p->i = i + n + sz;
}
if( p->eType==JSONB_ARRAY && p->nParent ){
@@ -215423,7 +219402,7 @@ static int jsonEachColumn(
break;
}
default: {
- sqlite3_result_text(ctx, p->path.zBuf, p->nRoot, SQLITE_STATIC);
+ sqlite3_result_text(ctx, p->path.zBuf, p->nRoot, SQLITE_TRANSIENT);
break;
}
case JEACH_JSON: {
@@ -215546,7 +219525,7 @@ static int jsonEachFilter(
if( p->sParse.oom ){
return SQLITE_NOMEM;
}
- goto json_each_malformed_input;
+ return jsonEachMalformedInput(cur);
}
}
if( idxNum==3 ){
@@ -215554,7 +219533,7 @@ static int jsonEachFilter(
if( zRoot==0 ) return SQLITE_OK;
if( zRoot[0]!='$' ){
sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
+ cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0);
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
@@ -215572,7 +219551,7 @@ static int jsonEachFilter(
return SQLITE_OK;
}
sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
+ cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0);
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
@@ -215607,12 +219586,6 @@ static int jsonEachFilter(
p->aParent[0].iValue = i;
}
return SQLITE_OK;
-
-json_each_malformed_input:
- sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
- jsonEachCursorReset(p);
- return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
/* The methods of the json_each virtual table */
@@ -215662,6 +219635,8 @@ SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){
JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc),
JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc),
JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc),
+ JFUNCTION(json_array_insert, -1,1,1, 1,0,JSON_AINS, jsonSetFunc),
+ JFUNCTION(jsonb_array_insert,-1,1,0, 1,1,JSON_AINS, jsonSetFunc),
JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),
JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc),
JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc),
@@ -215900,7 +219875,7 @@ struct Rtree {
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
u8 nBytesPerCell; /* Bytes consumed per cell */
u8 inWrTrans; /* True if inside write transaction */
- u8 nAux; /* # of auxiliary columns in %_rowid */
+ u16 nAux; /* # of auxiliary columns in %_rowid */
#ifdef SQLITE_ENABLE_GEOPOLY
u8 nAuxNotNull; /* Number of initial not-null aux columns */
#endif
@@ -216040,7 +220015,7 @@ struct RtreeCursor {
sqlite3_stmt *pReadAux; /* Statement to read aux-data */
RtreeSearchPoint sPoint; /* Cached next search point */
RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
- u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */
+ u32 anQueue[RTREE_MAX_DEPTH+2]; /* Number of queued entries by iLevel */
};
/* Return the Rtree of a RtreeCursor */
@@ -216220,7 +220195,7 @@ struct RtreeMatchArg {
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
-** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
+** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
*/
#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */
@@ -216276,8 +220251,11 @@ static void readCoord(u8 *p, RtreeCoord *pCoord){
);
#endif
}
+
static i64 readInt64(u8 *p){
-#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+#if defined(SQLITE_AMALGAMATION)
+ return (i64)sqlite3Get8byte(p);
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
u64 x;
memcpy(&x, p, 8);
return (i64)_byteswap_uint64(x);
@@ -216357,6 +220335,18 @@ static int writeInt64(u8 *p, i64 i){
return 8;
}
+/*
+** Translate pVal into a 32-bit integer. If pVal is an integer
+** that is larger than 32 bits, the cap it at the largest or
+** smallest 32-bit integer.
+*/
+static int rtreeValueInt32(sqlite3_value *pVal){
+ i64 v64 = sqlite3_value_int64(pVal);
+ if( v64>2147483647 ) return 2147483647;
+ if( v64<-2147483648LL ) return (int)-2147483648LL;
+ return (int)v64;
+}
+
/*
** Increment the reference count of node p.
*/
@@ -216495,6 +220485,9 @@ static int nodeAcquire(
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
+ }else if( iNode<=0 ){
+ RTREE_IS_CORRUPT(pRtree);
+ rc = SQLITE_CORRUPT_VTAB;
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
@@ -216520,7 +220513,7 @@ static int nodeAcquire(
*/
if( rc==SQLITE_OK && pNode && iNode==1 ){
pRtree->iDepth = readInt16(pNode->zData);
- if( pRtree->iDepth>RTREE_MAX_DEPTH ){
+ if( pRtree->iDepth>=RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
@@ -216634,7 +220627,17 @@ static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){
sqlite3_bind_null(p, 2);
if( pNode->iNode==0 && rc==SQLITE_OK ){
pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
- nodeHashInsert(pRtree, pNode);
+ if( pNode->iNode==0 ){
+ /* If the SQL statement has succeeded but sqlite3_last_insert_rowid()
+ ** returns 0, then the shadow table schema has been corrupted somehow
+ ** (e.g. the %_node table has been replaced by a WITHOUT ROWID table).
+ ** It would be dangerous to continue in this case as the hash table
+ ** implementation assumes iNode==0 means that the node is not part
+ ** of the hash table. */
+ rc = SQLITE_CORRUPT_VTAB;
+ }else{
+ nodeHashInsert(pRtree, pNode);
+ }
}
}
return rc;
@@ -216771,7 +220774,17 @@ static void rtreeRelease(Rtree *pRtree){
pRtree->inWrTrans = 0;
assert( pRtree->nCursor==0 );
nodeBlobReset(pRtree);
- assert( pRtree->nNodeRef==0 || pRtree->bCorrupt );
+ if( pRtree->nNodeRef ){
+ int i;
+ assert( pRtree->bCorrupt );
+ for(i=0; iaHash[i] ){
+ RtreeNode *pNext = pRtree->aHash[i]->pNext;
+ sqlite3_free(pRtree->aHash[i]);
+ pRtree->aHash[i] = pNext;
+ }
+ }
+ }
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
@@ -217126,7 +221139,7 @@ static int nodeRowidIndex(
){
int ii;
int nCell = NCELL(pNode);
- assert( nCell<200 );
+ assert( nCell<65536 && nCell>=0 );
for(ii=0; iiRTREE_MAXCELLS ){
+ RTREE_IS_CORRUPT(pRtree);
+ return SQLITE_CORRUPT_VTAB;
+ }
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
while( p->iCell100) ){
+ if( cnt>100 ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -218421,15 +222437,6 @@ static int SplitNode(
rc = updateMapping(pRtree, pCell->iRowid, pLeft, iHeight);
}
- if( rc==SQLITE_OK ){
- rc = nodeRelease(pRtree, pRight);
- pRight = 0;
- }
- if( rc==SQLITE_OK ){
- rc = nodeRelease(pRtree, pLeft);
- pLeft = 0;
- }
-
splitnode_out:
nodeRelease(pRtree, pRight);
nodeRelease(pRtree, pLeft);
@@ -218614,7 +222621,7 @@ static int rtreeInsertCell(
rc = SplitNode(pRtree, pNode, pCell, iHeight);
}else{
rc = AdjustTree(pRtree, pNode, pCell);
- if( ALWAYS(rc==SQLITE_OK) ){
+ if( rc==SQLITE_OK ){
if( iHeight==0 ){
rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
}else{
@@ -218753,12 +222760,6 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
return rc;
}
-/*
-** Rounding constants for float->double conversion.
-*/
-#define RNDTOWARDS (1.0 - 1.0/8388608.0) /* Round towards zero */
-#define RNDAWAY (1.0 + 1.0/8388608.0) /* Round away from zero */
-
#if !defined(SQLITE_RTREE_INT_ONLY)
/*
** Convert an sqlite3_value into an RtreeValue (presumably a float)
@@ -218768,7 +222769,10 @@ static RtreeValue rtreeValueDown(sqlite3_value *v){
double d = sqlite3_value_double(v);
float f = (float)d;
if( f>d ){
- f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS));
+ unsigned int x;
+ memcpy(&x, &f, 4);
+ x = (x & 0x80000000)!=0 ? x+1 : x-1;
+ memcpy(&f, &x, 4);
}
return f;
}
@@ -218776,12 +222780,40 @@ static RtreeValue rtreeValueUp(sqlite3_value *v){
double d = sqlite3_value_double(v);
float f = (float)d;
if( fcell.aCoord[ii+1].i ){
rc = rtreeConstraintError(pRtree, ii+1);
goto constraint;
@@ -219374,7 +223406,7 @@ static int rtreeInit(
"Auxiliary rtree columns must be last" /* 4 */
};
- assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
+ assert( RTREE_MAX_AUX_COLUMN<256 );
if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
return SQLITE_ERROR;
@@ -219497,12 +223529,14 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
int nData;
int errCode;
sqlite3_str *pOut;
+ i64 nDim64;
UNUSED_PARAMETER(nArg);
memset(&node, 0, sizeof(RtreeNode));
memset(&tree, 0, sizeof(Rtree));
- tree.nDim = (u8)sqlite3_value_int(apArg[0]);
- if( tree.nDim<1 || tree.nDim>5 ) return;
+ nDim64 = sqlite3_value_int64(apArg[0]);
+ if( nDim64<1 || nDim64>5 ) return;
+ tree.nDim = (u8)nDim64;
tree.nDim2 = tree.nDim*2;
tree.nBytesPerCell = 8 + 8 * tree.nDim;
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
@@ -220242,7 +224276,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
/* The sqlite3AtoF() routine is much much faster than atof(), if it
** is available */
double r;
- (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
+ (void)sqlite3AtoF((const char*)p->z, &r);
*pVal = r;
#else
*pVal = (GeoCoord)atof((const char*)p->z);
@@ -220300,7 +224334,7 @@ static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){
break;
}
if( geopolySkipSpace(&s)==']'
- && s.nVertex>=4
+ && s.nVertex>=4 && s.nVertex<16777216
&& s.a[0]==s.a[s.nVertex*2-2]
&& s.a[1]==s.a[s.nVertex*2-1]
&& (s.z++, geopolySkipSpace(&s)==0)
@@ -220626,6 +224660,8 @@ static double geopolySine(double r){
**
** Construct a simple, convex, regular polygon centered at X, Y
** with circumradius R and with N sides.
+**
+** Maximum N is 1000. Maximum R is 1.0e+300.
*/
static void geopolyRegularFunc(
sqlite3_context *context,
@@ -220635,12 +224671,12 @@ static void geopolyRegularFunc(
double x = sqlite3_value_double(argv[0]);
double y = sqlite3_value_double(argv[1]);
double r = sqlite3_value_double(argv[2]);
- int n = sqlite3_value_int(argv[3]);
+ i64 n = sqlite3_value_int64(argv[3]);
int i;
GeoPoly *p;
(void)argc;
- if( n<3 || r<=0.0 ) return;
+ if( n<3 || r<=0.0 || r>=1e300 ) return;
if( n>1000 ) n = 1000;
p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) );
if( p==0 ){
@@ -221293,6 +225329,11 @@ static int geopolyInit(
int ii;
(void)pAux;
+ if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
+ *pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
+ return SQLITE_ERROR;
+ }
+
sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
@@ -221900,6 +225941,12 @@ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "rtreecheck", -1, utf8, 0,rtreecheck, 0,0);
}
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_RTREE_INT_ONLY)
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_function(db, "rtree_round", 2, utf8, 0,
+ rtreeRoundFunc, 0, 0);
+ }
+#endif /* SQLITE_DEBUG && !SQLITE_RTREE_INT_ONLY */
if( rc==SQLITE_OK ){
#ifdef SQLITE_RTREE_INT_ONLY
void *c = (void *)RTREE_COORD_INT32;
@@ -222170,6 +226217,9 @@ static const unsigned char icuUtf8Trans1[] = {
while( (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
+ if( c<0x80 \
+ || (c&0xFFFFF800)==0xD800 \
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
}
#define SQLITE_ICU_SKIP_UTF8(zIn) \
@@ -222427,7 +226477,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
const UChar *zInput; /* Pointer to input string */
UChar *zOutput = 0; /* Pointer to output buffer */
int nInput; /* Size of utf-16 input string in bytes */
- int nOut; /* Size of output buffer in bytes */
+ sqlite3_int64 nOut; /* Size of output buffer in bytes */
int cnt;
int bToUpper; /* True for toupper(), false for tolower() */
UErrorCode status;
@@ -222450,7 +226500,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
}
for(cnt=0; cnt<2; cnt++){
- UChar *zNew = sqlite3_realloc(zOutput, nOut);
+ UChar *zNew = sqlite3_realloc64(zOutput, nOut);
if( zNew==0 ){
sqlite3_free(zOutput);
sqlite3_result_error_nomem(p);
@@ -222459,9 +226509,9 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
zOutput = zNew;
status = U_ZERO_ERROR;
if( bToUpper ){
- nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
+ nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
}else{
- nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
+ nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
}
if( U_SUCCESS(status) ){
@@ -222581,6 +226631,7 @@ static void icuLoadCollation(
}
sqlite3_result_error(p, sqlite3_str_value(pStr), -1);
sqlite3_free(sqlite3_str_finish(pStr));
+ ucol_close(pUCollator);
return;
}
}
@@ -224074,16 +228125,26 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
-1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
unsigned int v = 0;
int c;
unsigned char *z = (unsigned char*)*pz;
- unsigned char *zStart = z;
- while( (c = zValue[0x7f&*(z++)])>=0 ){
- v = (v<<6) + c;
+ unsigned char *zEnd = z + (*pLen);
+ while( z=0 ){
+ v = (v<<6) + c;
+ z++;
}
- z--;
- *pLen -= (int)(z - zStart);
+
+ *pLen -= (int)(z - (unsigned char*)*pz);
*pz = (char*)z;
return v;
}
@@ -224152,21 +228213,22 @@ static int rbuDeltaApply(
int lenDelta, /* Length of the delta */
char *zOut /* Write the output into this preallocated buffer */
){
- unsigned int limit;
- unsigned int total = 0;
+ sqlite3_uint64 limit;
+ sqlite3_uint64 total = 0;
#if RBU_ENABLE_DELTA_CKSUM
char *zOrigOut = zOut;
#endif
limit = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( *zDelta!='\n' ){
+ if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
- zDelta++; lenDelta--;
- while( *zDelta && lenDelta>0 ){
+ zDelta++; lenDelta--; /* Skip the \n */
+ while( lenDelta>0 && zDelta[0] ){
unsigned int cnt, ofst;
cnt = rbuDeltaGetInt(&zDelta, &lenDelta);
+ if( lenDelta<=0 ) return -1;
switch( zDelta[0] ){
case '@': {
zDelta++; lenDelta--;
@@ -224181,7 +228243,7 @@ static int rbuDeltaApply(
/* ERROR: copy exceeds output file size */
return -1;
}
- if( (int)(ofst+cnt) > lenSrc ){
+ if( (u64)ofst+(u64)cnt > (u64)lenSrc ){
/* ERROR: copy extends past end of input */
return -1;
}
@@ -224196,7 +228258,7 @@ static int rbuDeltaApply(
/* ERROR: insert command gives an output larger than predicted */
return -1;
}
- if( (int)cnt>lenDelta ){
+ if( cnt>lenDelta ){
/* ERROR: insert count exceeds size of delta */
return -1;
}
@@ -224234,7 +228296,7 @@ static int rbuDeltaApply(
static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){
int size;
size = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( *zDelta!='\n' ){
+ if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
@@ -224282,7 +228344,7 @@ static void rbuFossilDeltaFunc(
return;
}
- aOut = sqlite3_malloc(nOut+1);
+ aOut = sqlite3_malloc64((i64)nOut+1);
if( aOut==0 ){
sqlite3_result_error_nomem(context);
}else{
@@ -224965,15 +229027,27 @@ static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){
/* Check that all non-HIDDEN columns in the destination table are also
** present in the input table. Populate the abTblPk[], azTblType[] and
- ** aiTblOrder[] arrays at the same time. */
+ ** aiTblOrder[] arrays at the same time.
+ **
+ ** RBU does not support tables with GENERATED columns. If the target
+ ** table has any, return an error. */
if( p->rc==SQLITE_OK ){
p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg,
- sqlite3_mprintf("PRAGMA table_info(%Q)", pIter->zTbl)
+ sqlite3_mprintf("PRAGMA table_xinfo(%Q)", pIter->zTbl)
);
}
while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
- if( zName==0 ) break; /* An OOM - finalize() below returns S_NOMEM */
+ int eHidden = sqlite3_column_int(pStmt, 6);
+ if( zName==0 ) break; /* An OOM. Bail out */
+ if( eHidden==1 ) continue; /* Hidden column. Ignore */
+ if( eHidden!=0 ){
+ p->rc = SQLITE_ERROR;
+ p->zErrmsg = sqlite3_mprintf(
+ "generated columns not supported: %s.%s", pIter->zTbl, zName
+ );
+ break;
+ }
for(i=iOrder; inTblCol; i++){
if( 0==strcmp(zName, pIter->azTblCol[i]) ) break;
}
@@ -225826,9 +229900,9 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
char c = zSql[i];
/* If necessary, grow the pIter->aIdxCol[] array */
- if( iIdxCol==nIdxAlloc ){
- RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc(
- pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan)
+ if( iIdxCol>=(nIdxAlloc-1) ){
+ RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc64(
+ pIter->aIdxCol, nIdxAlloc*sizeof(RbuSpan) + 16*sizeof(RbuSpan)
);
if( aIdxCol==0 ){
rc = SQLITE_NOMEM;
@@ -226209,13 +230283,13 @@ static int rbuGetUpdateStmt(
char *zUpdate = 0;
pUp->zMask = (char*)&pUp[1];
- memcpy(pUp->zMask, zMask, pIter->nTblCol);
pUp->pNext = pIter->pRbuUpdate;
pIter->pRbuUpdate = pUp;
if( zSet ){
const char *zPrefix = "";
-
+ assert( p->rc==SQLITE_OK );
+ memcpy(pUp->zMask, zMask, pIter->nTblCol);
if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_";
zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s",
zPrefix, pIter->zTbl, zSet, zWhere
@@ -226305,6 +230379,9 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
case RBU_STATE_ROW:
pRet->nRow = sqlite3_column_int(pStmt, 1);
+ if( pRet->nRow<0 ){
+ rc = SQLITE_CORRUPT;
+ }
break;
case RBU_STATE_PROGRESS:
@@ -227213,7 +231290,12 @@ static void rbuCreateTargetSchema(sqlite3rbu *p){
while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
- p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
+ sqlite3_stmt *pStmt = 0;
+ p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, zSql);
+ if( p->rc==SQLITE_OK ){
+ sqlite3_step(pStmt);
+ rbuFinalize(p, pStmt);
+ }
}
rbuFinalize(p, pSql);
if( p->rc!=SQLITE_OK ) return;
@@ -229620,12 +233702,14 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
while( p->iCellnCell ){
StatCell *pCell = &p->aCell[p->iCell];
while( pCell->iOvflnOvfl ){
- int nUsable, iOvfl;
+ int nUsable;
+ int iOvfl = pCell->iOvfl;
sqlite3BtreeEnter(pBt);
nUsable = sqlite3BtreeGetPageSize(pBt) -
sqlite3BtreeGetReserveNoMutex(pBt);
sqlite3BtreeLeave(pBt);
pCsr->nPage++;
+ pCsr->iPageno = pCell->aOvfl[iOvfl];
statSizeAndOffset(pCsr);
if( pCell->iOvflnOvfl-1 ){
pCsr->nPayload += nUsable - 4;
@@ -229633,11 +233717,9 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
pCsr->nPayload += pCell->nLastOvfl;
pCsr->nUnused += nUsable - 4 - pCell->nLastOvfl;
}
- iOvfl = pCell->iOvfl;
pCell->iOvfl++;
if( !pCsr->isAgg ){
pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
- pCsr->iPageno = pCell->aOvfl[iOvfl];
pCsr->zPagetype = "overflow";
pCsr->zPath = z = sqlite3_mprintf(
"%s%.3x+%.6x", p->zPath, p->iCell, iOvfl
@@ -230176,12 +234258,13 @@ static int dbpageFilter(
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
if( idxNum & 1 ){
+ i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
assert( argc>(idxNum>>1) );
- pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
- if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
+ if( iPg<1 || iPg>pCsr->mxPgno ){
pCsr->pgno = 1;
pCsr->mxPgno = 0;
}else{
+ pCsr->pgno = (Pgno)iPg;
pCsr->mxPgno = pCsr->pgno;
}
}else{
@@ -230261,6 +234344,7 @@ static int dbpageUpdate(
){
DbpageTable *pTab = (DbpageTable *)pVtab;
Pgno pgno;
+ sqlite3_int64 pgno64;
DbPage *pDbPage = 0;
int rc = SQLITE_OK;
char *zErr = 0;
@@ -230280,11 +234364,11 @@ static int dbpageUpdate(
goto update_fail;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
- pgno = (Pgno)sqlite3_value_int64(argv[2]);
+ pgno64 = sqlite3_value_int64(argv[2]);
isInsert = 1;
}else{
- pgno = (Pgno)sqlite3_value_int64(argv[0]);
- if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
+ pgno64 = (Pgno)sqlite3_value_int64(argv[0]);
+ if( sqlite3_value_int64(argv[1])!=pgno64 ){
zErr = "cannot insert";
goto update_fail;
}
@@ -230301,10 +234385,11 @@ static int dbpageUpdate(
}
}
pBt = pTab->db->aDb[iDb].pBt;
- if( pgno<1 || NEVER(pBt==0) ){
+ if( pgno64<1 || pgno64>4294967294U || NEVER(pBt==0) ){
zErr = "bad page number";
goto update_fail;
}
+ pgno = (Pgno)pgno64;
szPage = sqlite3BtreeGetPageSize(pBt);
if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
|| sqlite3_value_bytes(argv[3])!=szPage
@@ -230501,6 +234586,7 @@ struct carray_bind {
int nData; /* Number of elements */
int mFlags; /* Control flags */
void (*xDel)(void*); /* Destructor for aData */
+ void *pDel; /* Alternative argument to xDel() */
};
@@ -230637,8 +234723,14 @@ static int carrayColumn(
default: {
const struct iovec *p = (struct iovec*)pCur->pPtr;
assert( pCur->eType==CARRAY_BLOB );
- sqlite3_result_blob(ctx, p[pCur->iRowid-1].iov_base,
- (int)p[pCur->iRowid-1].iov_len, SQLITE_TRANSIENT);
+ p += pCur->iRowid-1;
+ if( p->iov_len>0x7fffffff ){
+ sqlite3_result_error_toobig(ctx);
+ return SQLITE_TOOBIG;
+ }else{
+ sqlite3_result_blob(ctx, p->iov_base, (int)p->iov_len,
+ SQLITE_TRANSIENT);
+ }
return SQLITE_OK;
}
}
@@ -230833,7 +234925,7 @@ static sqlite3_module carrayModule = {
static void carrayBindDel(void *pPtr){
carray_bind *p = (carray_bind*)pPtr;
if( p->xDel!=SQLITE_STATIC ){
- p->xDel(p->aData);
+ p->xDel(p->pDel);
}
sqlite3_free(p);
}
@@ -230841,14 +234933,26 @@ static void carrayBindDel(void *pPtr){
/*
** Invoke this interface in order to bind to the single-argument
** version of CARRAY().
+**
+** pStmt The prepared statement to which to bind
+** idx The index of the parameter of pStmt to which to bind
+** aData The data to be bound
+** nData The number of elements in aData
+** mFlags One of SQLITE_CARRAY_xxxx indicating datatype of aData
+** xDestroy Destructor for pDestroy or aData if pDestroy==NULL.
+** pDestroy Invoke xDestroy on this pointer if not NULL
+**
+** The destructor is called pDestroy if pDestroy!=NULL, or against
+** aData if pDestroy==NULL.
*/
-SQLITE_API int sqlite3_carray_bind(
+SQLITE_API int sqlite3_carray_bind_v2(
sqlite3_stmt *pStmt,
int idx,
void *aData,
int nData,
int mFlags,
- void (*xDestroy)(void*)
+ void (*xDestroy)(void*),
+ void *pDestroy
){
carray_bind *pNew = 0;
int i;
@@ -230925,20 +235029,38 @@ SQLITE_API int sqlite3_carray_bind(
memcpy(pNew->aData, aData, sz);
}
pNew->xDel = sqlite3_free;
+ pNew->pDel = pNew->aData;
}else{
pNew->aData = aData;
pNew->xDel = xDestroy;
+ pNew->pDel = pDestroy;
}
return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel);
carray_bind_error:
if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){
- xDestroy(aData);
+ xDestroy(pDestroy);
}
sqlite3_free(pNew);
return rc;
}
+/*
+** Invoke this interface in order to bind to the single-argument
+** version of CARRAY(). Same as sqlite3_carray_bind_v2() with the
+** pDestroy parameter set to NULL.
+*/
+SQLITE_API int sqlite3_carray_bind(
+ sqlite3_stmt *pStmt,
+ int idx,
+ void *aData,
+ int nData,
+ int mFlags,
+ void (*xDestroy)(void*)
+){
+ return sqlite3_carray_bind_v2(pStmt,idx,aData,nData,mFlags,xDestroy,aData);
+}
+
/*
** Invoke this routine to register the carray() function.
*/
@@ -231298,7 +235420,24 @@ static int sessionVarintLen(int iVal){
** bytes read.
*/
static int sessionVarintGet(const u8 *aBuf, int *piVal){
- return getVarint32(aBuf, *piVal);
+ int ret = getVarint32(aBuf, *piVal);
+ *piVal = (*piVal & 0x7FFFFFFF);
+ return ret;
+}
+
+/*
+** Read a varint value from buffer aBuf[], size nBuf bytes, into *piVal.
+** Return the number of bytes read.
+*/
+static int sessionVarintGetSafe(const u8 *aBuf, int nBuf, int *piVal){
+ u8 aCopy[9];
+ const u8 *aRead = aBuf;
+ memset(aCopy, 0, sizeof(aCopy));
+ if( nBuf> 0) & 0xFF;
}
+/*
+** Write a double value to the buffer aBuf[].
+*/
+static void sessionPutDouble(u8 *aBuf, double r){
+ /* TODO: SQLite does something special to deal with mixed-endian
+ ** floating point values (e.g. ARM7). This code probably should
+ ** too. */
+ u64 i;
+ assert( sizeof(double)==8 && sizeof(u64)==8 );
+ memcpy(&i, &r, 8);
+ sessionPutI64(aBuf, i);
+}
+
/*
** This function is used to serialize the contents of value pValue (see
** comment titled "RECORD FORMAT" above).
@@ -231366,16 +235518,13 @@ static int sessionSerializeValue(
/* TODO: SQLite does something special to deal with mixed-endian
** floating point values (e.g. ARM7). This code probably should
** too. */
- u64 i;
if( eType==SQLITE_INTEGER ){
- i = (u64)sqlite3_value_int64(pValue);
+ u64 i = (u64)sqlite3_value_int64(pValue);
+ sessionPutI64(&aBuf[1], i);
}else{
- double r;
- assert( sizeof(double)==8 && sizeof(u64)==8 );
- r = sqlite3_value_double(pValue);
- memcpy(&i, &r, 8);
+ double r = sqlite3_value_double(pValue);
+ sessionPutDouble(&aBuf[1], r);
}
- sessionPutI64(&aBuf[1], i);
}
nByte = 9;
break;
@@ -231565,10 +235714,11 @@ static int sessionSerialLen(const u8 *a){
int n;
assert( a!=0 );
e = *a;
- if( e==0 || e==0xFF ) return 1;
- if( e==SQLITE_NULL ) return 1;
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
- return sessionVarintGet(&a[1], &n) + 1 + n;
+ if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
+ return sessionVarintGet(&a[1], &n) + 1 + n;
+ }
+ return 1;
}
/*
@@ -231591,31 +235741,31 @@ static unsigned int sessionChangeHash(
u8 *a = aRecord; /* Used to iterate through change record */
for(i=0; inCol; i++){
- int eType = *a;
int isPK = pTab->abPK[i];
if( bPkOnly && isPK==0 ) continue;
- /* It is not possible for eType to be SQLITE_NULL here. The session
- ** module does not record changes for rows with NULL values stored in
- ** primary key columns. */
- assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
- || eType==SQLITE_TEXT || eType==SQLITE_BLOB
- || eType==SQLITE_NULL || eType==0
- );
- assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) );
-
if( isPK ){
- a++;
+ int eType = *a++;
+
+ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
+ || eType==SQLITE_TEXT || eType==SQLITE_BLOB
+ || eType==SQLITE_NULL || eType==0
+ );
+
h = sessionHashAppendType(h, eType);
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
h = sessionHashAppendI64(h, sessionGetI64(a));
a += 8;
- }else{
+ }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
int n;
a += sessionVarintGet(a, &n);
h = sessionHashAppendBlob(h, n, a);
a += n;
}
+ /* It should not be possible for eType to be SQLITE_NULL or 0x00 here,
+ ** as the session module does not record changes for rows with NULL
+ ** values stored in primary key columns. But a corrupt changesets
+ ** may contain such a value. */
}else{
a += sessionSerialLen(a);
}
@@ -232307,9 +236457,7 @@ static void sessionUpdateOneChange(
case SQLITE_FLOAT: {
double rVal = sqlite3_column_double(pDflt, iField);
- i64 iVal = 0;
- memcpy(&iVal, &rVal, sizeof(rVal));
- sessionPutI64(&pNew->aRecord[pNew->nRecord], iVal);
+ sessionPutDouble(&pNew->aRecord[pNew->nRecord], rVal);
pNew->nRecord += 8;
break;
}
@@ -232405,7 +236553,7 @@ static void sessionAppendStr(
int *pRc
){
int nStr = sqlite3Strlen30(zStr);
- if( 0==sessionBufferGrow(p, nStr+1, pRc) ){
+ if( 0==sessionBufferGrow(p, (i64)nStr+1, pRc) ){
memcpy(&p->aBuf[p->nBuf], zStr, nStr);
p->nBuf += nStr;
p->aBuf[p->nBuf] = 0x00;
@@ -232473,6 +236621,16 @@ static int sessionPrepareDfltStmt(
return rc;
}
+/*
+** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
+** called, set it to the results of the sqlite3_finalize() call. Or, if
+** it is already set to an error code, leave it as is.
+*/
+static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
+ int rc = sqlite3_finalize(pStmt);
+ if( *pRc==SQLITE_OK ) *pRc = rc;
+}
+
/*
** Table pTab has one or more existing change-records with old.* records
** with fewer than pTab->nCol columns. This function updates all such
@@ -232495,9 +236653,8 @@ static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){
}
}
+ sessionFinalizeStmt(pStmt, &rc);
pSession->rc = rc;
- rc = sqlite3_finalize(pStmt);
- if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
return pSession->rc;
}
@@ -233065,7 +237222,7 @@ static int sessionDiffFindNew(
rc = SQLITE_NOMEM;
}else{
sqlite3_stmt *pStmt;
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
pDiffCtx->pStmt = pStmt;
@@ -233128,7 +237285,7 @@ static int sessionDiffFindModified(
rc = SQLITE_NOMEM;
}else{
sqlite3_stmt *pStmt;
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
@@ -233566,15 +237723,14 @@ static void sessionAppendCol(
int eType = sqlite3_column_type(pStmt, iCol);
sessionAppendByte(p, (u8)eType, pRc);
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- sqlite3_int64 i;
u8 aBuf[8];
if( eType==SQLITE_INTEGER ){
- i = sqlite3_column_int64(pStmt, iCol);
+ sqlite3_int64 i = sqlite3_column_int64(pStmt, iCol);
+ sessionPutI64(aBuf, i);
}else{
double r = sqlite3_column_double(pStmt, iCol);
- memcpy(&i, &r, 8);
+ sessionPutDouble(aBuf, r);
}
- sessionPutI64(aBuf, i);
sessionAppendBlob(p, aBuf, 8, pRc);
}
if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){
@@ -233780,6 +237936,33 @@ static int sessionPrepare(
return rc;
}
+/*
+** Prepare the statement specified by printf format zFmt and its trailing
+** arguments.
+*/
+static void sessionPrepareMprintf(
+ int *pRc,
+ sqlite3 *db,
+ sqlite3_stmt **pp,
+ char **pzErrmsg,
+ const char *zFmt,
+ ...
+){
+ if( *pRc==SQLITE_OK ){
+ char *zSql;
+ va_list ap;
+ va_start(ap, zFmt);
+ zSql = sqlite3_vmprintf(zFmt, ap);
+ if( zSql==0 ){
+ *pRc = SQLITE_NOMEM;
+ }else{
+ *pRc = sessionPrepare(db, pp, pzErrmsg, zSql);
+ sqlite3_free(zSql);
+ }
+ va_end(ap);
+ }
+}
+
/*
** Formulate and prepare a SELECT statement to retrieve a row from table
** zTab in database zDb based on its primary key. i.e.
@@ -233824,11 +238007,11 @@ static int sessionSelectStmt(
);
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
}else{
- #if 0
+#if 0
if( bRowid ){
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
}
- #endif
+#endif
for(i=0; irc ) return pSession->rc;
- rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
- if( rc!=SQLITE_OK ) return rc;
sqlite3_mutex_enter(sqlite3_db_mutex(db));
+ rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
+ if( rc!=SQLITE_OK ){
+ sqlite3_mutex_leave(sqlite3_db_mutex(db));
+ return rc;
+ }
for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
if( pTab->nEntry ){
@@ -234510,7 +238696,8 @@ static int sessionReadRecord(
u8 *aVal = &pIn->aData[pIn->iNext];
if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
int nByte;
- pIn->iNext += sessionVarintGet(aVal, &nByte);
+ int nRem = pIn->nData - pIn->iNext;
+ pIn->iNext += sessionVarintGetSafe(aVal, nRem, &nByte);
rc = sessionInputBuffer(pIn, nByte);
if( rc==SQLITE_OK ){
if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
@@ -234563,7 +238750,8 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){
rc = sessionInputBuffer(pIn, 9);
if( rc==SQLITE_OK ){
- nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol);
+ int nBuf = pIn->nData - pIn->iNext;
+ nRead += sessionVarintGetSafe(&pIn->aData[pIn->iNext], nBuf, &nCol);
/* The hard upper limit for the number of columns in an SQLite
** database table is, according to sqliteLimit.h, 32676. So
** consider any table-header that purports to have more than 65536
@@ -234583,8 +238771,15 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){
while( (pIn->iNext + nRead)nData && pIn->aData[pIn->iNext + nRead] ){
nRead++;
}
+
+ /* Break out of the loop if if the nul-terminator byte has been found.
+ ** Otherwise, read some more input data and keep seeking. If there is
+ ** no more input data, consider the changeset corrupt. */
if( (pIn->iNext + nRead)nData ) break;
rc = sessionInputBuffer(pIn, nRead + 100);
+ if( rc==SQLITE_OK && (pIn->iNext + nRead)>=pIn->nData ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
}
*pnByte = nRead+1;
return rc;
@@ -234605,22 +238800,32 @@ static int sessionChangesetBufferRecord(
int *pnByte /* OUT: Size of record in bytes */
){
int rc = SQLITE_OK;
- int nByte = 0;
+ i64 nByte = 0;
int i;
for(i=0; rc==SQLITE_OK && iaData[pIn->iNext + nByte++];
- if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
- int n;
- nByte += sessionVarintGet(&pIn->aData[pIn->iNext+nByte], &n);
- nByte += n;
- rc = sessionInputBuffer(pIn, nByte);
- }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- nByte += 8;
+ if( pIn->iNext+nByte>=pIn->nData ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ eType = pIn->aData[pIn->iNext + nByte++];
+ if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
+ int n;
+ int nRem = pIn->nData - (pIn->iNext + nByte);
+ nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem,&n);
+ nByte += n;
+ rc = sessionInputBuffer(pIn, nByte);
+ }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
+ nByte += 8;
+ }else if( eType!=0 && eType!=SQLITE_NULL ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
}
}
+ if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
}
*pnByte = nByte;
return rc;
@@ -234716,10 +238921,10 @@ static int sessionChangesetNextOne(
memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2);
}
- /* Make sure the buffer contains at least 10 bytes of input data, or all
- ** remaining data if there are less than 10 bytes available. This is
- ** sufficient either for the 'T' or 'P' byte and the varint that follows
- ** it, or for the two single byte values otherwise. */
+ /* Make sure the buffer contains at least 2 bytes of input data, or all
+ ** remaining data if there are less than 2 bytes available. This is
+ ** sufficient either for the 'T' or 'P' byte that begins a new table,
+ ** or for the "op" and "bIndirect" single bytes otherwise. */
p->rc = sessionInputBuffer(&p->in, 2);
if( p->rc!=SQLITE_OK ) return p->rc;
@@ -234749,11 +238954,13 @@ static int sessionChangesetNextOne(
return (p->rc = SQLITE_CORRUPT_BKPT);
}
- p->op = op;
- p->bIndirect = p->in.aData[p->in.iNext++];
- if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){
+ if( (op!=SQLITE_UPDATE && op!=SQLITE_DELETE && op!=SQLITE_INSERT)
+ || (p->in.iNext>=p->in.nData)
+ ){
return (p->rc = SQLITE_CORRUPT_BKPT);
}
+ p->op = op;
+ p->bIndirect = p->in.aData[p->in.iNext++];
if( paRec ){
int nVal; /* Number of values to buffer */
@@ -235062,7 +239269,13 @@ static int sessionChangesetInvert(
/* Test for EOF. */
if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
- if( pInput->iNext>=pInput->nData ) break;
+ if( pInput->iNext+1>=pInput->nData ){
+ if( pInput->iNext!=pInput->nData ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto finished_invert;
+ }
+ break;
+ }
eType = pInput->aData[pInput->iNext];
switch( eType ){
@@ -235258,6 +239471,7 @@ struct SessionApplyCtx {
u8 bRebaseStarted; /* If table header is already in rebase */
u8 bRebase; /* True to collect rebase information */
u8 bIgnoreNoop; /* True to ignore no-op conflicts */
+ u8 bNoUpdateLoop; /* No update-loop processing */
int bRowid;
char *zErr; /* Error message, if any */
};
@@ -235831,7 +240045,7 @@ static int sessionConflictHandler(
u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
int nBlob = pIter->in.iNext - pIter->in.iCurrent;
sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
- return SQLITE_OK;
+ return rc;
}else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
|| eType==SQLITE_CHANGESET_CONFLICT
){
@@ -235953,7 +240167,7 @@ static int sessionApplyOneOp(
for(i=0; rc==SQLITE_OK && iabPK[i] || (bPatchset==0 && pOld) ){
+ if( pOld && (p->abPK[i] || bPatchset==0) ){
rc = sessionBindValue(pUp, i*2+2, pOld);
}
if( rc==SQLITE_OK && pNew ){
@@ -236079,7 +240293,321 @@ static int sessionApplyOneWithRetry(
}
/*
-** Retry the changes accumulated in the pApply->constraints buffer.
+** Create an iterator to iterate through the retry buffer pRetry.
+*/
+static int sessionRetryIterInit(
+ SessionBuffer *pRetry, /* Buffer to iterate through */
+ int bPatchset, /* True for patchset, false for changeset */
+ const char *zTab, /* Table name */
+ SessionApplyCtx *pApply, /* Session apply context */
+ sqlite3_changeset_iter **ppIter /* OUT: New iterator */
+){
+ sqlite3_changeset_iter *pRet = 0;
+ int rc = SQLITE_OK;
+
+ rc = sessionChangesetStart(
+ &pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply->bInvertConstraints, 1
+ );
+ if( rc==SQLITE_OK ){
+ size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
+ pRet->bPatchset = bPatchset;
+ pRet->zTab = (char*)zTab;
+ pRet->nCol = pApply->nCol;
+ pRet->abPK = pApply->abPK;
+ sessionBufferGrow(&pRet->tblhdr, nByte, &rc);
+ pRet->apValue = (sqlite3_value**)pRet->tblhdr.aBuf;
+ if( rc==SQLITE_OK ){
+ memset(pRet->apValue, 0, nByte);
+ }else{
+ sqlite3changeset_finalize(pRet);
+ pRet = 0;
+ }
+ }
+
+ *ppIter = pRet;
+ return rc;
+}
+
+/*
+** Attempt to apply all the changes in retry buffer pRetry to the database.
+** Except, if parameter iSkip is greater than or equal to 0, skip change
+** iSkip.
+*/
+static int sessionApplyRetryBuffer(
+ SessionBuffer *pRetry, /* Buffer to apply changes from */
+ int iSkip, /* If >=0, index of change to omit */
+ sqlite3 *db, /* Database handle */
+ int bPatchset, /* True for patchset, false for changeset */
+ const char *zTab, /* Name of table to write to */
+ SessionApplyCtx *pApply, /* Apply context */
+ int(*xConflict)(void*, int, sqlite3_changeset_iter*),
+ void *pCtx /* First argument passed to xConflict */
+){
+ int rc = SQLITE_OK;
+ int rc2 = SQLITE_OK;
+ int ii = 0;
+ sqlite3_changeset_iter *pIter = 0;
+
+ assert( pApply->constraints.nBuf==0 );
+
+ rc = sessionRetryIterInit(pRetry, bPatchset, zTab, pApply, &pIter);
+
+ for(ii=0; rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter); ii++){
+ if( ii!=iSkip ){
+ rc = sessionApplyOneWithRetry(db, pIter, pApply, xConflict, pCtx);
+ }
+ }
+
+ rc2 = sqlite3changeset_finalize(pIter);
+ if( rc==SQLITE_OK ) rc = rc2;
+ assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
+
+ return rc;
+}
+
+/*
+** Buffer aUnique[] is pApply->nCol entries in size. This function sets
+** aUnique[i] to true if column i of table zTab in the "main" database
+** of db is part of at least one UNIQUE constraint, or to false otherwise.
+**
+** If the table has a unique index on an expression, or a partial unique
+** index, all entries of aUnique[] are set to true.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+static int sessionUniqueColumns(
+ sqlite3 *db, /* Database handle */
+ const char *zTab, /* Table name */
+ SessionApplyCtx *pApply, /* Apply context */
+ u8 *aUnique /* OUT: Array of pApply->nCol flags */
+){
+ sqlite3_stmt *pList = 0; /* PRAGMA index_list */
+ int rc = SQLITE_OK;
+
+ /* Ordinary PRAGMA statements are used here instead of the equivalent
+ ** table-valued functions (pragma_index_list() etc.) so that this works
+ ** in builds with SQLITE_OMIT_VIRTUALTABLE defined. */
+ memset(aUnique, 0, pApply->nCol);
+ sessionPrepareMprintf(&rc, db, &pList, &pApply->zErr,
+ "PRAGMA main.index_list(%Q)", zTab
+ );
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){
+ /* Columns of PRAGMA index_list are (seq, name, unique, origin, partial) */
+ const char *zIdx = (const char*)sqlite3_column_text(pList, 1);
+ int bUnique = sqlite3_column_int(pList, 2);
+ int bPartial = sqlite3_column_int(pList, 4);
+ sqlite3_stmt *pInfo = 0; /* PRAGMA index_xinfo */
+
+ if( bUnique==0 ) continue;
+ sessionPrepareMprintf(&rc, db, &pInfo, &pApply->zErr,
+ "PRAGMA main.index_xinfo(%Q)", zIdx
+ );
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pInfo) ){
+ /* Columns of PRAGMA index_xinfo are (seqno, cid, name, desc, coll, key)*/
+ int iCid = sqlite3_column_int(pInfo, 1);
+ const char *zCol = (const char*)sqlite3_column_text(pInfo, 2);
+ int bKey = sqlite3_column_int(pInfo, 5);
+ int ii;
+ if( bKey==0 ) continue;
+ for(ii=0; iinCol; ii++){
+ if( bPartial
+ || iCid==-2
+ || (zCol && 0==sqlite3_stricmp(zCol, pApply->azCol[ii]))
+ ){
+ aUnique[ii] = 1;
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_finalize(pInfo);
+ }else{
+ sqlite3_finalize(pInfo);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_finalize(pList);
+ }else{
+ sqlite3_finalize(pList);
+ }
+
+ return rc;
+}
+
+/*
+** Iterator pUp points to an UPDATE change. This function updates the
+** affected row to set each column modified by the UPDATE change that
+** is also part of at least one UNIQUE constraint to a "random" value,
+** and creates another UPDATE statement that may be used to later set
+** all columns modified by pUp to the actual values required by pUp.
+**
+** Each random value has the same type as the final value required by
+** pUp for the same column:
+**
+** NULL -> NULL
+** INTEGER -> random()
+** REAL -> random()
+** TEXT -> CAST(random() AS TEXT)
+** BLOB -> unhex(hex(random()))
+**
+** If none of the columns modified by pUp are part of a UNIQUE constraint,
+** then SQLITE_CONSTRAINT is returned.
+**
+** If successful, SQLITE_OK is returned and output variable (*ppUpdate)
+** is left pointing to a prepared UPDATE statement. It is the responsibility
+** of the caller to eventually free this statement using sqlite3_finalize().
+** Or, if an error occurs, an SQLite error code is returned and (*ppUpdate)
+** set to NULL. pApply->zErr may be set to an error message in this case.
+** Except - it is guaranteed that pApply->zErr is not set if SQLITE_CONSTRAINT
+** is returned.
+*/
+static int sessionUpdateToUpdate(
+ sqlite3 *db, /* Database to write to */
+ const char *zTab, /* Table name */
+ SessionApplyCtx *pApply, /* Apply context */
+ sqlite3_changeset_iter *pUp, /* Iterator pointing to UPDATE change */
+ sqlite3_stmt **ppUpdate /* OUT: UPDATE statement */
+){
+ sqlite3_stmt *pRet = 0; /* UPDATE to set the final values */
+ sqlite3_stmt *pRand = 0; /* UPDATE to set random values */
+ int rc = SQLITE_OK;
+ u8 *aUnique = 0; /* aUnique[i] true if col i is UNIQUE */
+ SessionBuffer randset = {0, 0, 0};
+ SessionBuffer upset = {0, 0, 0};
+ SessionBuffer where = {0, 0, 0};
+ int ii;
+
+ aUnique = (u8*)sqlite3_malloc64(pApply->nCol);
+ if( aUnique==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sessionUniqueColumns(db, zTab, pApply, aUnique);
+ }
+
+ /* Assuming a table structure like this:
+ **
+ ** CREATE TABLE x(a, b UNIQUE, c, d UNIQUE, e, PRIMARY KEY(a, c));
+ **
+ ** and an UPDATE change that sets column b to an integer, column d to
+ ** a text value and column e to any value, the two statements prepared
+ ** are:
+ **
+ ** UPDATE main.x SET b = random(), d = CAST(random() AS TEXT)
+ ** WHERE a IS ?1 AND c IS ?3
+ ** UPDATE main.x SET b = ?2, d = ?4, e = ?5 WHERE a IS ?1 AND c IS ?3
+ */
+ for(ii=0; rc==SQLITE_OK && iinCol; ii++){
+ sqlite3_value *pNew = 0;
+ if( pApply->abPK[ii] ){
+ if( where.nBuf>0 ) sessionAppendStr(&where, " AND ", &rc);
+ sessionAppendIdent(&where, pApply->azCol[ii], &rc);
+ sessionAppendPrintf(&where, &rc, " IS ?%d", ii+1);
+ }else if( (pNew = sessionChangesetNew(pUp, ii))!=0 ){
+ if( aUnique[ii] ){
+ const char *zRand = 0;
+ switch( sqlite3_value_type(pNew) ){
+ case SQLITE_NULL: zRand = "NULL"; break;
+ case SQLITE_TEXT: zRand = "CAST(random() AS TEXT)"; break;
+ case SQLITE_BLOB: zRand = "unhex(hex(random()))"; break;
+ default: zRand = "random()"; break;
+ }
+ if( randset.nBuf>0 ) sessionAppendStr(&randset, ", ", &rc);
+ sessionAppendIdent(&randset, pApply->azCol[ii], &rc);
+ sessionAppendStr(&randset, " = ", &rc);
+ sessionAppendStr(&randset, zRand, &rc);
+ }
+ if( upset.nBuf>0 ) sessionAppendStr(&upset, ", ", &rc);
+ sessionAppendIdent(&upset, pApply->azCol[ii], &rc);
+ sessionAppendPrintf(&upset, &rc, " = ?%d", ii+1);
+ }
+ }
+
+ if( rc==SQLITE_OK && randset.nBuf==0 ){
+ /* None of the columns modified by this change are part of a UNIQUE
+ ** constraint. So setting them to random values cannot help resolve
+ ** a constraint conflict. Report this as a constraint failure. */
+ rc = SQLITE_CONSTRAINT;
+ }
+
+ sessionPrepareMprintf(&rc, db, &pRand, &pApply->zErr,
+ "UPDATE main.\"%w\" SET %s WHERE %s",
+ zTab, (char*)randset.aBuf, (char*)where.aBuf
+ );
+ sessionPrepareMprintf(&rc, db, &pRet, &pApply->zErr,
+ "UPDATE main.\"%w\" SET %s WHERE %s",
+ zTab, (char*)upset.aBuf, (char*)where.aBuf
+ );
+
+ /* Bind the PK values to both statements, and the new.* values to pRet. */
+ if( rc==SQLITE_OK ){
+ rc = sessionBindRow(
+ pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pRand
+ );
+ }
+ if( rc==SQLITE_OK ){
+ rc = sessionBindRow(
+ pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pRet
+ );
+ }
+ for(ii=0; rc==SQLITE_OK && iinCol; ii++){
+ sqlite3_value *pNew = sessionChangesetNew(pUp, ii);
+ if( pApply->abPK[ii]==0 && pNew ){
+ rc = sessionBindValue(pRet, ii+1, pNew);
+ }
+ }
+
+ /* Evaluate the statement to set each modified column of the row to a random
+ ** value. If this fails with a constraint error, SQLITE_CONSTRAINT is
+ ** returned to the caller, but pApply->zErr is not set. */
+ if( rc==SQLITE_OK ){
+ sqlite3_step(pRand);
+ rc = sqlite3_reset(pRand);
+ }
+ sqlite3_finalize(pRand);
+
+ if( rc!=SQLITE_OK ){
+ sqlite3_finalize(pRet);
+ pRet = 0;
+ }
+ *ppUpdate = pRet;
+
+ sqlite3_free(aUnique);
+ sqlite3_free(randset.aBuf);
+ sqlite3_free(upset.aBuf);
+ sqlite3_free(where.aBuf);
+
+ return rc;
+}
+
+/*
+** Retry the changes accumulated in the pApply->constraints buffer. The
+** pApply->constraints buffer contains all changes to table zTab that
+** could not be applied due to SQLITE_CONSTRAINT errors. This function
+** attempts to apply them as follows:
+**
+** 1) It runs through the buffer and attempts to retry each change,
+** removing any that are successfully applied from the buffer. This
+** is repeated until no further progress can be made.
+**
+** 2) For each UPDATE change in the buffer, try the following in a
+** savepoint transaction:
+**
+** a) UPDATE the affected row, setting each column modified by the
+** UPDATE change to a random value,
+** b) Attempt step (1) with remaining changes,
+** c) Attempt to UPDATE the affected row again, this time setting
+** each modified column to the value required by the UPDATE change.
+**
+** If both (a) and (c) succeed, the savepoint is committed and all
+** successfully applied changes are removed from the buffer. Step (2)
+** is then repeated. Otherwise, if either (a) or (c) fails with
+** SQLITE_CONSTRAINT, the savepoint is rolled back and the next UPDATE
+** in the buffer is tried.
+**
+** 3) Once step (2) has been attempted for each UPDATE in the change,
+** a final attempt is made to apply each remaining change. This time,
+** if an SQLITE_CONSTRAINT error is encountered, the conflict handler
+** is invoked and the user has to decide whether to omit the change
+** or rollback the entire _apply() operation.
*/
static int sessionRetryConstraints(
sqlite3 *db,
@@ -236090,41 +240618,115 @@ static int sessionRetryConstraints(
void *pCtx /* First argument passed to xConflict */
){
int rc = SQLITE_OK;
+ int iUpdate = 0;
+ /* Step (1) */
while( pApply->constraints.nBuf ){
- sqlite3_changeset_iter *pIter2 = 0;
SessionBuffer cons = pApply->constraints;
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
- rc = sessionChangesetStart(
- &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
+ rc = sessionApplyRetryBuffer(
+ &cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
+ );
+
+ sqlite3_free(cons.aBuf);
+ if( rc!=SQLITE_OK ) break;
+
+ /* If no progress has been made this round, break out of the loop. */
+ if( pApply->constraints.nBuf>=cons.nBuf ) break;
+ }
+
+ /* Step (2) */
+ while( rc==SQLITE_OK && pApply->constraints.nBuf && !pApply->bNoUpdateLoop ){
+ SessionBuffer cons = {0, 0, 0};
+ sqlite3_changeset_iter *pUp = 0;
+ sqlite3_stmt *pUpdate = 0;
+ int iSkip = 0;
+ int bConstraint = 0; /* True if an SQLITE_CONSTRAINT occurs */
+
+ rc = sessionRetryIterInit(
+ &pApply->constraints, bPatchset, zTab, pApply, &pUp
);
if( rc==SQLITE_OK ){
- size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
- int rc2;
- pIter2->bPatchset = bPatchset;
- pIter2->zTab = (char*)zTab;
- pIter2->nCol = pApply->nCol;
- pIter2->abPK = pApply->abPK;
- sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
- pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
- if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte);
+ int iThis = -1;
+ while( SQLITE_ROW==sqlite3changeset_next(pUp) ){
+ if( pUp->op==SQLITE_UPDATE ) iThis++;
+ if( iThis==iUpdate ) break;
+ iSkip++;
+ }
+ if( iThis==iUpdate ){
+ rc = sqlite3_exec(db, "SAVEPOINT update_op", 0, 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = sessionUpdateToUpdate(db, zTab, pApply, pUp, &pUpdate);
+ if( (rc&0xff)==SQLITE_CONSTRAINT ){
+ bConstraint = 1;
+ rc = SQLITE_OK;
+ }
+ }
+ }
+ sqlite3changeset_finalize(pUp);
+ if( iThis!=iUpdate ) break;
+ }
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){
- rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx);
+ if( rc==SQLITE_OK ){
+ cons = pApply->constraints;
+ if( bConstraint ){
+ memset(&pApply->constraints, 0, sizeof(SessionBuffer));
}
- rc2 = sqlite3changeset_finalize(pIter2);
- if( rc==SQLITE_OK ) rc = rc2;
+ while( rc==SQLITE_OK && pApply->constraints.nBuf>0 ){
+ SessionBuffer app = pApply->constraints;
+ memset(&pApply->constraints, 0, sizeof(SessionBuffer));
+ rc = sessionApplyRetryBuffer(
+ &app, iSkip, db, bPatchset, zTab, pApply, xConflict, pCtx
+ );
+ if( app.aBuf!=cons.aBuf ){
+ sqlite3_free(app.aBuf);
+ }
+ if( pApply->constraints.nBuf>=app.nBuf ){
+ break;
+ }
+ iSkip = -1;
+ }
}
- assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
- sqlite3_free(cons.aBuf);
- if( rc!=SQLITE_OK ) break;
- if( pApply->constraints.nBuf>=cons.nBuf ){
- /* No progress was made on the last round. */
- pApply->bDeferConstraints = 0;
+ iUpdate++;
+ if( rc==SQLITE_OK ){
+ if( bConstraint==0 ){
+ sqlite3_step(pUpdate);
+ rc = sqlite3_finalize(pUpdate);
+ pUpdate = 0;
+ if( (rc&0xff)==SQLITE_CONSTRAINT ){
+ bConstraint = 1;
+ rc = SQLITE_OK;
+ }
+ }
+ if( bConstraint ){
+ rc = sqlite3_exec(db, "ROLLBACK TO update_op", 0, 0, 0);
+ sqlite3_free(pApply->constraints.aBuf);
+ pApply->constraints = cons;
+ memset(&cons, 0, sizeof(cons));
+ }else if( rc==SQLITE_OK ){
+ iUpdate = 0;
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_exec(db, "RELEASE update_op", 0, 0, 0);
+ }
}
+ sqlite3_finalize(pUpdate);
+
+ sqlite3_free(cons.aBuf);
+ }
+
+ /* Step (3) */
+ if( rc==SQLITE_OK && pApply->constraints.nBuf ){
+ SessionBuffer cons = pApply->constraints;
+ memset(&pApply->constraints, 0, sizeof(SessionBuffer));
+ pApply->bDeferConstraints = 0;
+ rc = sessionApplyRetryBuffer(
+ &cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
+ );
+ sqlite3_free(cons.aBuf);
}
return rc;
@@ -236160,10 +240762,10 @@ static int sessionChangesetApply(
int schemaMismatch = 0;
int rc = SQLITE_OK; /* Return code */
const char *zTab = 0; /* Name of current table */
- int nTab = 0; /* Result of sqlite3Strlen30(zTab) */
SessionApplyCtx sApply; /* changeset_apply() context object */
int bPatchset;
u64 savedFlag = db->flags & SQLITE_FkNoAction;
+ int bNew = 0; /* True for first entry of new table */
assert( xConflict!=0 );
@@ -236178,21 +240780,23 @@ static int sessionChangesetApply(
sApply.bRebase = (ppRebase && pnRebase);
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
+ sApply.bNoUpdateLoop = !!(flags & SQLITE_CHANGESETAPPLY_NOUPDATELOOP);
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0);
}
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){
+ while( rc==SQLITE_OK && SQLITE_ROW==sessionChangesetNext(pIter, 0, 0,&bNew) ){
int nCol;
int op;
const char *zNew;
sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0);
- if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){
+ if( bNew ){
u8 *abPK;
+ bNew = 0;
rc = sessionRetryConstraints(
db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx
@@ -236227,7 +240831,6 @@ static int sessionChangesetApply(
rc = SQLITE_NOMEM;
break;
}
- nTab = (int)strlen(zTab);
sApply.azCol = (const char **)zTab;
}else{
int nMinCol = 0;
@@ -236280,7 +240883,6 @@ static int sessionChangesetApply(
sApply.bStat1 = 0;
}
}
- nTab = sqlite3Strlen30(zTab);
}
}
@@ -236601,6 +241203,21 @@ SQLITE_API int sqlite3changeset_apply_strm(
);
}
+/*
+** The parts of the sqlite3_changegroup structure used by the
+** sqlite3changegroup_change_xxx() APIs.
+*/
+typedef struct ChangeData ChangeData;
+struct ChangeData {
+ SessionTable *pTab;
+ int bIndirect;
+ int eOp;
+
+ int nBufAlloc;
+ SessionBuffer *aBuf;
+ SessionBuffer record;
+};
+
/*
** sqlite3_changegroup handle.
*/
@@ -236612,12 +241229,17 @@ struct sqlite3_changegroup {
sqlite3 *db; /* Configured by changegroup_schema() */
char *zDb; /* Configured by changegroup_schema() */
+ ChangeData cd; /* Used by changegroup_change_xxx() APIs. */
};
/*
** This function is called to merge two changes to the same row together as
** part of an sqlite3changeset_concat() operation. A new change object is
** allocated and a pointer to it stored in *ppNew.
+**
+** Because they have been vetted by sqlite3changegroup_add() or similar,
+** both the aRec[] change and the pExist change are safe to use without
+** checking for buffer overflows.
*/
static int sessionChangeMerge(
SessionTable *pTab, /* Table structure */
@@ -236758,7 +241380,7 @@ static int sessionChangeMerge(
memcpy(aCsr, aRec, nRec);
aCsr += nRec;
}else{
- if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist, 0,aRec,0) ){
+ if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist,0,aRec,0) ){
sqlite3_free(pNew);
pNew = 0;
}
@@ -236851,15 +241473,14 @@ static int sessionChangesetExtendRecord(
switch( eType ){
case SQLITE_FLOAT:
case SQLITE_INTEGER: {
- i64 iVal;
- if( eType==SQLITE_INTEGER ){
- iVal = sqlite3_column_int64(pTab->pDfltStmt, ii);
- }else{
- double rVal = sqlite3_column_int64(pTab->pDfltStmt, ii);
- memcpy(&iVal, &rVal, sizeof(i64));
- }
if( SQLITE_OK==sessionBufferGrow(pOut, 8, &rc) ){
- sessionPutI64(&pOut->aBuf[pOut->nBuf], iVal);
+ if( eType==SQLITE_INTEGER ){
+ sqlite3_int64 iVal = sqlite3_column_int64(pTab->pDfltStmt, ii);
+ sessionPutI64(&pOut->aBuf[pOut->nBuf], iVal);
+ }else{
+ double rVal = sqlite3_column_double(pTab->pDfltStmt, ii);
+ sessionPutDouble(&pOut->aBuf[pOut->nBuf], rVal);
+ }
pOut->nBuf += 8;
}
break;
@@ -236930,13 +241551,19 @@ static int sessionChangesetFindTable(
int nCol = 0;
*ppTab = 0;
- sqlite3changeset_pk(pIter, &abPK, &nCol);
/* Search the list for an existing table */
for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
if( 0==sqlite3_strnicmp(pTab->zName, zTab, nTab+1) ) break;
}
+
+ if( pIter ){
+ sqlite3changeset_pk(pIter, &abPK, &nCol);
+ }else if( !pTab && !pGrp->db ){
+ return SQLITE_ERROR;
+ }
+
/* If one was not found above, create a new table now */
if( !pTab ){
SessionTable **ppNew;
@@ -236948,17 +241575,19 @@ static int sessionChangesetFindTable(
memset(pTab, 0, sizeof(SessionTable));
pTab->nCol = nCol;
pTab->abPK = (u8*)&pTab[1];
- memcpy(pTab->abPK, abPK, nCol);
+ if( nCol>0 ){
+ memcpy(pTab->abPK, abPK, nCol);
+ }
pTab->zName = (char*)&pTab->abPK[nCol];
memcpy(pTab->zName, zTab, nTab+1);
if( pGrp->db ){
pTab->nCol = 0;
rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb);
- if( rc ){
- assert( pTab->azCol==0 );
+ if( rc || pTab->nCol==0 ){
+ sqlite3_free(pTab->azCol);
sqlite3_free(pTab);
- return rc;
+ return rc ? rc : SQLITE_ERROR;
}
}
@@ -236971,7 +241600,7 @@ static int sessionChangesetFindTable(
}
/* Check that the table is compatible. */
- if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
+ if( pIter && !sessionChangesetCheckCompat(pTab, nCol, abPK) ){
rc = SQLITE_SCHEMA;
}
@@ -236980,44 +241609,27 @@ static int sessionChangesetFindTable(
}
/*
-** Add the change currently indicated by iterator pIter to the hash table
-** belonging to changegroup pGrp.
+** Add a single change to the changegroup pGrp.
*/
static int sessionOneChangeToHash(
- sqlite3_changegroup *pGrp,
- sqlite3_changeset_iter *pIter,
- int bRebase
+ sqlite3_changegroup *pGrp, /* Changegroup to update */
+ SessionTable *pTab, /* Table change pertains to */
+ int op, /* One of SQLITE_INSERT, UPDATE, DELETE */
+ int bIndirect, /* True to flag change as "indirect" */
+ int nCol, /* Number of columns in record(s) */
+ u8 *aRec, /* Serialized change record(s) */
+ int nRec, /* Size of aRec[] in bytes */
+ int bRebase /* True if this is a rebase blob */
){
int rc = SQLITE_OK;
- int nCol = 0;
- int op = 0;
int iHash = 0;
- int bIndirect = 0;
SessionChange *pChange = 0;
SessionChange *pExist = 0;
SessionChange **pp = 0;
- SessionTable *pTab = 0;
- u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
- int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;
assert( nRec>0 );
- /* Ensure that only changesets, or only patchsets, but not a mixture
- ** of both, are being combined. It is an error to try to combine a
- ** changeset and a patchset. */
- if( pGrp->pList==0 ){
- pGrp->bPatch = pIter->bPatchset;
- }else if( pIter->bPatchset!=pGrp->bPatch ){
- rc = SQLITE_ERROR;
- }
-
- if( rc==SQLITE_OK ){
- const char *zTab = 0;
- sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
- rc = sessionChangesetFindTable(pGrp, zTab, pIter, &pTab);
- }
-
- if( rc==SQLITE_OK && nColnCol ){
+ if( nColnCol ){
SessionBuffer *pBuf = &pGrp->rec;
rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, pBuf);
aRec = pBuf->aBuf;
@@ -237025,7 +241637,7 @@ static int sessionOneChangeToHash(
assert( pGrp->db );
}
- if( rc==SQLITE_OK && sessionGrowHash(0, pIter->bPatchset, pTab) ){
+ if( rc==SQLITE_OK && sessionGrowHash(0, pGrp->bPatch, pTab) ){
rc = SQLITE_NOMEM;
}
@@ -237033,12 +241645,12 @@ static int sessionOneChangeToHash(
/* Search for existing entry. If found, remove it from the hash table.
** Code below may link it back in. */
iHash = sessionChangeHash(
- pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange
+ pTab, (pGrp->bPatch && op==SQLITE_DELETE), aRec, pTab->nChange
);
for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){
int bPkOnly1 = 0;
int bPkOnly2 = 0;
- if( pIter->bPatchset ){
+ if( pGrp->bPatch ){
bPkOnly1 = (*pp)->op==SQLITE_DELETE;
bPkOnly2 = op==SQLITE_DELETE;
}
@@ -237053,7 +241665,7 @@ static int sessionOneChangeToHash(
if( rc==SQLITE_OK ){
rc = sessionChangeMerge(pTab, bRebase,
- pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange
+ pGrp->bPatch, pExist, op, bIndirect, aRec, nRec, &pChange
);
}
if( rc==SQLITE_OK && pChange ){
@@ -237062,6 +241674,47 @@ static int sessionOneChangeToHash(
pTab->nEntry++;
}
+ return rc;
+}
+
+/*
+** Add the change currently indicated by iterator pIter to the hash table
+** belonging to changegroup pGrp.
+*/
+static int sessionOneChangeIterToHash(
+ sqlite3_changegroup *pGrp,
+ sqlite3_changeset_iter *pIter,
+ int bRebase
+){
+ u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
+ int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;
+ const char *zTab = 0;
+ int nCol = 0;
+ int op = 0;
+ int bIndirect = 0;
+ int rc = SQLITE_OK;
+ SessionTable *pTab = 0;
+
+ /* Ensure that only changesets, or only patchsets, but not a mixture
+ ** of both, are being combined. It is an error to try to combine a
+ ** changeset and a patchset. */
+ if( pGrp->pList==0 ){
+ pGrp->bPatch = pIter->bPatchset;
+ }else if( pIter->bPatchset!=pGrp->bPatch ){
+ rc = SQLITE_ERROR;
+ }
+
+ if( rc==SQLITE_OK ){
+ sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
+ rc = sessionChangesetFindTable(pGrp, zTab, pIter, &pTab);
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = sessionOneChangeToHash(
+ pGrp, pTab, op, bIndirect, nCol, aRec, nRec, bRebase
+ );
+ }
+
if( rc==SQLITE_OK ) rc = pIter->rc;
return rc;
}
@@ -237081,7 +241734,12 @@ static int sessionChangesetToHash(
pIter->in.bNoDiscard = 1;
while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
- rc = sessionOneChangeToHash(pGrp, pIter, bRebase);
+ if( bRebase && pIter->bPatchset ){
+ /* A patchset may not be used as a rebase */
+ rc = SQLITE_ERROR;
+ }else{
+ rc = sessionOneChangeIterToHash(pGrp, pIter, bRebase);
+ }
if( rc!=SQLITE_OK ) break;
}
@@ -237171,6 +241829,33 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp){
return rc;
}
+/*
+** Configure a changegroup object.
+*/
+SQLITE_API int sqlite3changegroup_config(
+ sqlite3_changegroup *pGrp,
+ int op,
+ void *pArg
+){
+ int rc = SQLITE_OK;
+
+ switch( op ){
+ case SQLITE_CHANGEGROUP_CONFIG_PATCHSET: {
+ int arg = *(int*)pArg;
+ if( pGrp->pList==0 && arg>=0 ){
+ pGrp->bPatch = (arg>0);
+ }
+ *(int*)pArg = pGrp->bPatch;
+ break;
+ }
+ default:
+ rc = SQLITE_MISUSE;
+ break;
+ }
+
+ return rc;
+}
+
/*
** Provide a database schema to the changegroup object.
*/
@@ -237229,7 +241914,7 @@ SQLITE_API int sqlite3changegroup_add_change(
rc = SQLITE_ERROR;
}else{
pIter->in.bNoDiscard = 1;
- rc = sessionOneChangeToHash(pGrp, pIter, 0);
+ rc = sessionOneChangeIterToHash(pGrp, pIter, 0);
}
return rc;
}
@@ -237281,6 +241966,12 @@ SQLITE_API int sqlite3changegroup_output_strm(
*/
SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
if( pGrp ){
+ int ii;
+ for(ii=0; iicd.nBufAlloc; ii++){
+ sqlite3_free(pGrp->cd.aBuf[ii].aBuf);
+ }
+ sqlite3_free(pGrp->cd.record.aBuf);
+ sqlite3_free(pGrp->cd.aBuf);
sqlite3_free(pGrp->zDb);
sessionDeleteTable(0, pGrp->pList);
sqlite3_free(pGrp->rec.aBuf);
@@ -237366,14 +242057,17 @@ static void sessionAppendRecordMerge(
u8 *a2, int n2, /* Record 2 */
int *pRc /* IN/OUT: error code */
){
- sessionBufferGrow(pBuf, n1+n2, pRc);
+ u8 *a1Eof = &a1[n1];
+ u8 *a2Eof = &a2[n2];
+
+ sessionBufferGrow(pBuf, (i64)n1+n2, pRc);
if( *pRc==SQLITE_OK ){
int i;
u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
for(i=0; i0 && (*a1==0 || *a1==0xFF)) ){
memcpy(pOut, a2, nn2);
pOut += nn2;
}else{
@@ -237415,20 +242109,21 @@ static void sessionAppendPartialUpdate(
u8 *aChange, int nChange, /* Record to rebase against */
int *pRc /* IN/OUT: Return Code */
){
- sessionBufferGrow(pBuf, 2+nRec+nChange, pRc);
+ sessionBufferGrow(pBuf, (i64)2+nRec+nChange, pRc);
if( *pRc==SQLITE_OK ){
int bData = 0;
u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
int i;
u8 *a1 = aRec;
u8 *a2 = aChange;
+ u8 *a2Eof = &a2[nChange];
*pOut++ = SQLITE_UPDATE;
*pOut++ = pIter->bIndirect;
for(i=0; inCol; i++){
int n1 = sessionSerialLen(a1);
- int n2 = sessionSerialLen(a2);
- if( pIter->abPK[i] || a2[0]==0 ){
+ int n2 = (a2>=a2Eof) ? 0 : sessionSerialLen(a2);
+ if( n2<=0 || pIter->abPK[i] || a2[0]==0 ){
if( !pIter->abPK[i] && a1[0] ) bData = 1;
memcpy(pOut, a1, n1);
pOut += n1;
@@ -237629,8 +242324,8 @@ SQLITE_API int sqlite3rebaser_configure(
sqlite3_rebaser *p,
int nRebase, const void *pRebase
){
- sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */
int rc; /* Return code */
+ sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */
rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase);
if( rc==SQLITE_OK ){
rc = sessionChangesetToHash(pIter, &p->grp, 1);
@@ -237711,6 +242406,330 @@ SQLITE_API int sqlite3session_config(int op, void *pArg){
return rc;
}
+/*
+** Begin adding a change to a changegroup object.
+*/
+SQLITE_API int sqlite3changegroup_change_begin(
+ sqlite3_changegroup *pGrp,
+ int eOp,
+ const char *zTab,
+ int bIndirect,
+ char **pzErr
+){
+ SessionTable *pTab = 0;
+ int rc = SQLITE_OK;
+
+ if( pGrp->cd.pTab ){
+ rc = SQLITE_MISUSE;
+ }else if( eOp!=SQLITE_INSERT && eOp!=SQLITE_UPDATE && eOp!=SQLITE_DELETE ){
+ rc = SQLITE_ERROR;
+ }else{
+ rc = sessionChangesetFindTable(pGrp, zTab, 0, &pTab);
+ if( pTab==0 && pzErr ){
+ *pzErr = sqlite3_mprintf("no such table: %s", zTab);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ int nReq = pTab->nCol * (eOp==SQLITE_UPDATE ? 2 : 1);
+ pGrp->cd.pTab = pTab;
+ pGrp->cd.eOp = eOp;
+ pGrp->cd.bIndirect = bIndirect;
+
+ if( pGrp->cd.nBufAlloccd.aBuf, nReq * sizeof(SessionBuffer)
+ );
+ if( aBuf==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(&aBuf[pGrp->cd.nBufAlloc], 0,
+ sizeof(SessionBuffer) * (nReq - pGrp->cd.nBufAlloc)
+ );
+ pGrp->cd.aBuf = aBuf;
+ pGrp->cd.nBufAlloc = nReq;
+ }
+ }
+
+#ifdef SQLITE_DEBUG
+ {
+ /* Assert that all column values are currently undefined */
+ int ii;
+ for(ii=0; iicd.nBufAlloc; ii++){
+ assert( pGrp->cd.aBuf[ii].nBuf==0 );
+ }
+ }
+#endif
+ }
+
+ return rc;
+}
+
+/*
+** This function does processing common to the _change_int64(), _change_text()
+** and other similar APIs.
+*/
+static int checkChangeParams(
+ sqlite3_changegroup *pGrp,
+ int bNew,
+ int iCol,
+ sqlite3_int64 nReq,
+ SessionBuffer **ppBuf
+){
+ int rc = SQLITE_OK;
+ if( pGrp->cd.pTab==0 ){
+ rc = SQLITE_MISUSE;
+ }else if( iCol<0 || iCol>=pGrp->cd.pTab->nCol ){
+ rc = SQLITE_RANGE;
+ }else if(
+ (bNew && pGrp->cd.eOp==SQLITE_DELETE)
+ || (!bNew && pGrp->cd.eOp==SQLITE_INSERT)
+ ){
+ rc = SQLITE_ERROR;
+ }else{
+ SessionBuffer *pBuf = &pGrp->cd.aBuf[iCol];
+ if( pGrp->cd.eOp==SQLITE_UPDATE && bNew ){
+ pBuf += pGrp->cd.pTab->nCol;
+ }
+ pBuf->nBuf = 0;
+ sessionBufferGrow(pBuf, nReq, &rc);
+ pBuf->nBuf = nReq;
+ *ppBuf = pBuf;
+ }
+ return rc;
+}
+
+/*
+** Configure the change currently under construction with an integer value.
+*/
+SQLITE_API int sqlite3changegroup_change_int64(
+ sqlite3_changegroup *pGrp,
+ int bNew,
+ int iCol,
+ sqlite3_int64 iVal
+){
+ int rc = SQLITE_OK;
+ SessionBuffer *pBuf = 0;
+
+ if( SQLITE_OK!=(rc = checkChangeParams(pGrp, bNew, iCol, 9, &pBuf)) ){
+ return rc;
+ }
+
+ pBuf->aBuf[0] = SQLITE_INTEGER;
+ sessionPutI64(&pBuf->aBuf[1], iVal);
+ return SQLITE_OK;
+}
+
+/*
+** Configure the change currently under construction with a null value.
+*/
+SQLITE_API int sqlite3changegroup_change_null(
+ sqlite3_changegroup *pGrp,
+ int bNew,
+ int iCol
+){
+ int rc = SQLITE_OK;
+ SessionBuffer *pBuf = 0;
+
+ if( SQLITE_OK!=(rc = checkChangeParams(pGrp, bNew, iCol, 1, &pBuf)) ){
+ return rc;
+ }
+
+ pBuf->aBuf[0] = SQLITE_NULL;
+ return SQLITE_OK;
+}
+
+/*
+** Configure the change currently under construction with a real value.
+*/
+SQLITE_API int sqlite3changegroup_change_double(
+ sqlite3_changegroup *pGrp,
+ int bNew,
+ int iCol,
+ double fVal
+){
+ int rc = SQLITE_OK;
+ SessionBuffer *pBuf = 0;
+
+ if( SQLITE_OK!=(rc = checkChangeParams(pGrp, bNew, iCol, 9, &pBuf)) ){
+ return rc;
+ }
+
+ pBuf->aBuf[0] = SQLITE_FLOAT;
+ sessionPutDouble(&pBuf->aBuf[1], fVal);
+ return SQLITE_OK;
+}
+
+/*
+** Configure the change currently under construction with a text value.
+*/
+SQLITE_API int sqlite3changegroup_change_text(
+ sqlite3_changegroup *pGrp,
+ int bNew,
+ int iCol,
+ const char *pVal,
+ int nVal
+){
+ sqlite3_int64 nText = nVal>=0 ? nVal : strlen(pVal);
+ sqlite3_int64 nByte = 1 + sessionVarintLen(nText) + nText;
+ int rc = SQLITE_OK;
+ SessionBuffer *pBuf = 0;
+
+ if( SQLITE_OK!=(rc = checkChangeParams(pGrp, bNew, iCol, nByte, &pBuf)) ){
+ return rc;
+ }
+
+ pBuf->aBuf[0] = SQLITE_TEXT;
+ pBuf->nBuf = (1 + sessionVarintPut(&pBuf->aBuf[1], nText));
+ memcpy(&pBuf->aBuf[pBuf->nBuf], pVal, nText);
+ pBuf->nBuf += nText;
+
+ return SQLITE_OK;
+}
+
+/*
+** Configure the change currently under construction with a blob value.
+*/
+SQLITE_API int sqlite3changegroup_change_blob(
+ sqlite3_changegroup *pGrp,
+ int bNew,
+ int iCol,
+ const void *pVal,
+ int nVal
+){
+ sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + (i64)nVal;
+ int rc = SQLITE_OK;
+ SessionBuffer *pBuf = 0;
+
+ if( SQLITE_OK!=(rc = checkChangeParams(pGrp, bNew, iCol, nByte, &pBuf)) ){
+ return rc;
+ }
+
+ pBuf->aBuf[0] = SQLITE_BLOB;
+ pBuf->nBuf = (1 + sessionVarintPut(&pBuf->aBuf[1], nVal));
+ memcpy(&pBuf->aBuf[pBuf->nBuf], pVal, nVal);
+ pBuf->nBuf += nVal;
+
+ return SQLITE_OK;
+}
+
+/*
+** Finish any change currently being constructed by the changegroup object.
+*/
+SQLITE_API int sqlite3changegroup_change_finish(
+ sqlite3_changegroup *pGrp,
+ int bDiscard,
+ char **pzErr
+){
+ int rc = SQLITE_OK;
+ char *zErr = 0;
+ if( pGrp->cd.pTab ){
+ SessionBuffer *aBuf = pGrp->cd.aBuf;
+ int ii;
+
+ if( bDiscard==0 ){
+ int nBuf = pGrp->cd.pTab->nCol;
+ u8 eUndef = SQLITE_NULL;
+ if( pGrp->cd.eOp==SQLITE_UPDATE ){
+ for(ii=0; iicd.pTab->abPK[ii] ){
+ if( aBuf[ii].nBuf<=1 ){
+ zErr = sqlite3_mprintf(
+ "invalid change: %s value in PK of old.* record",
+ aBuf[ii].nBuf==1 ? "null" : "undefined"
+ );
+ rc = SQLITE_ERROR;
+ break;
+ }else if( aBuf[ii + nBuf].nBuf>0 ){
+ zErr = sqlite3_mprintf(
+ "invalid change: defined value in PK of new.* record"
+ );
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }else
+ if( pGrp->bPatch==0 && (aBuf[ii].nBuf>0)!=(aBuf[ii+nBuf].nBuf>0) ){
+ zErr = sqlite3_mprintf(
+ "invalid change: column %d "
+ "- old.* value is %sdefined but new.* is %sdefined",
+ ii, aBuf[ii].nBuf ? "" : "un", aBuf[ii+nBuf].nBuf ? "" : "un"
+ );
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }
+ eUndef = 0x00;
+ if( pGrp->bPatch==0 ) nBuf = nBuf * 2;
+ }else{
+ for(ii=0; iicd.pTab->abPK[ii];
+ if( (pGrp->cd.eOp==SQLITE_INSERT || pGrp->bPatch==0 || isPK)
+ && aBuf[ii].nBuf==0
+ ){
+ zErr = sqlite3_mprintf(
+ "invalid change: column %d is undefined", ii
+ );
+ rc = SQLITE_ERROR;
+ break;
+ }
+ if( aBuf[ii].nBuf==1 && isPK ){
+ zErr = sqlite3_mprintf(
+ "invalid change: null value in PK"
+ );
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }
+ }
+
+ pGrp->cd.record.nBuf = 0;
+ for(ii=0; iicd.aBuf[ii];
+ if( pGrp->bPatch ){
+ if( pGrp->cd.pTab->abPK[ii]==0 ){
+ if( pGrp->cd.eOp==SQLITE_UPDATE ){
+ p += pGrp->cd.pTab->nCol;
+ }else if( pGrp->cd.eOp==SQLITE_DELETE ){
+ continue;
+ }
+ }
+ }
+ if( 0==sessionBufferGrow(&pGrp->cd.record, p->nBuf?p->nBuf:1, &rc) ){
+ if( p->nBuf ){
+ memcpy(&pGrp->cd.record.aBuf[pGrp->cd.record.nBuf],p->aBuf,p->nBuf);
+ pGrp->cd.record.nBuf += p->nBuf;
+ }else{
+ pGrp->cd.record.aBuf[pGrp->cd.record.nBuf++] = eUndef;
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ rc = sessionOneChangeToHash(
+ pGrp, pGrp->cd.pTab,
+ pGrp->cd.eOp, pGrp->cd.bIndirect, pGrp->cd.pTab->nCol,
+ pGrp->cd.record.aBuf, pGrp->cd.record.nBuf, 0
+ );
+ }
+ }
+
+ /* Reset all aBuf[] entries to "undefined". */
+ {
+ int nZero = pGrp->cd.pTab->nCol;
+ if( pGrp->cd.eOp==SQLITE_UPDATE ) nZero += nZero;
+ for(ii=0; iicd.aBuf[ii].nBuf = 0;
+ }
+ }
+ pGrp->cd.pTab = 0;
+ }
+
+ if( pzErr ){
+ *pzErr = zErr;
+ }else{
+ sqlite3_free(zErr);
+ }
+ return rc;
+}
+
#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
/************** End of sqlite3session.c **************************************/
@@ -239504,7 +244523,7 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
** interstitial "-" characters) contained in this template is changed into
** the value of the %name directive from the grammar. Otherwise, the content
-** of this template is copied straight through into the generate parser
+** of this template is copied straight through into the generated parser
** source file.
**
** The following is the concatenation of all %include directives from the
@@ -239641,14 +244660,22 @@ typedef union {
#define sqlite3Fts5ParserARG_PARAM ,pParse
#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse;
#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse;
+#undef fts5YYREALLOC
#define fts5YYREALLOC realloc
+#undef fts5YYFREE
#define fts5YYFREE free
+#undef fts5YYDYNSTACK
#define fts5YYDYNSTACK 0
+#undef fts5YYSIZELIMIT
+#define sqlite3Fts5ParserCTX(P) 0
#define sqlite3Fts5ParserCTX_SDECL
#define sqlite3Fts5ParserCTX_PDECL
#define sqlite3Fts5ParserCTX_PARAM
#define sqlite3Fts5ParserCTX_FETCH
#define sqlite3Fts5ParserCTX_STORE
+#undef fts5YYERRORSYMBOL
+#undef fts5YYERRSYMDT
+#undef fts5YYFALLBACK
#define fts5YYNSTATE 35
#define fts5YYNRULE 28
#define fts5YYNRULE_WITH_ACTION 28
@@ -239973,15 +245000,24 @@ static int fts5yyGrowStack(fts5yyParser *p){
int newSize;
int idx;
fts5yyStackEntry *pNew;
+#ifdef fts5YYSIZELIMIT
+ int nLimit = fts5YYSIZELIMIT(sqlite3Fts5ParserCTX(p));
+#endif
newSize = oldSize*2 + 100;
+#ifdef fts5YYSIZELIMIT
+ if( newSize>nLimit ){
+ newSize = nLimit;
+ if( newSize<=oldSize ) return 1;
+ }
+#endif
idx = (int)(p->fts5yytos - p->fts5yystack);
if( p->fts5yystack==p->fts5yystk0 ){
- pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0]));
+ pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0]), sqlite3Fts5ParserCTX(p));
if( pNew==0 ) return 1;
memcpy(pNew, p->fts5yystack, oldSize*sizeof(pNew[0]));
}else{
- pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0]));
+ pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0]), sqlite3Fts5ParserCTX(p));
if( pNew==0 ) return 1;
}
p->fts5yystack = pNew;
@@ -240161,7 +245197,9 @@ static void sqlite3Fts5ParserFinalize(void *p){
}
#if fts5YYGROWABLESTACK
- if( pParser->fts5yystack!=pParser->fts5yystk0 ) fts5YYFREE(pParser->fts5yystack);
+ if( pParser->fts5yystack!=pParser->fts5yystk0 ){
+ fts5YYFREE(pParser->fts5yystack, sqlite3Fts5ParserCTX(pParser));
+ }
#endif
}
@@ -241214,6 +246252,16 @@ static int fts5HighlightCb(
return rc;
}
+/*
+** Return the integer value of pVal, clamped to the range [-1, 0x7FFFFFFF].
+** This is used for the column-number arguments of auxiliary functions,
+** so that 64-bit values that are too large or too small to fit in a
+** 32-bit signed integer are not truncated to what might be a valid
+** column number.
+*/
+static int fts5ValueClampedInt(sqlite3_value *pVal){
+ return (int)MIN(MAX(sqlite3_value_int64(pVal), -1), 0x7FFFFFFF);
+}
/*
** Implementation of highlight() function.
@@ -241235,7 +246283,7 @@ static void fts5HighlightFunction(
return;
}
- iCol = sqlite3_value_int(apVal[0]);
+ iCol = fts5ValueClampedInt(apVal[0]);
memset(&ctx, 0, sizeof(HighlightContext));
ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]);
ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
@@ -241414,7 +246462,7 @@ static void fts5SnippetFunction(
int rc = SQLITE_OK; /* Return code */
int iCol; /* 1st argument to snippet() */
const char *zEllips; /* 4th argument to snippet() */
- int nToken; /* 5th argument to snippet() */
+ i64 nToken; /* 5th argument to snippet() */
int nInst = 0; /* Number of instance matches this row */
int i; /* Used to iterate through instances */
int nPhrase; /* Number of phrases in query */
@@ -241434,16 +246482,16 @@ static void fts5SnippetFunction(
nCol = pApi->xColumnCount(pFts);
memset(&ctx, 0, sizeof(HighlightContext));
- iCol = sqlite3_value_int(apVal[0]);
+ iCol = fts5ValueClampedInt(apVal[0]);
ctx.zOpen = fts5ValueToText(apVal[1]);
ctx.zClose = fts5ValueToText(apVal[2]);
ctx.iRangeEnd = -1;
zEllips = fts5ValueToText(apVal[3]);
- nToken = sqlite3_value_int(apVal[4]);
+ nToken = (int)(MIN( MAX(sqlite3_value_int64(apVal[4]), 0), 64));
iBestCol = (iCol>=0 ? iCol : 0);
nPhrase = pApi->xPhraseCount(pFts);
- aSeen = sqlite3_malloc(nPhrase);
+ aSeen = sqlite3_malloc64(nPhrase);
if( aSeen==0 ){
rc = SQLITE_NOMEM;
}
@@ -241766,7 +246814,7 @@ static void fts5GetLocaleFunction(
return;
}
- iCol = sqlite3_value_int(apVal[0]);
+ iCol = fts5ValueClampedInt(apVal[0]);
if( iCol<0 || iCol>=pApi->xColumnCount(pFts) ){
sqlite3_result_error_code(pCtx, SQLITE_RANGE);
return;
@@ -242098,7 +247146,7 @@ static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
if( nIn<0 ){
nIn = (int)strlen(pIn);
}
- zRet = (char*)sqlite3_malloc(nIn+1);
+ zRet = (char*)sqlite3_malloc64((i64)nIn+1);
if( zRet ){
memcpy(zRet, pIn, nIn);
zRet[nIn] = '\0';
@@ -242798,7 +247846,7 @@ static int sqlite3Fts5ConfigParse(
sqlite3_int64 nByte;
int bUnindexed = 0; /* True if there are one or more UNINDEXED */
- *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
+ *ppOut = pRet = (Fts5Config*)sqlite3_malloc64(sizeof(Fts5Config));
if( pRet==0 ) return SQLITE_NOMEM;
memset(pRet, 0, sizeof(Fts5Config));
pRet->pGlobal = pGlobal;
@@ -243346,8 +248394,6 @@ static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){
va_end(ap);
}
-
-
/*
** 2014 May 31
**
@@ -243664,7 +248710,7 @@ static int sqlite3Fts5ExprNew(
assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
if( sParse.rc==SQLITE_OK ){
- *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
+ *ppNew = pNew = sqlite3_malloc64(sizeof(Fts5Expr));
if( pNew==0 ){
sParse.rc = SQLITE_NOMEM;
sqlite3Fts5ParseNodeFree(sParse.pExpr);
@@ -243816,7 +248862,7 @@ static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
p2->pRoot = 0;
if( sParse.rc==SQLITE_OK ){
- Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
+ Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc64(
p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
);
if( ap==0 ){
@@ -244157,7 +249203,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
i64 iPos = a[i].reader.iPos;
Fts5PoslistWriter *pWriter = &a[i].writer;
if( a[i].pOut->n==0 || iPos!=pWriter->iPrev ){
- sqlite3Fts5PoslistWriterAppend(a[i].pOut, pWriter, iPos);
+ sqlite3Fts5PoslistSafeAppend(a[i].pOut, &pWriter->iPrev, iPos);
}
}
@@ -245108,10 +250154,10 @@ static int fts5ParseTokenize(
memset(pSyn, 0, (size_t)nByte);
pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
pSyn->nFullTerm = pSyn->nQueryTerm = nToken;
+ memcpy(pSyn->pTerm, pToken, nToken);
if( pCtx->pConfig->bTokendata ){
pSyn->nQueryTerm = (int)strlen(pSyn->pTerm);
}
- memcpy(pSyn->pTerm, pToken, nToken);
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
}
@@ -246728,7 +251774,7 @@ static int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte
int rc = SQLITE_OK;
Fts5Hash *pNew;
- *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
+ *ppNew = pNew = (Fts5Hash*)sqlite3_malloc64(sizeof(Fts5Hash));
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -246960,7 +252006,7 @@ static int sqlite3Fts5HashWrite(
** + 5 bytes for the new position offset (32-bit max).
*/
if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
- sqlite3_int64 nNew = p->nAlloc * 2;
+ sqlite3_int64 nNew = (i64)p->nAlloc * 2;
Fts5HashEntry *pNew;
Fts5HashEntry **pp;
pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
@@ -247513,7 +252559,12 @@ static void sqlite3Fts5HashScanEntry(
#define FTS5_DATA_ID_B 16 /* Max seg id number 65535 */
#define FTS5_DATA_DLI_B 1 /* Doclist-index flag (1 bit) */
#define FTS5_DATA_HEIGHT_B 5 /* Max dlidx tree height of 32 */
-#define FTS5_DATA_PAGE_B 31 /* Max page number of 2147483648 */
+#define FTS5_DATA_PAGE_B 31 /* 31-bit page numbers */
+
+/* Maximum page number within a segment. Declare any structure read from
+** the database with a page number greater than this corrupt. It is not
+** actually possible to create a database this large. */
+#define FTS5_MAX_PGNO 0x7FFFFF00
#define fts5_dri(segid, dlidx, height, pgno) ( \
((i64)(segid) << (FTS5_DATA_PAGE_B+FTS5_DATA_HEIGHT_B+FTS5_DATA_DLI_B)) + \
@@ -248111,6 +253162,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
if( pRet ){
pRet->nn = nByte;
+ pRet->szLeaf = 0;
aOut = pRet->p = (u8*)pRet + szData;
}else{
rc = SQLITE_NOMEM;
@@ -248123,10 +253175,8 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
sqlite3_free(pRet);
pRet = 0;
}else{
- /* TODO1: Fix this */
pRet->p[nByte] = 0x00;
pRet->p[nByte+1] = 0x00;
- pRet->szLeaf = fts5GetU16(&pRet->p[2]);
}
}
p->rc = rc;
@@ -248147,10 +253197,18 @@ static void fts5DataRelease(Fts5Data *pData){
sqlite3_free(pData);
}
+/*
+** Read a leaf-page record. This is similar to fts5DataRead(), except that
+** it fills in the Fts5Data.szLeaf value before returning.
+*/
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
Fts5Data *pRet = fts5DataRead(p, iRowid);
if( pRet ){
- if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
+ assert( pRet->szLeaf==0 );
+ if( pRet->nn>=4 ){
+ pRet->szLeaf = fts5GetU16(&pRet->p[2]);
+ }
+ if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
FTS5_CORRUPT_ROWID(p, iRowid);
fts5DataRelease(pRet);
pRet = 0;
@@ -248394,7 +253452,7 @@ static int fts5StructureDecode(
i += fts5GetVarint32(&pData[i], nTotal);
if( nTotalnMerge ) rc = FTS5_CORRUPT;
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
- nTotal * sizeof(Fts5StructureSegment)
+ (i64)nTotal * sizeof(Fts5StructureSegment)
);
nSegment -= nTotal;
}
@@ -248419,7 +253477,7 @@ static int fts5StructureDecode(
i += fts5GetVarint(&pData[i], &pSeg->nEntry);
nOriginCntr = MAX(nOriginCntr, pSeg->iOrigin2);
}
- if( pSeg->pgnoLastpgnoFirst ){
+ if( pSeg->pgnoLastpgnoFirst || pSeg->pgnoLast>FTS5_MAX_PGNO ){
rc = FTS5_CORRUPT;
break;
}
@@ -248923,6 +253981,7 @@ static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
pLvl->bEof = 1;
}else{
u8 *a = pLvl->pData->p;
+ int nn = pLvl->pData->nn;
pLvl->iOff = 0;
fts5DlidxLvlNext(pLvl);
@@ -248931,7 +253990,7 @@ static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
int ii = pLvl->iOff;
u64 delta = 0;
- while( a[ii]==0 ){
+ while( iinLvl = i+1;
+ if( pIter->nLvl > (1<rc = FTS5_CORRUPT;
+ }
}
}
@@ -249321,7 +254383,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
/* If necessary, grow the pIter->aRowidOffset[] array. */
if( iRowidOffset>=pIter->nRowidOffset ){
- int nNew = pIter->nRowidOffset + 8;
+ i64 nNew = pIter->nRowidOffset + 8;
int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
@@ -249350,7 +254412,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){
Fts5Data *pNew;
pIter->iLeafPgno--;
- pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
+ pNew = fts5LeafRead(p, FTS5_SEGMENT_ROWID(
pIter->pSeg->iSegid, pIter->iLeafPgno
));
if( pNew ){
@@ -249804,6 +254866,10 @@ static void fts5LeafSeek(
if( nKeepn ){
+ FTS5_CORRUPT_ITER(p, pIter);
+ return;
+ }
assert( nKeep>=nMatch );
if( nKeep==nMatch ){
@@ -250055,6 +255121,10 @@ static void fts5SegIterNextInit(
pIter->iPgidxOff = pIter->pLeaf->szLeaf;
pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], iTermOff);
+ if( iTermOff > pIter->pLeaf->szLeaf ){
+ p->rc = FTS5_CORRUPT;
+ return;
+ }
pIter->iLeafOffset = iTermOff;
fts5SegIterLoadTerm(p, pIter, 0);
fts5SegIterLoadNPos(p, pIter);
@@ -250780,8 +255850,7 @@ static void fts5PoslistFilterCallback(
do {
while( ieState ){
fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
@@ -250930,7 +255999,7 @@ static void fts5IndexExtractColset(
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
** not part of a varint */
while( paiCol[i]==iCurrent ){
@@ -250998,6 +256067,7 @@ static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){
static void fts5IterSetOutputs_ZeroColset(Fts5Iter *pIter, Fts5SegIter *pSeg){
UNUSED_PARAM(pSeg);
pIter->base.nData = 0;
+ pIter->base.bEof = 1;
}
/*
@@ -251027,8 +256097,11 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
assert( pIter->pColset );
+ assert( pIter->poslist.nSpace>=pIter->pIndex->pConfig->nCol );
- if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
+ if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf
+ || pSeg->nPos>pIter->pIndex->pConfig->nCol
+ ){
fts5IterSetOutputs_Col(pIter, pSeg);
}else{
u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
@@ -252379,7 +257452,7 @@ static void fts5SecureDeleteOverflow(
int iNext = 0;
u8 *aPg = 0;
- pLeaf = fts5DataRead(p, iRowid);
+ pLeaf = fts5LeafRead(p, iRowid);
if( pLeaf==0 ) break;
aPg = pLeaf->p;
@@ -252387,7 +257460,7 @@ static void fts5SecureDeleteOverflow(
if( iNext!=0 ){
*pbLastInDoclist = 0;
}
- if( iNext==0 && pLeaf->szLeaf!=pLeaf->nn ){
+ if( iNext==0 && pLeaf->szLeafnn ){
fts5GetVarint32(&aPg[pLeaf->szLeaf], iNext);
}
@@ -252468,7 +257541,7 @@ static void fts5DoSecureDelete(
int iSegid = pSeg->pSeg->iSegid;
u8 *aPg = pSeg->pLeaf->p;
int nPg = pSeg->pLeaf->nn;
- int iPgIdx = pSeg->pLeaf->szLeaf;
+ int iPgIdx = pSeg->pLeaf->szLeaf; /* Offset of page footer */
u64 iDelta = 0;
int iNextOff = 0;
@@ -252522,6 +257595,11 @@ static void fts5DoSecureDelete(
}else{
iStart = fts5GetU16(&aPg[0]);
}
+ if( iStart>nPg ){
+ FTS5_CORRUPT_IDX(p);
+ sqlite3_free(aIdx);
+ return;
+ }
iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
assert_nc( iSOP<=pSeg->iLeafOffset );
@@ -252547,7 +257625,7 @@ static void fts5DoSecureDelete(
iSOP += fts5GetVarint32(&aPg[iSOP], nPos);
}
assert_nc( iSOP==pSeg->iLeafOffset );
- iNextOff = pSeg->iLeafOffset + pSeg->nPos;
+ iNextOff = iSOP + pSeg->nPos;
}
}
@@ -252627,31 +257705,31 @@ static void fts5DoSecureDelete(
** is another term following it on this page. So the subsequent term
** needs to be moved to replace the term associated with the entry
** being removed. */
- int nPrefix = 0;
- int nSuffix = 0;
- int nPrefix2 = 0;
- int nSuffix2 = 0;
+ u64 nPrefix = 0;
+ u64 nSuffix = 0;
+ u64 nPrefix2 = 0;
+ u64 nSuffix2 = 0;
iDelKeyOff = iNextOff;
- iNextOff += fts5GetVarint32(&aPg[iNextOff], nPrefix2);
- iNextOff += fts5GetVarint32(&aPg[iNextOff], nSuffix2);
+ iNextOff += fts5GetVarint(&aPg[iNextOff], &nPrefix2);
+ iNextOff += fts5GetVarint(&aPg[iNextOff], &nSuffix2);
if( iKey!=1 ){
- iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nPrefix);
+ iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nPrefix);
}
- iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix);
+ iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nSuffix);
nPrefix = MIN(nPrefix, nPrefix2);
nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
- if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){
+ if( (iKeyOff+nSuffix)>(u64)iPgIdx || (iNextOff+nSuffix2)>(u64)iPgIdx ){
FTS5_CORRUPT_IDX(p);
}else{
if( iKey!=1 ){
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
}
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
- if( nPrefix2>pSeg->term.n ){
+ if( nPrefix2>(u64)pSeg->term.n ){
FTS5_CORRUPT_IDX(p);
}else if( nPrefix2>nPrefix ){
memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix);
@@ -252669,7 +257747,7 @@ static void fts5DoSecureDelete(
/* The entry being removed may be the only position list in
** its doclist. */
for(iPgno=pSeg->iLeafPgno-1; iPgno>pSeg->iTermLeafPgno; iPgno-- ){
- Fts5Data *pPg = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
+ Fts5Data *pPg = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
int bEmpty = (pPg && pPg->nn==4);
fts5DataRelease(pPg);
if( bEmpty==0 ) break;
@@ -252677,12 +257755,12 @@ static void fts5DoSecureDelete(
if( iPgno==pSeg->iTermLeafPgno ){
i64 iId = FTS5_SEGMENT_ROWID(iSegid, pSeg->iTermLeafPgno);
- Fts5Data *pTerm = fts5DataRead(p, iId);
+ Fts5Data *pTerm = fts5LeafRead(p, iId);
if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
int nTermIdx = pTerm->nn - pTerm->szLeaf;
int iTermIdx = 0;
- int iTermOff = 0;
+ i64 iTermOff = 0;
while( 1 ){
u32 iVal = 0;
@@ -252693,12 +257771,15 @@ static void fts5DoSecureDelete(
}
nTermIdx = iTermIdx;
- memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
- fts5PutU16(&pTerm->p[2], iTermOff);
-
- fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
- if( nTermIdx==0 ){
- fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
+ if( iTermOff>pTerm->szLeaf ){
+ FTS5_CORRUPT_IDX(p);
+ }else{
+ memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
+ fts5PutU16(&pTerm->p[2], iTermOff);
+ fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
+ if( nTermIdx==0 ){
+ fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
+ }
}
}
fts5DataRelease(pTerm);
@@ -252717,32 +257798,38 @@ static void fts5DoSecureDelete(
if( p->rc==SQLITE_OK ){
const int nMove = nPg - iNextOff; /* Number of bytes to move */
int nShift = iNextOff - iOff; /* Distance to move them */
-
+ int nNewPg = 0;
int iPrevKeyOut = 0;
- int iKeyIn = 0;
+ i64 iKeyIn = 0;
- memmove(&aPg[iOff], &aPg[iNextOff], nMove);
+ if( nMove>0 ){
+ memmove(&aPg[iOff], &aPg[iNextOff], nMove);
+ }
iPgIdx -= nShift;
- nPg = iPgIdx;
+ nNewPg = iPgIdx;
fts5PutU16(&aPg[2], iPgIdx);
for(iIdx=0; iIdxnPg ){
+ FTS5_CORRUPT_IDX(p);
+ break;
+ }
if( iKeyIn!=iDelKeyOff ){
int iKeyOut = (iKeyIn - (iKeyIn>iOff ? nShift : 0));
- nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOut - iPrevKeyOut);
+ nNewPg += sqlite3Fts5PutVarint(&aPg[nNewPg], iKeyOut - iPrevKeyOut);
iPrevKeyOut = iKeyOut;
}
}
- if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){
+ if( p->rc==SQLITE_OK && iPgIdx==nNewPg && nIdx>0 && pSeg->iLeafPgno!=1 ){
fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno);
}
- assert_nc( nPg>4 || fts5GetU16(aPg)==0 );
- fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid,pSeg->iLeafPgno), aPg, nPg);
+ assert_nc( nNewPg>4 || fts5GetU16(aPg)==0 );
+ fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid,pSeg->iLeafPgno), aPg, nNewPg);
}
sqlite3_free(aIdx);
}
@@ -252890,7 +257977,6 @@ static void fts5FlushOneHash(Fts5Index *p){
iOff++;
if( iOff=pIter->aEof ){
pIter->aPoslist = 0;
}else{
- i64 iDelta;
+ u64 iDelta;
- p += fts5GetVarint(p, (u64*)&iDelta);
+ p += fts5GetVarint(p, &iDelta);
pIter->iRowid += iDelta;
/* Read position list size */
@@ -253305,7 +258391,7 @@ static void fts5MergeRowidLists(
(void)nBuf;
memset(&out, 0, sizeof(out));
assert( nBuf==1 );
- sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
+ sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9);
if( p->rc ) return;
fts5NextRowid(p1, &i1, &iRowid1);
@@ -253313,12 +258399,12 @@ static void fts5MergeRowidLists(
while( i1>=0 || i2>=0 ){
if( i1>=0 && (i2<0 || iRowid1iOut );
- fts5BufferSafeAppendVarint(&out, iRowid1 - iOut);
+ fts5BufferSafeAppendVarint(&out, (u64)iRowid1 - (u64)iOut);
iOut = iRowid1;
fts5NextRowid(p1, &i1, &iRowid1);
}else{
assert( iOut==0 || iRowid2>iOut );
- fts5BufferSafeAppendVarint(&out, iRowid2 - iOut);
+ fts5BufferSafeAppendVarint(&out, (u64)iRowid2 - (u64)iOut);
iOut = iRowid2;
if( i1>=0 && iRowid1==iRowid2 ){
fts5NextRowid(p1, &i1, &iRowid1);
@@ -253641,16 +258727,16 @@ struct Fts5TokenDataMap {
** aMap[] variables.
*/
struct Fts5TokenDataIter {
- int nMapAlloc; /* Allocated size of aMap[] in entries */
- int nMap; /* Number of valid entries in aMap[] */
+ i64 nMapAlloc; /* Allocated size of aMap[] in entries */
+ i64 nMap; /* Number of valid entries in aMap[] */
Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
/* The following are used for prefix-queries only. */
Fts5Buffer terms;
/* The following are used for other full-token tokendata queries only. */
- int nIter;
- int nIterAlloc;
+ i64 nIter;
+ i64 nIterAlloc;
Fts5PoslistReader *aPoslistReader;
int *aPoslistToIter;
Fts5Iter *apIter[FLEXARRAY];
@@ -253706,11 +258792,11 @@ static void fts5TokendataIterAppendMap(
){
if( p->rc==SQLITE_OK ){
if( pT->nMap==pT->nMapAlloc ){
- int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
- int nAlloc = nNew * sizeof(Fts5TokenDataMap);
+ i64 nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
+ i64 nAlloc = nNew * sizeof(Fts5TokenDataMap);
Fts5TokenDataMap *aNew;
- aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
+ aNew = (Fts5TokenDataMap*)sqlite3_realloc64(pT->aMap, nAlloc);
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
return;
@@ -253736,7 +258822,7 @@ static void fts5TokendataIterAppendMap(
*/
static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
Fts5TokenDataMap *aTmp = 0;
- int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
+ i64 nByte = pT->nMap * sizeof(Fts5TokenDataMap);
aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( aTmp ){
@@ -254270,9 +259356,10 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
if( p->rc==SQLITE_OK ){
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
- int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
- int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
- Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
+ i64 nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
+ i64 nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
+ Fts5TokenDataIter *pNew;
+ pNew = (Fts5TokenDataIter*)sqlite3_realloc64(pIn, nByte);
if( pNew==0 ){
p->rc = SQLITE_NOMEM;
@@ -254369,8 +259456,8 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
/* Ensure the token-mapping is large enough */
if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){
- int nNew = (pT->nMapAlloc + nByte) * 2;
- Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc(
+ i64 nNew = (pT->nMapAlloc + nByte) * 2;
+ Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc64(
pT->aMap, nNew*sizeof(Fts5TokenDataMap)
);
if( aNew==0 ){
@@ -255201,8 +260288,8 @@ static void fts5IndexTombstoneRebuild(
){
const int MINSLOT = 32;
int nSlotPerPage = MAX(MINSLOT, (p->pConfig->pgsz - 8) / szKey);
- int nSlot = 0; /* Number of slots in each output page */
- int nOut = 0;
+ i64 nSlot = 0; /* Number of slots in each output page */
+ i64 nOut = 0;
/* Figure out how many output pages (nOut) and how many slots per
** page (nSlot). There are three possibilities:
@@ -255227,23 +260314,26 @@ static void fts5IndexTombstoneRebuild(
nSlot = MINSLOT;
}else if( pSeg->nPgTombstone==1 ){
/* Case 2. */
- int nElem = (int)fts5GetU32(&pData1->p[4]);
+ u32 nElem = fts5GetU32(&pData1->p[4]);
assert( pData1 && iPg1==0 );
- nOut = 1;
- nSlot = MAX(nElem*4, MINSLOT);
- if( nSlot>nSlotPerPage ) nOut = 0;
+ if( nElem>((u32)nSlotPerPage/4) ){
+ nOut = 0;
+ }else{
+ nOut = 1;
+ nSlot = MAX((i64)nElem*4, MINSLOT);
+ }
}
if( nOut==0 ){
/* Case 3. */
- nOut = (pSeg->nPgTombstone * 2 + 1);
+ nOut = ((i64)pSeg->nPgTombstone * 2 + 1);
nSlot = nSlotPerPage;
}
/* Allocate the required array and output pages */
while( 1 ){
int res = 0;
- int ii = 0;
- int szPage = 0;
+ i64 ii = 0;
+ i64 szPage = 0;
Fts5Data **apOut = 0;
/* Allocate space for the new hash table */
@@ -255484,6 +260574,9 @@ static int fts5QueryCksum(
}
/*
+** This function is purely an internal test. It does not contribute to
+** FTS functionality, or even the integrity-check, in any way.
+**
** Check if buffer z[], size n bytes, contains as series of valid utf-8
** encoded codepoints. If so, return 0. Otherwise, if the buffer does not
** contain valid utf-8, return non-zero.
@@ -255505,8 +260598,8 @@ static int fts5TestUtf8(const char *z, int n){
}else
if( (z[i] & 0xF8)==0xF0 ){
if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
- if( (z[i+2] & 0xC0)!=0x80 ) return 1;
- i += 3;
+ if( (z[i+3] & 0xC0)!=0x80 ) return 1;
+ i += 4;
}else{
return 1;
}
@@ -255620,7 +260713,7 @@ static void fts5IndexIntegrityCheckEmpty(
/* Now check that the iter.nEmpty leaves following the current leaf
** (a) exist and (b) contain no terms. */
for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){
- Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
+ Fts5Data *pLeaf = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
if( pLeaf ){
if( !fts5LeafIsTermless(pLeaf)
|| (i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf))
@@ -255748,9 +260841,13 @@ static void fts5IndexIntegrityCheckSegment(
FTS5_CORRUPT_ROWID(p, iRow);
}else{
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
- res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
- if( res==0 ) res = nTerm - nIdxTerm;
- if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow);
+ if( (i64)iOff+(i64)nTerm>(i64)pLeaf->szLeaf ){
+ FTS5_CORRUPT_ROWID(p, iRow);
+ }else{
+ res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
+ if( res==0 ) res = nTerm - nIdxTerm;
+ if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow);
+ }
}
fts5IntegrityCheckPgidx(p, iRow, pLeaf);
@@ -255781,7 +260878,7 @@ static void fts5IndexIntegrityCheckSegment(
/* Check any rowid-less pages that occur before the current leaf. */
for(iPg=iPrevLeaf+1; iPg=3008002 )
#endif
{
- pIdxInfo->estimatedRows = nRow;
+ pIdxInfo->estimatedRows = MAX(1, nRow);
}
#endif
}
@@ -257354,19 +262451,30 @@ static int fts5UsePatternMatch(
** a) If a MATCH operator is present, the cost depends on the other
** constraints also present. As follows:
**
-** * No other constraints: cost=1000.0
-** * One rowid range constraint: cost=750.0
-** * Both rowid range constraints: cost=500.0
-** * An == rowid constraint: cost=100.0
+** * No other constraints: cost=50000.0
+** * One rowid range constraint: cost=37500.0
+** * Both rowid range constraints: cost=30000.0
+** * An == rowid constraint: cost=25000.0
**
** b) Otherwise, if there is no MATCH:
**
-** * No other constraints: cost=1000000.0
-** * One rowid range constraint: cost=750000.0
-** * Both rowid range constraints: cost=250000.0
-** * An == rowid constraint: cost=10.0
+** * No other constraints: cost=3000000.0
+** * One rowid range constraints: cost=2250000.0
+** * Both rowid range constraint: cost=750000.0
+** * An == rowid constraint: cost=25.0
**
** Costs are not modified by the ORDER BY clause.
+**
+** The ratios used in case (a) are based on informal results obtained from
+** the tool/fts5cost.tcl script. The "MATCH and ==" combination has the
+** cost set quite high because the query may be a prefix query. Unless
+** there is a prefix index, prefix queries with rowid constraints are much
+** more expensive than non-prefix queries with rowid constraints.
+**
+** The estimated rows returned is set to the cost/40. For simple queries,
+** experimental results show that cost/4 might be about right. But for
+** more complex queries that use multiple terms the number of rows might
+** be far fewer than this. So we compromise and use cost/40.
*/
static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
Fts5Table *pTab = (Fts5Table*)pVTab;
@@ -257399,7 +262507,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_ERROR;
}
- idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
+ idxStr = (char*)sqlite3_malloc64((i64)pInfo->nConstraint * 8 + 1);
if( idxStr==0 ) return SQLITE_NOMEM;
pInfo->idxStr = idxStr;
pInfo->needToFreeIdxStr = 1;
@@ -257492,21 +262600,35 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
/* Calculate the estimated cost based on the flags set in idxFlags. */
if( bSeenEq ){
- pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0;
- fts5SetUniqueFlag(pInfo);
+ pInfo->estimatedCost = nSeenMatch ? 25000.0 : 25.0;
fts5SetEstimatedRows(pInfo, 1);
+ fts5SetUniqueFlag(pInfo);
}else{
- if( bSeenLt && bSeenGt ){
- pInfo->estimatedCost = nSeenMatch ? 5000.0 : 750000.0;
- }else if( bSeenLt || bSeenGt ){
- pInfo->estimatedCost = nSeenMatch ? 7500.0 : 2250000.0;
+ i64 nEstRows;
+ if( nSeenMatch ){
+ if( bSeenLt && bSeenGt ){
+ pInfo->estimatedCost = 50000.0;
+ }else if( bSeenLt || bSeenGt ){
+ pInfo->estimatedCost = 37500.0;
+ }else{
+ pInfo->estimatedCost = 50000.0;
+ }
+ nEstRows = (i64)(pInfo->estimatedCost / 40.0);
+ for(i=1; iestimatedCost *= 2.5;
+ nEstRows = nEstRows / 2;
+ }
}else{
- pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0;
- }
- for(i=1; iestimatedCost *= 0.4;
+ if( bSeenLt && bSeenGt ){
+ pInfo->estimatedCost = 750000.0;
+ }else if( bSeenLt || bSeenGt ){
+ pInfo->estimatedCost = 2250000.0;
+ }else{
+ pInfo->estimatedCost = 3000000.0;
+ }
+ nEstRows = (i64)(pInfo->estimatedCost / 4.0);
}
- fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0));
+ fts5SetEstimatedRows(pInfo, nEstRows);
}
pInfo->idxNum = idxFlags;
@@ -258849,6 +263971,7 @@ static int fts5UpdateMethod(
}
update_out:
+ sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -259446,19 +264569,23 @@ static int fts5ApiPhraseFirstColumn(
if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
Fts5Sorter *pSorter = pCsr->pSorter;
- int n;
- if( pSorter ){
- int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
- n = pSorter->aIdx[iPhrase] - i1;
- pIter->a = &pSorter->aPoslist[i1];
+ if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
+ rc = SQLITE_RANGE;
}else{
- rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
- }
- if( rc==SQLITE_OK ){
- assert( pIter->a || n==0 );
- pIter->b = (pIter->a ? &pIter->a[n] : 0);
- *piCol = 0;
- fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
+ int n;
+ if( pSorter ){
+ int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
+ n = pSorter->aIdx[iPhrase] - i1;
+ pIter->a = &pSorter->aPoslist[i1];
+ }else{
+ rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
+ }
+ if( rc==SQLITE_OK ){
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
+ *piCol = 0;
+ fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
+ }
}
}else{
int n;
@@ -260366,7 +265493,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76", -1, SQLITE_TRANSIENT);
}
/*
@@ -260530,7 +265657,7 @@ static int fts5Init(sqlite3 *db){
int rc;
Fts5Global *pGlobal = 0;
- pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
+ pGlobal = (Fts5Global*)sqlite3_malloc64(sizeof(Fts5Global));
if( pGlobal==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -261008,34 +266135,31 @@ static int sqlite3Fts5StorageOpen(
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|| pConfig->eContent==FTS5_CONTENT_UNINDEXED
){
- int nDefn = 32 + pConfig->nCol*10;
- char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
- if( zDefn==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int i;
- int iOff;
- sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
- iOff = (int)strlen(zDefn);
- for(i=0; inCol; i++){
- if( pConfig->eContent==FTS5_CONTENT_NORMAL
- || pConfig->abUnindexed[i]
- ){
- sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
- iOff += (int)strlen(&zDefn[iOff]);
- }
+ int i = 0;
+ char *zDefn = 0;
+ sqlite3_str *pDefn = sqlite3_str_new(pConfig->db);
+
+ sqlite3_str_appendf(pDefn, "id INTEGER PRIMARY KEY");
+ for(i=0; inCol; i++){
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->abUnindexed[i] ){
+ sqlite3_str_appendf(pDefn, ", c%d", i);
}
- if( pConfig->bLocale ){
- for(i=0; inCol; i++){
- if( pConfig->abUnindexed[i]==0 ){
- sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
- iOff += (int)strlen(&zDefn[iOff]);
- }
+ }
+ if( pConfig->bLocale ){
+ for(i=0; inCol; i++){
+ if( pConfig->abUnindexed[i]==0 ){
+ sqlite3_str_appendf(pDefn, ", l%d", i);
}
}
+ }
+ zDefn = sqlite3_str_finish(pDefn);
+
+ if( zDefn ){
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
+ sqlite3_free(zDefn);
+ }else{
+ rc = SQLITE_NOMEM;
}
- sqlite3_free(zDefn);
}
if( rc==SQLITE_OK && pConfig->bColumnsize ){
@@ -261262,6 +266386,64 @@ static void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage *pStorage){
pStorage->pSavedRow = 0;
}
+/*
+** Load the contents of the "averages" record from disk into the
+** p->nTotalRow and p->aTotalSize[] variables. If successful, and if
+** argument bCache is true, set the p->bTotalsValid flag to indicate
+** that the contents of aTotalSize[] and nTotalRow are valid until
+** further notice.
+**
+** Return SQLITE_OK if successful, or an SQLite error code if an error
+** occurs.
+*/
+static int fts5StorageLoadTotals(Fts5Storage *p, int bCache){
+ int rc = SQLITE_OK;
+ if( p->bTotalsValid==0 ){
+ rc = sqlite3Fts5IndexGetAverages(p->pIndex, &p->nTotalRow, p->aTotalSize);
+ p->bTotalsValid = bCache;
+ }
+ return rc;
+}
+
+/*
+** Store the current contents of the p->nTotalRow and p->aTotalSize[]
+** variables in the "averages" record on disk.
+**
+** Return SQLITE_OK if successful, or an SQLite error code if an error
+** occurs.
+*/
+static int fts5StorageSaveTotals(Fts5Storage *p){
+ int nCol = p->pConfig->nCol;
+ int i;
+ Fts5Buffer buf;
+ int rc = SQLITE_OK;
+ memset(&buf, 0, sizeof(buf));
+
+ sqlite3Fts5BufferAppendVarint(&rc, &buf, p->nTotalRow);
+ for(i=0; iaTotalSize[i]);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5IndexSetAverages(p->pIndex, buf.p, buf.n);
+ }
+ sqlite3_free(buf.p);
+
+ return rc;
+}
+
+static int fts5StorageDecodeSizeArray(
+ int *aCol, int nCol, /* Array to populate */
+ const u8 *aBlob, int nBlob /* Record to read varints from */
+){
+ int i;
+ int iOff = 0;
+ for(i=0; i=nBlob ) return 1;
+ iOff += fts5GetVarint32(&aBlob[iOff], aCol[i]);
+ }
+ return (iOff!=nBlob);
+}
+
/*
** This function is called to process a DELETE on a contentless_delete=1
** table. It adds the tombstone required to delete the entry with rowid
@@ -261278,19 +266460,41 @@ static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){
|| p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
);
+ rc = fts5StorageLoadTotals(p, 1);
+ if( rc!=SQLITE_OK ) return rc;
+
/* Look up the origin of the document in the %_docsize table. Store
** this in stack variable iOrigin. */
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
if( rc==SQLITE_OK ){
+ int rc2;
sqlite3_bind_int64(pLookup, 1, iDel);
if( SQLITE_ROW==sqlite3_step(pLookup) ){
- iOrigin = sqlite3_column_int64(pLookup, 1);
+ int *aCol = (int*)sqlite3_malloc64(p->pConfig->nCol * sizeof(int));
+ if( aCol==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ const u8 *aBlob = sqlite3_column_blob(pLookup, 0);
+ int nBlob = sqlite3_column_bytes(pLookup, 0);
+ int ii;
+ if( fts5StorageDecodeSizeArray(aCol, p->pConfig->nCol, aBlob, nBlob) ){
+ rc = SQLITE_CORRUPT_VTAB;
+ }else{
+ for(ii=0; iipConfig->nCol; ii++){
+ p->aTotalSize[ii] -= aCol[ii];
+ }
+ }
+ sqlite3_free(aCol);
+ }
+ iOrigin = sqlite3_column_int(pLookup, 1);
}
- rc = sqlite3_reset(pLookup);
+ rc2 = sqlite3_reset(pLookup);
+ if( rc==SQLITE_OK ) rc = rc2;
}
if( rc==SQLITE_OK && iOrigin!=0 ){
rc = sqlite3Fts5IndexContentlessDelete(p->pIndex, iOrigin, iDel);
+ p->nTotalRow--;
}
return rc;
@@ -261331,51 +266535,6 @@ static int fts5StorageInsertDocsize(
return rc;
}
-/*
-** Load the contents of the "averages" record from disk into the
-** p->nTotalRow and p->aTotalSize[] variables. If successful, and if
-** argument bCache is true, set the p->bTotalsValid flag to indicate
-** that the contents of aTotalSize[] and nTotalRow are valid until
-** further notice.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs.
-*/
-static int fts5StorageLoadTotals(Fts5Storage *p, int bCache){
- int rc = SQLITE_OK;
- if( p->bTotalsValid==0 ){
- rc = sqlite3Fts5IndexGetAverages(p->pIndex, &p->nTotalRow, p->aTotalSize);
- p->bTotalsValid = bCache;
- }
- return rc;
-}
-
-/*
-** Store the current contents of the p->nTotalRow and p->aTotalSize[]
-** variables in the "averages" record on disk.
-**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
-** occurs.
-*/
-static int fts5StorageSaveTotals(Fts5Storage *p){
- int nCol = p->pConfig->nCol;
- int i;
- Fts5Buffer buf;
- int rc = SQLITE_OK;
- memset(&buf, 0, sizeof(buf));
-
- sqlite3Fts5BufferAppendVarint(&rc, &buf, p->nTotalRow);
- for(i=0; iaTotalSize[i]);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexSetAverages(p->pIndex, buf.p, buf.n);
- }
- sqlite3_free(buf.p);
-
- return rc;
-}
-
/*
** Remove a row from the FTS table.
*/
@@ -262037,19 +267196,6 @@ static void sqlite3Fts5StorageStmtRelease(
}
}
-static int fts5StorageDecodeSizeArray(
- int *aCol, int nCol, /* Array to populate */
- const u8 *aBlob, int nBlob /* Record to read varints from */
-){
- int i;
- int iOff = 0;
- for(i=0; i=nBlob ) return 1;
- iOff += fts5GetVarint32(&aBlob[iOff], aCol[i]);
- }
- return (iOff!=nBlob);
-}
-
/*
** Argument aCol points to an array of integers containing one entry for
** each table column. This function reads the %_docsize record for the
@@ -262246,7 +267392,7 @@ static int fts5AsciiCreate(
if( nArg%2 ){
rc = SQLITE_ERROR;
}else{
- p = sqlite3_malloc(sizeof(AsciiTokenizer));
+ p = sqlite3_malloc64(sizeof(AsciiTokenizer));
if( p==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -262351,13 +267497,10 @@ static int fts5AsciiTokenize(
/*
-** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
-** from the sqlite3 source file utf.c. If this file is compiled as part
-** of the amalgamation, they are not required.
+** The following two macros - FTS5_READ_UTF8 and FTS5_WRITE_UTF8 - have
+** been copied from the sqlite3 source file utf.c.
*/
-#ifndef SQLITE_AMALGAMATION
-
-static const unsigned char sqlite3Utf8Trans1[] = {
+static const unsigned char fts5Utf8Trans1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -262368,45 +267511,43 @@ static const unsigned char sqlite3Utf8Trans1[] = {
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
};
-#define READ_UTF8(zIn, zTerm, c) \
+#define FTS5_READ_UTF8(zIn, zTerm, c) \
c = *(zIn++); \
if( c>=0xc0 ){ \
- c = sqlite3Utf8Trans1[c-0xc0]; \
+ c = fts5Utf8Trans1[c-0xc0]; \
while( zIn>6)&0x1F); \
- *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
- } \
- else if( c<0x10000 ){ \
- *zOut++ = 0xE0 + (unsigned char)((c>>12)&0x0F); \
- *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
- }else{ \
- *zOut++ = 0xF0 + (unsigned char)((c>>18) & 0x07); \
- *zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \
- *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
- } \
+#define FTS5_WRITE_UTF8(zOut, c) { \
+ if( c<0x00080 ){ \
+ *zOut++ = (unsigned char)(c&0xFF); \
+ } \
+ else if( c<0x00800 ){ \
+ *zOut++ = 0xC0 + (unsigned char)((c>>6)&0x1F); \
+ *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
+ } \
+ else if( c<0x10000 ){ \
+ *zOut++ = 0xE0 + (unsigned char)((c>>12)&0x0F); \
+ *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
+ }else{ \
+ *zOut++ = 0xF0 + (unsigned char)((c>>18) & 0x07); \
+ *zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \
+ *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
+ } \
}
-#endif /* ifndef SQLITE_AMALGAMATION */
-
-#define FTS5_SKIP_UTF8(zIn) { \
- if( ((unsigned char)(*(zIn++)))>=0xc0 ){ \
- while( (((unsigned char)*zIn) & 0xc0)==0x80 ){ zIn++; } \
- } \
+#define FTS5_SKIP_UTF8(zIn) { \
+ if( ((unsigned char)(*(zIn++)))>=0xc0 ){ \
+ while( (((unsigned char)*zIn) & 0xc0)==0x80 ){zIn++;} \
+ } \
}
typedef struct Unicode61Tokenizer Unicode61Tokenizer;
@@ -262445,7 +267586,7 @@ static int fts5UnicodeAddExceptions(
while( zCsr |