aboutsummaryrefslogtreecommitdiff
path: root/contrib/sqlite3/sqlite3.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sqlite3/sqlite3.c')
-rw-r--r--contrib/sqlite3/sqlite3.c17725
1 files changed, 11452 insertions, 6273 deletions
diff --git a/contrib/sqlite3/sqlite3.c b/contrib/sqlite3/sqlite3.c
index 946815f13ec8..0b071b2b6cc2 100644
--- a/contrib/sqlite3/sqlite3.c
+++ b/contrib/sqlite3/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.46.1. By combining all the individual C code files into this
+** version 3.50.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -18,8 +18,11 @@
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
-** c9c2ab54ba1f5f46360f1b4f35d849cd3f08.
+** 2af157d77fb1304a74176eaee7fbc7c7e932 with changes in files:
+**
+**
*/
+#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
@@ -256,10 +259,13 @@
/*
** Macro to disable warnings about missing "break" at the end of a "case".
*/
-#if GCC_VERSION>=7000000
-# define deliberate_fall_through __attribute__((fallthrough));
-#else
-# define deliberate_fall_through
+#if defined(__has_attribute)
+# if __has_attribute(fallthrough)
+# define deliberate_fall_through __attribute__((fallthrough));
+# endif
+#endif
+#if !defined(deliberate_fall_through)
+# define deliberate_fall_through
#endif
/*
@@ -446,7 +452,7 @@ extern "C" {
**
** Since [version 3.6.18] ([dateof:3.6.18]),
** SQLite source code has been stored in the
-** <a href="http://www.fossil-scm.org/">Fossil configuration management
+** <a href="http://fossil-scm.org/">Fossil configuration management
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
@@ -459,9 +465,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.46.1"
-#define SQLITE_VERSION_NUMBER 3046001
-#define SQLITE_SOURCE_ID "2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33"
+#define SQLITE_VERSION "3.50.2"
+#define SQLITE_VERSION_NUMBER 3050002
+#define SQLITE_SOURCE_ID "2025-06-28 14:00:48 2af157d77fb1304a74176eaee7fbc7c7e932d946bf25325e9c26c91db19e3079"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -965,6 +971,13 @@ SQLITE_API int sqlite3_exec(
** filesystem supports doing multiple write operations atomically when those
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
+**
+** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read
+** from the database file in amounts that are not a multiple of the
+** page size and that do not begin at a page boundary. Without this
+** property, SQLite is careful to only do full-page reads and write
+** on aligned pages, with the one exception that it will do a sub-page
+** read of the first page to access the database header.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -981,6 +994,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
+#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000
/*
** CAPI3REF: File Locking Levels
@@ -1085,8 +1099,8 @@ struct sqlite3_file {
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
-** PENDING, or EXCLUSIVE lock on the file. It returns true
-** if such a lock exists and false otherwise.
+** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
+** pointer parameter, true if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom
** VFS implementations to directly control an open file using the
@@ -1127,6 +1141,7 @@ struct sqlite3_file {
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** <li> [SQLITE_IOCAP_IMMUTABLE]
** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
+** <li> [SQLITE_IOCAP_SUBPAGE_READ]
** </ul>
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -1404,6 +1419,11 @@ struct sqlite3_io_methods {
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
+** <li>[[SQLITE_FCNTL_NULL_IO]]
+** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor
+** or file handle for the [sqlite3_file] object such that it will no longer
+** read or write to the database file.
+**
** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
** be advantageous to block on the next WAL lock if the lock is not immediately
@@ -1462,6 +1482,12 @@ struct sqlite3_io_methods {
** the value that M is to be set to. Before returning, the 32-bit signed
** integer is overwritten with the previous value of M.
**
+** <li>[[SQLITE_FCNTL_BLOCK_ON_CONNECT]]
+** The [SQLITE_FCNTL_BLOCK_ON_CONNECT] opcode is used to configure the
+** VFS to block when taking a SHARED lock to connect to a wal mode database.
+** This is used to implement the functionality associated with
+** SQLITE_SETLK_BLOCK_ON_CONNECT.
+**
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
** a database file. The argument is a pointer to a 32-bit unsigned integer.
@@ -1557,6 +1583,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_EXTERNAL_READER 40
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
+#define SQLITE_FCNTL_NULL_IO 43
+#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2287,13 +2315,16 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
** <dd> ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine
-** the default size of lookaside memory on each [database connection].
+** the default size of [lookaside memory] on each [database connection].
** The first argument is the
-** size of each lookaside buffer slot and the second is the number of
-** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE
-** sets the <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
-** option to [sqlite3_db_config()] can be used to change the lookaside
-** configuration on individual connections.)^ </dd>
+** size of each lookaside buffer slot ("sz") and the second is the number of
+** slots allocated to each database connection ("cnt").)^
+** ^(SQLITE_CONFIG_LOOKASIDE sets the <i>default</i> lookaside size.
+** The [SQLITE_DBCONFIG_LOOKASIDE] option to [sqlite3_db_config()] can
+** be used to change the lookaside configuration on individual connections.)^
+** The [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to change the
+** default lookaside configuration at compile-time.
+** </dd>
**
** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is
@@ -2509,7 +2540,15 @@ struct sqlite3_mem_methods {
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
-** can be passed as the second argument to the [sqlite3_db_config()] interface.
+** can be passed as the second parameter to the [sqlite3_db_config()] interface.
+**
+** The [sqlite3_db_config()] interface is a var-args functions. It takes a
+** variable number of parameters, though always at least two. The number of
+** parameters passed into sqlite3_db_config() depends on which of these
+** constants is given as the second parameter. This documentation page
+** refers to parameters beyond the second as "arguments". Thus, when this
+** page says "the N-th argument" it means "the N-th parameter past the
+** configuration option" or "the (N+2)-th parameter to sqlite3_db_config()".
**
** New configuration options may be added in future releases of SQLite.
** Existing configuration options might be discontinued. Applications
@@ -2521,31 +2560,57 @@ struct sqlite3_mem_methods {
** <dl>
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
-** <dd> ^This option takes three additional arguments that determine the
-** [lookaside memory allocator] configuration for the [database connection].
-** ^The first argument (the third parameter to [sqlite3_db_config()] is a
+** <dd> The SQLITE_DBCONFIG_LOOKASIDE option is used to adjust the
+** configuration of the [lookaside memory allocator] within a database
+** connection.
+** The arguments to the SQLITE_DBCONFIG_LOOKASIDE option are <i>not</i>
+** in the [DBCONFIG arguments|usual format].
+** The SQLITE_DBCONFIG_LOOKASIDE option takes three arguments, not two,
+** so that a call to [sqlite3_db_config()] that uses SQLITE_DBCONFIG_LOOKASIDE
+** should have a total of five parameters.
+** <ol>
+** <li><p>The first argument ("buf") is a
** pointer to a memory buffer to use for lookaside memory.
-** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
-** may be NULL in which case SQLite will allocate the
-** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
-** size of each lookaside buffer slot. ^The third argument is the number of
-** slots. The size of the buffer in the first argument must be greater than
-** or equal to the product of the second and third arguments. The buffer
-** must be aligned to an 8-byte boundary. ^If the second argument to
-** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
-** rounded down to the next smaller multiple of 8. ^(The lookaside memory
+** The first argument may be NULL in which case SQLite will allocate the
+** lookaside buffer itself using [sqlite3_malloc()].
+** <li><P>The second argument ("sz") is the
+** size of each lookaside buffer slot. Lookaside is disabled if "sz"
+** is less than 8. The "sz" argument should be a multiple of 8 less than
+** 65536. If "sz" does not meet this constraint, it is reduced in size until
+** it does.
+** <li><p>The third argument ("cnt") is the number of slots. Lookaside is disabled
+** if "cnt"is less than 1. The "cnt" value will be reduced, if necessary, so
+** that the product of "sz" and "cnt" does not exceed 2,147,418,112. The "cnt"
+** parameter is usually chosen so that the product of "sz" and "cnt" is less
+** than 1,000,000.
+** </ol>
+** <p>If the "buf" argument is not NULL, then it must
+** point to a memory buffer with a size that is greater than
+** or equal to the product of "sz" and "cnt".
+** The buffer must be aligned to an 8-byte boundary.
+** The lookaside memory
** configuration for a database connection can only be changed when that
** connection is not currently using lookaside memory, or in other words
-** when the "current value" returned by
-** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero.
+** when the value returned by [SQLITE_DBSTATUS_LOOKASIDE_USED] is zero.
** Any attempt to change the lookaside memory configuration when lookaside
** memory is in use leaves the configuration unchanged and returns
-** [SQLITE_BUSY].)^</dd>
+** [SQLITE_BUSY].
+** If the "buf" argument is NULL and an attempt
+** to allocate memory based on "sz" and "cnt" fails, then
+** lookaside is silently disabled.
+** <p>
+** The [SQLITE_CONFIG_LOOKASIDE] configuration option can be used to set the
+** default lookaside configuration at initialization. The
+** [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to set the default lookaside
+** configuration at compile-time. Typical values for lookaside are 1200 for
+** "sz" and 40 to 100 for "cnt".
+** </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of
-** [foreign key constraints]. There should be two additional arguments.
+** [foreign key constraints]. This is the same setting that is
+** enabled or disabled by the [PRAGMA foreign_keys] statement.
** The first argument is an integer which is 0 to disable FK enforcement,
** positive to enable FK enforcement or negative to leave FK enforcement
** unchanged. The second parameter is a pointer to an integer into which
@@ -2567,13 +2632,13 @@ struct sqlite3_mem_methods {
** <p>Originally this option disabled all triggers. ^(However, since
** SQLite version 3.35.0, TEMP triggers are still allowed even if
** this option is off. So, in other words, this option now only disables
-** triggers in the main database schema or in the schemas of ATTACH-ed
+** triggers in the main database schema or in the schemas of [ATTACH]-ed
** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
-** There should be two additional arguments.
+** There must be two additional arguments.
** The first argument is an integer which is 0 to disable views,
** positive to enable views or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
@@ -2592,7 +2657,7 @@ struct sqlite3_mem_methods {
** <dd> ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
-** There should be two additional arguments.
+** There must be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
@@ -2607,7 +2672,7 @@ struct sqlite3_mem_methods {
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
-** There should be two additional arguments.
+** There must be two additional arguments.
** When the first argument to this interface is 1, then only the C-API is
** enabled and the SQL function remains disabled. If the first argument to
** this interface is 0, then both the C-API and the SQL function are disabled.
@@ -2621,23 +2686,30 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database
-** schema. ^The sole argument is a pointer to a constant UTF8 string
-** which will become the new schema name in place of "main". ^SQLite
-** does not make a copy of the new main schema name string, so the application
-** must ensure that the argument passed into this DBCONFIG option is unchanged
-** until after the database connection closes.
+** schema. This option does not follow the
+** [DBCONFIG arguments|usual SQLITE_DBCONFIG argument format].
+** This option takes exactly one additional argument so that the
+** [sqlite3_db_config()] call has a total of three parameters. The
+** extra argument must be a pointer to a constant UTF8 string which
+** will become the new schema name in place of "main". ^SQLite does
+** not make a copy of the new main schema name string, so the application
+** must ensure that the argument passed into SQLITE_DBCONFIG MAINDBNAME
+** is unchanged until after the database connection closes.
** </dd>
**
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
-** <dd> Usually, when a database in wal mode is closed or detached from a
-** database handle, SQLite checks if this will mean that there are now no
-** connections at all to the database. If so, it performs a checkpoint
-** operation before closing the connection. This option may be used to
-** override this behavior. The first parameter passed to this operation
-** is an integer - positive to disable checkpoints-on-close, or zero (the
-** default) to enable them, and negative to leave the setting unchanged.
-** The second parameter is a pointer to an integer
+** <dd> Usually, when a database in [WAL mode] is closed or detached from a
+** database handle, SQLite checks if if there are other connections to the
+** same database, and if there are no other database connection (if the
+** connection being closed is the last open connection to the database),
+** then SQLite performs a [checkpoint] before closing the connection and
+** deletes the WAL file. The SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE option can
+** be used to override that behavior. The first argument passed to this
+** operation (the third parameter to [sqlite3_db_config()]) is an integer
+** which is positive to disable checkpoints-on-close, or zero (the default)
+** to enable them, and negative to leave the setting unchanged.
+** The second argument (the fourth parameter) is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
@@ -2798,7 +2870,7 @@ struct sqlite3_mem_methods {
** statistics. For statistics to be collected, the flag must be set on
** the database handle both when the SQL statement is prepared and when it
** is stepped. The flag is set (collection of statistics is enabled)
-** by default. This option takes two arguments: an integer and a pointer to
+** by default. <p>This option takes two arguments: an integer and a pointer to
** an integer.. The first argument is 1, 0, or -1 to enable, disable, or
** leave unchanged the statement scanstatus option. If the second argument
** is not NULL, then the value of the statement scanstatus setting after
@@ -2812,7 +2884,7 @@ struct sqlite3_mem_methods {
** in which tables and indexes are scanned so that the scans start at the end
** and work toward the beginning rather than starting at the beginning and
** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
-** same as setting [PRAGMA reverse_unordered_selects]. This option takes
+** same as setting [PRAGMA reverse_unordered_selects]. <p>This option takes
** two arguments which are an integer and a pointer to an integer. The first
** argument is 1, 0, or -1 to enable, disable, or leave unchanged the
** reverse scan order flag, respectively. If the second argument is not NULL,
@@ -2821,7 +2893,76 @@ struct sqlite3_mem_methods {
** first argument.
** </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]]
+** <dt>SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE</dt>
+** <dd>The SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE option enables or disables
+** the ability of the [ATTACH DATABASE] SQL command to create a new database
+** file if the database filed named in the ATTACH command does not already
+** exist. This ability of ATTACH to create a new database is enabled by
+** default. Applications can disable or reenable the ability for ATTACH to
+** create new database files using this DBCONFIG option.<p>
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the attach-create flag, respectively. If the second
+** argument is not NULL, then 0 or 1 is written into the integer that the
+** second argument points to depending on if the attach-create flag is set
+** after processing the first argument.
+** </dd>
+**
+** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]]
+** <dt>SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE</dt>
+** <dd>The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the
+** ability of the [ATTACH DATABASE] SQL command to open a database for writing.
+** This capability is enabled by default. Applications can disable or
+** reenable this capability using the current DBCONFIG option. If the
+** the this capability is disabled, the [ATTACH] command will still work,
+** but the database will be opened read-only. If this option is disabled,
+** then the ability to create a new database using [ATTACH] is also disabled,
+** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]
+** option.<p>
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the ability to ATTACH another database for writing,
+** respectively. If the second argument is not NULL, then 0 or 1 is written
+** into the integer to which the second argument points, depending on whether
+** the ability to ATTACH a read/write database is enabled or disabled
+** after processing the first argument.
+** </dd>
+**
+** [[SQLITE_DBCONFIG_ENABLE_COMMENTS]]
+** <dt>SQLITE_DBCONFIG_ENABLE_COMMENTS</dt>
+** <dd>The SQLITE_DBCONFIG_ENABLE_COMMENTS option enables or disables the
+** ability to include comments in SQL text. Comments are enabled by default.
+** An application can disable or reenable comments in SQL text using this
+** DBCONFIG option.<p>
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the ability to use comments in SQL text,
+** respectively. If the second argument is not NULL, then 0 or 1 is written
+** into the integer that the second argument points to depending on if
+** comments are allowed in SQL text after processing the first argument.
+** </dd>
+**
** </dl>
+**
+** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3>
+**
+** <p>Most of the SQLITE_DBCONFIG options take two arguments, so that the
+** overall call to [sqlite3_db_config()] has a total of four parameters.
+** The first argument (the third parameter to sqlite3_db_config()) is a integer.
+** The second argument is a pointer to an integer. If the first argument is 1,
+** then the option becomes enabled. If the first integer argument is 0, then the
+** option is disabled. If the first argument is -1, then the option setting
+** is unchanged. The second argument, the pointer to an integer, may be NULL.
+** If the second argument is not NULL, then a value of 0 or 1 is written into
+** the integer to which the second argument points, depending on whether the
+** setting is disabled or enabled after applying any changes specified by
+** the first argument.
+**
+** <p>While most SQLITE_DBCONFIG options use the argument format
+** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME]
+** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the
+** documentation of those exceptional options for details.
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
@@ -2843,7 +2984,10 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */
#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -2935,10 +3079,14 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
** The two functions are identical except for the type of the return value
-** and that if the number of rows modified by the most recent INSERT, UPDATE
+** and that if the number of rows modified by the most recent INSERT, UPDATE,
** or DELETE is greater than the maximum value supported by type "int", then
** the return value of sqlite3_changes() is undefined. ^Executing any other
** type of SQL statement does not modify the value returned by these functions.
+** For the purposes of this interface, a CREATE TABLE AS SELECT statement
+** does not count as an INSERT, UPDATE or DELETE statement and hence the rows
+** added to the new table by the CREATE TABLE AS SELECT statement are not
+** counted.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
@@ -3194,6 +3342,44 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
/*
+** CAPI3REF: Set the Setlk Timeout
+** METHOD: sqlite3
+**
+** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If
+** the VFS supports blocking locks, it sets the timeout in ms used by
+** eligible locks taken on wal mode databases by the specified database
+** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does
+** not support blocking locks, this function is a no-op.
+**
+** Passing 0 to this function disables blocking locks altogether. Passing
+** -1 to this function requests that the VFS blocks for a long time -
+** indefinitely if possible. The results of passing any other negative value
+** are undefined.
+**
+** Internally, each SQLite database handle store two timeout values - the
+** busy-timeout (used for rollback mode databases, or if the VFS does not
+** support blocking locks) and the setlk-timeout (used for blocking locks
+** on wal-mode databases). The sqlite3_busy_timeout() method sets both
+** values, this function sets only the setlk-timeout value. Therefore,
+** to configure separate busy-timeout and setlk-timeout values for a single
+** database handle, call sqlite3_busy_timeout() followed by this function.
+**
+** Whenever the number of connections to a wal mode database falls from
+** 1 to 0, the last connection takes an exclusive lock on the database,
+** then checkpoints and deletes the wal file. While it is doing this, any
+** new connection that tries to read from the database fails with an
+** SQLITE_BUSY error. Or, if the SQLITE_SETLK_BLOCK_ON_CONNECT flag is
+** passed to this API, the new connection blocks until the exclusive lock
+** has been released.
+*/
+SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags);
+
+/*
+** CAPI3REF: Flags for sqlite3_setlk_timeout()
+*/
+#define SQLITE_SETLK_BLOCK_ON_CONNECT 0x01
+
+/*
** CAPI3REF: Convenience Routines For Running Queries
** METHOD: sqlite3
**
@@ -3883,8 +4069,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
**
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
** <dd>The database connection comes up in "extended result code mode".
-** In other words, the database behaves has if
-** [sqlite3_extended_result_codes(db,1)] where called on the database
+** In other words, the database behaves as if
+** [sqlite3_extended_result_codes(db,1)] were called on the database
** connection as soon as the connection is created. In addition to setting
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
** to return an extended result code.</dd>
@@ -4212,7 +4398,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
**
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
** database filename D with corresponding journal file J and WAL file W and
-** with N URI parameters key/values pairs in the array P. The result from
+** an array P of N URI Key/Value pairs. The result from
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
** is safe to pass to routines like:
** <ul>
@@ -4498,11 +4684,22 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
** to return an error (error code SQLITE_ERROR) if the statement uses
** any virtual tables.
+**
+** [[SQLITE_PREPARE_DONT_LOG]] <dt>SQLITE_PREPARE_DONT_LOG</dt>
+** <dd>The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
+** errors from being sent to the error log defined by
+** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
+** compiles to see if some SQL syntax is well-formed, without generating
+** messages on the global error log when it is not. If the test compile
+** fails, the sqlite3_prepare_v3() call returns the same error indications
+** with or without this flag; it just omits the call to [sqlite3_log()] that
+** logs the error.
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
#define SQLITE_PREPARE_NO_VTAB 0x04
+#define SQLITE_PREPARE_DONT_LOG 0x10
/*
** CAPI3REF: Compiling An SQL Statement
@@ -4535,13 +4732,17 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** and sqlite3_prepare16_v3() use UTF-16.
**
** ^If the nByte argument is negative, then zSql is read up to the
-** first zero terminator. ^If nByte is positive, then it is the
-** number of bytes read from zSql. ^If nByte is zero, then no prepared
+** first zero terminator. ^If nByte is positive, then it is the maximum
+** number of bytes read from zSql. When nByte is positive, zSql is read
+** up to the first zero terminator or until the nByte bytes have been read,
+** whichever comes first. ^If nByte is zero, then no prepared
** statement is generated.
** If the caller knows that the supplied string is nul-terminated, then
** there is a small performance advantage to passing an nByte parameter that
** is the number of bytes in the input string <i>including</i>
** the nul-terminator.
+** Note that nByte measure the length of the input in bytes, not
+** characters, even for the UTF-16 interfaces.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
@@ -4878,7 +5079,7 @@ typedef struct sqlite3_context sqlite3_context;
** METHOD: sqlite3_stmt
**
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
-** literals may be replaced by a [parameter] that matches one of following
+** literals may be replaced by a [parameter] that matches one of the following
** templates:
**
** <ul>
@@ -4923,7 +5124,7 @@ typedef struct sqlite3_context sqlite3_context;
**
** [[byte-order determination rules]] ^The byte-order of
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
-** found in first character, which is removed, or in the absence of a BOM
+** found in the first character, which is removed, or in the absence of a BOM
** the byte order is the native byte order of the host
** machine for sqlite3_bind_text16() or the byte order specified in
** the 6th parameter for sqlite3_bind_text64().)^
@@ -4943,7 +5144,7 @@ typedef struct sqlite3_context sqlite3_context;
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
-** terminated. If any NUL characters occurs at byte offsets less than
+** terminated. If any NUL characters occur at byte offsets less than
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
@@ -5155,7 +5356,7 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** METHOD: sqlite3_stmt
**
** ^These routines provide a means to determine the database, table, and
-** table column that is the origin of a particular result column in
+** table column that is the origin of a particular result column in a
** [SELECT] statement.
** ^The name of the database or table or column can be returned as
** either a UTF-8 or UTF-16 string. ^The _database_ routines return
@@ -5293,7 +5494,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
+** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
** sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
@@ -5724,8 +5925,8 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
**
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
-** used inside of triggers, view, CHECK constraints, or other elements of
-** the database schema. This flags is especially recommended for SQL
+** used inside of triggers, views, CHECK constraints, or other elements of
+** the database schema. This flag is especially recommended for SQL
** functions that have side effects or reveal internal application state.
** Without this flag, an attacker might be able to modify the schema of
** a database file to include invocations of the function with parameters
@@ -5756,7 +5957,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** [user-defined window functions|available here].
**
** ^(If the final parameter to sqlite3_create_function_v2() or
-** sqlite3_create_window_function() is not NULL, then it is destructor for
+** sqlite3_create_window_function() is not NULL, then it is the destructor for
** the application data pointer. The destructor is invoked when the function
** is deleted, either by being overloaded or when the database connection
** closes.)^ ^The destructor is also invoked if the call to
@@ -5912,7 +6113,7 @@ SQLITE_API int sqlite3_create_window_function(
** This flag instructs SQLite to omit some corner-case optimizations that
** might disrupt the operation of the [sqlite3_value_subtype()] function,
** causing it to return zero rather than the correct subtype().
-** SQL functions that invokes [sqlite3_value_subtype()] should have this
+** All SQL functions that invoke [sqlite3_value_subtype()] should have this
** property. If the SQLITE_SUBTYPE property is omitted, then the return
** value from [sqlite3_value_subtype()] might sometimes be zero even though
** a non-zero subtype was specified by the function argument expression.
@@ -5928,6 +6129,15 @@ SQLITE_API int sqlite3_create_window_function(
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes.
+**
+** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd>
+** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
+** that internally orders the values provided to the first argument. The
+** ordered-set aggregate SQL notation with a single ORDER BY term can be
+** used to invoke this function. If the ordered-set aggregate notation is
+** used on a function that lacks this flag, then an error is raised. Note
+** that the ordered-set aggregate syntax is only available if SQLite is
+** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
** </dd>
** </dl>
*/
@@ -5936,6 +6146,7 @@ SQLITE_API int sqlite3_create_window_function(
#define SQLITE_SUBTYPE 0x000100000
#define SQLITE_INNOCUOUS 0x000200000
#define SQLITE_RESULT_SUBTYPE 0x001000000
+#define SQLITE_SELFORDER1 0x002000000
/*
** CAPI3REF: Deprecated Functions
@@ -6133,7 +6344,7 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
-** Every [application-defined SQL function] that invoke this interface
+** Every [application-defined SQL function] that invokes this interface
** should include the [SQLITE_SUBTYPE] property in the text
** encoding argument when the function is [sqlite3_create_function|registered].
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
@@ -6146,7 +6357,7 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
-** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
+** object V and returns a pointer to that copy. ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
** memory allocation fails. ^If V is a [pointer value], then the result
@@ -6184,7 +6395,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
** allocation error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
-** determined by the N parameter on first successful call. Changing the
+** determined by the N parameter on the first successful call. Changing the
** value of N in any subsequent call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
@@ -6346,7 +6557,7 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
**
** Security Warning: These interfaces should not be exposed in scripting
** languages or in other circumstances where it might be possible for an
-** an attacker to invoke them. Any agent that can invoke these interfaces
+** attacker to invoke them. Any agent that can invoke these interfaces
** can probably also take control of the process.
**
** Database connection client data is only available for SQLite
@@ -6460,7 +6671,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** pointed to by the 2nd parameter are taken as the application-defined
** function result. If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
-** appear if the string where NUL terminated. If any NUL characters occur
+** appear if the string were NUL terminated. If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
** parameter, then the resulting string will contain embedded NULs and the
** result of expressions operating on strings with embedded NULs is undefined.
@@ -6518,7 +6729,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** string and preferably a string literal. The sqlite3_result_pointer()
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
**
-** If these routines are called from within the different thread
+** If these routines are called from within a different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
@@ -6924,7 +7135,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
-** for the N-th database on database connection D, or a NULL pointer of N is
+** for the N-th database on database connection D, or a NULL pointer if N is
** out of range. An N value of 0 means the main database file. An N of 1 is
** the "temp" schema. Larger values of N correspond to various ATTACH-ed
** databases.
@@ -7019,7 +7230,7 @@ SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
** <dd>The SQLITE_TXN_READ state means that the database is currently
** in a read transaction. Content has been read from the database file
** but nothing in the database file has changed. The transaction state
-** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** will be advanced to SQLITE_TXN_WRITE if any changes occur and there are
** no other conflicting concurrent write transactions. The transaction
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
** [COMMIT].</dd>
@@ -7028,7 +7239,7 @@ SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
** <dd>The SQLITE_TXN_WRITE state means that the database is currently
** in a write transaction. Content has been written to the database file
** but has not yet committed. The transaction state will change to
-** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
+** SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
*/
#define SQLITE_TXN_NONE 0
#define SQLITE_TXN_READ 1
@@ -7179,6 +7390,8 @@ SQLITE_API int sqlite3_autovacuum_pages(
**
** ^The second argument is a pointer to the function to invoke when a
** row is updated, inserted or deleted in a rowid table.
+** ^The update hook is disabled by invoking sqlite3_update_hook()
+** with a NULL pointer as the second parameter.
** ^The first argument to the callback is a copy of the third argument
** to sqlite3_update_hook().
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -7307,7 +7520,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** CAPI3REF: Impose A Limit On Heap Size
**
** These interfaces impose limits on the amount of heap memory that will be
-** by all database connections within a single process.
+** used by all database connections within a single process.
**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
@@ -7365,7 +7578,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** </ul>)^
**
** The circumstances under which SQLite will enforce the heap limits may
-** changes in future releases of SQLite.
+** change in future releases of SQLite.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
@@ -7480,8 +7693,8 @@ SQLITE_API int sqlite3_table_column_metadata(
** ^The entry point is zProc.
** ^(zProc may be 0, in which case SQLite will try to come up with an
** entry point name on its own. It first tries "sqlite3_extension_init".
-** If that does not work, it constructs a name "sqlite3_X_init" where the
-** X is consists of the lower-case equivalent of all ASCII alphabetic
+** If that does not work, it constructs a name "sqlite3_X_init" where
+** X consists of the lower-case equivalent of all ASCII alphabetic
** characters in the filename from the last "/" to the first following
** "." and omitting any initial "lib".)^
** ^The sqlite3_load_extension() interface returns
@@ -7552,7 +7765,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects an integer result as if the signature of the
-** entry point where as follows:
+** entry point were as follows:
**
** <blockquote><pre>
** &nbsp; int xEntryPoint(
@@ -7716,7 +7929,7 @@ struct sqlite3_module {
** virtual table and might not be checked again by the byte code.)^ ^(The
** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
** is left in its default setting of false, the constraint will always be
-** checked separately in byte code. If the omit flag is change to true, then
+** checked separately in byte code. If the omit flag is changed to true, then
** the constraint may or may not be checked in byte code. In other words,
** when the omit flag is true there is no guarantee that the constraint will
** not be checked again using byte code.)^
@@ -7740,9 +7953,11 @@ struct sqlite3_module {
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
-** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
-** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
-** assumes that the strategy may visit at most one row.
+** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
+** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
+** output to show the idxNum as hex instead of as decimal. Another flag is
+** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
+** return at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
@@ -7806,7 +8021,9 @@ struct sqlite3_index_info {
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
-#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */
+ /* in EXPLAIN QUERY PLAN */
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
@@ -7879,7 +8096,7 @@ struct sqlite3_index_info {
** the implementation of the [virtual table module]. ^The fourth
** parameter is an arbitrary client data pointer that is passed through
** into the [xCreate] and [xConnect] methods of the virtual table module
-** when a new virtual table is be being created or reinitialized.
+** when a new virtual table is being created or reinitialized.
**
** ^The sqlite3_create_module_v2() interface has a fifth parameter which
** is a pointer to a destructor for the pClientData. ^SQLite will
@@ -8044,7 +8261,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** in *ppBlob. Otherwise an [error code] is returned and, unless the error
** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
** the API is not misused, it is always safe to call [sqlite3_blob_close()]
-** on *ppBlob after this function it returns.
+** on *ppBlob after this function returns.
**
** This function fails with SQLITE_ERROR if any of the following are true:
** <ul>
@@ -8164,7 +8381,7 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
**
** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
-** incremental blob I/O routines can only read or overwriting existing
+** incremental blob I/O routines can only read or overwrite existing
** blob content; they cannot change the size of a blob.
**
** This routine only works on a [BLOB handle] which has been created
@@ -8314,7 +8531,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
** ^The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
** routine returns NULL if it is unable to allocate the requested
-** mutex. The argument to sqlite3_mutex_alloc() must one of these
+** mutex. The argument to sqlite3_mutex_alloc() must be one of these
** integer constants:
**
** <ul>
@@ -8547,7 +8764,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
**
-** ^This interface returns a pointer the [sqlite3_mutex] object that
+** ^This interface returns a pointer to the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
** ^If the [threading mode] is Single-thread or Multi-thread then this
@@ -8643,6 +8860,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
+#define SQLITE_TESTCTRL_GETOPT 16
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
@@ -8662,14 +8880,14 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_TRACEFLAGS 31
#define SQLITE_TESTCTRL_TUNE 32
#define SQLITE_TESTCTRL_LOGEST 33
-#define SQLITE_TESTCTRL_USELONGDOUBLE 34
+#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
**
** These routines provide access to the set of SQL language keywords
-** recognized by SQLite. Applications can uses these routines to determine
+** recognized by SQLite. Applications can use these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
** by enclosing in double-quotes) so as not to confuse the parser.
**
@@ -8837,7 +9055,7 @@ SQLITE_API void sqlite3_str_reset(sqlite3_str*);
** content of the dynamic string under construction in X. The value
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
** and might be freed or altered by any subsequent method on the same
-** [sqlite3_str] object. Applications must not used the pointer returned
+** [sqlite3_str] object. Applications must not use the pointer returned by
** [sqlite3_str_value(X)] after any subsequent method call on the same
** object. ^Applications may change the content of the string returned
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
@@ -8923,7 +9141,7 @@ SQLITE_API int sqlite3_status64(
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
** buffer and where forced to overflow to [sqlite3_malloc()]. The
** returned value includes allocations that overflowed because they
-** where too large (they were larger than the "sz" parameter to
+** were too large (they were larger than the "sz" parameter to
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.</dd>)^
**
@@ -9007,28 +9225,29 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number of malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
-** <dd>This parameter returns the number malloc attempts that might have
+** <dd>This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
** memory requested being larger than the lookaside slot size.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
-** <dd>This parameter returns the number malloc attempts that might have
+** <dd>This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
+** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED_SHARED</dt>
@@ -9037,10 +9256,10 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** memory used by that pager cache is divided evenly between the attached
** connections.)^ In other words, if none of the pager caches associated
** with the database connection are shared, this request returns the same
-** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are
+** value as DBSTATUS_CACHE_USED. Or, if one or more of the pager caches are
** shared, the value returned by this call will be smaller than that returned
** by DBSTATUS_CACHE_USED. ^The highwater mark associated with
-** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
+** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.</dd>
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
@@ -9050,6 +9269,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
+** </dd>
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
@@ -9086,7 +9306,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** been written to disk in the middle of a transaction due to the page
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
-** additional overhead. This parameter can be used help identify
+** additional overhead. This parameter can be used to help identify
** inefficiencies that can be resolved by increasing the cache size.
** </dd>
**
@@ -9566,7 +9786,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** external process or via a database connection other than the one being
** used by the backup operation, then the backup will be automatically
** restarted by the next call to sqlite3_backup_step(). ^If the source
-** database is modified by the using the same database connection as is used
+** database is modified by using the same database connection as is used
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
@@ -9583,7 +9803,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** and may not be used following a call to sqlite3_backup_finish().
**
** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
-** sqlite3_backup_step() errors occurred, regardless or whether or not
+** sqlite3_backup_step() errors occurred, regardless of whether or not
** sqlite3_backup_step() completed.
** ^If an out-of-memory condition or IO error occurred during any prior
** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
@@ -9638,6 +9858,16 @@ typedef struct sqlite3_backup sqlite3_backup;
** APIs are not strictly speaking threadsafe. If they are invoked at the
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
+**
+** <b>Alternatives To Using The Backup API</b>
+**
+** Other techniques for safely creating a consistent backup of an SQLite
+** database include:
+**
+** <ul>
+** <li> The [VACUUM INTO] command.
+** <li> The [sqlite3_rsync] utility program.
+** </ul>
*/
SQLITE_API sqlite3_backup *sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
@@ -10643,7 +10873,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
-** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
+** [sqlite3_db_cacheflush(D)] interface is invoked, any dirty
** pages in the pager-cache that are not currently in use are written out
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
@@ -10837,6 +11067,14 @@ typedef struct sqlite3_snapshot {
** If there is not already a read-transaction open on schema S when
** this function is called, one is opened automatically.
**
+** If a read-transaction is opened by this function, then it is guaranteed
+** that the returned snapshot object may not be invalidated by a database
+** writer or checkpointer until after the read-transaction is closed. This
+** is not guaranteed if a read-transaction is already open when this
+** function is called. In that case, any subsequent write or checkpoint
+** operation on the database may invalidate the returned snapshot handle,
+** even while the read-transaction remains open.
+**
** The following must be true for this function to succeed. If any of
** the following statements are false when sqlite3_snapshot_get() is
** called, SQLITE_ERROR is returned. The final value of *P is undefined
@@ -10994,8 +11232,9 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
/*
** CAPI3REF: Serialize a database
**
-** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
-** that is a serialization of the S database on [database connection] D.
+** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
+** memory that is a serialization of the S database on
+** [database connection] D. If S is a NULL pointer, the main database is used.
** If P is not a NULL pointer, then the size of the database in bytes
** is written into *P.
**
@@ -11145,8 +11384,6 @@ SQLITE_API int sqlite3_deserialize(
#if defined(__wasi__)
# undef SQLITE_WASI
# define SQLITE_WASI 1
-# undef SQLITE_OMIT_WAL
-# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
# ifndef SQLITE_OMIT_LOAD_EXTENSION
# define SQLITE_OMIT_LOAD_EXTENSION
# endif
@@ -11158,7 +11395,7 @@ SQLITE_API int sqlite3_deserialize(
#if 0
} /* End of the 'extern "C"' block */
#endif
-#endif /* SQLITE3_H */
+/* #endif for SQLITE3_H will be added by mksqlite3.tcl */
/******** Begin file sqlite3rtree.h *********/
/*
@@ -11639,9 +11876,10 @@ SQLITE_API void sqlite3session_table_filter(
** is inserted while a session object is enabled, then later deleted while
** the same session object is disabled, no INSERT record will appear in the
** changeset, even though the delete took place while the session was disabled.
-** Or, if one field of a row is updated while a session is disabled, and
-** another field of the same row is updated while the session is enabled, the
-** resulting changeset will contain an UPDATE change that updates both fields.
+** Or, if one field of a row is updated while a session is enabled, and
+** then another field of the same row is updated while the session is disabled,
+** the resulting changeset will contain an UPDATE change that updates both
+** fields.
*/
SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
@@ -11713,8 +11951,9 @@ SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession
** database zFrom the contents of the two compatible tables would be
** identical.
**
-** It an error if database zFrom does not exist or does not contain the
-** required compatible table.
+** Unless the call to this function is a no-op as described above, it is an
+** error if database zFrom does not exist or does not contain the required
+** compatible table.
**
** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
@@ -11849,7 +12088,7 @@ SQLITE_API int sqlite3changeset_start_v2(
** The following flags may passed via the 4th parameter to
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
**
-** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
+** <dt>SQLITE_CHANGESETSTART_INVERT <dd>
** Invert the changeset while iterating through it. This is equivalent to
** inverting a changeset using sqlite3changeset_invert() before applying it.
** It is an error to specify this flag with a patchset.
@@ -12164,19 +12403,6 @@ SQLITE_API int sqlite3changeset_concat(
void **ppOut /* OUT: Buffer containing output changeset */
);
-
-/*
-** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
-*/
-SQLITE_API int sqlite3changeset_upgrade(
- sqlite3 *db,
- const char *zDb,
- int nIn, const void *pIn, /* Input changeset */
- int *pnOut, void **ppOut /* OUT: Inverse of input */
-);
-
-
-
/*
** CAPI3REF: Changegroup Handle
**
@@ -13349,6 +13575,10 @@ struct Fts5PhraseIter {
** (i.e. if it is a contentless table), then this API always iterates
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
+** In all cases, matches are visited in (column ASC, offset ASC) order.
+** i.e. all those in column 0, sorted by offset, followed by those in
+** column 1, etc.
+**
** xPhraseNext()
** See xPhraseFirst above.
**
@@ -13405,19 +13635,57 @@ struct Fts5PhraseIter {
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
** output variable (*ppToken) is set to point to a buffer containing the
** matching document token, and (*pnToken) to the size of that buffer in
-** bytes. This API is not available if the specified token matches a
-** prefix query term. In that case both output variables are always set
-** to 0.
+** bytes.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
+** This API may be slow in some cases if the token identified by parameters
+** iIdx and iToken matched a prefix token in the query. In most cases, the
+** first call to this API for each prefix token in the query is forced
+** to scan the portion of the full-text index that matches the prefix
+** token to collect the extra data required by this API. If the prefix
+** token matches a large number of token instances in the document set,
+** this may be a performance problem.
+**
+** If the user knows in advance that a query may use this API for a
+** prefix token, FTS5 may be configured to collect all required data as part
+** of the initial querying of the full-text index, avoiding the second scan
+** entirely. This also causes prefix queries that do not use this API to
+** run more slowly and use more memory. FTS5 may be configured in this way
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
+** option, or on a per-query basis using the
+** [fts5_insttoken | fts5_insttoken()] user function.
+**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
+**
+** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of columns in the table, SQLITE_RANGE is returned.
+**
+** Otherwise, this function attempts to retrieve the locale associated
+** with column iCol of the current row. Usually, there is no associated
+** locale, and output parameters (*pzLocale) and (*pnLocale) are set
+** to NULL and 0, respectively. However, if the fts5_locale() function
+** was used to associate a locale with the value when it was inserted
+** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+** buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+** is set to the size in bytes of the buffer, not including the
+** nul-terminator.
+**
+** If successful, SQLITE_OK is returned. Or, if an error occurs, an
+** SQLite error code is returned. The final value of the output parameters
+** is undefined in this case.
+**
+** xTokenize_v2:
+** Tokenize text using the tokenizer belonging to the FTS5 table. This
+** API is the same as the xTokenize() API, except that it allows a tokenizer
+** locale to be specified.
*/
struct Fts5ExtensionApi {
- int iVersion; /* Currently always set to 3 */
+ int iVersion; /* Currently always set to 4 */
void *(*xUserData)(Fts5Context*);
@@ -13459,6 +13727,15 @@ struct Fts5ExtensionApi {
const char **ppToken, int *pnToken
);
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+
+ /* Below this point are iVersion>=4 only */
+ int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+ int (*xTokenize_v2)(Fts5Context*,
+ const char *pText, int nText, /* Text to tokenize */
+ const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
+ void *pCtx, /* Context passed to xToken() */
+ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
+ );
};
/*
@@ -13479,7 +13756,7 @@ struct Fts5ExtensionApi {
** A tokenizer instance is required to actually tokenize text.
**
** The first argument passed to this function is a copy of the (void*)
-** pointer provided by the application when the fts5_tokenizer object
+** pointer provided by the application when the fts5_tokenizer_v2 object
** was registered with FTS5 (the third argument to xCreateTokenizer()).
** The second and third arguments are an array of nul-terminated strings
** containing the tokenizer arguments, if any, specified following the
@@ -13503,7 +13780,7 @@ struct Fts5ExtensionApi {
** argument passed to this function is a pointer to an Fts5Tokenizer object
** returned by an earlier call to xCreate().
**
-** The second argument indicates the reason that FTS5 is requesting
+** The third argument indicates the reason that FTS5 is requesting
** tokenization of the supplied text. This is always one of the following
** four values:
**
@@ -13527,6 +13804,13 @@ struct Fts5ExtensionApi {
** on a columnsize=0 database.
** </ul>
**
+** The sixth and seventh arguments passed to xTokenize() - pLocale and
+** nLocale - are a pointer to a buffer containing the locale to use for
+** tokenization (e.g. "en_US") and its size in bytes, respectively. The
+** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+** which case nLocale is always 0) to indicate that the tokenizer should
+** use its default locale.
+**
** For each token in the input string, the supplied callback xToken() must
** be invoked. The first argument to it should be a copy of the pointer
** passed as the second argument to xTokenize(). The third and fourth
@@ -13550,6 +13834,30 @@ struct Fts5ExtensionApi {
** may abandon the tokenization and return any error code other than
** SQLITE_OK or SQLITE_DONE.
**
+** If the tokenizer is registered using an fts5_tokenizer_v2 object,
+** then the xTokenize() method has two additional arguments - pLocale
+** and nLocale. These specify the locale that the tokenizer should use
+** for the current request. If pLocale and nLocale are both 0, then the
+** tokenizer should use its default locale. Otherwise, pLocale points to
+** an nLocale byte buffer containing the name of the locale to use as utf-8
+** text. pLocale is not nul-terminated.
+**
+** FTS5_TOKENIZER
+**
+** There is also an fts5_tokenizer object. This is an older, deprecated,
+** version of fts5_tokenizer_v2. It is similar except that:
+**
+** <ul>
+** <li> There is no "iVersion" field, and
+** <li> The xTokenize() method does not take a locale argument.
+** </ul>
+**
+** Legacy fts5_tokenizer tokenizers must be registered using the
+** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+**
+** Tokenizer implementations registered using either API may be retrieved
+** using both xFindTokenizer() and xFindTokenizer_v2().
+**
** SYNONYM SUPPORT
**
** Custom tokenizers may also support synonyms. Consider a case in which a
@@ -13658,6 +13966,33 @@ struct Fts5ExtensionApi {
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
+typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+struct fts5_tokenizer_v2 {
+ int iVersion; /* Currently always 2 */
+
+ int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+ void (*xDelete)(Fts5Tokenizer*);
+ int (*xTokenize)(Fts5Tokenizer*,
+ void *pCtx,
+ int flags, /* Mask of FTS5_TOKENIZE_* flags */
+ const char *pText, int nText,
+ const char *pLocale, int nLocale,
+ int (*xToken)(
+ void *pCtx, /* Copy of 2nd argument to xTokenize() */
+ int tflags, /* Mask of FTS5_TOKEN_* flags */
+ const char *pToken, /* Pointer to buffer containing token */
+ int nToken, /* Size of token in bytes */
+ int iStart, /* Byte offset of token within input text */
+ int iEnd /* Byte offset of end of token within input text */
+ )
+ );
+};
+
+/*
+** New code should use the fts5_tokenizer_v2 type to define tokenizer
+** implementations. The following type is included for legacy applications
+** that still use it.
+*/
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
@@ -13677,6 +14012,7 @@ struct fts5_tokenizer {
);
};
+
/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY 0x0001
#define FTS5_TOKENIZE_PREFIX 0x0002
@@ -13696,7 +14032,7 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
- int iVersion; /* Currently always set to 2 */
+ int iVersion; /* Currently always set to 3 */
/* Create a new tokenizer */
int (*xCreateTokenizer)(
@@ -13723,6 +14059,25 @@ struct fts5_api {
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
+
+ /* APIs below this point are only available if iVersion>=3 */
+
+ /* Create a new tokenizer */
+ int (*xCreateTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void *pUserData,
+ fts5_tokenizer_v2 *pTokenizer,
+ void (*xDestroy)(void*)
+ );
+
+ /* Find an existing tokenizer */
+ int (*xFindTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void **ppUserData,
+ fts5_tokenizer_v2 **ppTokenizer
+ );
};
/*
@@ -13736,6 +14091,7 @@ struct fts5_api {
#endif /* _FTS5_H */
/******** End of fts5.h *********/
+#endif /* SQLITE3_H */
/************** End of sqlite3.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -13781,6 +14137,7 @@ struct fts5_api {
#ifndef SQLITE_MAX_LENGTH
# define SQLITE_MAX_LENGTH 1000000000
#endif
+#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
/*
** This is the maximum number of
@@ -13793,14 +14150,22 @@ struct fts5_api {
** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
** * Terms in the VALUES clause of an INSERT statement
**
-** The hard upper limit here is 32676. Most database people will
+** The hard upper limit here is 32767. Most database people will
** tell you that in a well-normalized database, you usually should
** not have more than a dozen or so columns in any table. And if
** that is the case, there is no point in having more than a few
** dozen values in any of the other situations described above.
+**
+** An index can only have SQLITE_MAX_COLUMN columns from the user
+** point of view, but the underlying b-tree that implements the index
+** might have up to twice as many columns in a WITHOUT ROWID table,
+** since must also store the primary key at the end. Hence the
+** column count for Index is u16 instead of i16.
*/
-#ifndef SQLITE_MAX_COLUMN
+#if !defined(SQLITE_MAX_COLUMN)
# define SQLITE_MAX_COLUMN 2000
+#elif SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN may not exceed 32767
#endif
/*
@@ -13846,9 +14211,13 @@ struct fts5_api {
/*
** The maximum number of arguments to an SQL function.
+**
+** This value has a hard upper limit of 32767 due to storage
+** constraints (it needs to fit inside a i16). We keep it
+** lower than that to prevent abuse.
*/
#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 127
+# define SQLITE_MAX_FUNCTION_ARG 1000
#endif
/*
@@ -14448,6 +14817,7 @@ struct HashElem {
HashElem *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
const char *pKey; /* Key associated with this element */
+ unsigned int h; /* hash for pKey */
};
/*
@@ -14532,132 +14902,132 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_OR 43
#define TK_AND 44
#define TK_IS 45
-#define TK_MATCH 46
-#define TK_LIKE_KW 47
-#define TK_BETWEEN 48
-#define TK_IN 49
-#define TK_ISNULL 50
-#define TK_NOTNULL 51
-#define TK_NE 52
-#define TK_EQ 53
-#define TK_GT 54
-#define TK_LE 55
-#define TK_LT 56
-#define TK_GE 57
-#define TK_ESCAPE 58
-#define TK_ID 59
-#define TK_COLUMNKW 60
-#define TK_DO 61
-#define TK_FOR 62
-#define TK_IGNORE 63
-#define TK_INITIALLY 64
-#define TK_INSTEAD 65
-#define TK_NO 66
-#define TK_KEY 67
-#define TK_OF 68
-#define TK_OFFSET 69
-#define TK_PRAGMA 70
-#define TK_RAISE 71
-#define TK_RECURSIVE 72
-#define TK_REPLACE 73
-#define TK_RESTRICT 74
-#define TK_ROW 75
-#define TK_ROWS 76
-#define TK_TRIGGER 77
-#define TK_VACUUM 78
-#define TK_VIEW 79
-#define TK_VIRTUAL 80
-#define TK_WITH 81
-#define TK_NULLS 82
-#define TK_FIRST 83
-#define TK_LAST 84
-#define TK_CURRENT 85
-#define TK_FOLLOWING 86
-#define TK_PARTITION 87
-#define TK_PRECEDING 88
-#define TK_RANGE 89
-#define TK_UNBOUNDED 90
-#define TK_EXCLUDE 91
-#define TK_GROUPS 92
-#define TK_OTHERS 93
-#define TK_TIES 94
-#define TK_GENERATED 95
-#define TK_ALWAYS 96
-#define TK_MATERIALIZED 97
-#define TK_REINDEX 98
-#define TK_RENAME 99
-#define TK_CTIME_KW 100
-#define TK_ANY 101
-#define TK_BITAND 102
-#define TK_BITOR 103
-#define TK_LSHIFT 104
-#define TK_RSHIFT 105
-#define TK_PLUS 106
-#define TK_MINUS 107
-#define TK_STAR 108
-#define TK_SLASH 109
-#define TK_REM 110
-#define TK_CONCAT 111
-#define TK_PTR 112
-#define TK_COLLATE 113
-#define TK_BITNOT 114
-#define TK_ON 115
-#define TK_INDEXED 116
-#define TK_STRING 117
-#define TK_JOIN_KW 118
-#define TK_CONSTRAINT 119
-#define TK_DEFAULT 120
-#define TK_NULL 121
-#define TK_PRIMARY 122
-#define TK_UNIQUE 123
-#define TK_CHECK 124
-#define TK_REFERENCES 125
-#define TK_AUTOINCR 126
-#define TK_INSERT 127
-#define TK_DELETE 128
-#define TK_UPDATE 129
-#define TK_SET 130
-#define TK_DEFERRABLE 131
-#define TK_FOREIGN 132
-#define TK_DROP 133
-#define TK_UNION 134
-#define TK_ALL 135
-#define TK_EXCEPT 136
-#define TK_INTERSECT 137
-#define TK_SELECT 138
-#define TK_VALUES 139
-#define TK_DISTINCT 140
-#define TK_DOT 141
-#define TK_FROM 142
-#define TK_JOIN 143
-#define TK_USING 144
-#define TK_ORDER 145
-#define TK_GROUP 146
-#define TK_HAVING 147
-#define TK_LIMIT 148
-#define TK_WHERE 149
-#define TK_RETURNING 150
-#define TK_INTO 151
-#define TK_NOTHING 152
-#define TK_FLOAT 153
-#define TK_BLOB 154
-#define TK_INTEGER 155
-#define TK_VARIABLE 156
-#define TK_CASE 157
-#define TK_WHEN 158
-#define TK_THEN 159
-#define TK_ELSE 160
-#define TK_INDEX 161
-#define TK_ALTER 162
-#define TK_ADD 163
-#define TK_WINDOW 164
-#define TK_OVER 165
-#define TK_FILTER 166
-#define TK_COLUMN 167
-#define TK_AGG_FUNCTION 168
-#define TK_AGG_COLUMN 169
-#define TK_TRUEFALSE 170
-#define TK_ISNOT 171
+#define TK_ISNOT 46
+#define TK_MATCH 47
+#define TK_LIKE_KW 48
+#define TK_BETWEEN 49
+#define TK_IN 50
+#define TK_ISNULL 51
+#define TK_NOTNULL 52
+#define TK_NE 53
+#define TK_EQ 54
+#define TK_GT 55
+#define TK_LE 56
+#define TK_LT 57
+#define TK_GE 58
+#define TK_ESCAPE 59
+#define TK_ID 60
+#define TK_COLUMNKW 61
+#define TK_DO 62
+#define TK_FOR 63
+#define TK_IGNORE 64
+#define TK_INITIALLY 65
+#define TK_INSTEAD 66
+#define TK_NO 67
+#define TK_KEY 68
+#define TK_OF 69
+#define TK_OFFSET 70
+#define TK_PRAGMA 71
+#define TK_RAISE 72
+#define TK_RECURSIVE 73
+#define TK_REPLACE 74
+#define TK_RESTRICT 75
+#define TK_ROW 76
+#define TK_ROWS 77
+#define TK_TRIGGER 78
+#define TK_VACUUM 79
+#define TK_VIEW 80
+#define TK_VIRTUAL 81
+#define TK_WITH 82
+#define TK_NULLS 83
+#define TK_FIRST 84
+#define TK_LAST 85
+#define TK_CURRENT 86
+#define TK_FOLLOWING 87
+#define TK_PARTITION 88
+#define TK_PRECEDING 89
+#define TK_RANGE 90
+#define TK_UNBOUNDED 91
+#define TK_EXCLUDE 92
+#define TK_GROUPS 93
+#define TK_OTHERS 94
+#define TK_TIES 95
+#define TK_GENERATED 96
+#define TK_ALWAYS 97
+#define TK_MATERIALIZED 98
+#define TK_REINDEX 99
+#define TK_RENAME 100
+#define TK_CTIME_KW 101
+#define TK_ANY 102
+#define TK_BITAND 103
+#define TK_BITOR 104
+#define TK_LSHIFT 105
+#define TK_RSHIFT 106
+#define TK_PLUS 107
+#define TK_MINUS 108
+#define TK_STAR 109
+#define TK_SLASH 110
+#define TK_REM 111
+#define TK_CONCAT 112
+#define TK_PTR 113
+#define TK_COLLATE 114
+#define TK_BITNOT 115
+#define TK_ON 116
+#define TK_INDEXED 117
+#define TK_STRING 118
+#define TK_JOIN_KW 119
+#define TK_CONSTRAINT 120
+#define TK_DEFAULT 121
+#define TK_NULL 122
+#define TK_PRIMARY 123
+#define TK_UNIQUE 124
+#define TK_CHECK 125
+#define TK_REFERENCES 126
+#define TK_AUTOINCR 127
+#define TK_INSERT 128
+#define TK_DELETE 129
+#define TK_UPDATE 130
+#define TK_SET 131
+#define TK_DEFERRABLE 132
+#define TK_FOREIGN 133
+#define TK_DROP 134
+#define TK_UNION 135
+#define TK_ALL 136
+#define TK_EXCEPT 137
+#define TK_INTERSECT 138
+#define TK_SELECT 139
+#define TK_VALUES 140
+#define TK_DISTINCT 141
+#define TK_DOT 142
+#define TK_FROM 143
+#define TK_JOIN 144
+#define TK_USING 145
+#define TK_ORDER 146
+#define TK_GROUP 147
+#define TK_HAVING 148
+#define TK_LIMIT 149
+#define TK_WHERE 150
+#define TK_RETURNING 151
+#define TK_INTO 152
+#define TK_NOTHING 153
+#define TK_FLOAT 154
+#define TK_BLOB 155
+#define TK_INTEGER 156
+#define TK_VARIABLE 157
+#define TK_CASE 158
+#define TK_WHEN 159
+#define TK_THEN 160
+#define TK_ELSE 161
+#define TK_INDEX 162
+#define TK_ALTER 163
+#define TK_ADD 164
+#define TK_WINDOW 165
+#define TK_OVER 166
+#define TK_FILTER 167
+#define TK_COLUMN 168
+#define TK_AGG_FUNCTION 169
+#define TK_AGG_COLUMN 170
+#define TK_TRUEFALSE 171
#define TK_FUNCTION 172
#define TK_UPLUS 173
#define TK_UMINUS 174
@@ -14671,7 +15041,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_ERROR 182
#define TK_QNUMBER 183
#define TK_SPACE 184
-#define TK_ILLEGAL 185
+#define TK_COMMENT 185
+#define TK_ILLEGAL 186
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -14680,6 +15051,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#include <string.h>
#include <assert.h>
#include <stddef.h>
+#include <ctype.h>
/*
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
@@ -14700,7 +15072,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
# define float sqlite_int64
-# define LONGDOUBLE_TYPE sqlite_int64
+# define fabs(X) ((X)<0?-(X):(X))
+# define sqlite3IsOverflow(X) 0
# ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
# endif
@@ -14805,7 +15178,17 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
** ourselves.
*/
#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+
+/*
+** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
+** to avoid complaints from -fsanitize=strict-bounds.
+*/
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
#endif
/*
@@ -14875,9 +15258,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define INT8_TYPE signed char
# endif
#endif
-#ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
-#endif
typedef sqlite_int64 i64; /* 8-byte signed integer */
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
@@ -14886,6 +15266,11 @@ typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef INT8_TYPE i8; /* 1-byte signed integer */
+/* A bitfield type for use inside of structures. Always follow with :N where
+** N is the number of bits.
+*/
+typedef unsigned bft; /* Bit Field Type */
+
/*
** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
** that can be stored in a u32 without loss of data. The value
@@ -14924,6 +15309,8 @@ typedef u64 tRowcnt;
** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
*/
typedef INT16_TYPE LogEst;
+#define LOGEST_MIN (-32768)
+#define LOGEST_MAX (32767)
/*
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
@@ -15053,6 +15440,14 @@ typedef INT16_TYPE LogEst;
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
/*
+** Macro SMXV(n) return the maximum value that can be held in variable n,
+** assuming n is a signed integer type. UMXV(n) is similar for unsigned
+** integer types.
+*/
+#define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1)
+#define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1)
+
+/*
** Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures.
**
@@ -15194,7 +15589,7 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace;
** 0xFFFF---- Low-level debug messages
**
** 0x00000001 Code generation
-** 0x00000002 Solver
+** 0x00000002 Solver (Use 0x40000 for less detail)
** 0x00000004 Solver costs
** 0x00000008 WhereLoop inserts
**
@@ -15213,6 +15608,8 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace;
**
** 0x00010000 Show more detail when printing WHERE terms
** 0x00020000 Show WHERE terms returned from whereScanNext()
+** 0x00040000 Solver overview messages
+** 0x00080000 Star-query heuristic
*/
@@ -15377,6 +15774,7 @@ typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+typedef struct Subquery Subquery;
typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
@@ -15850,6 +16248,22 @@ typedef struct PgHdr DbPage;
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
+#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL)
+
+/*
+** The argument to this macro is a file descriptor (type sqlite3_file*).
+** Return 0 if it is not open, or non-zero (but not 1) if it is.
+**
+** This is so that expressions can be written as:
+**
+** if( isOpen(pPager->jfd) ){ ...
+**
+** instead of
+**
+** if( pPager->jfd->pMethods ){ ...
+*/
+#define isOpen(pFd) ((pFd)->pMethods!=0)
+
/*
** Flags that make up the mask passed to sqlite3PagerGet().
*/
@@ -16259,6 +16673,9 @@ SQLITE_PRIVATE int sqlite3BtreeCursor(
);
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*);
+#endif
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -16477,6 +16894,20 @@ typedef struct Vdbe Vdbe;
*/
typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
+typedef struct SubrtnSig SubrtnSig;
+
+/*
+** A signature for a reusable subroutine that materializes the RHS of
+** an IN operator.
+*/
+struct SubrtnSig {
+ int selId; /* SELECT-id for the SELECT statement on the RHS */
+ u8 bComplete; /* True if fully coded and available for reusable */
+ char *zAff; /* Affinity of the overall IN expression */
+ int iTable; /* Ephemeral table generated by the subroutine */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+};
/*
** A single instruction of the virtual machine has an opcode
@@ -16505,6 +16936,7 @@ struct VdbeOp {
u32 *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
Table *pTab; /* Used when p4type is P4_TABLE */
+ SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
@@ -16572,6 +17004,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
+#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -16663,16 +17096,16 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
#define OP_Program 48 /* jump0 */
#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
-#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
-#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
-#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
-#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
-#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
-#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
-#define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfPos 50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
+#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
+#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
+#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
+#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
+#define OP_Ge 58 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
+#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */
#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
#define OP_IncrVacuum 62 /* jump */
@@ -16715,23 +17148,23 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_ReadCookie 99
#define OP_SetCookie 100
#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-#define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 102 /* synopsis: root=P2 iDb=P3 */
+#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight 106 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_OpenDup 115
+#define OP_OpenDup 114
+#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
-#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */
+#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */
#define OP_SorterOpen 119
#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
@@ -16766,8 +17199,8 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_LoadAnalysis 150
#define OP_DropTable 151
#define OP_DropIndex 152
-#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_DropTrigger 154
+#define OP_DropTrigger 153
+#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
#define OP_IntegrityCk 155
#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
#define OP_Param 157
@@ -16823,20 +17256,20 @@ typedef struct VdbeOpList VdbeOpList;
/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\
/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
-/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
+/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
+/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\
/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
-/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\
+/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
+/* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\
/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
+/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\
/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
@@ -16857,7 +17290,7 @@ typedef struct VdbeOpList VdbeOpList;
** Additional non-public SQLITE_PREPARE_* flags
*/
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
-#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
+#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
/*
** Prototypes for the VDBE interface. See comments on the implementation
@@ -16990,8 +17423,8 @@ SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
#endif
-/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
-** each VDBE opcode.
+/* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra
+** comments on each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
@@ -17572,47 +18005,11 @@ struct FuncDefHash {
};
#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
-#if defined(SQLITE_USER_AUTHENTICATION)
-# warning "The SQLITE_USER_AUTHENTICATION extension is deprecated. \
- See ext/userauth/user-auth.txt for details."
-#endif
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** Information held in the "sqlite3" database connection object and used
-** to manage user authentication.
-*/
-typedef struct sqlite3_userauth sqlite3_userauth;
-struct sqlite3_userauth {
- u8 authLevel; /* Current authentication level */
- int nAuthPW; /* Size of the zAuthPW in bytes */
- char *zAuthPW; /* Password used to authenticate */
- char *zAuthUser; /* User name used to authenticate */
-};
-
-/* Allowed values for sqlite3_userauth.authLevel */
-#define UAUTH_Unknown 0 /* Authentication not yet checked */
-#define UAUTH_Fail 1 /* User authentication failed */
-#define UAUTH_User 2 /* Authenticated as a normal user */
-#define UAUTH_Admin 3 /* Authenticated as an administrator */
-
-/* Functions used only by user authorization logic */
-SQLITE_PRIVATE int sqlite3UserAuthTable(const char*);
-SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
-SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*);
-SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
-
-#endif /* SQLITE_USER_AUTHENTICATION */
-
/*
** typedef for the authorization callback function.
*/
-#ifdef SQLITE_USER_AUTHENTICATION
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*, const char*);
-#else
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*);
-#endif
+typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
+ const char*);
#ifndef SQLITE_OMIT_DEPRECATED
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
@@ -17750,6 +18147,10 @@ struct sqlite3 {
Savepoint *pSavepoint; /* List of active savepoints */
int nAnalysisLimit; /* Number of index rows to ANALYZE */
int busyTimeout; /* Busy handler timeout, in msec */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int setlkTimeout; /* Blocking lock timeout, in msec. -1 -> inf. */
+ int setlkFlags; /* Flags passed to setlk_timeout() */
+#endif
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
@@ -17773,9 +18174,6 @@ struct sqlite3 {
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- sqlite3_userauth auth; /* User authentication information */
-#endif
};
/*
@@ -17839,6 +18237,9 @@ struct sqlite3 {
#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */
#define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */
#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */
+#define SQLITE_AttachCreate HI(0x00010) /* ATTACH allowed to create new dbs */
+#define SQLITE_AttachWrite HI(0x00020) /* ATTACH allowed to open for write */
+#define SQLITE_Comments HI(0x00040) /* Enable SQL comments */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
@@ -17897,6 +18298,8 @@ struct sqlite3 {
#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */
+#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */
+#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
@@ -17933,7 +18336,7 @@ struct sqlite3 {
** field is used by per-connection app-def functions.
*/
struct FuncDef {
- i8 nArg; /* Number of arguments. -1 means unlimited */
+ i16 nArg; /* Number of arguments. -1 means unlimited */
u32 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
@@ -18302,6 +18705,7 @@ struct CollSeq {
#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
#define SQLITE_AFF_REAL 0x45 /* 'E' */
#define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */
+#define SQLITE_AFF_DEFER 0x58 /* 'X' - defer computation until later */
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@@ -18426,6 +18830,7 @@ struct Table {
} u;
Trigger *pTrigger; /* List of triggers on this object */
Schema *pSchema; /* Schema that contains this table */
+ u8 aHx[16]; /* Column aHt[K%sizeof(aHt)] might have hash K */
};
/*
@@ -18559,9 +18964,13 @@ struct FKey {
struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
int iFrom; /* Index of column in pFrom */
char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
- } aCol[1]; /* One entry for each of nCol columns */
+ } aCol[FLEXARRAY]; /* One entry for each of nCol columns */
};
+/* The size (in bytes) of an FKey object holding N columns. The answer
+** does NOT include space to hold the zTo name. */
+#define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap))
+
/*
** SQLite supports many different ways to resolve a constraint
** error. ROLLBACK processing means that a constraint violation
@@ -18623,9 +19032,12 @@ struct KeyInfo {
u16 nAllField; /* Total columns, including key plus others */
sqlite3 *db; /* The database connection */
u8 *aSortFlags; /* Sort order for each column. */
- CollSeq *aColl[1]; /* Collating sequence for each term of the key */
+ CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
};
+/* The size (in bytes) of a KeyInfo object with up to N fields */
+#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
+
/*
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
*/
@@ -18745,7 +19157,7 @@ struct Index {
Pgno tnum; /* DB Page containing root of this index */
LogEst szIdxRow; /* Estimated average row size in bytes */
u16 nKeyCol; /* Number of columns forming the key */
- u16 nColumn; /* Number of columns stored in the index */
+ u16 nColumn; /* Nr columns in btree. Can be 2*Table.nCol */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
@@ -18754,9 +19166,9 @@ struct Index {
unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
- unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
+ unsigned bIdxRowid:1; /* One or more of the index keys is the ROWID */
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
unsigned bHasExpr:1; /* Index contains an expression, either a literal
** expression, or a reference to a VIRTUAL column */
@@ -18844,7 +19256,7 @@ struct AggInfo {
** from source tables rather than from accumulators */
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
** than the source table */
- u16 nSortingColumn; /* Number of columns in the sorting index */
+ u32 nSortingColumn; /* Number of columns in the sorting index */
int sortingIdx; /* Cursor number of the sorting index */
int sortingIdxPTab; /* Cursor number of pseudo-table */
int iFirstReg; /* First register in range for aCol[] and aFunc[] */
@@ -18853,8 +19265,8 @@ struct AggInfo {
Table *pTab; /* Source table */
Expr *pCExpr; /* The original expression */
int iTable; /* Cursor number of the source table */
- i16 iColumn; /* Column number within the source table */
- i16 iSorterColumn; /* Column number in the sorting index */
+ int iColumn; /* Column number within the source table */
+ int iSorterColumn; /* Column number in the sorting index */
} *aCol;
int nColumn; /* Number of used entries in aCol[] */
int nAccumulator; /* Number of columns that show through to the output.
@@ -18884,9 +19296,15 @@ struct AggInfo {
** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
** The assert()s that are part of this macro verify that constraint.
*/
+#ifndef NDEBUG
#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I))
#define AggInfoFuncReg(A,I) \
(assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))
+#else
+#define AggInfoColumnReg(A,I) ((A)->iFirstReg+(I))
+#define AggInfoFuncReg(A,I) \
+ ((A)->iFirstReg+(A)->nColumn+(I))
+#endif
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
@@ -19067,7 +19485,7 @@ struct Expr {
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
- /* 0x80000000 // Available */
+#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
@@ -19077,10 +19495,10 @@ struct Expr {
/* Macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
-#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
-#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
-#define ExprSetProperty(E,P) (E)->flags|=(P)
-#define ExprClearProperty(E,P) (E)->flags&=~(P)
+#define ExprHasProperty(E,P) (((E)->flags&(u32)(P))!=0)
+#define ExprHasAllProperty(E,P) (((E)->flags&(u32)(P))==(u32)(P))
+#define ExprSetProperty(E,P) (E)->flags|=(u32)(P)
+#define ExprClearProperty(E,P) (E)->flags&=~(u32)(P)
#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)
#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0)
@@ -19192,9 +19610,14 @@ struct ExprList {
int iConstExprReg; /* Register in which Expr value is cached. Used only
** by Parse.pConstExpr */
} u;
- } a[1]; /* One slot for each expression in the list */
+ } a[FLEXARRAY]; /* One slot for each expression in the list */
};
+/* The size (in bytes) of an ExprList object that is big enough to hold
+** as many as N expressions. */
+#define SZ_EXPRLIST(N) \
+ (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item))
+
/*
** Allowed values for Expr.a.eEName
*/
@@ -19220,16 +19643,14 @@ struct ExprList {
*/
struct IdList {
int nId; /* Number of identifiers on the list */
- u8 eU4; /* Which element of a.u4 is valid */
struct IdList_item {
char *zName; /* Name of the identifier */
- union {
- int idx; /* Index in some Table.aCol[] of a column named zName */
- Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */
- } u4;
- } a[1];
+ } a[FLEXARRAY];
};
+/* The size (in bytes) of an IdList object that can hold up to N IDs. */
+#define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item))
+
/*
** Allowed values for IdList.eType, which determines which value of the a.u4
** is valid.
@@ -19239,6 +19660,16 @@ struct IdList {
#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */
/*
+** Details of the implementation of a subquery.
+*/
+struct Subquery {
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to initialize a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
+};
+
+/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
**
@@ -19250,29 +19681,40 @@ struct IdList {
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
**
-** Union member validity:
+** Aggressive use of "union" helps keep the size of the object small. This
+** has been shown to boost performance, in addition to saving memory.
+** Access to union elements is gated by the following rules which should
+** always be checked, either by an if-statement or by an assert().
**
-** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
-** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
+** Field Only access if this is true
+** --------------- -----------------------------------
+** u1.zIndexedBy fg.isIndexedBy
+** u1.pFuncArg fg.isTabFunc
** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
**
-** u2.pIBIndex fg.isIndexedBy && !fg.isCte
-** u2.pCteUse fg.isCte && !fg.isIndexedBy
+** u2.pIBIndex fg.isIndexedBy
+** u2.pCteUse fg.isCte
+**
+** u3.pOn !fg.isUsing
+** u3.pUsing fg.isUsing
+**
+** u4.zDatabase !fg.fixedSchema && !fg.isSubquery
+** u4.pSchema fg.fixedSchema
+** u4.pSubq fg.isSubquery
+**
+** See also the sqlite3SrcListDelete() routine for assert() statements that
+** check invariants on the fields of this object, especially the flags
+** inside the fg struct.
*/
struct SrcItem {
- Schema *pSchema; /* Schema to which this item is fixed */
- char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int addrFillSub; /* Address of subroutine to manifest a subquery */
- int regReturn; /* Register holding return address of addrFillSub */
- int regResult; /* Registers holding results of a co-routine */
+ Table *pSTab; /* Table object for zName. Mnemonic: Srcitem-TABle */
struct {
u8 jointype; /* Type of join between this table and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
+ unsigned isSubquery :1; /* True if this term is a subquery */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned isMaterialized:1; /* This is a materialized view */
@@ -19286,12 +19728,10 @@ struct SrcItem {
unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
unsigned rowidUsed :1; /* The ROWID of this table is referenced */
+ unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */
+ unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
- union {
- Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
- IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
- } u3;
Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
@@ -19302,6 +19742,15 @@ struct SrcItem {
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */
} u2;
+ union {
+ Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
+ IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
+ } u3;
+ union {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ Subquery *pSubq; /* Description of a subquery */
+ } u4;
};
/*
@@ -19321,11 +19770,19 @@ struct OnOrUsing {
**
*/
struct SrcList {
- int nSrc; /* Number of tables or subqueries in the FROM clause */
- u32 nAlloc; /* Number of entries allocated in a[] below */
- SrcItem a[1]; /* One entry for each identifier on the list */
+ int nSrc; /* Number of tables or subqueries in the FROM clause */
+ u32 nAlloc; /* Number of entries allocated in a[] below */
+ SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */
};
+/* Size (in bytes) of a SrcList object that can hold as many as N
+** SrcItem objects. */
+#define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem))
+
+/* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a
+** special case of SZ_SRCITEM(1) that comes up often. */
+#define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem))
+
/*
** Permitted values of the SrcList.a.jointype field
*/
@@ -19433,7 +19890,7 @@ struct NameContext {
#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x002000 /* True if a function or subquery seen */
+/* 0x002000 // available for reuse */
#define NC_AllowWin 0x004000 /* Window functions are allowed here */
#define NC_HasWin 0x008000 /* One or more window functions seen */
#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
@@ -19561,8 +20018,10 @@ struct Select {
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated 0x20000000 /* True if references the outer context */
-/* True if S exists and has SF_NestedFrom */
-#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
+/* True if SrcItem X is a subquery that has SF_NestedFrom */
+#define IsNestedFrom(X) \
+ ((X)->fg.isSubquery && \
+ ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -19592,7 +20051,11 @@ struct Select {
** SRT_Set The result must be a single column. Store each
** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
-** results. Used to implement "IN (SELECT ...)".
+** results. if pDest->iSDParm2 is positive, then it is
+** a register holding a Bloom filter for the IN operator
+** that should be populated in addition to the
+** pDest->iSDParm table. This SRT is used to
+** implement "IN (SELECT ...)".
**
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
** the result there. The cursor is left open after
@@ -19788,24 +20251,32 @@ struct Parse {
char *zErrMsg; /* An error message */
Vdbe *pVdbe; /* An engine for executing database bytecode */
int rc; /* Return code from execution */
- u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
- u8 checkSchema; /* Causes schema cookie check after an error */
+ LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
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 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
- u8 bHasWith; /* True if statement contains WITH */
+ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
+ 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
#ifdef SQLITE_DEBUG
u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */
+ 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 */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -19820,12 +20291,9 @@ struct Parse {
ExprList *pConstExpr;/* Constant expressions */
IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */
- Token constraintName;/* Name of the constraint currently being parsed */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
- int regRowid; /* Register holding rowid of CREATE TABLE entry */
- int regRoot; /* Register holding root page number for new objects */
- int nMaxArg; /* Max args passed to user function by sub-program */
+ int nMaxArg; /* Max args to xUpdate and xFilter vtab methods */
int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
@@ -19839,17 +20307,6 @@ struct Parse {
Table *pTriggerTab; /* Table triggers are being coded for */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
- union {
- int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
- Returning *pReturning; /* The RETURNING clause */
- } u1;
- u32 oldmask; /* Mask of old.* columns referenced */
- u32 newmask; /* Mask of new.* columns referenced */
- LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
- 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 */
/**************************************************************************
** Fields above must be initialized to zero. The fields that follow,
@@ -19861,6 +20318,19 @@ struct Parse {
int aTempReg[8]; /* Holding area for temporary registers */
Parse *pOuterParse; /* Outer Parse object when nested */
Token sNameToken; /* Token with unqualified schema object name */
+ u32 oldmask; /* Mask of old.* columns referenced */
+ u32 newmask; /* Mask of new.* columns referenced */
+ union {
+ struct { /* These fields available when isCreate is true */
+ int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
+ int regRowid; /* Register holding rowid of CREATE TABLE entry */
+ int regRoot; /* Register holding root page for new objects */
+ Token constraintName; /* Name of the constraint currently being parsed */
+ } cr;
+ struct { /* These fields available to all other statements */
+ Returning *pReturning; /* The RETURNING clause */
+ } d;
+ } u1;
/************************************************************************
** Above is constant between recursions. Below is reset before and after
@@ -19878,9 +20348,7 @@ struct Parse {
int nVtabLock; /* Number of virtual tables to lock */
#endif
int nHeight; /* Expression tree height of current sub-select */
-#ifndef SQLITE_OMIT_EXPLAIN
int addrExplain; /* Address of current OP_Explain opcode */
-#endif
VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
@@ -20095,7 +20563,7 @@ struct Returning {
};
/*
-** An objected used to accumulate the text of a string where we
+** An object used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct sqlite3_str {
@@ -20109,7 +20577,7 @@ struct sqlite3_str {
};
#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
-#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
+#define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */
#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
@@ -20187,7 +20655,6 @@ struct Sqlite3Config {
u8 bUseCis; /* Use covering indices for full-scans */
u8 bSmallMalloc; /* Avoid large memory allocations if true */
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
- u8 bUseLongDouble; /* Make use of long double */
#ifdef SQLITE_DEBUG
u8 bJsonSelfcheck; /* Double-check JSON parsing */
#endif
@@ -20379,9 +20846,13 @@ struct With {
int nCte; /* Number of CTEs in the WITH clause */
int bView; /* Belongs to the outermost Select of a view */
With *pOuter; /* Containing WITH clause, or NULL */
- Cte a[1]; /* For each CTE in the WITH clause.... */
+ Cte a[FLEXARRAY]; /* For each CTE in the WITH clause.... */
};
+/* The size (in bytes) of a With object that can hold as many
+** as N different CTEs. */
+#define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte))
+
/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation. (The query flattener or other parser tree
@@ -20410,9 +20881,13 @@ struct DbClientData {
DbClientData *pNext; /* Next in a linked list */
void *pData; /* The data */
void (*xDestructor)(void*); /* Destructor. Might be NULL */
- char zName[1]; /* Name of this client data. MUST BE LAST */
+ char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */
};
+/* The size (in bytes) of a DbClientData object that can has a name
+** that is N bytes long, including the zero-terminator. */
+#define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N))
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
@@ -20563,15 +21038,6 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
#endif
/*
-** The ctype.h header is needed for non-ASCII systems. It is also
-** needed by FTS3 when FTS3 is included in the amalgamation.
-*/
-#if !defined(SQLITE_ASCII) || \
- (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
-# include <ctype.h>
-#endif
-
-/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
** sqlite versions only work for ASCII characters, regardless of locale.
@@ -20864,7 +21330,7 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char);
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int);
SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
-SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16);
+SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index*, int);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
@@ -20949,6 +21415,9 @@ SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3*,Subquery*);
+SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3*,SrcItem*);
+SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(Parse*, SrcItem*, Select*, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
@@ -20959,7 +21428,7 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
-SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
+SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
@@ -20998,6 +21467,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
@@ -21060,7 +21530,7 @@ SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,i
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
#endif
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*);
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
@@ -21094,7 +21564,8 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const Select*,int);
SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*);
SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
-SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*);
+SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*,int);
+SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char*, u32);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void);
@@ -21188,7 +21659,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
#ifndef SQLITE_OMIT_UTF16
-SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar);
#endif
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
@@ -21959,6 +22430,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_BUG_COMPATIBLE_20160819
"BUG_COMPATIBLE_20160819",
#endif
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
+ "BUG_COMPATIBLE_20250510",
+#endif
#ifdef SQLITE_CASE_SENSITIVE_LIKE
"CASE_SENSITIVE_LIKE",
#endif
@@ -22174,6 +22648,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
"ENABLE_OFFSET_SQL_FUNC",
#endif
+#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
+ "ENABLE_ORDERED_SET_AGGREGATES",
+#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
@@ -22192,6 +22669,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_SESSION
"ENABLE_SESSION",
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ "ENABLE_SETLK_TIMEOUT",
+#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
"ENABLE_SNAPSHOT",
#endif
@@ -22246,6 +22726,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_EXTRA_INIT
"EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
#endif
+#ifdef SQLITE_EXTRA_INIT_MUTEXED
+ "EXTRA_INIT_MUTEXED=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT_MUTEXED),
+#endif
#ifdef SQLITE_EXTRA_SHUTDOWN
"EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
#endif
@@ -22643,9 +23126,6 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_UNTESTABLE
"UNTESTABLE",
#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- "USER_AUTHENTICATION",
-#endif
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
@@ -22921,7 +23401,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
- sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
#ifdef SQLITE_DEBUG
0, /* bJsonSelfcheck */
#endif
@@ -23234,12 +23713,19 @@ struct VdbeCursor {
#endif
VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
- /* 2*nField extra array elements allocated for aType[], beyond the one
- ** static element declared in the structure. nField total array slots for
- ** aType[] and nField+1 array slots for aOffset[] */
- u32 aType[1]; /* Type values record decode. MUST BE LAST */
+ /* Space is allocated for aType to hold at least 2*nField+1 entries:
+ ** nField slots for aType[] and nField+1 array slots for aOffset[] */
+ u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */
};
+/*
+** The size (in bytes) of a VdbeCursor object that has an nField value of N
+** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple
+** of 8.
+*/
+#define SZ_VDBECURSOR(N) \
+ (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64))
+
/* Return true if P is a null-only cursor
*/
#define IsNullCursor(P) \
@@ -23345,6 +23831,7 @@ struct sqlite3_value {
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */
+ u8 bScopy; /* The pScopyFrom of some other Mem *might* point here */
#endif
};
@@ -23494,14 +23981,17 @@ struct sqlite3_context {
int isError; /* Error code returned by the function. */
u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
- u8 argc; /* Number of arguments */
- sqlite3_value *argv[1]; /* Argument set */
+ u16 argc; /* Number of arguments */
+ sqlite3_value *argv[FLEXARRAY]; /* Argument set */
};
-/* A bitfield type for use inside of structures. Always follow with :N where
-** N is the number of bits.
+/*
+** The size (in bytes) of an sqlite3_context object that holds N
+** argv[] arguments.
*/
-typedef unsigned bft; /* Bit Field Type */
+#define SZ_CONTEXT(N) \
+ (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*))
+
/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
@@ -23562,7 +24052,7 @@ struct Vdbe {
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
Mem *aMem; /* The memory locations */
- Mem **apArg; /* Arguments to currently executing user function */
+ Mem **apArg; /* Arguments xUpdate and xFilter vtab methods */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
Mem *aVar; /* Values for the OP_Variable opcode. */
@@ -23582,6 +24072,7 @@ struct Vdbe {
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
+ int napArg; /* Size of the apArg[] array */
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
u16 nResAlloc; /* Column slots allocated to aColName[] */
@@ -23634,16 +24125,19 @@ struct PreUpdate {
VdbeCursor *pCsr; /* Cursor to read old values from */
int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
u8 *aRecord; /* old.* database record */
- KeyInfo keyinfo;
+ KeyInfo *pKeyinfo; /* Key information */
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
+ Mem oldipk; /* Memory cell holding "old" IPK value */
Mem *aNew; /* Array of new.* values */
Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
+ sqlite3_value **apDflt; /* Array of default values, if required */
+ u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */
};
/*
@@ -24010,8 +24504,9 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
nInit += countLookasideSlots(db->lookaside.pSmallInit);
nFree += countLookasideSlots(db->lookaside.pSmallFree);
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
- if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
- return db->lookaside.nSlot - (nInit+nFree);
+ assert( db->lookaside.nSlot >= nInit+nFree );
+ if( pHighwater ) *pHighwater = (int)(db->lookaside.nSlot - nInit);
+ return (int)(db->lookaside.nSlot - (nInit+nFree));
}
/*
@@ -24064,7 +24559,7 @@ SQLITE_API int sqlite3_db_status(
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
*pCurrent = 0;
- *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
+ *pHighwater = (int)db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT];
if( resetFlag ){
db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
}
@@ -24441,6 +24936,9 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
zDate++;
}
ms /= rScale;
+ /* Truncate to avoid problems with sub-milliseconds
+ ** rounding. https://sqlite.org/forum/forumpost/766a2c9231 */
+ if( ms>0.999 ) ms = 0.999;
}
}else{
s = 0;
@@ -24490,8 +24988,8 @@ static void computeJD(DateTime *p){
Y--;
M += 12;
}
- A = Y/100;
- B = 2 - A + (A/4);
+ A = (Y+4800)/100;
+ B = 38 - A + (A/4);
X1 = 36525*(Y+4716)/100;
X2 = 306001*(M+1)/10000;
p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
@@ -24675,7 +25173,7 @@ static int validJulianDay(sqlite3_int64 iJD){
** Compute the Year, Month, and Day from the julian day number.
*/
static void computeYMD(DateTime *p){
- int Z, A, B, C, D, E, X1;
+ int Z, alpha, A, B, C, D, E, X1;
if( p->validYMD ) return;
if( !p->validJD ){
p->Y = 2000;
@@ -24686,8 +25184,8 @@ static void computeYMD(DateTime *p){
return;
}else{
Z = (int)((p->iJD + 43200000)/86400000);
- A = (int)((Z - 1867216.25)/36524.25);
- A = Z + 1 + A - (A/4);
+ alpha = (int)((Z + 32044.75)/36524.25) - 52;
+ A = Z + 1 + alpha - ((alpha+100)/4) + 25;
B = A + 1524;
C = (int)((B - 122.1)/365.25);
D = (36525*(C&32767))/100;
@@ -24886,8 +25384,8 @@ static const struct {
/* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
/* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
/* 3 */ { 3, "day", 5373485.0, 86400.0 },
- /* 4 */ { 5, "month", 176546.0, 30.0*86400.0 },
- /* 5 */ { 4, "year", 14713.0, 365.0*86400.0 },
+ /* 4 */ { 5, "month", 176546.0, 2592000.0 },
+ /* 5 */ { 4, "year", 14713.0, 31536000.0 },
};
/*
@@ -25573,7 +26071,7 @@ static int daysAfterMonday(DateTime *pDate){
** In other words, return the day of the week according
** to this code:
**
-** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday
+** 0=Sunday, 1=Monday, 2=Tuesday, ..., 6=Saturday
*/
static int daysAfterSunday(DateTime *pDate){
assert( pDate->validJD );
@@ -25648,7 +26146,7 @@ static void strftimeFunc(
}
case 'f': { /* Fractional seconds. (Non-standard) */
double s = x.s;
- if( s>59.999 ) s = 59.999;
+ if( NEVER(s>59.999) ) s = 59.999;
sqlite3_str_appendf(&sRes, "%06.3f", s);
break;
}
@@ -29089,16 +29587,29 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
+**
+** Because these routines raise false-positive alerts in TSAN, disable
+** them (make them always return 1) when compiling with TSAN.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
-#endif
+#endif /* NDEBUG */
#endif /* !defined(SQLITE_MUTEX_OMIT) */
@@ -29769,6 +30280,8 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
#ifdef __CYGWIN__
# include <sys/cygwin.h>
+# include <sys/stat.h> /* amalgamator: dontcache */
+# include <unistd.h> /* amalgamator: dontcache */
# include <errno.h> /* amalgamator: dontcache */
#endif
@@ -31163,17 +31676,17 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
#define etPERCENT 7 /* Percent symbol. %% */
#define etCHARX 8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
-#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
-#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
- NULL pointers replaced by SQL NULL. %Q */
-#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCITEM 12 /* a pointer to a SrcItem */
-#define etPOINTER 13 /* The %p conversion */
-#define etSQLESCAPE3 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_q 9 /* Strings with '\'' doubled. %q */
+#define etESCAPE_Q 10 /* Strings with '\'' doubled and enclosed in '',
+ NULL pointers replaced by SQL NULL. %Q */
+#define etTOKEN 11 /* a pointer to a Token structure */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
+#define etPOINTER 13 /* The %p conversion */
+#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 etINVALID 17 /* Any unrecognized conversion type */
+#define etINVALID 17 /* Any unrecognized conversion type */
/*
@@ -31212,9 +31725,9 @@ static const et_info fmtinfo[] = {
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 },
- { 'q', 0, 4, etSQLESCAPE, 0, 0 },
- { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
- { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
+ { 'q', 0, 4, etESCAPE_q, 0, 0 },
+ { 'Q', 0, 4, etESCAPE_Q, 0, 0 },
+ { 'w', 0, 4, etESCAPE_w, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etDECIMAL, 0, 0 },
@@ -31811,25 +32324,7 @@ SQLITE_API void sqlite3_str_vappendf(
}
}else{
unsigned int ch = va_arg(ap,unsigned int);
- if( ch<0x00080 ){
- buf[0] = ch & 0xff;
- length = 1;
- }else if( ch<0x00800 ){
- buf[0] = 0xc0 + (u8)((ch>>6)&0x1f);
- buf[1] = 0x80 + (u8)(ch & 0x3f);
- length = 2;
- }else if( ch<0x10000 ){
- buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
- buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[2] = 0x80 + (u8)(ch & 0x3f);
- length = 3;
- }else{
- buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
- buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
- buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[3] = 0x80 + (u8)(ch & 0x3f);
- length = 4;
- }
+ length = sqlite3AppendOneUtf8Character(buf, ch);
}
if( precision>1 ){
i64 nPrior = 1;
@@ -31909,22 +32404,31 @@ SQLITE_API void sqlite3_str_vappendf(
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
}
break;
- case etSQLESCAPE: /* %q: Escape ' characters */
- case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
- case etSQLESCAPE3: { /* %w: Escape " characters */
+ case etESCAPE_q: /* %q: Escape ' characters */
+ case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */
+ case etESCAPE_w: { /* %w: Escape " characters */
i64 i, j, k, n;
- int needQuote, isnull;
+ int needQuote = 0;
char ch;
- char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg;
+ char q;
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
- isnull = escarg==0;
- if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
+ if( escarg==0 ){
+ escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)");
+ }else if( xtype==etESCAPE_Q ){
+ needQuote = 1;
+ }
+ if( xtype==etESCAPE_w ){
+ q = '"';
+ flag_alternateform = 0;
+ }else{
+ q = '\'';
+ }
/* For %q, %Q, and %w, the precision is the number of bytes (or
** characters if the ! flags is present) to use from the input.
** Because of the extra quoting characters inserted, the number
@@ -31937,7 +32441,30 @@ SQLITE_API void sqlite3_str_vappendf(
while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
}
}
- needQuote = !isnull && xtype==etSQLESCAPE2;
+ if( flag_alternateform ){
+ /* For %#q, do unistr()-style backslash escapes for
+ ** 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;
+ for(k=0; k<i; k++){
+ if( escarg[k]=='\\' ){
+ nBack++;
+ }else if( ((u8*)escarg)[k]<=0x1f ){
+ nCtrl++;
+ }
+ }
+ if( nCtrl || xtype==etESCAPE_q ){
+ n += nBack + 5*nCtrl;
+ if( xtype==etESCAPE_Q ){
+ n += 10;
+ needQuote = 2;
+ }
+ }else{
+ flag_alternateform = 0;
+ }
+ }
n += i + 3;
if( n>etBUFSIZE ){
bufpt = zExtra = printfTempBuf(pAccum, n);
@@ -31946,13 +32473,41 @@ SQLITE_API void sqlite3_str_vappendf(
bufpt = buf;
}
j = 0;
- if( needQuote ) bufpt[j++] = q;
+ if( needQuote ){
+ if( needQuote==2 ){
+ memcpy(&bufpt[j], "unistr('", 8);
+ j += 8;
+ }else{
+ bufpt[j++] = '\'';
+ }
+ }
k = i;
- for(i=0; i<k; i++){
- bufpt[j++] = ch = escarg[i];
- if( ch==q ) bufpt[j++] = ch;
+ if( flag_alternateform ){
+ for(i=0; i<k; i++){
+ bufpt[j++] = ch = escarg[i];
+ if( ch==q ){
+ bufpt[j++] = ch;
+ }else if( ch=='\\' ){
+ bufpt[j++] = '\\';
+ }else if( ((unsigned char)ch)<=0x1f ){
+ bufpt[j-1] = '\\';
+ bufpt[j++] = 'u';
+ bufpt[j++] = '0';
+ bufpt[j++] = '0';
+ bufpt[j++] = ch>=0x10 ? '1' : '0';
+ bufpt[j++] = "0123456789abcdef"[ch&0xf];
+ }
+ }
+ }else{
+ for(i=0; i<k; i++){
+ bufpt[j++] = ch = escarg[i];
+ if( ch==q ) bufpt[j++] = ch;
+ }
+ }
+ if( needQuote ){
+ bufpt[j++] = '\'';
+ if( needQuote==2 ) bufpt[j++] = ')';
}
- if( needQuote ) bufpt[j++] = q;
bufpt[j] = 0;
length = j;
goto adjust_width_for_utf8;
@@ -31986,16 +32541,19 @@ SQLITE_API void sqlite3_str_vappendf(
if( pItem->zAlias && !flag_altform2 ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
}else if( pItem->zName ){
- if( pItem->zDatabase ){
- sqlite3_str_appendall(pAccum, pItem->zDatabase);
+ if( pItem->fg.fixedSchema==0
+ && pItem->fg.isSubquery==0
+ && pItem->u4.zDatabase!=0
+ ){
+ sqlite3_str_appendall(pAccum, pItem->u4.zDatabase);
sqlite3_str_append(pAccum, ".", 1);
}
sqlite3_str_appendall(pAccum, pItem->zName);
}else if( pItem->zAlias ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
- }else{
- Select *pSel = pItem->pSelect;
- assert( pSel!=0 ); /* Because of tag-20240424-1 */
+ }else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */
+ Select *pSel = pItem->u4.pSubq->pSelect;
+ assert( pSel!=0 );
if( pSel->selFlags & SF_NestedFrom ){
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
}else if( pSel->selFlags & SF_MultiValue ){
@@ -32073,6 +32631,7 @@ SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExp
pExpr = pExpr->pLeft;
}
if( pExpr==0 ) return;
+ if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
db->errByteOffset = pExpr->w.iOfst;
}
@@ -32191,7 +32750,7 @@ SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){
static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
char *zText;
assert( p->mxAlloc>0 && !isMalloced(p) );
- zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+ zText = sqlite3DbMallocRaw(p->db, 1+(u64)p->nChar );
if( zText ){
memcpy(zText, p->zText, p->nChar+1);
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
@@ -32436,6 +32995,15 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
return zBuf;
}
+/* Maximum size of an sqlite3_log() message. */
+#if defined(SQLITE_MAX_LOG_MESSAGE)
+ /* Leave the definition as supplied */
+#elif SQLITE_PRINT_BUF_SIZE*10>10000
+# define SQLITE_MAX_LOG_MESSAGE 10000
+#else
+# define SQLITE_MAX_LOG_MESSAGE (SQLITE_PRINT_BUF_SIZE*10)
+#endif
+
/*
** This is the routine that actually formats the sqlite3_log() message.
** We house it in a separate routine from sqlite3_log() to avoid using
@@ -32452,7 +33020,7 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
*/
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
- char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
+ char zMsg[SQLITE_MAX_LOG_MESSAGE]; /* Complete log message */
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
sqlite3_str_vappendf(&acc, zFormat, ap);
@@ -32777,9 +33345,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
- if( pItem->pTab ){
+ if( pItem->pSTab ){
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
- pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab,
+ pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab,
pItem->colUsed,
pItem->fg.rowidUsed ? "+rowid" : "");
}
@@ -32799,10 +33367,13 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
sqlite3_str_appendf(&x, " DDL");
}
if( pItem->fg.isCte ){
- sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
+ static const char *aMat[] = {",MAT", "", ",NO-MAT"};
+ sqlite3_str_appendf(&x, " CteUse=%d%s",
+ pItem->u2.pCteUse->nUse,
+ aMat[pItem->u2.pCteUse->eM10d]);
}
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
- sqlite3_str_appendf(&x, " ON");
+ sqlite3_str_appendf(&x, " isOn");
}
if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
@@ -32810,25 +33381,27 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte");
if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom");
+ if( pItem->fg.fixedSchema ) sqlite3_str_appendf(&x, " fixedSchema");
+ if( pItem->fg.hadSchema ) sqlite3_str_appendf(&x, " hadSchema");
+ if( pItem->fg.isSubquery ) sqlite3_str_appendf(&x, " isSubquery");
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
n = 0;
- if( pItem->pSelect ) n++;
+ if( pItem->fg.isSubquery ) n++;
if( pItem->fg.isTabFunc ) n++;
if( pItem->fg.isUsing ) n++;
if( pItem->fg.isUsing ){
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
}
- if( pItem->pSelect ){
- sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
- if( pItem->pTab ){
- Table *pTab = pItem->pTab;
+ if( pItem->fg.isSubquery ){
+ assert( n==1 );
+ if( pItem->pSTab ){
+ Table *pTab = pItem->pSTab;
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
}
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
- sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
- sqlite3TreeViewPop(&pView);
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
+ sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);
}
if( pItem->fg.isTabFunc ){
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
@@ -32870,7 +33443,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
n = 1000;
}else{
n = 0;
- if( p->pSrc && p->pSrc->nSrc ) n++;
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
@@ -32896,7 +33469,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewPop(&pView);
}
#endif
- if( p->pSrc && p->pSrc->nSrc ){
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){
sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, p->pSrc);
@@ -33404,7 +33977,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case OE_Ignore: zType = "ignore"; break;
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
- sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
+ sqlite3TreeViewLine(pView, "RAISE %s", zType);
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif
@@ -33484,9 +34058,10 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
+ u8 sortFlags = pList->a[i].fg.sortFlags;
char *zName = pList->a[i].zEName;
int moreToFollow = i<pList->nExpr - 1;
- if( j || zName ){
+ if( j || zName || sortFlags ){
sqlite3TreeViewPush(&pView, moreToFollow);
moreToFollow = 0;
sqlite3TreeViewLine(pView, 0);
@@ -33507,13 +34082,18 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
}
}
if( j ){
- fprintf(stdout, "iOrderByCol=%d", j);
+ fprintf(stdout, "iOrderByCol=%d ", j);
+ }
+ if( sortFlags & KEYINFO_ORDER_DESC ){
+ fprintf(stdout, "DESC ");
+ }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){
+ fprintf(stdout, "NULLS-LAST");
}
fprintf(stdout, "\n");
fflush(stdout);
}
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
- if( j || zName ){
+ if( j || zName || sortFlags ){
sqlite3TreeViewPop(&pView);
}
}
@@ -33550,21 +34130,7 @@ SQLITE_PRIVATE void sqlite3TreeViewBareIdList(
if( zName==0 ) zName = "(null)";
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewLine(pView, 0);
- if( pList->eU4==EU4_NONE ){
- fprintf(stdout, "%s\n", zName);
- }else if( pList->eU4==EU4_IDX ){
- fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
- }else{
- assert( pList->eU4==EU4_EXPR );
- if( pList->a[i].u4.pExpr==0 ){
- fprintf(stdout, "%s (pExpr=NULL)\n", zName);
- }else{
- fprintf(stdout, "%s\n", zName);
- sqlite3TreeViewPush(&pView, i<pList->nId-1);
- sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
- sqlite3TreeViewPop(&pView);
- }
- }
+ fprintf(stdout, "%s\n", zName);
sqlite3TreeViewPop(&pView);
}
}
@@ -33874,6 +34440,10 @@ SQLITE_PRIVATE void sqlite3TreeViewTrigger(
** accessible to the debugging, and to avoid warnings about unused
** functions. But these routines only exist in debugging builds, so they
** do not contaminate the interface.
+**
+** See Also:
+**
+** sqlite3ShowWhereTerm() in where.c
*/
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
@@ -34446,6 +35016,35 @@ static const unsigned char sqlite3Utf8Trans1[] = {
}
/*
+** Write a single UTF8 character whose value is v into the
+** buffer starting at zOut. zOut must be sized to hold at
+** least four bytes. Return the number of bytes needed
+** to encode the new character.
+*/
+SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
+ if( v<0x00080 ){
+ zOut[0] = (u8)(v & 0xff);
+ return 1;
+ }
+ if( v<0x00800 ){
+ zOut[0] = 0xc0 + (u8)((v>>6) & 0x1f);
+ zOut[1] = 0x80 + (u8)(v & 0x3f);
+ return 2;
+ }
+ if( v<0x10000 ){
+ zOut[0] = 0xe0 + (u8)((v>>12) & 0x0f);
+ zOut[1] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[2] = 0x80 + (u8)(v & 0x3f);
+ return 3;
+ }
+ zOut[0] = 0xf0 + (u8)((v>>18) & 0x07);
+ zOut[1] = 0x80 + (u8)((v>>12) & 0x3f);
+ zOut[2] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[3] = 0x80 + (u8)(v & 0x3f);
+ return 4;
+}
+
+/*
** Translate a single UTF-8 character. Return the unicode value.
**
** During translation, assume that the byte that zTerm points
@@ -34476,7 +35075,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ while( zIn<zTerm && (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
@@ -34854,20 +35453,22 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
}
/*
-** zIn is a UTF-16 encoded unicode string at least nChar characters long.
+** zIn is a UTF-16 encoded unicode string at least nByte bytes long.
** Return the number of bytes in the first nChar unicode characters
-** in pZ. nChar must be non-negative.
+** in pZ. nChar must be non-negative. Surrogate pairs count as a single
+** character.
*/
-SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nByte, int nChar){
int c;
unsigned char const *z = zIn;
+ unsigned char const *zEnd = &z[nByte-1];
int n = 0;
if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++;
- while( n<nChar ){
+ while( n<nChar && z<=zEnd ){
c = z[0];
z += 2;
- if( c>=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
+ if( c>=0xd8 && c<0xdc && z<=zEnd && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
n++;
}
return (int)(z-(unsigned char const *)zIn)
@@ -35448,6 +36049,8 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
int eValid = 1; /* True exponent is either not used or is well-formed */
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
+ u64 s2; /* round-tripped significand */
+ double rr[2];
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
@@ -35550,7 +36153,7 @@ do_atof_calc:
e = (e*esign) + d;
/* Try to adjust the exponent to make it smaller */
- while( e>0 && s<(LARGEST_UINT64/10) ){
+ while( e>0 && s<((LARGEST_UINT64-0x7ff)/10) ){
s *= 10;
e--;
}
@@ -35559,68 +36162,52 @@ do_atof_calc:
e++;
}
- if( e==0 ){
- *pResult = s;
- }else if( sqlite3Config.bUseLongDouble ){
- LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
- if( e>0 ){
- while( e>=100 ){ e-=100; r *= 1.0e+100L; }
- while( e>=10 ){ e-=10; r *= 1.0e+10L; }
- while( e>=1 ){ e-=1; r *= 1.0e+01L; }
- }else{
- while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
- while( e<=-10 ){ e+=10; r *= 1.0e-10L; }
- while( e<=-1 ){ e+=1; r *= 1.0e-01L; }
- }
- assert( r>=0.0 );
- if( r>+1.7976931348623157081452742373e+308L ){
-#ifdef INFINITY
- *pResult = +INFINITY;
-#else
- *pResult = 1.0e308*10.0;
+ rr[0] = (double)s;
+ assert( sizeof(s2)==sizeof(rr[0]) );
+#ifdef SQLITE_DEBUG
+ rr[1] = 18446744073709549568.0;
+ memcpy(&s2, &rr[1], sizeof(s2));
+ assert( s2==0x43efffffffffffffLL );
#endif
- }else{
- *pResult = (double)r;
- }
- }else{
- double rr[2];
- u64 s2;
- rr[0] = (double)s;
+ /* Largest double that can be safely converted to u64
+ ** vvvvvvvvvvvvvvvvvvvvvv */
+ if( rr[0]<=18446744073709549568.0 ){
s2 = (u64)rr[0];
-#if defined(_MSC_VER) && _MSC_VER<1700
- if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
-#endif
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
- if( e>0 ){
- while( e>=100 ){
- e -= 100;
- dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
- }
- while( e>=10 ){
- e -= 10;
- dekkerMul2(rr, 1.0e+10, 0.0);
- }
- while( e>=1 ){
- e -= 1;
- dekkerMul2(rr, 1.0e+01, 0.0);
- }
- }else{
- while( e<=-100 ){
- e += 100;
- dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
- }
- while( e<=-10 ){
- e += 10;
- dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
- }
- while( e<=-1 ){
- e += 1;
- dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
- }
+ }else{
+ rr[1] = 0.0;
+ }
+ assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */
+
+ if( e>0 ){
+ while( e>=100 ){
+ e -= 100;
+ dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+ }
+ while( e>=10 ){
+ e -= 10;
+ dekkerMul2(rr, 1.0e+10, 0.0);
+ }
+ while( e>=1 ){
+ e -= 1;
+ dekkerMul2(rr, 1.0e+01, 0.0);
+ }
+ }else{
+ while( e<=-100 ){
+ e += 100;
+ dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+ }
+ while( e<=-10 ){
+ e += 10;
+ dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+ }
+ while( e<=-1 ){
+ e += 1;
+ dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
}
- *pResult = rr[0]+rr[1];
- if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
}
+ *pResult = rr[0]+rr[1];
+ if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
if( sign<0 ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
@@ -35924,10 +36511,13 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){
** Decode a floating-point value into an approximate decimal
** representation.
**
-** Round the decimal representation to n significant digits if
-** n is positive. Or round to -n signficant digits after the
-** decimal point if n is negative. No rounding is performed if
-** n is zero.
+** If iRound<=0 then round to -iRound significant digits to the
+** the left of the decimal point, or to a maximum of mxRound total
+** significant digits.
+**
+** If iRound>0 round to min(iRound,mxRound) significant digits total.
+**
+** mxRound must be positive.
**
** The significant digits of the decimal representation are
** stored in p->z[] which is a often (but not always) a pointer
@@ -35938,8 +36528,11 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
int i;
u64 v;
int e, exp = 0;
+ double rr[2];
+
p->isSpecial = 0;
p->z = p->zBuf;
+ assert( mxRound>0 );
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
** NaN. */
@@ -35966,62 +36559,45 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
/* Multiply r by powers of ten until it lands somewhere in between
** 1.0e+19 and 1.0e+17.
+ **
+ ** Use Dekker-style double-double computation to increase the
+ ** precision.
+ **
+ ** The error terms on constants like 1.0e+100 computed using the
+ ** decimal extension, for example as follows:
+ **
+ ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
*/
- if( sqlite3Config.bUseLongDouble ){
- LONGDOUBLE_TYPE rr = r;
- if( rr>=1.0e+19 ){
- while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
- while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; }
- while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; }
- }else{
- while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; }
- while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; }
- while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; }
+ rr[0] = r;
+ rr[1] = 0.0;
+ if( rr[0]>9.223372036854774784e+18 ){
+ while( rr[0]>9.223372036854774784e+118 ){
+ exp += 100;
+ dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+ }
+ while( rr[0]>9.223372036854774784e+28 ){
+ exp += 10;
+ dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+ }
+ while( rr[0]>9.223372036854774784e+18 ){
+ exp += 1;
+ dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
}
- v = (u64)rr;
}else{
- /* If high-precision floating point is not available using "long double",
- ** then use Dekker-style double-double computation to increase the
- ** precision.
- **
- ** The error terms on constants like 1.0e+100 computed using the
- ** decimal extension, for example as follows:
- **
- ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
- */
- double rr[2];
- rr[0] = r;
- rr[1] = 0.0;
- if( rr[0]>9.223372036854774784e+18 ){
- while( rr[0]>9.223372036854774784e+118 ){
- exp += 100;
- dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
- }
- while( rr[0]>9.223372036854774784e+28 ){
- exp += 10;
- dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
- }
- while( rr[0]>9.223372036854774784e+18 ){
- exp += 1;
- dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
- }
- }else{
- while( rr[0]<9.223372036854774784e-83 ){
- exp -= 100;
- dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
- }
- while( rr[0]<9.223372036854774784e+07 ){
- exp -= 10;
- dekkerMul2(rr, 1.0e+10, 0.0);
- }
- while( rr[0]<9.22337203685477478e+17 ){
- exp -= 1;
- dekkerMul2(rr, 1.0e+01, 0.0);
- }
+ while( rr[0]<9.223372036854774784e-83 ){
+ exp -= 100;
+ dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+ }
+ while( rr[0]<9.223372036854774784e+07 ){
+ exp -= 10;
+ dekkerMul2(rr, 1.0e+10, 0.0);
+ }
+ while( rr[0]<9.22337203685477478e+17 ){
+ exp -= 1;
+ dekkerMul2(rr, 1.0e+01, 0.0);
}
- v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
}
-
+ v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
/* Extract significant digits. */
i = sizeof(p->zBuf)-1;
@@ -36064,7 +36640,11 @@ 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) );
- while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
+ assert( p->n>0 );
+ while( p->z[p->n-1]=='0' ){
+ p->n--;
+ assert( p->n>0 );
+ }
}
/*
@@ -36569,7 +37149,7 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
}
/*
-** Compute the absolute value of a 32-bit signed integer, of possible. Or
+** Compute the absolute value of a 32-bit signed integer, if possible. Or
** if the integer has a value of -2147483648, return +2147483647
*/
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
@@ -36792,104 +37372,6 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam
return 0;
}
-/*
-** High-resolution hardware timer used for debugging and testing only.
-*/
-#if defined(VDBE_PROFILE) \
- || defined(SQLITE_PERFORMANCE_TRACE) \
- || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-/************** Include hwtime.h in the middle of util.c *********************/
-/************** Begin file hwtime.h ******************************************/
-/*
-** 2008 May 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on Pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if !defined(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlite3Hwtime() routine.
- **
- ** sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in util.c ***********************/
-#endif
-
/************** End of util.c ************************************************/
/************** Begin file hash.c ********************************************/
/*
@@ -36948,12 +37430,19 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
*/
static unsigned int strHash(const char *z){
unsigned int h = 0;
- unsigned char c;
- while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
+ while( z[0] ){ /*OPTIMIZATION-IF-TRUE*/
/* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
** 0x9e3779b1 is 2654435761 which is the closest prime number to
- ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
- h += sqlite3UpperToLower[c];
+ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2.
+ **
+ ** Only bits 0xdf for ASCII and bits 0xbf for EBCDIC each octet are
+ ** hashed since the omitted bits determine the upper/lower case difference.
+ */
+#ifdef SQLITE_EBCDIC
+ h += 0xbf & (unsigned char)*(z++);
+#else
+ h += 0xdf & (unsigned char)*(z++);
+#endif
h *= 0x9e3779b1;
}
return h;
@@ -37026,9 +37515,8 @@ static int rehash(Hash *pH, unsigned int new_size){
pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
memset(new_ht, 0, new_size*sizeof(struct _ht));
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- unsigned int h = strHash(elem->pKey) % new_size;
next_elem = elem->next;
- insertElement(pH, &new_ht[h], elem);
+ insertElement(pH, &new_ht[elem->h % new_size], elem);
}
return 1;
}
@@ -37046,23 +37534,22 @@ static HashElem *findElementWithHash(
HashElem *elem; /* Used to loop thru the element list */
unsigned int count; /* Number of elements left to test */
unsigned int h; /* The computed hash */
- static HashElem nullElement = { 0, 0, 0, 0 };
+ static HashElem nullElement = { 0, 0, 0, 0, 0 };
+ h = strHash(pKey);
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry;
- h = strHash(pKey) % pH->htsize;
- pEntry = &pH->ht[h];
+ pEntry = &pH->ht[h % pH->htsize];
elem = pEntry->chain;
count = pEntry->count;
}else{
- h = 0;
elem = pH->first;
count = pH->count;
}
if( pHash ) *pHash = h;
while( count ){
assert( elem!=0 );
- if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
+ if( h==elem->h && sqlite3StrICmp(elem->pKey,pKey)==0 ){
return elem;
}
elem = elem->next;
@@ -37074,10 +37561,9 @@ static HashElem *findElementWithHash(
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
-static void removeElementGivenHash(
+static void removeElement(
Hash *pH, /* The pH containing "elem" */
- HashElem* elem, /* The element to be removed from the pH */
- unsigned int h /* Hash value for the element */
+ HashElem *elem /* The element to be removed from the pH */
){
struct _ht *pEntry;
if( elem->prev ){
@@ -37089,7 +37575,7 @@ static void removeElementGivenHash(
elem->next->prev = elem->prev;
}
if( pH->ht ){
- pEntry = &pH->ht[h];
+ pEntry = &pH->ht[elem->h % pH->htsize];
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
@@ -37140,7 +37626,7 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
if( elem->data ){
void *old_data = elem->data;
if( data==0 ){
- removeElementGivenHash(pH,elem,h);
+ removeElement(pH,elem);
}else{
elem->data = data;
elem->pKey = pKey;
@@ -37151,15 +37637,13 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
new_elem->pKey = pKey;
+ new_elem->h = h;
new_elem->data = data;
pH->count++;
- if( pH->count>=10 && pH->count > 2*pH->htsize ){
- if( rehash(pH, pH->count*2) ){
- assert( pH->htsize>0 );
- h = strHash(pKey) % pH->htsize;
- }
+ if( pH->count>=5 && pH->count > 2*pH->htsize ){
+ rehash(pH, pH->count*3);
}
- insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem);
+ insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem);
return 0;
}
@@ -37227,16 +37711,16 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
/* 48 */ "Program" OpHelp(""),
/* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
- /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
- /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
- /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
- /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
- /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
- /* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
- /* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
- /* 58 */ "ElseEq" OpHelp(""),
- /* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
+ /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
+ /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
+ /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
+ /* 57 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
+ /* 58 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
+ /* 59 */ "ElseEq" OpHelp(""),
/* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
/* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
/* 62 */ "IncrVacuum" OpHelp(""),
@@ -37279,23 +37763,23 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 99 */ "ReadCookie" OpHelp(""),
/* 100 */ "SetCookie" OpHelp(""),
/* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
- /* 105 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
- /* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 102 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
+ /* 106 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
+ /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
/* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 115 */ "OpenDup" OpHelp(""),
+ /* 114 */ "OpenDup" OpHelp(""),
+ /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
/* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 117 */ "String8" OpHelp("r[P2]='P4'"),
- /* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 118 */ "String8" OpHelp("r[P2]='P4'"),
/* 119 */ "SorterOpen" OpHelp(""),
/* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
/* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
@@ -37330,8 +37814,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 150 */ "LoadAnalysis" OpHelp(""),
/* 151 */ "DropTable" OpHelp(""),
/* 152 */ "DropIndex" OpHelp(""),
- /* 153 */ "Real" OpHelp("r[P2]=P4"),
- /* 154 */ "DropTrigger" OpHelp(""),
+ /* 153 */ "DropTrigger" OpHelp(""),
+ /* 154 */ "Real" OpHelp("r[P2]=P4"),
/* 155 */ "IntegrityCk" OpHelp(""),
/* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
/* 157 */ "Param" OpHelp(""),
@@ -38571,7 +39055,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){
# endif
#else /* !SQLITE_WASI */
# ifndef HAVE_FCHMOD
-# define HAVE_FCHMOD
+# define HAVE_FCHMOD 1
# endif
#endif /* SQLITE_WASI */
@@ -38642,6 +39126,7 @@ struct unixFile {
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
unsigned iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect; /* True to block for SHARED locks */
#endif
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID */
@@ -38680,7 +39165,7 @@ static pid_t randomnessPid = 0;
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-#ifndef SQLITE_DISABLE_DIRSYNC
+#if !defined(SQLITE_DISABLE_DIRSYNC) && !defined(_AIX)
# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
#else
# define UNIXFILE_DIRSYNC 0x00
@@ -40022,7 +40507,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
if( pInode->bProcessLock==0 ){
struct flock lock;
- assert( pInode->nLock==0 );
+ /* assert( pInode->nLock==0 ); <-- Not true if unix-excl READONLY used */
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
@@ -40035,6 +40520,13 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
rc = 0;
}
}else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK
+ && pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE
+ ){
+ rc = osFcntl(pFile->h, F_SETLKW, pLock);
+ }else
+#endif
rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
}
return rc;
@@ -40637,26 +41129,22 @@ static int nolockClose(sqlite3_file *id) {
/*
** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-**
-** In dotfile locking, either a lock exists or it does not. So in this
-** variation of CheckReservedLock(), *pResOut is set to true if any lock
-** is held on the file and false if the file is unlocked.
+** file by this or any other process. If the caller holds a SHARED
+** or greater lock when it is called, then it is assumed that no other
+** client may hold RESERVED. Or, if the caller holds no lock, then it
+** is assumed another client holds RESERVED if the lock-file exists.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
unixFile *pFile = (unixFile*)id;
-
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
- assert( pFile );
- reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
- *pResOut = reserved;
- return rc;
+ if( pFile->eFileLock>=SHARED_LOCK ){
+ *pResOut = 0;
+ }else{
+ *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
+ }
+ OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
+ return SQLITE_OK;
}
/*
@@ -40826,54 +41314,33 @@ static int robust_flock(int fd, int op){
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+#ifdef SQLITE_DEBUG
unixFile *pFile = (unixFile*)id;
+#else
+ UNUSED_PARAMETER(id);
+#endif
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
+ assert( pFile->eFileLock<=SHARED_LOCK );
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- /* attempt to get the lock */
- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
- /* got the lock, unlock it */
- lrc = robust_flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- } else {
- int tErrno = errno;
- reserved = 1;
- /* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(lrc) ){
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
+ /* The flock VFS only ever takes exclusive locks (see function flockLock).
+ ** Therefore, if this connection is holding any lock at all, no other
+ ** connection may be holding a RESERVED lock. So set *pResOut to 0
+ ** in this case.
+ **
+ ** Or, this connection may be holding no lock. In that case, set *pResOut to
+ ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the
+ ** db in order to roll the hot journal back. If there is another connection
+ ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to
+ ** the user. With other VFS, we try to avoid this, in order to allow a reader
+ ** to proceed while a writer is preparing its transaction. But that won't
+ ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is
+ ** not a problem in this case. */
+ *pResOut = 0;
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & 0xff) == SQLITE_IOERR ){
- rc = SQLITE_OK;
- reserved=1;
- }
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- *pResOut = reserved;
- return rc;
+ return SQLITE_OK;
}
/*
@@ -42345,7 +42812,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
static int unixFcntlExternalReader(unixFile*, int*);
#endif
@@ -42370,6 +42837,11 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+ case SQLITE_FCNTL_NULL_IO: {
+ osClose(pFile->h);
+ pFile->h = -1;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
@@ -42416,8 +42888,9 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
- pFile->iBusyTimeout = *(int*)pArg;
+ pFile->iBusyTimeout = iNew<0 ? 0x7FFFFFFF : (unsigned)iNew;
#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
pFile->iBusyTimeout = !!(*(int*)pArg);
#else
@@ -42426,7 +42899,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = iOld;
return SQLITE_OK;
}
-#endif
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
@@ -42472,7 +42950,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
case SQLITE_FCNTL_EXTERNAL_READER: {
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
#else
*(int*)pArg = 0;
@@ -42511,6 +42989,7 @@ static void setDeviceCharacteristics(unixFile *pFd){
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
+ pFd->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ;
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
@@ -42561,7 +43040,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -42569,7 +43048,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -42645,7 +43124,7 @@ static int unixGetpagesize(void){
#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
/*
** Object used to represent an shared memory buffer.
@@ -43398,21 +43877,20 @@ static int unixShmLock(
/* Check that, if this to be a blocking lock, no locks that occur later
** in the following list than the lock being obtained are already held:
**
- ** 1. Checkpointer lock (ofst==1).
- ** 2. Write lock (ofst==0).
- ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
+ ** 1. Recovery lock (ofst==2).
+ ** 2. Checkpointer lock (ofst==1).
+ ** 3. Write lock (ofst==0).
+ ** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
**
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held.
- **
- ** It is not permitted to block on the RECOVER lock.
*/
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
- (ofst!=2) /* not RECOVER */
+ (ofst!=2 || lockMask==0)
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<<ofst))
@@ -45217,7 +45695,7 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
/* Almost all modern unix systems support nanosleep(). But if you are
** compiling for one of the rare exceptions, you can use
- ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if
+ ** -DHAVE_NANOSLEEP=0 (perhaps in conjunction with -DHAVE_USLEEP if
** usleep() is available) in order to bypass the use of nanosleep() */
nanosleep(&sp, NULL);
@@ -46938,8 +47416,18 @@ struct winFile {
sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ DWORD iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect;
+#endif
};
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+# define winFileBusyTimeout(pDbFd) pDbFd->iBusyTimeout
+#else
+# define winFileBusyTimeout(pDbFd) 0
+#endif
+
/*
** The winVfsAppData structure is used for the pAppData member for all of the
** Win32 VFS variants.
@@ -47258,7 +47746,7 @@ static struct win_syscall {
{ "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
#endif
-#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(const FILETIME*, \
LPFILETIME))aSyscall[11].pCurrent)
#if SQLITE_OS_WINCE
@@ -47267,7 +47755,7 @@ static struct win_syscall {
{ "FileTimeToSystemTime", (SYSCALL)0, 0 },
#endif
-#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+#define osFileTimeToSystemTime ((BOOL(WINAPI*)(const FILETIME*, \
LPSYSTEMTIME))aSyscall[12].pCurrent)
{ "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
@@ -47373,6 +47861,12 @@ static struct win_syscall {
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
LPWSTR*))aSyscall[25].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[26].pCurrent)
@@ -47541,7 +48035,7 @@ static struct win_syscall {
{ "LockFile", (SYSCALL)0, 0 },
#endif
-#ifndef osLockFile
+#if !defined(osLockFile) && defined(SQLITE_WIN32_HAS_ANSI)
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[47].pCurrent)
#endif
@@ -47605,7 +48099,7 @@ static struct win_syscall {
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
-#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
+#define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \
LPFILETIME))aSyscall[56].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
@@ -47614,7 +48108,7 @@ static struct win_syscall {
{ "UnlockFile", (SYSCALL)0, 0 },
#endif
-#ifndef osUnlockFile
+#if !defined(osUnlockFile) && defined(SQLITE_WIN32_HAS_ANSI)
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[57].pCurrent)
#endif
@@ -47655,11 +48149,13 @@ static struct win_syscall {
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
DWORD,DWORD))aSyscall[62].pCurrent)
-#if !SQLITE_OS_WINRT
+/*
+** 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 },
-#else
- { "WaitForSingleObject", (SYSCALL)0, 0 },
-#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
DWORD))aSyscall[63].pCurrent)
@@ -47806,6 +48302,97 @@ static struct win_syscall {
#define osFlushViewOfFile \
((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].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[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)
+
+#ifndef _WIN32
+ { "getenv", (SYSCALL)getenv, 0 },
+#else
+ { "getenv", (SYSCALL)0, 0 },
+#endif
+
+#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent)
+
+#ifndef _WIN32
+ { "getcwd", (SYSCALL)getcwd, 0 },
+#else
+ { "getcwd", (SYSCALL)0, 0 },
+#endif
+
+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].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)
+
+#ifndef _WIN32
+ { "lstat", (SYSCALL)lstat, 0 },
+#else
+ { "lstat", (SYSCALL)0, 0 },
+#endif
+
+#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent)
+
+#ifndef _WIN32
+ { "__errno", (SYSCALL)__errno, 0 },
+#else
+ { "__errno", (SYSCALL)0, 0 },
+#endif
+
+#define osErrno (*((int*(*)(void))aSyscall[87].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)
+
}; /* End of the overrideable system calls */
/*
@@ -47979,6 +48566,7 @@ SQLITE_API int sqlite3_win32_reset_heap(){
}
#endif /* SQLITE_WIN32_MALLOC */
+#ifdef _WIN32
/*
** This function outputs the specified (ANSI) string to the Win32 debugger
** (if available).
@@ -48021,6 +48609,7 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
}
#endif
}
+#endif /* _WIN32 */
/*
** The following routine suspends the current thread for at least ms
@@ -48104,7 +48693,9 @@ SQLITE_API int sqlite3_win32_is_nt(void){
}
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
+ 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
@@ -48319,6 +48910,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
}
#endif /* SQLITE_WIN32_MALLOC */
+#ifdef _WIN32
/*
** Convert a UTF-8 string to Microsoft Unicode.
**
@@ -48344,6 +48936,7 @@ static LPWSTR winUtf8ToUnicode(const char *zText){
}
return zWideText;
}
+#endif /* _WIN32 */
/*
** Convert a Microsoft Unicode string to UTF-8.
@@ -48378,28 +48971,29 @@ static char *winUnicodeToUtf8(LPCWSTR zWideText){
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){
- int nByte;
+ int nWideChar;
LPWSTR zMbcsText;
int codepage = useAnsi ? CP_ACP : CP_OEMCP;
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
- 0)*sizeof(WCHAR);
- if( nByte==0 ){
+ nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
+ 0);
+ if( nWideChar==0 ){
return 0;
}
- zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) );
+ zMbcsText = sqlite3MallocZero( nWideChar*sizeof(WCHAR) );
if( zMbcsText==0 ){
return 0;
}
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
- nByte);
- if( nByte==0 ){
+ nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
+ nWideChar);
+ if( nWideChar==0 ){
sqlite3_free(zMbcsText);
zMbcsText = 0;
}
return zMbcsText;
}
+#ifdef _WIN32
/*
** Convert a Microsoft Unicode string to a multi-byte character string,
** using the ANSI or OEM code page.
@@ -48427,6 +49021,7 @@ static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){
}
return zText;
}
+#endif /* _WIN32 */
/*
** Convert a multi-byte character string to UTF-8.
@@ -48446,6 +49041,7 @@ static char *winMbcsToUtf8(const char *zText, int useAnsi){
return zTextUtf8;
}
+#ifdef _WIN32
/*
** Convert a UTF-8 string to a multi-byte character string.
**
@@ -48495,6 +49091,7 @@ 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.
@@ -48512,6 +49109,7 @@ 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.
*/
@@ -48636,6 +49234,7 @@ SQLITE_API int sqlite3_win32_set_directory(
){
return sqlite3_win32_set_directory16(type, zValue);
}
+#endif /* _WIN32 */
/*
** The return value of winGetLastErrorMsg
@@ -49184,14 +49783,99 @@ static BOOL winLockFile(
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
}
/*
+** Lock a region of nByte bytes starting at offset offset of file hFile.
+** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock
+** otherwise. If nMs is greater than zero and the lock cannot be obtained
+** immediately, block for that many ms before giving up.
+**
+** This function returns SQLITE_OK if the lock is obtained successfully. If
+** some other process holds the lock, SQLITE_BUSY is returned if nMs==0, or
+** SQLITE_BUSY_TIMEOUT otherwise. Or, if an error occurs, SQLITE_IOERR.
+*/
+static int winHandleLockTimeout(
+ HANDLE hFile,
+ DWORD offset,
+ DWORD nByte,
+ int bExcl,
+ DWORD nMs
+){
+ DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0);
+ int rc = SQLITE_OK;
+ BOOL ret;
+
+ 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;
+ }
+#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 ){
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ rc = SQLITE_BUSY_TIMEOUT;
+#else
+ 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);
+ }
+
+ osCloseHandle(ovlp.hEvent);
+#endif
+ }
+
+ if( rc==SQLITE_OK && !ret ){
+ rc = SQLITE_BUSY;
+ }
+ return rc;
+}
+
+/*
** Unlock a file region.
*/
static BOOL winUnlockFile(
@@ -49215,13 +49899,23 @@ static BOOL winUnlockFile(
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
}
+/*
+** Remove an nByte lock starting at offset iOff from HANDLE h.
+*/
+static int winHandleUnlock(HANDLE h, int iOff, int nByte){
+ BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0);
+ return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK);
+}
+
/*****************************************************************************
** The next group of routines implement the I/O methods specified
** by the sqlite3_io_methods object.
@@ -49235,66 +49929,70 @@ static BOOL winUnlockFile(
#endif
/*
-** Move the current position of the file handle passed as the first
-** argument to offset iOffset within the file. If successful, return 0.
-** Otherwise, set pFile->lastErrno and return non-zero.
+** Seek the file handle h to offset nByte of the file.
+**
+** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite
+** error code.
*/
-static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
+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() */
- DWORD lastErrno; /* Value returned by GetLastError() */
-
- OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
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().
- */
- dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
-
- if( (dwRet==INVALID_SET_FILE_POINTER
- && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ ** GetLastError(). */
+ if( dwRet==INVALID_SET_FILE_POINTER ){
+ DWORD lastErrno = osGetLastError();
+ if( lastErrno!=NO_ERROR ){
+ rc = SQLITE_IOERR_SEEK;
+ }
}
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
#else
- /*
- ** Same as above, except that this implementation works for WinRT.
- */
-
+ /* This implementation works for WinRT. */
LARGE_INTEGER x; /* The new offset */
BOOL bRet; /* Value returned by SetFilePointerEx() */
x.QuadPart = iOffset;
- bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
+ bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN);
if(!bRet){
- pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ rc = SQLITE_IOERR_SEEK;
}
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
#endif
+
+ OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc)));
+ return rc;
}
+/*
+** Move the current position of the file handle passed as the first
+** argument to offset iOffset within the file. If successful, return 0.
+** Otherwise, set pFile->lastErrno and return non-zero.
+*/
+static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
+ int rc;
+
+ rc = winHandleSeek(pFile->h, iOffset);
+ if( rc!=SQLITE_OK ){
+ pFile->lastErrno = osGetLastError();
+ winLogError(rc, pFile->lastErrno, "winSeekFile", pFile->zPath);
+ }
+ return rc;
+}
+
+
#if SQLITE_MAX_MMAP_SIZE>0
/* Forward references to VFS helper methods used for memory mapped files */
static int winMapfile(winFile*, sqlite3_int64);
@@ -49555,6 +50253,60 @@ static int winWrite(
}
/*
+** Truncate the file opened by handle h to nByte bytes in size.
+*/
+static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){
+ int rc = SQLITE_OK; /* Return code */
+ rc = winHandleSeek(h, nByte);
+ if( rc==SQLITE_OK ){
+ if( 0==osSetEndOfFile(h) ){
+ rc = SQLITE_IOERR_TRUNCATE;
+ }
+ }
+ return rc;
+}
+
+/*
+** Determine the size in bytes of the file opened by the handle passed as
+** the first argument.
+*/
+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;
+
+ assert( pnByte );
+ lowerBits = osGetFileSize(h, &upperBits);
+ *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits;
+ if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){
+ rc = SQLITE_IOERR_FSTAT;
+ }
+#endif
+
+ return rc;
+}
+
+/*
+** Close the handle passed as the only argument.
+*/
+static void winHandleClose(HANDLE h){
+ if( h!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(h);
+ }
+}
+
+/*
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
@@ -49809,8 +50561,9 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
** Different API routines are called depending on whether or not this
** is Win9x or WinNT.
*/
-static int winGetReadLock(winFile *pFile){
+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
@@ -49820,7 +50573,7 @@ static int winGetReadLock(winFile *pFile){
*/
res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
#else
- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0,
SHARED_SIZE, 0);
#endif
}
@@ -49829,7 +50582,7 @@ static int winGetReadLock(winFile *pFile){
int lk;
sqlite3_randomness(sizeof(lk), &lk);
pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask,
SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
}
#endif
@@ -49924,46 +50677,62 @@ static int winLock(sqlite3_file *id, int locktype){
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
- /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
+ /* Lock the PENDING_LOCK byte if we need to acquire an EXCLUSIVE lock or
** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
** the PENDING_LOCK byte is temporary.
*/
newLocktype = pFile->locktype;
- if( pFile->locktype==NO_LOCK
- || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
){
int cnt = 3;
- while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
- PENDING_BYTE, 0, 1, 0))==0 ){
+
+ /* Flags for the LockFileEx() call. This should be an exclusive lock if
+ ** this call is to obtain EXCLUSIVE, or a shared lock if this call is to
+ ** obtain SHARED. */
+ int flags = LOCKFILE_FAIL_IMMEDIATELY;
+ if( locktype==EXCLUSIVE_LOCK ){
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+ while( cnt>0 ){
/* Try 3 times to get the pending lock. This is needed to work
** around problems caused by indexing and/or anti-virus software on
** Windows systems.
+ **
** If you are using this code as a model for alternative VFSes, do not
- ** copy this retry logic. It is a hack intended for Windows only.
- */
+ ** copy this retry logic. It is a hack intended for Windows only. */
+ res = winLockFile(&pFile->h, flags, PENDING_BYTE, 0, 1, 0);
+ if( res ) break;
+
lastErrno = osGetLastError();
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
- pFile->h, cnt, res));
+ pFile->h, cnt, res
+ ));
+
if( lastErrno==ERROR_INVALID_HANDLE ){
pFile->lastErrno = lastErrno;
rc = SQLITE_IOERR_LOCK;
OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
- pFile->h, cnt, sqlite3ErrName(rc)));
+ pFile->h, cnt, sqlite3ErrName(rc)
+ ));
return rc;
}
- if( cnt ) sqlite3_win32_sleep(1);
+
+ cnt--;
+ if( cnt>0 ) sqlite3_win32_sleep(1);
}
gotPendingLock = res;
- if( !res ){
- lastErrno = osGetLastError();
- }
}
/* Acquire a shared lock
*/
if( locktype==SHARED_LOCK && res ){
assert( pFile->locktype==NO_LOCK );
- res = winGetReadLock(pFile);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ res = winGetReadLock(pFile, pFile->bBlockOnConnect);
+#else
+ res = winGetReadLock(pFile, 0);
+#endif
if( res ){
newLocktype = SHARED_LOCK;
}else{
@@ -50001,7 +50770,7 @@ static int winLock(sqlite3_file *id, int locktype){
newLocktype = EXCLUSIVE_LOCK;
}else{
lastErrno = osGetLastError();
- winGetReadLock(pFile);
+ winGetReadLock(pFile, 0);
}
}
@@ -50081,7 +50850,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
+ if( locktype==SHARED_LOCK && !winGetReadLock(pFile, 0) ){
/* This should never happen. We should always be able to
** reacquire the read lock */
rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
@@ -50250,6 +51019,11 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
#endif
+ case SQLITE_FCNTL_NULL_IO: {
+ (void)osCloseHandle(pFile->h);
+ pFile->h = NULL;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = 0;
int rc = winGetTempname(pFile->pVfs, &zTFile);
@@ -50286,6 +51060,28 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return rc;
}
#endif
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ case SQLITE_FCNTL_LOCK_TIMEOUT: {
+ int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ pFile->iBusyTimeout = (iNew < 0) ? INFINITE : (DWORD)iNew;
+#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
+ pFile->iBusyTimeout = (DWORD)(!!iNew);
+#else
+# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
+#endif
+ *(int*)pArg = iOld;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
+
}
OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
return SQLITE_NOTFOUND;
@@ -50311,7 +51107,7 @@ static int winSectorSize(sqlite3_file *id){
*/
static int winDeviceCharacteristics(sqlite3_file *id){
winFile *p = (winFile*)id;
- return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
+ return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ |
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}
@@ -50366,23 +51162,27 @@ static int winShmMutexHeld(void) {
**
** The following fields are read-only after the object is created:
**
-** fid
** zFilename
**
** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
** winShmMutexHeld() is true when reading or writing any other field
** in this structure.
**
+** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate
+** the *-shm file if the DMS-locking protocol demands it, and (c) map
+** regions of the *-shm file into memory using MapViewOfFile() or
+** similar. Other locks are taken by individual clients using the
+** winShm.hShm handles.
*/
struct winShmNode {
sqlite3_mutex *mutex; /* Mutex to access this object */
char *zFilename; /* Name of the file */
- winFile hFile; /* File handle from winOpen */
+ HANDLE hSharedShm; /* File handle open on zFilename */
+ int isUnlocked; /* DMS lock has not yet been obtained */
+ int isReadonly; /* True if read-only */
int szRegion; /* Size of shared-memory regions */
int nRegion; /* Size of array apRegion */
- u8 isReadonly; /* True if read-only */
- u8 isUnlocked; /* True if no DMS lock held */
struct ShmRegion {
HANDLE hMap; /* File handle from CreateFileMapping */
@@ -50391,7 +51191,6 @@ struct winShmNode {
DWORD lastErrno; /* The Windows errno from the last I/O error */
int nRef; /* Number of winShm objects pointing to this */
- winShm *pFirst; /* All winShm objects pointing to this */
winShmNode *pNext; /* Next in list of all winShmNode objects */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 nextShmId; /* Next available winShm.id value */
@@ -50407,23 +51206,15 @@ static winShmNode *winShmNodeList = 0;
/*
** Structure used internally by this VFS to record the state of an
-** open shared memory connection.
-**
-** The following fields are initialized when this object is created and
-** are read-only thereafter:
-**
-** winShm.pShmNode
-** winShm.id
-**
-** All other fields are read/write. The winShm.pShmNode->mutex must be held
-** while accessing any read/write fields.
+** open shared memory connection. There is one such structure for each
+** winFile open on a wal mode database.
*/
struct winShm {
winShmNode *pShmNode; /* The underlying winShmNode object */
- winShm *pNext; /* Next winShm with the same winShmNode */
- u8 hasMutex; /* True if holding the winShmNode mutex */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
+ HANDLE hShm; /* File-handle on *-shm file. For locking. */
+ int bReadonly; /* True if hShm is opened read-only */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 id; /* Id of this connection with its winShmNode */
#endif
@@ -50435,50 +51226,6 @@ struct winShm {
#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-/*
-** Apply advisory locks for all n bytes beginning at ofst.
-*/
-#define WINSHM_UNLCK 1
-#define WINSHM_RDLCK 2
-#define WINSHM_WRLCK 3
-static int winShmSystemLock(
- winShmNode *pFile, /* Apply locks to this open shared-memory segment */
- int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
- int ofst, /* Offset to first byte to be locked/unlocked */
- int nByte /* Number of bytes to lock or unlock */
-){
- int rc = 0; /* Result code form Lock/UnlockFileEx() */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
-
- OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
- pFile->hFile.h, lockType, ofst, nByte));
-
- /* Release/Acquire the system-level lock */
- if( lockType==WINSHM_UNLCK ){
- rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
- }else{
- /* Initialize the locking parameters */
- DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
- if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
- rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
- }
-
- if( rc!= 0 ){
- rc = SQLITE_OK;
- }else{
- pFile->lastErrno = osGetLastError();
- rc = SQLITE_BUSY;
- }
-
- OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
- pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" :
- "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
-
- return rc;
-}
-
/* Forward references to VFS methods */
static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
static int winDelete(sqlite3_vfs *,const char*,int);
@@ -50510,11 +51257,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
UNUSED_VARIABLE_VALUE(bRc);
}
- if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
- SimulateIOErrorBenign(1);
- winClose((sqlite3_file *)&p->hFile);
- SimulateIOErrorBenign(0);
- }
+ winHandleClose(p->hSharedShm);
if( deleteFlag ){
SimulateIOErrorBenign(1);
sqlite3BeginBenignMalloc();
@@ -50532,42 +51275,239 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
}
/*
-** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
-** take it now. Return SQLITE_OK if successful, or an SQLite error
-** code otherwise.
-**
-** If the DMS cannot be locked because this is a readonly_shm=1
-** connection and no other process already holds a lock, return
-** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
+** The DMS lock has not yet been taken on the shm file associated with
+** pShmNode. Take the lock. Truncate the *-shm file if required.
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
-static int winLockSharedMemory(winShmNode *pShmNode){
- int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
+static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){
+ HANDLE h = pShmNode->hSharedShm;
+ int rc = SQLITE_OK;
+ assert( sqlite3_mutex_held(pShmNode->mutex) );
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 1, 0);
if( rc==SQLITE_OK ){
+ /* We have an EXCLUSIVE lock on the DMS byte. This means that this
+ ** is the first process to open the file. Truncate it to zero bytes
+ ** in this case. */
if( pShmNode->isReadonly ){
- pShmNode->isUnlocked = 1;
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return SQLITE_READONLY_CANTINIT;
- }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
- "winLockSharedMemory", pShmNode->zFilename);
+ rc = SQLITE_READONLY_CANTINIT;
+ }else{
+ rc = winHandleTruncate(h, 0);
}
+
+ /* Release the EXCLUSIVE lock acquired above. */
+ winUnlockFile(&h, WIN_SHM_DMS, 0, 1, 0);
+ }else if( (rc & 0xFF)==SQLITE_BUSY ){
+ rc = SQLITE_OK;
}
if( rc==SQLITE_OK ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
+ /* Take a SHARED lock on the DMS byte. */
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 0, nMs);
+ if( rc==SQLITE_OK ){
+ pShmNode->isUnlocked = 0;
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+** Convert a UTF-8 filename into whatever form the underlying
+** operating system wants filenames in. Space to hold the result
+** is obtained from malloc and must be freed by the calling
+** function
+**
+** On Cygwin, 3 possible input forms are accepted:
+** - If the filename starts with "<drive>:/" or "<drive>:\",
+** it is converted to UTF-16 as-is.
+** - If the filename contains '/', it is assumed to be a
+** Cygwin absolute path, it is converted to a win32
+** absolute path in UTF-16.
+** - Otherwise it must be a filename only, the win32 filename
+** is returned in UTF-16.
+** Note: If the function cygwin_conv_path() fails, only
+** UTF-8 -> UTF-16 conversion will be done. This can only
+** happen when the file path >32k, in which case winUtf8ToUnicode()
+** will fail too.
+*/
+static void *winConvertFromUtf8Filename(const char *zFilename){
+ void *zConverted = 0;
+ if( osIsNT() ){
+#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;
+ }
+ 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());
+ }
+#endif
+ /* caller will handle out of memory */
+ return zConverted;
+}
+
+/*
+** This function is used to open a handle on a *-shm file.
+**
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file
+** is opened with FILE_FLAG_OVERLAPPED specified. If not, it is not.
+*/
+static int winHandleOpen(
+ const char *zUtf8, /* File to open */
+ int *pbReadonly, /* IN/OUT: True for readonly handle */
+ HANDLE *ph /* OUT: New HANDLE for file */
+){
+ int rc = SQLITE_OK;
+ void *zConverted = 0;
+ int bReadonly = *pbReadonly;
+ HANDLE h = INVALID_HANDLE_VALUE;
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ const DWORD flag_overlapped = FILE_FLAG_OVERLAPPED;
+#else
+ const DWORD flag_overlapped = 0;
+#endif
+
+ /* Convert the filename to the system encoding. */
+ zConverted = winConvertFromUtf8Filename(zUtf8);
+ if( zConverted==0 ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8));
+ rc = SQLITE_IOERR_NOMEM_BKPT;
+ goto winopenfile_out;
+ }
+
+ /* Ensure the file we are trying to open is not actually a directory. */
+ if( winIsDir(zConverted) ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8));
+ rc = SQLITE_CANTOPEN_ISDIR;
+ goto winopenfile_out;
+ }
+
+ /* 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
}
- return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
+ if( h==INVALID_HANDLE_VALUE ){
+ if( bReadonly==0 ){
+ bReadonly = 1;
+ rc = winHandleOpen(zUtf8, &bReadonly, &h);
+ }else{
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+ }
+
+ winopenfile_out:
+ sqlite3_free(zConverted);
+ *pbReadonly = bReadonly;
+ *ph = h;
+ return rc;
}
+
/*
** Open the shared-memory area associated with database file pDbFd.
-**
-** When opening a new shared-memory file, if no other instances of that
-** file are currently open, in this process or in other processes, then
-** the file must be truncated to zero length or have its header cleared.
*/
static int winOpenSharedMemory(winFile *pDbFd){
struct winShm *p; /* The connection to be opened */
@@ -50579,98 +51519,83 @@ static int winOpenSharedMemory(winFile *pDbFd){
assert( pDbFd->pShm==0 ); /* Not previously opened */
/* Allocate space for the new sqlite3_shm object. Also speculatively
- ** allocate space for a new winShmNode and filename.
- */
+ ** allocate space for a new winShmNode and filename. */
p = sqlite3MallocZero( sizeof(*p) );
if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT;
nName = sqlite3Strlen30(pDbFd->zPath);
- pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
+ pNew = sqlite3MallocZero( sizeof(*pShmNode) + (i64)nName + 17 );
if( pNew==0 ){
sqlite3_free(p);
return SQLITE_IOERR_NOMEM_BKPT;
}
pNew->zFilename = (char*)&pNew[1];
+ pNew->hSharedShm = INVALID_HANDLE_VALUE;
+ pNew->isUnlocked = 1;
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
+ /* Open a file-handle on the *-shm file for this connection. This file-handle
+ ** is only used for locking. The mapping of the *-shm file is created using
+ ** the shared file handle in winShmNode.hSharedShm. */
+ p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0);
+ rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm);
+
/* Look to see if there is an existing winShmNode that can be used.
- ** If no matching winShmNode currently exists, create a new one.
- */
+ ** If no matching winShmNode currently exists, then create a new one. */
winShmEnterMutex();
for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
/* TBD need to come up with better match here. Perhaps
- ** use FILE_ID_BOTH_DIR_INFO Structure.
- */
+ ** use FILE_ID_BOTH_DIR_INFO Structure. */
if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
}
- if( pShmNode ){
- sqlite3_free(pNew);
- }else{
- int inFlags = SQLITE_OPEN_WAL;
- int outFlags = 0;
-
+ if( pShmNode==0 ){
pShmNode = pNew;
- pNew = 0;
- ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
- pShmNode->pNext = winShmNodeList;
- winShmNodeList = pShmNode;
+ /* Allocate a mutex for this winShmNode object, if one is required. */
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
- rc = SQLITE_IOERR_NOMEM_BKPT;
- goto shm_open_err;
- }
+ if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT;
}
- if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
- }else{
- inFlags |= SQLITE_OPEN_READONLY;
- }
- rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
- (sqlite3_file*)&pShmNode->hFile,
- inFlags, &outFlags);
- if( rc!=SQLITE_OK ){
- rc = winLogError(rc, osGetLastError(), "winOpenShm",
- pShmNode->zFilename);
- goto shm_open_err;
+ /* Open a file-handle to use for mappings, and for the DMS lock. */
+ if( rc==SQLITE_OK ){
+ HANDLE h = INVALID_HANDLE_VALUE;
+ pShmNode->isReadonly = p->bReadonly;
+ rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h);
+ pShmNode->hSharedShm = h;
}
- if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
- rc = winLockSharedMemory(pShmNode);
- if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
+ /* If successful, link the new winShmNode into the global list. If an
+ ** error occurred, free the object. */
+ if( rc==SQLITE_OK ){
+ pShmNode->pNext = winShmNodeList;
+ winShmNodeList = pShmNode;
+ pNew = 0;
+ }else{
+ sqlite3_mutex_free(pShmNode->mutex);
+ if( pShmNode->hSharedShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(pShmNode->hSharedShm);
+ }
+ }
}
- /* Make the new connection a child of the winShmNode */
- p->pShmNode = pShmNode;
+ /* If no error has occurred, link the winShm object to the winShmNode and
+ ** the winShm to pDbFd. */
+ if( rc==SQLITE_OK ){
+ p->pShmNode = pShmNode;
+ pShmNode->nRef++;
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- p->id = pShmNode->nextShmId++;
+ p->id = pShmNode->nextShmId++;
#endif
- pShmNode->nRef++;
- pDbFd->pShm = p;
- winShmLeaveMutex();
-
- /* The reference count on pShmNode has already been incremented under
- ** the cover of the winShmEnterMutex() mutex and the pointer from the
- ** new (struct winShm) object to the pShmNode has been set. All that is
- ** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
- */
- sqlite3_mutex_enter(pShmNode->mutex);
- p->pNext = pShmNode->pFirst;
- pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
+ pDbFd->pShm = p;
+ }else if( p ){
+ winHandleClose(p->hShm);
+ sqlite3_free(p);
+ }
- /* Jump here on any error */
-shm_open_err:
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
- sqlite3_free(p);
- sqlite3_free(pNew);
+ assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 );
winShmLeaveMutex();
+ sqlite3_free(pNew);
return rc;
}
@@ -50685,27 +51610,19 @@ static int winShmUnmap(
winFile *pDbFd; /* Database holding shared-memory */
winShm *p; /* The connection to be closed */
winShmNode *pShmNode; /* The underlying shared-memory file */
- winShm **pp; /* For looping over sibling connections */
pDbFd = (winFile*)fd;
p = pDbFd->pShm;
if( p==0 ) return SQLITE_OK;
- pShmNode = p->pShmNode;
-
- /* Remove connection p from the set of connections associated
- ** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
- *pp = p->pNext;
+ if( p->hShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(p->hShm);
+ }
- /* Free the connection p */
- sqlite3_free(p);
- pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
+ pShmNode = p->pShmNode;
+ winShmEnterMutex();
/* If pShmNode->nRef has reached 0, then close the underlying
- ** shared-memory file, too */
- winShmEnterMutex();
+ ** shared-memory file, too. */
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
@@ -50713,6 +51630,9 @@ static int winShmUnmap(
}
winShmLeaveMutex();
+ /* Free the connection p */
+ sqlite3_free(p);
+ pDbFd->pShm = 0;
return SQLITE_OK;
}
@@ -50727,10 +51647,9 @@ static int winShmLock(
){
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
winShm *p = pDbFd->pShm; /* The shared memory being locked */
- winShm *pX; /* For looping over all siblings */
winShmNode *pShmNode;
int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
+ u16 mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); /* Mask of locks to [un]take */
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
pShmNode = p->pShmNode;
@@ -50744,85 +51663,81 @@ static int winShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
- assert( n>1 || mask==(1<<ofst) );
- sqlite3_mutex_enter(pShmNode->mutex);
- if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
-
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
+ /* Check that, if this to be a blocking lock, no locks that occur later
+ ** in the following list than the lock being obtained are already held:
+ **
+ ** 1. Recovery lock (ofst==2).
+ ** 2. Checkpointer lock (ofst==1).
+ ** 3. Write lock (ofst==0).
+ ** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
+ **
+ ** In other words, if this is a blocking lock, none of the locks that
+ ** occur later in the above list than the lock being obtained may be
+ ** held.
+ */
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
+ {
+ u16 lockMask = (p->exclMask|p->sharedMask);
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
+ (ofst!=2 || lockMask==0)
+ && (ofst!=1 || lockMask==0 || lockMask==2)
+ && (ofst!=0 || lockMask<3)
+ && (ofst<3 || lockMask<(1<<ofst))
+ ));
+ }
+#endif
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
+ /* Check if there is any work to do. There are three cases:
+ **
+ ** a) An unlock operation where there are locks to unlock,
+ ** b) An shared lock where the requested lock is not already held
+ ** c) An exclusive lock where the requested lock is not already held
+ **
+ ** The SQLite core never requests an exclusive lock that it already holds.
+ ** This is assert()ed immediately below. */
+ assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
+ || 0==(p->exclMask & mask)
+ );
+ if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
+ || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
+ || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
+ ){
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
+ if( flags & SQLITE_SHM_UNLOCK ){
+ /* Case (a) - unlock. */
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
+ assert( (p->exclMask & p->sharedMask)==0 );
+ assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
+ assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
- }
+ rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n);
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
+ /* If successful, also clear the bits in sharedMask/exclMask */
+ if( rc==SQLITE_OK ){
+ p->exclMask = (p->exclMask & ~mask);
+ p->sharedMask = (p->sharedMask & ~mask);
}
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- if( rc==SQLITE_OK ){
- rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n);
+ }else{
+ int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0);
+ DWORD nMs = winFileBusyTimeout(pDbFd);
+ rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs);
if( rc==SQLITE_OK ){
- assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
+ if( bExcl ){
+ p->exclMask = (p->exclMask | mask);
+ }else{
+ p->sharedMask = (p->sharedMask | mask);
+ }
}
}
}
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
- osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
- sqlite3ErrName(rc)));
+
+ OSTRACE((
+ "SHM-LOCK(%d,%d,%d) pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x,"
+ " rc=%s\n",
+ ofst, n, flags,
+ osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
+ sqlite3ErrName(rc))
+ );
return rc;
}
@@ -50884,13 +51799,15 @@ static int winShmMap(
sqlite3_mutex_enter(pShmNode->mutex);
if( pShmNode->isUnlocked ){
- rc = winLockSharedMemory(pShmNode);
+ /* Take the DMS lock. */
+ assert( pShmNode->nRegion==0 );
+ rc = winLockSharedMemory(pShmNode, winFileBusyTimeout(pDbFd));
if( rc!=SQLITE_OK ) goto shmpage_out;
- pShmNode->isUnlocked = 0;
}
- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
if( pShmNode->nRegion<=iRegion ){
+ HANDLE hShared = pShmNode->hSharedShm;
struct ShmRegion *apNew; /* New aRegion[] array */
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
sqlite3_int64 sz; /* Current size of wal-index file */
@@ -50901,10 +51818,9 @@ static int winShmMap(
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
+ rc = winHandleSize(hShared, &sz);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap1", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap1", pDbFd->zPath);
goto shmpage_out;
}
@@ -50913,19 +51829,17 @@ static int winShmMap(
** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
**
** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
- ** the requested memory region.
- */
+ ** the requested memory region. */
if( !isWrite ) goto shmpage_out;
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
+ rc = winHandleTruncate(hShared, nByte);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap2", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap2", pDbFd->zPath);
goto shmpage_out;
}
}
/* Map the requested memory region into this processes address space. */
- apNew = (struct ShmRegion *)sqlite3_realloc64(
+ apNew = (struct ShmRegion*)sqlite3_realloc64(
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
@@ -50944,18 +51858,13 @@ static int winShmMap(
void *pMap = 0; /* Mapped memory region */
#if SQLITE_OS_WINRT
- hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
- NULL, protect, nByte, NULL
- );
+ hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL);
#elif defined(SQLITE_WIN32_HAS_WIDE)
- hMap = osCreateFileMappingW(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+ hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL);
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- hMap = osCreateFileMappingA(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+ hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
#endif
+
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
hMap ? "ok" : "failed"));
@@ -50998,7 +51907,9 @@ shmpage_out:
}else{
*pp = 0;
}
- if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
+ if( pShmNode->isReadonly && rc==SQLITE_OK ){
+ rc = SQLITE_READONLY;
+ }
sqlite3_mutex_leave(pShmNode->mutex);
return rc;
}
@@ -51318,47 +52229,6 @@ static winVfsAppData winNolockAppData = {
** sqlite3_vfs object.
*/
-#if defined(__CYGWIN__)
-/*
-** Convert a filename from whatever the underlying operating system
-** supports for filenames into UTF-8. Space to hold the result is
-** obtained from malloc and must be freed by the calling function.
-*/
-static char *winConvertToUtf8Filename(const void *zFilename){
- char *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUnicodeToUtf8(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-#endif
-
-/*
-** Convert a UTF-8 filename into whatever form the underlying
-** operating system wants filenames in. Space to hold the result
-** is obtained from malloc and must be freed by the calling
-** function.
-*/
-static void *winConvertFromUtf8Filename(const char *zFilename){
- void *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUtf8ToUnicode(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-
/*
** This function returns non-zero if the specified UTF-8 string buffer
** ends with a directory separator character or one was successfully
@@ -51371,7 +52241,14 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){
if( winIsDirSep(zBuf[nLen-1]) ){
return 1;
}else if( nLen+1<nBuf ){
- zBuf[nLen] = winGetDirSep();
+ if( !osGetenv ){
+ zBuf[nLen] = winGetDirSep();
+ }else if( winIsDriveLetterAndColon(zBuf) && winIsDirSep(zBuf[2]) ){
+ zBuf[nLen] = '\\';
+ zBuf[2]='\\';
+ }else{
+ zBuf[nLen] = '/';
+ }
zBuf[nLen+1] = '\0';
return 1;
}
@@ -51398,14 +52275,14 @@ static int winTempDirDefined(void){
** The pointer returned in pzBuf must be freed via sqlite3_free().
*/
static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
- static char zChars[] =
+ static const char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
size_t i, j;
DWORD pid;
int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
- int nMax, nBuf, nDir, nLen;
+ i64 nMax, nBuf, nDir, nLen;
char *zBuf;
/* It's odd to simulate an io-error here, but really this is just
@@ -51417,7 +52294,8 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
/* Allocate a temporary buffer to store the fully qualified file
** name for the temporary file. If this fails, we cannot continue.
*/
- nMax = pVfs->mxPathname; nBuf = nMax + 2;
+ nMax = pVfs->mxPathname;
+ nBuf = 2 + (i64)nMax;
zBuf = sqlite3MallocZero( nBuf );
if( !zBuf ){
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
@@ -51448,7 +52326,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
}
#if defined(__CYGWIN__)
- else{
+ else if( osGetenv!=NULL ){
static const char *azDirs[] = {
0, /* getenv("SQLITE_TMPDIR") */
0, /* getenv("TMPDIR") */
@@ -51464,11 +52342,11 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
unsigned int i;
const char *zDir = 0;
- if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
- if( !azDirs[2] ) azDirs[2] = getenv("TMP");
- if( !azDirs[3] ) azDirs[3] = getenv("TEMP");
- if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE");
+ if( !azDirs[0] ) azDirs[0] = osGetenv("SQLITE_TMPDIR");
+ if( !azDirs[1] ) azDirs[1] = osGetenv("TMPDIR");
+ if( !azDirs[2] ) azDirs[2] = osGetenv("TMP");
+ if( !azDirs[3] ) azDirs[3] = osGetenv("TEMP");
+ if( !azDirs[4] ) azDirs[4] = osGetenv("USERPROFILE");
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
void *zConverted;
if( zDir==0 ) continue;
@@ -51477,7 +52355,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
** it must be converted to a native Win32 path via the Cygwin API
** prior to using it.
*/
- if( winIsDriveLetterAndColon(zDir) ){
+ {
zConverted = winConvertFromUtf8Filename(zDir);
if( !zConverted ){
sqlite3_free(zBuf);
@@ -51490,44 +52368,12 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
break;
}
sqlite3_free(zConverted);
- }else{
- zConverted = sqlite3MallocZero( nMax+1 );
- if( !zConverted ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
- zConverted, nMax+1)<0 ){
- sqlite3_free(zConverted);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
- return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
- "winGetTempname2", zDir);
- }
- if( winIsDir(zConverted) ){
- /* At this point, we know the candidate directory exists and should
- ** be used. However, we may need to convert the string containing
- ** its name into UTF-8 (i.e. if it is UTF-16 right now).
- */
- char *zUtf8 = winConvertToUtf8Filename(zConverted);
- if( !zUtf8 ){
- sqlite3_free(zConverted);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zConverted);
- break;
- }
- sqlite3_free(zConverted);
}
}
}
-#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+#endif
+
+#if !SQLITE_OS_WINRT && defined(_WIN32)
else if( osIsNT() ){
char *zMulti;
LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) );
@@ -51651,7 +52497,7 @@ static int winIsDir(const void *zConverted){
return 0; /* Invalid name? */
}
attr = sAttrData.dwFileAttributes;
-#if SQLITE_OS_WINCE==0
+#if SQLITE_OS_WINCE==0 && defined(SQLITE_WIN32_HAS_ANSI)
}else{
attr = osGetFileAttributesA((char*)zConverted);
#endif
@@ -51668,6 +52514,12 @@ static int winAccess(
);
/*
+** The Windows version of xAccess() accepts an extra bit in the flags
+** parameter that prevents an anti-virus retry loop.
+*/
+#define NORETRY 0x4000
+
+/*
** Open a file.
*/
static int winOpen(
@@ -51691,6 +52543,7 @@ static int winOpen(
void *zConverted; /* Filename in OS encoding */
const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
int cnt = 0;
+ int isRO = 0; /* file is known to be accessible readonly */
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
@@ -51699,7 +52552,7 @@ static int winOpen(
int rc = SQLITE_OK; /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
- int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int eType = flags&0x0FFF00; /* Type of file to open */
#endif
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
@@ -51855,9 +52708,9 @@ static int winOpen(
&extendedParameters);
if( h!=INVALID_HANDLE_VALUE ) break;
if( isReadWrite ){
- int rc2, isRO = 0;
+ int rc2;
sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
+ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
@@ -51872,9 +52725,9 @@ static int winOpen(
NULL);
if( h!=INVALID_HANDLE_VALUE ) break;
if( isReadWrite ){
- int rc2, isRO = 0;
+ int rc2;
sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
+ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
@@ -51892,9 +52745,9 @@ static int winOpen(
NULL);
if( h!=INVALID_HANDLE_VALUE ) break;
if( isReadWrite ){
- int rc2, isRO = 0;
+ int rc2;
sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
+ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
@@ -51909,7 +52762,7 @@ static int winOpen(
if( h==INVALID_HANDLE_VALUE ){
sqlite3_free(zConverted);
sqlite3_free(zTmpname);
- if( isReadWrite && !isExclusive ){
+ if( isReadWrite && isRO && !isExclusive ){
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY) &
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
@@ -52111,8 +52964,14 @@ static int winAccess(
int rc = 0;
DWORD lastErrno = 0;
void *zConverted;
+ int noRetry = 0; /* Do not use winRetryIoerr() */
UNUSED_PARAMETER(pVfs);
+ if( (flags & NORETRY)!=0 ){
+ noRetry = 1;
+ flags &= ~NORETRY;
+ }
+
SimulateIOError( return SQLITE_IOERR_ACCESS; );
OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
zFilename, flags, pResOut));
@@ -52135,7 +52994,10 @@ static int winAccess(
memset(&sAttrData, 0, sizeof(sAttrData));
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
GetFileExInfoStandard,
- &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
+ &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.
@@ -52203,6 +53065,7 @@ static BOOL winIsDriveLetterAndColon(
return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' );
}
+#ifdef _WIN32
/*
** Returns non-zero if the specified path name should be used verbatim. If
** non-zero is returned from this function, the calling function must simply
@@ -52239,6 +53102,70 @@ static BOOL winIsVerbatimPathname(
*/
return FALSE;
}
+#endif /* _WIN32 */
+
+#ifdef __CYGWIN__
+/*
+** Simplify a filename into its canonical form
+** by making the following changes:
+**
+** * convert any '/' to '\' (win32) or reverse (Cygwin)
+** * removing any trailing and duplicate / (except for UNC paths)
+** * convert /./ into just /
+**
+** Changes are made in-place. Return the new name length.
+**
+** The original filename is in z[0..]. If the path is shortened,
+** no-longer used bytes will be written by '\0'.
+*/
+static void winSimplifyName(char *z){
+ int i, j;
+ for(i=j=0; z[i]; ++i){
+ if( winIsDirSep(z[i]) ){
+#if !defined(SQLITE_TEST)
+ /* Some test-cases assume that "./foo" and "foo" are different */
+ if( z[i+1]=='.' && winIsDirSep(z[i+2]) ){
+ ++i;
+ continue;
+ }
+#endif
+ if( !z[i+1] || (winIsDirSep(z[i+1]) && (i!=0)) ){
+ continue;
+ }
+ z[j++] = osGetenv?'/':'\\';
+ }else{
+ z[j++] = z[i];
+ }
+ }
+ while(j<i) z[j++] = '\0';
+}
+
+#define SQLITE_MAX_SYMLINKS 100
+
+static int mkFullPathname(
+ const char *zPath, /* Input path */
+ char *zOut, /* Output buffer */
+ int nOut /* Allocated size of buffer zOut */
+){
+ int nPath = sqlite3Strlen30(zPath);
+ int iOff = 0;
+ if( zPath[0]!='/' ){
+ if( osGetcwd(zOut, nOut-2)==0 ){
+ return winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "getcwd", zPath);
+ }
+ iOff = sqlite3Strlen30(zOut);
+ zOut[iOff++] = '/';
+ }
+ if( (iOff+nPath+1)>nOut ){
+ /* SQLite assumes that xFullPathname() nul-terminates the output buffer
+ ** even if it returns an error. */
+ zOut[iOff] = '\0';
+ return SQLITE_CANTOPEN_BKPT;
+ }
+ sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
+ return SQLITE_OK;
+}
+#endif /* __CYGWIN__ */
/*
** Turn a relative pathname into a full pathname. Write the full
@@ -52251,8 +53178,8 @@ static int winFullPathnameNoMutex(
int nFull, /* Size of output buffer in bytes */
char *zFull /* Output buffer */
){
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
- DWORD nByte;
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+ int nByte;
void *zConverted;
char *zOut;
#endif
@@ -52265,64 +53192,82 @@ static int winFullPathnameNoMutex(
zRelative++;
}
-#if defined(__CYGWIN__)
SimulateIOError( return SQLITE_ERROR );
- UNUSED_PARAMETER(nFull);
- assert( nFull>=pVfs->mxPathname );
- 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 slash.
- */
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
- CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname1", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
- sqlite3_data_directory, winGetDirSep(), zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
- }
- }else{
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
- zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname2", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
+
+#ifdef __CYGWIN__
+ if( osGetcwd ){
+ 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 */
+ 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. */
+ 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);
+ }
+ }else{
+ bLink = ((buf.st_mode & 0170000) == 0120000);
+ }
+
+ if( bLink ){
+ if( zDel==0 ){
+ zDel = sqlite3MallocZero(nFull);
+ if( zDel==0 ) rc = SQLITE_NOMEM;
+ }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+
+ if( rc==SQLITE_OK ){
+ nByte = osReadlink(zIn, zDel, nFull-1);
+ if( nByte ==(DWORD)-1 ){
+ rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "readlink", zIn);
+ }else{
+ if( zDel[0]!='/' ){
+ int n;
+ for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
+ if( nByte+n+1>nFull ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }else{
+ memmove(&zDel[n], zDel, nByte+1);
+ memcpy(zDel, zIn, n);
+ nByte += n;
+ }
+ }
+ zDel[nByte] = '\0';
+ }
+ }
+
+ zIn = zDel;
+ }
+ }
+
+ assert( rc!=SQLITE_OK || zIn!=zFull || zIn[0]=='/' );
+ if( rc==SQLITE_OK && zIn!=zFull ){
+ rc = mkFullPathname(zIn, zFull, nFull);
+ }
+ if( bLink==0 ) break;
+ zIn = zFull;
+ }while( rc==SQLITE_OK );
+
+ sqlite3_free(zDel);
+ winSimplifyName(zFull);
+ return rc;
}
}
- return SQLITE_OK;
-#endif
+#endif /* __CYGWIN__ */
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__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. */
@@ -52341,7 +53286,8 @@ static int winFullPathnameNoMutex(
return SQLITE_OK;
#endif
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+#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
** function failing. This function could fail if, for example, the
@@ -52359,6 +53305,7 @@ static int winFullPathnameNoMutex(
sqlite3_data_directory, winGetDirSep(), zRelative);
return SQLITE_OK;
}
+#endif
zConverted = winConvertFromUtf8Filename(zRelative);
if( zConverted==0 ){
return SQLITE_IOERR_NOMEM_BKPT;
@@ -52397,13 +53344,12 @@ static int winFullPathnameNoMutex(
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
"winFullPathname3", zRelative);
}
- nByte += 3;
- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+ 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, zTemp, 0);
+ nByte = osGetFullPathNameA((char*)zConverted, nByte+3, zTemp, 0);
if( nByte==0 ){
sqlite3_free(zConverted);
sqlite3_free(zTemp);
@@ -52416,7 +53362,26 @@ static int winFullPathnameNoMutex(
}
#endif
if( zOut ){
+#ifdef __CYGWIN__
+ if( memcmp(zOut, "\\\\?\\", 4) ){
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+ }else if( memcmp(zOut+4, "UNC\\", 4) ){
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+4);
+ }else{
+ char *p = zOut+6;
+ *p = '\\';
+ if( osGetcwd ){
+ /* On Cygwin, UNC paths use forward slashes */
+ while( *p ){
+ if( *p=='\\' ) *p = '/';
+ ++p;
+ }
+ }
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+6);
+ }
+#else
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+#endif /* __CYGWIN__ */
sqlite3_free(zOut);
return SQLITE_OK;
}else{
@@ -52446,25 +53411,8 @@ static int winFullPathname(
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
-#if defined(__CYGWIN__)
- int nFull = pVfs->mxPathname+1;
- char *zFull = sqlite3MallocZero( nFull );
- void *zConverted = 0;
- if( zFull==0 ){
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
- sqlite3_free(zFull);
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- zConverted = winConvertFromUtf8Filename(zFull);
- sqlite3_free(zFull);
-#else
void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
-#endif
if( zConverted==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
@@ -52813,7 +53761,7 @@ SQLITE_API int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==80 );
+ assert( ArraySize(aSyscall)==89 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
@@ -53432,13 +54380,13 @@ static int memdbOpen(
}
if( p==0 ){
MemStore **apNew;
- p = sqlite3Malloc( sizeof(*p) + szName + 3 );
+ p = sqlite3Malloc( sizeof(*p) + (i64)szName + 3 );
if( p==0 ){
sqlite3_mutex_leave(pVfsMutex);
return SQLITE_NOMEM;
}
apNew = sqlite3Realloc(memdb_g.apMemStore,
- sizeof(apNew[0])*(memdb_g.nMemStore+1) );
+ sizeof(apNew[0])*(1+(i64)memdb_g.nMemStore) );
if( apNew==0 ){
sqlite3_free(p);
sqlite3_mutex_leave(pVfsMutex);
@@ -53871,7 +54819,7 @@ SQLITE_PRIVATE int sqlite3MemdbInit(void){
** no fewer collisions than the no-op *1. */
#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
-#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
+#define BITVEC_NPTR ((u32)(BITVEC_USIZE/sizeof(Bitvec *)))
/*
@@ -54020,7 +54968,9 @@ bitvec_set_rehash:
}else{
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
memset(p->u.apSub, 0, sizeof(p->u.apSub));
- p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
+ p->iDivisor = p->iSize/BITVEC_NPTR;
+ if( (p->iSize%BITVEC_NPTR)!=0 ) p->iDivisor++;
+ if( p->iDivisor<BITVEC_NBIT ) p->iDivisor = BITVEC_NBIT;
rc = sqlite3BitvecSet(p, i);
for(j=0; j<BITVEC_NINT; j++){
if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
@@ -54054,7 +55004,7 @@ SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
}
}
if( p->iSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
+ p->u.aBitmap[i/BITVEC_SZELEM] &= ~(BITVEC_TELEM)(1<<(i&(BITVEC_SZELEM-1)));
}else{
unsigned int j;
u32 *aiValues = pBuf;
@@ -54105,7 +55055,7 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
** individual bits within V.
*/
#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
-#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
+#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7))
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
/*
@@ -54148,7 +55098,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
/* Allocate the Bitvec to be tested and a linear array of
** bits to act as the reference */
pBitvec = sqlite3BitvecCreate( sz );
- pV = sqlite3MallocZero( (sz+7)/8 + 1 );
+ pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
@@ -54730,6 +55680,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
memset(pPgHdr->pExtra, 0, 8);
+ assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) );
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
pPgHdr->flags = PGHDR_CLEAN;
@@ -55388,10 +56339,6 @@ static SQLITE_WSD struct PCacheGlobal {
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
PgFreeslot *pFree; /* Free page blocks */
int nFreeSlot; /* Number of unused pcache slots */
- /* The following value requires a mutex to change. We skip the mutex on
- ** reading because (1) most platforms read a 32-bit integer atomically and
- ** (2) even if an incorrect value is read, no great harm is done since this
- ** is really just an optimization. */
int bUnderPressure; /* True if low on PAGECACHE memory */
} pcache1_g;
@@ -55439,7 +56386,7 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
pcache1.pStart = pBuf;
pcache1.pFree = 0;
- pcache1.bUnderPressure = 0;
+ AtomicStore(&pcache1.bUnderPressure,0);
while( n-- ){
p = (PgFreeslot*)pBuf;
p->pNext = pcache1.pFree;
@@ -55476,7 +56423,8 @@ static int pcache1InitBulk(PCache1 *pCache){
do{
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
- pX->page.pExtra = &pX[1];
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
@@ -55506,7 +56454,7 @@ static void *pcache1Alloc(int nByte){
if( p ){
pcache1.pFree = pcache1.pFree->pNext;
pcache1.nFreeSlot--;
- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
+ AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
assert( pcache1.nFreeSlot>=0 );
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
@@ -55545,7 +56493,7 @@ static void pcache1Free(void *p){
pSlot->pNext = pcache1.pFree;
pcache1.pFree = pSlot;
pcache1.nFreeSlot++;
- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
+ AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
assert( pcache1.nFreeSlot<=pcache1.nSlot );
sqlite3_mutex_leave(pcache1.mutex);
}else{
@@ -55613,7 +56561,8 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
if( pPg==0 ) return 0;
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
p->page.pBuf = pPg;
- p->page.pExtra = &p[1];
+ p->page.pExtra = (u8*)p + ROUND8(sizeof(*p));
+ assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) );
p->isBulkLocal = 0;
p->isAnchor = 0;
p->pLruPrev = 0; /* Initializing this saves a valgrind error */
@@ -55675,7 +56624,7 @@ SQLITE_PRIVATE void sqlite3PageFree(void *p){
*/
static int pcache1UnderMemoryPressure(PCache1 *pCache){
if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
- return pcache1.bUnderPressure;
+ return AtomicLoad(&pcache1.bUnderPressure);
}else{
return sqlite3HeapNearlyFull();
}
@@ -55692,12 +56641,12 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){
*/
static void pcache1ResizeHash(PCache1 *p){
PgHdr1 **apNew;
- unsigned int nNew;
- unsigned int i;
+ u64 nNew;
+ u32 i;
assert( sqlite3_mutex_held(p->pGroup->mutex) );
- nNew = p->nHash*2;
+ nNew = 2*(u64)p->nHash;
if( nNew<256 ){
nNew = 256;
}
@@ -55920,7 +56869,7 @@ static void pcache1Destroy(sqlite3_pcache *p);
static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
PCache1 *pCache; /* The newly created page cache */
PGroup *pGroup; /* The group the new page cache will belong to */
- int sz; /* Bytes of memory required to allocate the new cache */
+ i64 sz; /* Bytes of memory required to allocate the new cache */
assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
assert( szExtra < 300 );
@@ -57808,6 +58757,9 @@ struct Pager {
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
char *zWal; /* File name for write-ahead log */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3 *dbWal;
+#endif
};
/*
@@ -57897,39 +58849,33 @@ static const unsigned char aJournalMagic[] = {
# define USEFETCH(x) 0
#endif
-/*
-** The argument to this macro is a file descriptor (type sqlite3_file*).
-** Return 0 if it is not open, or non-zero (but not 1) if it is.
-**
-** This is so that expressions can be written as:
-**
-** if( isOpen(pPager->jfd) ){ ...
-**
-** instead of
-**
-** if( pPager->jfd->pMethods ){ ...
-*/
-#define isOpen(pFd) ((pFd)->pMethods!=0)
-
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
** Return true if page pgno can be read directly from the database file
** by the b-tree layer. This is the case if:
**
-** * the database file is open,
-** * there are no dirty pages in the cache, and
-** * the desired page is not currently in the wal file.
+** (1) the database file is open
+** (2) the VFS for the database is able to do unaligned sub-page reads
+** (3) there are no dirty pages in the cache, and
+** (4) the desired page is not currently in the wal file.
*/
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
- if( pPager->fd->pMethods==0 ) return 0;
- if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
+ assert( pPager!=0 );
+ assert( pPager->fd!=0 );
+ if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */
#ifndef SQLITE_OMIT_WAL
if( pPager->pWal ){
u32 iRead = 0;
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return iRead==0;
+ if( iRead ) return 0; /* Case (4) */
}
#endif
+ assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
+ if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
+ & SQLITE_IOCAP_SUBPAGE_READ)==0 ){
+ return 0; /* Case (2) */
+ }
return 1;
}
#endif
@@ -58405,7 +59351,7 @@ static void checkPage(PgHdr *pPg){
** If an error occurs while reading from the journal file, an SQLite
** error code is returned.
*/
-static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
+static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
int rc; /* Return code */
u32 len; /* Length in bytes of super-journal name */
i64 szJ; /* Total size in bytes of journal file pJrnl */
@@ -58960,6 +59906,15 @@ static void pager_unlock(Pager *pPager){
if( pagerUseWal(pPager) ){
assert( !isOpen(pPager->jfd) );
+ if( pPager->eState==PAGER_ERROR ){
+ /* If an IO error occurs in wal.c while attempting to wrap the wal file,
+ ** then the Wal object may be holding a write-lock but no read-lock.
+ ** This call ensures that the write-lock is dropped as well. We cannot
+ ** have sqlite3WalEndReadTransaction() drop the write-lock, as it once
+ ** did, because this would break "BEGIN EXCLUSIVE" handling for
+ ** SQLITE_ENABLE_SETLK_TIMEOUT builds. */
+ sqlite3WalEndWriteTransaction(pPager->pWal);
+ }
sqlite3WalEndReadTransaction(pPager->pWal);
pPager->eState = PAGER_OPEN;
}else if( !pPager->exclusiveMode ){
@@ -59188,7 +60143,7 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
}
pPager->journalOff = 0;
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
- || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
+ || (pPager->exclusiveMode && pPager->journalMode<PAGER_JOURNALMODE_WAL)
){
rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
pPager->journalOff = 0;
@@ -59641,12 +60596,12 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
char *zJournal; /* Pointer to one journal within MJ file */
char *zSuperPtr; /* Space to hold super-journal filename */
char *zFree = 0; /* Free this buffer */
- int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
+ i64 nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
/* Allocate space for both the pJournal and pSuper file descriptors.
** If successful, open the super-journal file for reading.
*/
- pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
+ pSuper = (sqlite3_file *)sqlite3MallocZero(2 * (i64)pVfs->szOsFile);
if( !pSuper ){
rc = SQLITE_NOMEM_BKPT;
pJournal = 0;
@@ -59664,11 +60619,14 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
*/
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
- nSuperPtr = pVfs->mxPathname+1;
+ nSuperPtr = 1 + (i64)pVfs->mxPathname;
+ assert( nSuperJournal>=0 && nSuperPtr>0 );
zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
+ }else{
+ assert( nSuperJournal<=0x7fffffff );
}
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
zSuperJournal = &zFree[4];
@@ -59929,7 +60887,7 @@ static int pager_playback(Pager *pPager, int isHot){
** for pageSize.
*/
zSuper = pPager->pTmpSpace;
- rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
+ rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
if( rc==SQLITE_OK && zSuper[0] ){
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}
@@ -60068,7 +61026,7 @@ end_playback:
** which case it requires 4 0x00 bytes in memory immediately before
** the filename. */
zSuper = &pPager->pTmpSpace[4];
- rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
+ rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK
@@ -61172,6 +62130,7 @@ static int pagerAcquireMapPage(
return SQLITE_NOMEM_BKPT;
}
p->pExtra = (void *)&p[1];
+ assert( EIGHT_BYTE_ALIGNMENT( p->pExtra ) );
p->flags = PGHDR_MMAP;
p->nRef = 1;
p->pPager = pPager;
@@ -61838,6 +62797,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
const char *zUri = 0; /* URI args to copy */
int nUriByte = 1; /* Number of bytes of URI args at *zUri */
+
/* Figure out how much space is required for each journal file-handle
** (there are two of them, the main journal and the sub-journal). */
journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
@@ -61863,8 +62823,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
*/
if( zFilename && zFilename[0] ){
const char *z;
- nPathname = pVfs->mxPathname+1;
- zPathname = sqlite3DbMallocRaw(0, nPathname*2);
+ nPathname = pVfs->mxPathname + 1;
+ zPathname = sqlite3DbMallocRaw(0, 2*(i64)nPathname);
if( zPathname==0 ){
return SQLITE_NOMEM_BKPT;
}
@@ -61951,14 +62911,14 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
ROUND8(sizeof(*pPager)) + /* Pager structure */
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
+ (u64)journalFileSize * 2 + /* The two journal files */
SQLITE_PTRSIZE + /* Space to hold a pointer */
4 + /* Database prefix */
- nPathname + 1 + /* database filename */
- nUriByte + /* query parameters */
- nPathname + 8 + 1 + /* Journal filename */
+ (u64)nPathname + 1 + /* database filename */
+ (u64)nUriByte + /* query parameters */
+ (u64)nPathname + 8 + 1 + /* Journal filename */
#ifndef SQLITE_OMIT_WAL
- nPathname + 4 + 1 + /* WAL filename */
+ (u64)nPathname + 4 + 1 + /* WAL filename */
#endif
3 /* Terminator */
);
@@ -64681,6 +65641,11 @@ static int pagerOpenWal(Pager *pPager){
pPager->fd, pPager->zWal, pPager->exclusiveMode,
pPager->journalSizeLimit, &pPager->pWal
);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_OK ){
+ sqlite3WalDb(pPager->pWal, pPager->dbWal);
+ }
+#endif
}
pagerFixMaplimit(pPager);
@@ -64800,6 +65765,7 @@ SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
** blocking locks are required.
*/
SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
+ pPager->dbWal = db;
if( pagerUseWal(pPager) ){
sqlite3WalDb(pPager->pWal, db);
}
@@ -64955,7 +65921,7 @@ SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){
** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
**
** Immediately following the wal-header are zero or more frames. Each
-** frame consists of a 24-byte frame-header followed by a <page-size> bytes
+** frame consists of a 24-byte frame-header followed by <page-size> bytes
** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
@@ -65413,6 +66379,11 @@ struct WalCkptInfo {
/*
** An open write-ahead log file is represented by an instance of the
** following object.
+**
+** writeLock:
+** This is usually set to 1 whenever the WRITER lock is held. However,
+** if it is set to 2, then the WRITER lock is held but must be released
+** by walHandleException() if a SEH exception is thrown.
*/
struct Wal {
sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
@@ -65452,6 +66423,7 @@ struct Wal {
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
+ int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
sqlite3 *db;
@@ -65502,9 +66474,13 @@ struct WalIterator {
u32 *aPgno; /* Array of page numbers. */
int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
int iZero; /* Frame number associated with aPgno[0] */
- } aSegment[1]; /* One for every 32KB page in the wal-index */
+ } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */
};
+/* Size (in bytes) of a WalIterator object suitable for N or fewer segments */
+#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
@@ -65663,7 +66639,7 @@ static SQLITE_NOINLINE int walIndexPageRealloc(
/* Enlarge the pWal->apWiData[] array if required */
if( pWal->nWiData<=iPage ){
- sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
+ sqlite3_int64 nByte = sizeof(u32*)*(1+(i64)iPage);
volatile u32 **apNew;
apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
if( !apNew ){
@@ -65772,10 +66748,8 @@ static void walChecksumBytes(
s1 = s2 = 0;
}
- assert( nByte>=8 );
- assert( (nByte&0x00000007)==0 );
- assert( nByte<=65536 );
- assert( nByte%4==0 );
+ /* nByte is a multiple of 8 between 8 and 65536 */
+ assert( nByte>=8 && (nByte&7)==0 && nByte<=65536 );
if( !nativeCksum ){
do {
@@ -66865,8 +67839,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
/* Allocate space for the WalIterator object. */
nSegment = walFramePage(iLast) + 1;
- nByte = sizeof(WalIterator)
- + (nSegment-1)*sizeof(struct WalSegment)
+ nByte = SZ_WALITERATOR(nSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3_malloc64(nByte
+ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
@@ -66937,7 +67910,7 @@ static int walEnableBlockingMs(Wal *pWal, int nMs){
static int walEnableBlocking(Wal *pWal){
int res = 0;
if( pWal->db ){
- int tmout = pWal->db->busyTimeout;
+ int tmout = pWal->db->setlkTimeout;
if( tmout ){
res = walEnableBlockingMs(pWal, tmout);
}
@@ -67323,7 +68296,9 @@ static int walHandleException(Wal *pWal){
static const int S = 1;
static const int E = (1<<SQLITE_SHM_NLOCK);
int ii;
- u32 mUnlock = pWal->lockMask & ~(
+ u32 mUnlock;
+ if( pWal->writeLock==2 ) pWal->writeLock = 0;
+ mUnlock = pWal->lockMask & ~(
(pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock)))
| (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0)
| (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0)
@@ -67344,7 +68319,7 @@ static int walHandleException(Wal *pWal){
/*
** Assert that the Wal.lockMask mask, which indicates the locks held
-** by the connenction, is consistent with the Wal.readLock, Wal.writeLock
+** by the connection, is consistent with the Wal.readLock, Wal.writeLock
** and Wal.ckptLock variables. To be used as:
**
** assert( walAssertLockmask(pWal) );
@@ -67595,7 +68570,12 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
if( bWriteLock
|| SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1))
){
- pWal->writeLock = 1;
+ /* If the write-lock was just obtained, set writeLock to 2 instead of
+ ** the usual 1. This causes walIndexPage() to behave as if the
+ ** write-lock were held (so that it allocates new pages as required),
+ ** and walHandleException() to unlock the write-lock if a SEH exception
+ ** is thrown. */
+ if( !bWriteLock ) pWal->writeLock = 2;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
@@ -67896,11 +68876,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
*/
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
- u32 mxReadMark; /* Largest aReadMark[] value */
- int mxI; /* Index of largest aReadMark[] value */
- int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
- u32 mxFrame; /* Wal frame to lock to */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int nBlockTmout = 0;
#endif
@@ -67963,7 +68939,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = walIndexReadHdr(pWal, pChanged);
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- walDisableBlocking(pWal);
if( rc==SQLITE_BUSY_TIMEOUT ){
rc = SQLITE_BUSY;
*pCnt |= WAL_RETRY_BLOCKED_MASK;
@@ -67978,6 +68953,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
** WAL_RETRY this routine will be called again and will probably be
** right on the second iteration.
*/
+ (void)walEnableBlocking(pWal);
if( pWal->apWiData[0]==0 ){
/* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
** We assume this is a transient condition, so return WAL_RETRY. The
@@ -67994,6 +68970,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = SQLITE_BUSY_RECOVERY;
}
}
+ walDisableBlocking(pWal);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -68006,141 +68983,147 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
assert( pWal->apWiData[0]!=0 );
pInfo = walCkptInfo(pWal);
SEH_INJECT_FAULT;
- if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
+ {
+ u32 mxReadMark; /* Largest aReadMark[] value */
+ int mxI; /* Index of largest aReadMark[] value */
+ int i; /* Loop counter */
+ u32 mxFrame; /* Wal frame to lock to */
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
- && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
+ && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
#endif
- ){
- /* The WAL has been completely backfilled (or it is empty).
- ** and can be safely ignored.
- */
- rc = walLockShared(pWal, WAL_READ_LOCK(0));
- walShmBarrier(pWal);
- if( rc==SQLITE_OK ){
- if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
- /* It is not safe to allow the reader to continue here if frames
- ** may have been appended to the log before READ_LOCK(0) was obtained.
- ** When holding READ_LOCK(0), the reader ignores the entire log file,
- ** which implies that the database file contains a trustworthy
- ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
- ** happening, this is usually correct.
- **
- ** However, if frames have been appended to the log (or if the log
- ** is wrapped and written for that matter) before the READ_LOCK(0)
- ** is obtained, that is not necessarily true. A checkpointer may
- ** have started to backfill the appended frames but crashed before
- ** it finished. Leaving a corrupt image in the database file.
- */
- walUnlockShared(pWal, WAL_READ_LOCK(0));
- return WAL_RETRY;
+ ){
+ /* The WAL has been completely backfilled (or it is empty).
+ ** and can be safely ignored.
+ */
+ rc = walLockShared(pWal, WAL_READ_LOCK(0));
+ walShmBarrier(pWal);
+ if( rc==SQLITE_OK ){
+ if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr,sizeof(WalIndexHdr)) ){
+ /* It is not safe to allow the reader to continue here if frames
+ ** may have been appended to the log before READ_LOCK(0) was obtained.
+ ** When holding READ_LOCK(0), the reader ignores the entire log file,
+ ** which implies that the database file contains a trustworthy
+ ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
+ ** happening, this is usually correct.
+ **
+ ** However, if frames have been appended to the log (or if the log
+ ** is wrapped and written for that matter) before the READ_LOCK(0)
+ ** is obtained, that is not necessarily true. A checkpointer may
+ ** have started to backfill the appended frames but crashed before
+ ** it finished. Leaving a corrupt image in the database file.
+ */
+ walUnlockShared(pWal, WAL_READ_LOCK(0));
+ return WAL_RETRY;
+ }
+ pWal->readLock = 0;
+ return SQLITE_OK;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
}
- pWal->readLock = 0;
- return SQLITE_OK;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
}
- }
- /* If we get this far, it means that the reader will want to use
- ** the WAL to get at content from recent commits. The job now is
- ** to select one of the aReadMark[] entries that is closest to
- ** but not exceeding pWal->hdr.mxFrame and lock that entry.
- */
- mxReadMark = 0;
- mxI = 0;
- mxFrame = pWal->hdr.mxFrame;
+ /* If we get this far, it means that the reader will want to use
+ ** the WAL to get at content from recent commits. The job now is
+ ** to select one of the aReadMark[] entries that is closest to
+ ** but not exceeding pWal->hdr.mxFrame and lock that entry.
+ */
+ mxReadMark = 0;
+ mxI = 0;
+ mxFrame = pWal->hdr.mxFrame;
#ifdef SQLITE_ENABLE_SNAPSHOT
- if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){
- mxFrame = pWal->pSnapshot->mxFrame;
- }
-#endif
- for(i=1; i<WAL_NREADER; i++){
- u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT;
- if( mxReadMark<=thisMark && thisMark<=mxFrame ){
- assert( thisMark!=READMARK_NOT_USED );
- mxReadMark = thisMark;
- mxI = i;
+ if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){
+ mxFrame = pWal->pSnapshot->mxFrame;
}
- }
- if( (pWal->readOnly & WAL_SHM_RDONLY)==0
- && (mxReadMark<mxFrame || mxI==0)
- ){
+#endif
for(i=1; i<WAL_NREADER; i++){
- rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
- if( rc==SQLITE_OK ){
- AtomicStore(pInfo->aReadMark+i,mxFrame);
- mxReadMark = mxFrame;
+ u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT;
+ if( mxReadMark<=thisMark && thisMark<=mxFrame ){
+ assert( thisMark!=READMARK_NOT_USED );
+ mxReadMark = thisMark;
mxI = i;
- walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
- break;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
}
}
- }
- if( mxI==0 ){
- assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
- return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
- }
+ if( (pWal->readOnly & WAL_SHM_RDONLY)==0
+ && (mxReadMark<mxFrame || mxI==0)
+ ){
+ for(i=1; i<WAL_NREADER; i++){
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ if( rc==SQLITE_OK ){
+ AtomicStore(pInfo->aReadMark+i,mxFrame);
+ mxReadMark = mxFrame;
+ mxI = i;
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ break;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+ }
+ if( mxI==0 ){
+ assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
+ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
+ }
- (void)walEnableBlockingMs(pWal, nBlockTmout);
- rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
- walDisableBlocking(pWal);
- if( rc ){
+ (void)walEnableBlockingMs(pWal, nBlockTmout);
+ rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
+ walDisableBlocking(pWal);
+ if( rc ){
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- if( rc==SQLITE_BUSY_TIMEOUT ){
- *pCnt |= WAL_RETRY_BLOCKED_MASK;
- }
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ *pCnt |= WAL_RETRY_BLOCKED_MASK;
+ }
#else
- assert( rc!=SQLITE_BUSY_TIMEOUT );
+ assert( rc!=SQLITE_BUSY_TIMEOUT );
#endif
- assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT );
- return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
- }
- /* Now that the read-lock has been obtained, check that neither the
- ** value in the aReadMark[] array or the contents of the wal-index
- ** header have changed.
- **
- ** It is necessary to check that the wal-index header did not change
- ** between the time it was read and when the shared-lock was obtained
- ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
- ** that the log file may have been wrapped by a writer, or that frames
- ** that occur later in the log than pWal->hdr.mxFrame may have been
- ** copied into the database by a checkpointer. If either of these things
- ** happened, then reading the database with the current value of
- ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
- ** instead.
- **
- ** Before checking that the live wal-index header has not changed
- ** since it was read, set Wal.minFrame to the first frame in the wal
- ** file that has not yet been checkpointed. This client will not need
- ** to read any frames earlier than minFrame from the wal file - they
- ** can be safely read directly from the database file.
- **
- ** Because a ShmBarrier() call is made between taking the copy of
- ** nBackfill and checking that the wal-header in shared-memory still
- ** matches the one cached in pWal->hdr, it is guaranteed that the
- ** checkpointer that set nBackfill was not working with a wal-index
- ** header newer than that cached in pWal->hdr. If it were, that could
- ** cause a problem. The checkpointer could omit to checkpoint
- ** a version of page X that lies before pWal->minFrame (call that version
- ** A) on the basis that there is a newer version (version B) of the same
- ** page later in the wal file. But if version B happens to like past
- ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
- ** that it can read version A from the database file. However, since
- ** we can guarantee that the checkpointer that set nBackfill could not
- ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
- */
- pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
- walShmBarrier(pWal);
- if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
- || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
- ){
- walUnlockShared(pWal, WAL_READ_LOCK(mxI));
- return WAL_RETRY;
- }else{
- assert( mxReadMark<=pWal->hdr.mxFrame );
- pWal->readLock = (i16)mxI;
+ assert((rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT);
+ return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
+ }
+ /* Now that the read-lock has been obtained, check that neither the
+ ** value in the aReadMark[] array or the contents of the wal-index
+ ** header have changed.
+ **
+ ** It is necessary to check that the wal-index header did not change
+ ** between the time it was read and when the shared-lock was obtained
+ ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
+ ** that the log file may have been wrapped by a writer, or that frames
+ ** that occur later in the log than pWal->hdr.mxFrame may have been
+ ** copied into the database by a checkpointer. If either of these things
+ ** happened, then reading the database with the current value of
+ ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
+ ** instead.
+ **
+ ** Before checking that the live wal-index header has not changed
+ ** since it was read, set Wal.minFrame to the first frame in the wal
+ ** file that has not yet been checkpointed. This client will not need
+ ** to read any frames earlier than minFrame from the wal file - they
+ ** can be safely read directly from the database file.
+ **
+ ** Because a ShmBarrier() call is made between taking the copy of
+ ** nBackfill and checking that the wal-header in shared-memory still
+ ** matches the one cached in pWal->hdr, it is guaranteed that the
+ ** checkpointer that set nBackfill was not working with a wal-index
+ ** header newer than that cached in pWal->hdr. If it were, that could
+ ** cause a problem. The checkpointer could omit to checkpoint
+ ** a version of page X that lies before pWal->minFrame (call that version
+ ** A) on the basis that there is a newer version (version B) of the same
+ ** page later in the wal file. But if version B happens to like past
+ ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
+ ** that it can read version A from the database file. However, since
+ ** we can guarantee that the checkpointer that set nBackfill could not
+ ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
+ */
+ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
+ walShmBarrier(pWal);
+ if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
+ || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
+ ){
+ walUnlockShared(pWal, WAL_READ_LOCK(mxI));
+ return WAL_RETRY;
+ }else{
+ assert( mxReadMark<=pWal->hdr.mxFrame );
+ pWal->readLock = (i16)mxI;
+ }
}
return rc;
}
@@ -68378,8 +69361,11 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
** read-lock.
*/
SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){
- sqlite3WalEndWriteTransaction(pWal);
+#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
+ assert( pWal->writeLock==0 || pWal->readLock<0 );
+#endif
if( pWal->readLock>=0 ){
+ sqlite3WalEndWriteTransaction(pWal);
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
pWal->readLock = -1;
}
@@ -68572,7 +69558,7 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
** read-transaction was even opened, making this call a no-op.
** Return early. */
if( pWal->writeLock ){
- assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
+ assert( !memcmp(&pWal->hdr,(void*)pWal->apWiData[0],sizeof(WalIndexHdr)) );
return SQLITE_OK;
}
#endif
@@ -68672,6 +69658,7 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ pWal->iReCksum = 0;
}
return rc;
}
@@ -68719,6 +69706,9 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ if( pWal->iReCksum>pWal->hdr.mxFrame ){
+ pWal->iReCksum = 0;
+ }
}
return rc;
@@ -69408,7 +70398,20 @@ SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
Wal *pWal,
sqlite3_snapshot *pSnapshot
){
- pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+ if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){
+ /* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In
+ ** this case set the bGetSnapshot flag so that if the call to
+ ** sqlite3_snapshot_get() is about to read transaction on this wal
+ ** file, it does not take read-lock 0 if the wal file has been completely
+ ** checkpointed. Taking read-lock 0 would work, but then it would be
+ ** possible for a subsequent writer to destroy the snapshot even while
+ ** this connection is holding its read-transaction open. This is contrary
+ ** to user expectations, so we avoid it by not taking read-lock 0. */
+ pWal->bGetSnapshot = 1;
+ }else{
+ pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+ pWal->bGetSnapshot = 0;
+ }
}
/*
@@ -70009,6 +71012,12 @@ struct CellInfo {
#define BTCURSOR_MAX_DEPTH 20
/*
+** Maximum amount of storage local to a database page, regardless of
+** page size.
+*/
+#define BT_MAX_LOCAL 65501 /* 65536 - 35 */
+
+/*
** A cursor is a pointer to a particular entry within a particular
** b-tree within a database file.
**
@@ -70416,7 +71425,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
*/
static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
int i;
- int skipOk = 1;
+ u8 skipOk = 1;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nDb; i++){
@@ -71272,7 +72281,7 @@ static int saveCursorKey(BtCursor *pCur){
** below. */
void *pKey;
pCur->nKey = sqlite3BtreePayloadSize(pCur);
- pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
+ pKey = sqlite3Malloc( ((i64)pCur->nKey) + 9 + 8 );
if( pKey ){
rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
@@ -71562,7 +72571,7 @@ SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
*/
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
- pCur->hints = x;
+ pCur->hints = (u8)x;
}
@@ -71756,14 +72765,15 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
int maxLocal; /* Maximum amount of payload held locally */
maxLocal = pPage->maxLocal;
+ assert( nPayload>=0 );
if( nPayload<=maxLocal ){
- return nPayload;
+ return (int)nPayload;
}else{
int minLocal; /* Minimum amount of payload held locally */
int surplus; /* Overflow payload available for local storage */
minLocal = pPage->minLocal;
- surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
- return ( surplus <= maxLocal ) ? surplus : minLocal;
+ surplus = (int)(minLocal +(nPayload - minLocal)%(pPage->pBt->usableSize-4));
+ return (surplus <= maxLocal) ? surplus : minLocal;
}
}
@@ -71873,11 +72883,13 @@ static void btreeParseCellPtr(
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
** on the local page. No overflow is required.
*/
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
+ pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell);
if( pInfo->nSize<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
}else{
@@ -71910,11 +72922,13 @@ static void btreeParseCellPtrIndex(
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
** on the local page. No overflow is required.
*/
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
+ pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell);
if( pInfo->nSize<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
}else{
@@ -72453,14 +73467,14 @@ static SQLITE_INLINE int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** at the end of the page. So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
-static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
- u16 iPtr; /* Address of ptr to next freeblock */
- u16 iFreeBlk; /* Address of the next freeblock */
+static int freeSpace(MemPage *pPage, int iStart, int iSize){
+ int iPtr; /* Address of ptr to next freeblock */
+ int iFreeBlk; /* Address of the next freeblock */
u8 hdr; /* Page header size. 0 or 100 */
- u8 nFrag = 0; /* Reduction in fragmentation */
- u16 iOrigSize = iSize; /* Original value of iSize */
- u16 x; /* Offset to cell content area */
- u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
+ int nFrag = 0; /* Reduction in fragmentation */
+ int iOrigSize = iSize; /* Original value of iSize */
+ int x; /* Offset to cell content area */
+ int iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
u8 *pTmp; /* Temporary ptr into data[] */
@@ -72487,7 +73501,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}
iPtr = iFreeBlk;
}
- if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
+ if( iFreeBlk>(int)pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB );
@@ -72502,7 +73516,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage);
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
- if( iEnd > pPage->pBt->usableSize ){
+ if( iEnd > (int)pPage->pBt->usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
iSize = iEnd - iStart;
@@ -72523,7 +73537,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}
}
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
- data[hdr+7] -= nFrag;
+ data[hdr+7] -= (u8)nFrag;
}
pTmp = &data[hdr+5];
x = get2byte(pTmp);
@@ -72544,7 +73558,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* Insert the new freeblock into the freelist */
put2byte(&data[iPtr], iStart);
put2byte(&data[iStart], iFreeBlk);
- put2byte(&data[iStart+2], iSize);
+ assert( iSize>=0 && iSize<=0xffff );
+ put2byte(&data[iStart+2], (u16)iSize);
}
pPage->nFree += iOrigSize;
return SQLITE_OK;
@@ -72770,7 +73785,7 @@ static int btreeInitPage(MemPage *pPage){
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
pPage->maskPage = (u16)(pBt->pageSize - 1);
pPage->nOverflow = 0;
- pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
+ pPage->cellOffset = (u16)(pPage->hdrOffset + 8 + pPage->childPtrSize);
pPage->aCellIdx = data + pPage->childPtrSize + 8;
pPage->aDataEnd = pPage->aData + pBt->pageSize;
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
@@ -72804,8 +73819,8 @@ static int btreeInitPage(MemPage *pPage){
static void zeroPage(MemPage *pPage, int flags){
unsigned char *data = pPage->aData;
BtShared *pBt = pPage->pBt;
- u8 hdr = pPage->hdrOffset;
- u16 first;
+ int hdr = pPage->hdrOffset;
+ int first;
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
@@ -72822,7 +73837,7 @@ static void zeroPage(MemPage *pPage, int flags){
put2byte(&data[hdr+5], pBt->usableSize);
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
- pPage->cellOffset = first;
+ pPage->cellOffset = (u16)first;
pPage->aDataEnd = &data[pBt->pageSize];
pPage->aCellIdx = &data[first];
pPage->aDataOfst = &data[pPage->childPtrSize];
@@ -73608,7 +74623,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve,
BtShared *pBt = p->pBt;
assert( nReserve>=0 && nReserve<=255 );
sqlite3BtreeEnter(p);
- pBt->nReserveWanted = nReserve;
+ pBt->nReserveWanted = (u8)nReserve;
x = pBt->pageSize - pBt->usableSize;
if( nReserve<x ) nReserve = x;
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
@@ -73714,7 +74729,7 @@ SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) );
if( newFlag>=0 ){
p->pBt->btsFlags &= ~BTS_FAST_SECURE;
- p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag;
+ p->pBt->btsFlags |= (u16)(BTS_SECURE_DELETE*newFlag);
}
b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE;
sqlite3BtreeLeave(p);
@@ -74234,6 +75249,13 @@ static SQLITE_NOINLINE int btreeBeginTrans(
(void)sqlite3PagerWalWriteLock(pPager, 0);
unlockBtreeIfUnused(pBt);
}
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ /* If a blocking lock timed out, break out of the loop here so that
+ ** the busy-handler is not invoked. */
+ break;
+ }
+#endif
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
sqlite3PagerWalDb(pPager, 0);
@@ -75289,6 +76311,25 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){
return ROUND8(sizeof(BtCursor));
}
+#ifdef SQLITE_DEBUG
+/*
+** Return true if and only if the Btree object will be automatically
+** closed with the BtCursor closes. This is used within assert() statements
+** only.
+*/
+SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(
+ Btree *pBtree, /* the btree object */
+ BtCursor *pCur /* Corresponding cursor */
+){
+ BtShared *pBt = pBtree->pBt;
+ if( (pBt->openFlags & BTREE_SINGLE)==0 ) return 0;
+ if( pBt->pCursor!=pCur ) return 0;
+ if( pCur->pNext!=0 ) return 0;
+ if( pCur->pBtree!=pBtree ) return 0;
+ return 1;
+}
+#endif
+
/*
** Initialize memory that will be converted into a BtCursor object.
**
@@ -76532,7 +77573,7 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
&& indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
- pCur->curFlags &= ~BTCF_ValidOvfl;
+ pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
@@ -76624,7 +77665,7 @@ bypass_moveto_root:
rc = SQLITE_CORRUPT_PAGE(pPage);
goto moveto_index_finish;
}
- pCellKey = sqlite3Malloc( nCell+nOverrun );
+ pCellKey = sqlite3Malloc( (u64)nCell+(u64)nOverrun );
if( pCellKey==0 ){
rc = SQLITE_NOMEM_BKPT;
goto moveto_index_finish;
@@ -78110,7 +79151,8 @@ static int rebuildPage(
if( j>(u32)usableSize ){ j = 0; }
memcpy(&pTmp[j], &aData[j], usableSize - j);
- for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i; k++){}
+ assert( pCArray->ixNx[NB*2-1]>i );
+ for(k=0; pCArray->ixNx[k]<=i; k++){}
pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
@@ -78142,7 +79184,8 @@ static int rebuildPage(
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
- pPg->nCell = nCell;
+ assert( nCell < 10922 );
+ pPg->nCell = (u16)nCell;
pPg->nOverflow = 0;
put2byte(&aData[hdr+1], 0);
@@ -78193,7 +79236,8 @@ static int pageInsertArray(
u8 *pEnd; /* Maximum extent of cell data */
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
if( iEnd<=iFirst ) return 0;
- for(k=0; ALWAYS(k<NB*2) && pCArray->ixNx[k]<=i ; k++){}
+ assert( pCArray->ixNx[NB*2-1]>i );
+ for(k=0; pCArray->ixNx[k]<=i ; k++){}
pEnd = pCArray->apEnd[k];
while( 1 /*Exit by break*/ ){
int sz, rc;
@@ -78388,9 +79432,13 @@ static int editPage(
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
iNew+nCell, nNew-nCell, pCArray
- ) ) goto editpage_fail;
+ )
+ ){
+ goto editpage_fail;
+ }
- pPg->nCell = nNew;
+ assert( nNew < 10922 );
+ pPg->nCell = (u16)nNew;
pPg->nOverflow = 0;
put2byte(&aData[hdr+3], pPg->nCell);
@@ -78478,6 +79526,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
b.szCell = &szCell;
b.apEnd[0] = pPage->aDataEnd;
b.ixNx[0] = 2;
+ b.ixNx[NB*2-1] = 0x7fffffff;
rc = rebuildPage(&b, 0, 1, pNew);
if( NEVER(rc) ){
releasePage(pNew);
@@ -78698,7 +79747,7 @@ static int balance_nonroot(
int pageFlags; /* Value of pPage->aData[0] */
int iSpace1 = 0; /* First unused byte of aSpace1[] */
int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */
- int szScratch; /* Size of scratch memory requested */
+ u64 szScratch; /* Size of scratch memory requested */
MemPage *apOld[NB]; /* pPage and up to two siblings */
MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */
u8 *pRight; /* Location in parent of right-sibling pointer */
@@ -78713,7 +79762,9 @@ static int balance_nonroot(
CellArray b; /* Parsed information on cells being balanced */
memset(abDone, 0, sizeof(abDone));
- memset(&b, 0, sizeof(b));
+ assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) );
+ memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0]));
+ b.ixNx[NB*2-1] = 0x7fffffff;
pBt = pParent->pBt;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -79304,7 +80355,8 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
- for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
+ assert( b.ixNx[NB*2-1]>j );
+ for(k=0; b.ixNx[k]<=j; k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
@@ -79980,7 +81032,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( pCur->info.nKey==pX->nKey ){
BtreePayload x2;
x2.pData = pX->pKey;
- x2.nData = pX->nKey;
+ x2.nData = (int)pX->nKey; assert( pX->nKey<=0x7fffffff );
x2.nZero = 0;
return btreeOverwriteCell(pCur, &x2);
}
@@ -80161,7 +81213,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
getCellInfo(pSrc);
if( pSrc->info.nPayload<0x80 ){
- *(aOut++) = pSrc->info.nPayload;
+ *(aOut++) = (u8)pSrc->info.nPayload;
}else{
aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
}
@@ -80174,7 +81226,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
nRem = pSrc->info.nPayload;
if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
memcpy(aOut, aIn, nIn);
- pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ pBt->nPreformatSize = nIn + (int)(aOut - pBt->pTmpSpace);
return SQLITE_OK;
}else{
int rc = SQLITE_OK;
@@ -80186,7 +81238,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
u32 nOut; /* Size of output buffer aOut[] */
nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
- pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ pBt->nPreformatSize = (int)nOut + (int)(aOut - pBt->pTmpSpace);
if( nOut<pSrc->info.nPayload ){
pPgnoOut = &aOut[nOut];
pBt->nPreformatSize += 4;
@@ -81807,6 +82859,7 @@ SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){
*/
SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
BtShared *pBt = p->pBt;
+ assert( nBytes==0 || nBytes==sizeof(Schema) );
sqlite3BtreeEnter(p);
if( !pBt->pSchema && nBytes ){
pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
@@ -82923,7 +83976,7 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
** corresponding string value, then it is important that the string be
** derived from the numeric value, not the other way around, to ensure
** that the index and table are consistent. See ticket
-** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for
+** https://sqlite.org/src/info/343634942dd54ab (2018-01-31) for
** an example.
**
** This routine looks at pMem to verify that if it has both a numeric
@@ -83109,7 +84162,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
return;
}
if( pMem->enc!=SQLITE_UTF8 ) return;
- if( NEVER(pMem->z==0) ) return;
+ assert( pMem->z!=0 );
if( pMem->flags & MEM_Dyn ){
if( pMem->xDel==sqlite3_free
&& sqlite3_msize(pMem->z) >= (u64)(pMem->n+1)
@@ -83828,27 +84881,30 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
int i;
Mem *pX;
- for(i=1, pX=pVdbe->aMem+1; i<pVdbe->nMem; i++, pX++){
- if( pX->pScopyFrom==pMem ){
- u16 mFlags;
- if( pVdbe->db->flags & SQLITE_VdbeTrace ){
- sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
- (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
- }
- /* If pX is marked as a shallow copy of pMem, then try to verify that
- ** no significant changes have been made to pX since the OP_SCopy.
- ** A significant change would indicated a missed call to this
- ** function for pX. Minor changes, such as adding or removing a
- ** dual type, are allowed, as long as the underlying value is the
- ** same. */
- mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
- assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
-
- /* pMem is the register that is changing. But also mark pX as
- ** undefined so that we can quickly detect the shallow-copy error */
- pX->flags = MEM_Undefined;
- pX->pScopyFrom = 0;
- }
+ if( pMem->bScopy ){
+ for(i=1, pX=pVdbe->aMem+1; i<pVdbe->nMem; i++, pX++){
+ if( pX->pScopyFrom==pMem ){
+ u16 mFlags;
+ if( pVdbe->db->flags & SQLITE_VdbeTrace ){
+ sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
+ (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
+ }
+ /* If pX is marked as a shallow copy of pMem, then try to verify that
+ ** no significant changes have been made to pX since the OP_SCopy.
+ ** A significant change would indicated a missed call to this
+ ** function for pX. Minor changes, such as adding or removing a
+ ** dual type, are allowed, as long as the underlying value is the
+ ** same. */
+ mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
+ assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
+
+ /* pMem is the register that is changing. But also mark pX as
+ ** undefined so that we can quickly detect the shallow-copy error */
+ pX->flags = MEM_Undefined;
+ pX->pScopyFrom = 0;
+ }
+ }
+ pMem->bScopy = 0;
}
pMem->pScopyFrom = 0;
}
@@ -84219,7 +85275,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
if( pRec==0 ){
Index *pIdx = p->pIdx; /* Index being probed */
- int nByte; /* Bytes of space to allocate */
+ i64 nByte; /* Bytes of space to allocate */
int i; /* Counter variable */
int nCol = pIdx->nColumn; /* Number of index columns including rowid */
@@ -84285,7 +85341,7 @@ static int valueFromFunction(
){
sqlite3_context ctx; /* Context object for function invocation */
sqlite3_value **apVal = 0; /* Function arguments */
- int nVal = 0; /* Size of apVal[] array */
+ int nVal = 0; /* Number of function arguments */
FuncDef *pFunc = 0; /* Function definition */
sqlite3_value *pVal = 0; /* New value */
int rc = SQLITE_OK; /* Return code */
@@ -84316,7 +85372,8 @@ static int valueFromFunction(
goto value_from_function_out;
}
for(i=0; i<nVal; i++){
- rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
+ rc = sqlite3Stat4ValueFromExpr(pCtx->pParse, pList->a[i].pExpr, aff,
+ &apVal[i]);
if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
}
}
@@ -85282,12 +86339,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(
int eCallCtx /* Calling context */
){
Vdbe *v = pParse->pVdbe;
- int nByte;
int addr;
sqlite3_context *pCtx;
assert( v );
- nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
- pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
+ pCtx = sqlite3DbMallocRawNN(pParse->db, SZ_CONTEXT(nArg));
if( pCtx==0 ){
assert( pParse->db->mallocFailed );
freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
@@ -85563,7 +86618,7 @@ static Op *opIterNext(VdbeOpIter *p){
}
if( pRet->p4type==P4_SUBPROGRAM ){
- int nByte = (p->nSub+1)*sizeof(SubProgram*);
+ i64 nByte = (1+(u64)p->nSub)*sizeof(SubProgram*);
int j;
for(j=0; j<p->nSub; j++){
if( p->apSub[j]==pRet->p4.pProgram ) break;
@@ -85693,8 +86748,8 @@ SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){
** (1) For each jump instruction with a negative P2 value (a label)
** resolve the P2 value to an actual address.
**
-** (2) Compute the maximum number of arguments used by any SQL function
-** and store that value in *pMaxFuncArgs.
+** (2) Compute the maximum number of arguments used by the xUpdate/xFilter
+** methods of any virtual table and store that value in *pMaxVtabArgs.
**
** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
** indicate what the prepared statement actually does.
@@ -85707,8 +86762,8 @@ SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){
** script numbers the opcodes correctly. Changes to this routine must be
** coordinated with changes to mkopcodeh.tcl.
*/
-static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
- int nMaxArgs = *pMaxFuncArgs;
+static void resolveP2Values(Vdbe *p, int *pMaxVtabArgs){
+ int nMaxVtabArgs = *pMaxVtabArgs;
Op *pOp;
Parse *pParse = p->pParse;
int *aLabel = pParse->aLabel;
@@ -85753,15 +86808,19 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
case OP_VUpdate: {
- if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
+ if( pOp->p2>nMaxVtabArgs ) nMaxVtabArgs = pOp->p2;
break;
}
case OP_VFilter: {
int n;
+ /* The instruction immediately prior to VFilter will be an
+ ** OP_Integer that sets the "argc" value for the VFilter. See
+ ** the code where OP_VFilter is generated at tag-20250207a. */
assert( (pOp - p->aOp) >= 3 );
assert( pOp[-1].opcode==OP_Integer );
+ assert( pOp[-1].p2==pOp->p3+1 );
n = pOp[-1].p1;
- if( n>nMaxArgs ) nMaxArgs = n;
+ if( n>nMaxVtabArgs ) nMaxVtabArgs = n;
/* Fall through into the default case */
/* no break */ deliberate_fall_through
}
@@ -85802,7 +86861,7 @@ resolve_p2_values_loop_exit:
pParse->aLabel = 0;
}
pParse->nLabel = 0;
- *pMaxFuncArgs = nMaxArgs;
+ *pMaxVtabArgs = nMaxVtabArgs;
assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
}
@@ -86031,7 +87090,7 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(
const char *zName /* Name of table or index being scanned */
){
if( IS_STMT_SCANSTATUS(p->db) ){
- sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
+ i64 nByte = (1+(i64)p->nScan) * sizeof(ScanStatus);
ScanStatus *aNew;
aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
if( aNew ){
@@ -86141,6 +87200,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
*/
SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
+#ifdef SQLITE_DEBUG
+ while( pOp->opcode==OP_ReleaseReg ) pOp--;
+#endif
if( pOp->p3==iDest && pOp->opcode==OP_Column ){
pOp->p5 |= OPFLAG_TYPEOFARG;
}
@@ -86250,6 +87312,12 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
break;
}
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = (SubrtnSig*)p4;
+ sqlite3DbFree(db, pSig->zAff);
+ sqlite3DbFree(db, pSig);
+ break;
+ }
}
}
@@ -86829,6 +87897,11 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
zP4 = pOp->p4.pTab->zName;
break;
}
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = pOp->p4.pSubrtnSig;
+ sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff);
+ break;
+ }
default: {
zP4 = pOp->p4.z;
}
@@ -86970,6 +88043,7 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
** will be initialized before use.
*/
static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
+ assert( db!=0 );
if( N>0 ){
do{
p->flags = flags;
@@ -86977,6 +88051,7 @@ static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
p->szMalloc = 0;
#ifdef SQLITE_DEBUG
p->pScopyFrom = 0;
+ p->bScopy = 0;
#endif
p++;
}while( (--N)>0 );
@@ -86995,6 +88070,7 @@ static void releaseMemArray(Mem *p, int N){
if( p && N ){
Mem *pEnd = &p[N];
sqlite3 *db = p->db;
+ assert( db!=0 );
if( db->pnBytesFreed ){
do{
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
@@ -87466,7 +88542,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
int nVar; /* Number of parameters */
int nMem; /* Number of VM memory registers */
int nCursor; /* Number of cursors required */
- int nArg; /* Number of arguments in subprograms */
+ int nArg; /* Max number args to xFilter or xUpdate */
int n; /* Loop counter */
struct ReusableSpace x; /* Reusable bulk memory */
@@ -87475,6 +88551,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
assert( pParse!=0 );
assert( p->eVdbeState==VDBE_INIT_STATE );
assert( pParse==p->pParse );
+ assert( pParse->db==p->db );
p->pVList = pParse->pVList;
pParse->pVList = 0;
db = p->db;
@@ -87537,6 +88614,9 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
}
}
+#ifdef SQLITE_DEBUG
+ p->napArg = nArg;
+#endif
if( db->mallocFailed ){
p->nVar = 0;
@@ -89034,6 +90114,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
){
UnpackedRecord *p; /* Unpacked record to return */
int nByte; /* Number of bytes required for *p */
+ assert( sizeof(UnpackedRecord) + sizeof(Mem)*65536 < 0x7fffffff );
nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
@@ -89338,7 +90419,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem
** We must use separate SQLITE_NOINLINE functions here, since otherwise
** optimizer code movement causes gcov to become very confused.
*/
-#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
static int SQLITE_NOINLINE doubleLt(double a, double b){ return a<b; }
static int SQLITE_NOINLINE doubleEq(double a, double b){ return a==b; }
#endif
@@ -89353,13 +90434,6 @@ SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){
/* SQLite considers NaN to be a NULL. And all integer values are greater
** than NULL */
return 1;
- }
- if( sqlite3Config.bUseLongDouble ){
- LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
- testcase( x<r );
- testcase( x>r );
- testcase( x==r );
- return (x<r) ? -1 : (x>r);
}else{
i64 y;
if( r<-9223372036854775808.0 ) return +1;
@@ -90347,10 +91421,11 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
preupdate.pCsr = pCsr;
preupdate.op = op;
preupdate.iNewReg = iReg;
- preupdate.keyinfo.db = db;
- preupdate.keyinfo.enc = ENC(db);
- preupdate.keyinfo.nKeyField = pTab->nCol;
- preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
+ preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace;
+ preupdate.pKeyinfo->db = db;
+ preupdate.pKeyinfo->enc = ENC(db);
+ preupdate.pKeyinfo->nKeyField = pTab->nCol;
+ preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
@@ -90360,8 +91435,9 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pUnpacked);
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pNewUnpacked);
+ sqlite3VdbeMemRelease(&preupdate.oldipk);
if( preupdate.aNew ){
int i;
for(i=0; i<pCsr->nField; i++){
@@ -90369,6 +91445,13 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
}
sqlite3DbNNFreeNN(db, preupdate.aNew);
}
+ if( preupdate.apDflt ){
+ int i;
+ for(i=0; i<pTab->nCol; i++){
+ sqlite3ValueFree(preupdate.apDflt[i]);
+ }
+ sqlite3DbFree(db, preupdate.apDflt);
+ }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -90439,7 +91522,6 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
- assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
@@ -91159,7 +92241,7 @@ static int sqlite3Step(Vdbe *p){
}
assert( db->nVdbeWrite>0 || db->autoCommit==0
- || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
+ || ((db->nDeferredCons + db->nDeferredImmCons)==0)
);
#ifndef SQLITE_OMIT_TRACE
@@ -91670,6 +92752,7 @@ static const Mem *columnNullValue(void){
#ifdef SQLITE_DEBUG
/* .pScopyFrom = */ (Mem*)0,
/* .mScopyFlags= */ 0,
+ /* .bScopy = */ 0,
#endif
};
return &nullMem;
@@ -91711,7 +92794,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
** sqlite3_column_int64()
** sqlite3_column_text()
** sqlite3_column_text16()
-** sqlite3_column_real()
+** sqlite3_column_double()
** sqlite3_column_bytes()
** sqlite3_column_bytes16()
** sqlite3_column_blob()
@@ -91997,6 +93080,17 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
+**
+** (tag-20240917-01) If vdbeUnbind(p,(u32)(i-1)) returns SQLITE_OK,
+** that means all of the the following will be true:
+**
+** p!=0
+** p->pVar!=0
+** i>0
+** i<=p->nVar
+**
+** An assert() is normally added after vdbeUnbind() to help static analyzers
+** realize this.
*/
static int vdbeUnbind(Vdbe *p, unsigned int i){
Mem *pVar;
@@ -92054,6 +93148,7 @@ static int bindText(
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
if( zData!=0 ){
pVar = &p->aVar[i-1];
rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
@@ -92103,6 +93198,7 @@ SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
sqlite3_mutex_leave(p->db->mutex);
}
@@ -92116,6 +93212,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
sqlite3_mutex_leave(p->db->mutex);
}
@@ -92126,6 +93223,7 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
@@ -92141,6 +93239,7 @@ SQLITE_API int sqlite3_bind_pointer(
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
sqlite3_mutex_leave(p->db->mutex);
}else if( xDestructor ){
@@ -92168,7 +93267,7 @@ SQLITE_API int sqlite3_bind_text64(
assert( xDel!=SQLITE_DYNAMIC );
if( enc!=SQLITE_UTF8 ){
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
- nData &= ~(u16)1;
+ nData &= ~(u64)1;
}
return bindText(pStmt, i, zData, nData, xDel, enc);
}
@@ -92222,6 +93321,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
@@ -92535,6 +93635,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
PreUpdate *p;
Mem *pMem;
int rc = SQLITE_OK;
+ int iStore = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( db==0 || ppValue==0 ){
@@ -92549,44 +93650,75 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_old_out;
}
if( p->pPk ){
- iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ }else{
+ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
+ if( iStore>=p->pCsr->nField || iStore<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
}
- /* If the old.* record has not yet been loaded into memory, do so now. */
- if( p->pUnpacked==0 ){
- u32 nRec;
- u8 *aRec;
+ if( iIdx==p->pTab->iPKey ){
+ *ppValue = pMem = &p->oldipk;
+ sqlite3VdbeMemSetInt64(pMem, p->iKey1);
+ }else{
- assert( p->pCsr->eCurType==CURTYPE_BTREE );
- nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
- aRec = sqlite3DbMallocRaw(db, nRec);
- if( !aRec ) goto preupdate_old_out;
- rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
- if( rc==SQLITE_OK ){
- p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
- if( !p->pUnpacked ) rc = SQLITE_NOMEM;
- }
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, aRec);
- goto preupdate_old_out;
+ /* If the old.* record has not yet been loaded into memory, do so now. */
+ if( p->pUnpacked==0 ){
+ u32 nRec;
+ u8 *aRec;
+
+ assert( p->pCsr->eCurType==CURTYPE_BTREE );
+ nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
+ aRec = sqlite3DbMallocRaw(db, nRec);
+ if( !aRec ) goto preupdate_old_out;
+ rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
+ if( rc==SQLITE_OK ){
+ p->pUnpacked = vdbeUnpackRecord(p->pKeyinfo, nRec, aRec);
+ if( !p->pUnpacked ) rc = SQLITE_NOMEM;
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, aRec);
+ goto preupdate_old_out;
+ }
+ p->aRecord = aRec;
}
- p->aRecord = aRec;
- }
- pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey1);
- }else if( iIdx>=p->pUnpacked->nField ){
- *ppValue = (sqlite3_value *)columnNullValue();
- }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & (MEM_Int|MEM_IntReal) ){
- testcase( pMem->flags & MEM_Int );
- testcase( pMem->flags & MEM_IntReal );
- sqlite3VdbeMemRealify(pMem);
+ pMem = *ppValue = &p->pUnpacked->aMem[iStore];
+ if( iStore>=p->pUnpacked->nField ){
+ /* This occurs when the table has been extended using ALTER TABLE
+ ** ADD COLUMN. The value to return is the default value of the column. */
+ Column *pCol = &p->pTab->aCol[iIdx];
+ if( pCol->iDflt>0 ){
+ if( p->apDflt==0 ){
+ int nByte;
+ assert( sizeof(sqlite3_value*)*UMXV(p->pTab->nCol) < 0x7fffffff );
+ nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
+ p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
+ if( p->apDflt==0 ) goto preupdate_old_out;
+ }
+ if( p->apDflt[iIdx]==0 ){
+ sqlite3_value *pVal = 0;
+ Expr *pDflt;
+ assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
+ pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
+ rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
+ if( rc==SQLITE_OK && pVal==0 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+ p->apDflt[iIdx] = pVal;
+ }
+ *ppValue = p->apDflt[iIdx];
+ }else{
+ *ppValue = (sqlite3_value *)columnNullValue();
+ }
+ }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
+ if( pMem->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pMem->flags & MEM_Int );
+ testcase( pMem->flags & MEM_IntReal );
+ sqlite3VdbeMemRealify(pMem);
+ }
}
}
@@ -92608,7 +93740,7 @@ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){
#else
p = db->pPreUpdate;
#endif
- return (p ? p->keyinfo.nKeyField : 0);
+ return (p ? p->pKeyinfo->nKeyField : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -92660,6 +93792,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
PreUpdate *p;
int rc = SQLITE_OK;
Mem *pMem;
+ int iStore = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( db==0 || ppValue==0 ){
@@ -92672,9 +93805,12 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_new_out;
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
- iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ }else{
+ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
+
+ if( iStore>=p->pCsr->nField || iStore<0 ){
rc = SQLITE_RANGE;
goto preupdate_new_out;
}
@@ -92687,40 +93823,41 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
Mem *pData = &p->v->aMem[p->iNewReg];
rc = ExpandBlob(pData);
if( rc!=SQLITE_OK ) goto preupdate_new_out;
- pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
+ pUnpack = vdbeUnpackRecord(p->pKeyinfo, pData->n, pData->z);
if( !pUnpack ){
rc = SQLITE_NOMEM;
goto preupdate_new_out;
}
p->pNewUnpacked = pUnpack;
}
- pMem = &pUnpack->aMem[iIdx];
+ pMem = &pUnpack->aMem[iStore];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
- }else if( iIdx>=pUnpack->nField ){
+ }else if( iStore>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
}
}else{
- /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
+ /* For an UPDATE, memory cell (p->iNewReg+1+iStore) contains the required
** value. Make a copy of the cell contents and return a pointer to it.
** It is not safe to return a pointer to the memory cell itself as the
** caller may modify the value text encoding.
*/
assert( p->op==SQLITE_UPDATE );
if( !p->aNew ){
- p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField);
+ assert( sizeof(Mem)*UMXV(p->pCsr->nField) < 0x7fffffff );
+ p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem)*p->pCsr->nField);
if( !p->aNew ){
rc = SQLITE_NOMEM;
goto preupdate_new_out;
}
}
- assert( iIdx>=0 && iIdx<p->pCsr->nField );
- pMem = &p->aNew[iIdx];
+ assert( iStore>=0 && iStore<p->pCsr->nField );
+ pMem = &p->aNew[iStore];
if( pMem->flags==0 ){
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}else{
- rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
+ rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iStore]);
if( rc!=SQLITE_OK ) goto preupdate_new_out;
}
}
@@ -93135,6 +94272,104 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
/* #include "vdbeInt.h" */
/*
+** High-resolution hardware timer used for debugging and testing only.
+*/
+#if defined(VDBE_PROFILE) \
+ || defined(SQLITE_PERFORMANCE_TRACE) \
+ || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+/************** Include hwtime.h in the middle of vdbe.c *********************/
+/************** Begin file hwtime.h ******************************************/
+/*
+** 2008 May 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains inline asm code for retrieving "high-performance"
+** counters for x86 and x86_64 class CPUs.
+*/
+#ifndef SQLITE_HWTIME_H
+#define SQLITE_HWTIME_H
+
+/*
+** The following routine only works on Pentium-class (or newer) processors.
+** It uses the RDTSC opcode to read the cycle count value out of the
+** processor and returns that value. This can be used for high-res
+** profiling.
+*/
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
+
+ #if defined(__GNUC__)
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+ #elif defined(_MSC_VER)
+
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+ __asm {
+ rdtsc
+ ret ; return value at EDX:EAX
+ }
+ }
+
+ #endif
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
+ }
+
+#else
+
+ /*
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
+ */
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+
+#endif
+
+#endif /* !defined(SQLITE_HWTIME_H) */
+
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in vdbe.c ***********************/
+#endif
+
+/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell. This macro verifies that shallow copies are
** not misused. A shallow copy of a string or blob just copies a
@@ -93380,11 +94615,11 @@ static VdbeCursor *allocateCursor(
*/
Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
- int nByte;
+ i64 nByte;
VdbeCursor *pCx = 0;
- nByte =
- ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
- (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
+ nByte = SZ_VDBECURSOR(nField);
+ assert( ROUND8(nByte)==nByte );
+ if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize();
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
@@ -93408,7 +94643,7 @@ static VdbeCursor *allocateCursor(
pMem->szMalloc = 0;
return 0;
}
- pMem->szMalloc = nByte;
+ pMem->szMalloc = (int)nByte;
}
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
@@ -93417,8 +94652,8 @@ static VdbeCursor *allocateCursor(
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) );
+ pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)];
sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
@@ -93711,6 +94946,7 @@ static void registerTrace(int iReg, Mem *p){
printf("R[%d] = ", iReg);
memTracePrint(p);
if( p->pScopyFrom ){
+ assert( p->pScopyFrom->bScopy );
printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
}
printf("\n");
@@ -94327,7 +95563,7 @@ case OP_HaltIfNull: { /* in3 */
/* no break */ deliberate_fall_through
}
-/* Opcode: Halt P1 P2 * P4 P5
+/* Opcode: Halt P1 P2 P3 P4 P5
**
** Exit immediately. All open cursors, etc are closed
** automatically.
@@ -94340,18 +95576,22 @@ case OP_HaltIfNull: { /* in3 */
** then back out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
-** If P4 is not null then it is an error message string.
+** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
+** text of an error message.
+**
+** If P3 is zero and P4 is not null then the error message string is held
+** in P4.
**
-** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
+** P5 is a value between 1 and 4, inclusive, then the P4 error message
+** string is modified as follows:
**
-** 0: (no change)
** 1: NOT NULL constraint failed: P4
** 2: UNIQUE constraint failed: P4
** 3: CHECK constraint failed: P4
** 4: FOREIGN KEY constraint failed: P4
**
-** If P5 is not zero and P4 is NULL, then everything after the ":" is
-** omitted.
+** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
+** the ":" is omitted.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
@@ -94364,6 +95604,9 @@ case OP_Halt: {
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
+ assert( pOp->p4type==P4_NOTUSED
+ || pOp->p4type==P4_STATIC
+ || pOp->p4type==P4_DYNAMIC );
/* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
** something is wrong with the code generator. Raise an assertion in order
@@ -94394,7 +95637,12 @@ case OP_Halt: {
p->errorAction = (u8)pOp->p2;
assert( pOp->p5<=4 );
if( p->rc ){
- if( pOp->p5 ){
+ if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){
+ const char *zErr;
+ assert( pOp->p3<=(p->nMem + 1 - p->nCursor) );
+ zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8);
+ sqlite3VdbeError(p, "%s", zErr);
+ }else if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
"FOREIGN KEY" };
testcase( pOp->p5==1 );
@@ -94409,7 +95657,7 @@ case OP_Halt: {
sqlite3VdbeError(p, "%s", pOp->p4.z);
}
pcx = (int)(pOp - aOp);
- sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
+ sqlite3_log(pOp->p1, "abort at %d: %s; [%s]", pcx, p->zErrMsg, p->zSql);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -94682,6 +95930,7 @@ case OP_Move: {
{ int i;
for(i=1; i<p->nMem; i++){
if( aMem[i].pScopyFrom==pIn1 ){
+ assert( aMem[i].bScopy );
aMem[i].pScopyFrom = pOut;
}
}
@@ -94754,6 +96003,7 @@ case OP_SCopy: { /* out2 */
#ifdef SQLITE_DEBUG
pOut->pScopyFrom = pIn1;
pOut->mScopyFlags = pIn1->flags;
+ pIn1->bScopy = 1;
#endif
break;
}
@@ -95197,7 +96447,7 @@ case OP_RealAffinity: { /* in1 */
}
#endif
-#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_ANALYZE)
+#if !defined(SQLITE_OMIT_CAST) || !defined(SQLITE_OMIT_ANALYZE)
/* Opcode: Cast P1 P2 * * *
** Synopsis: affinity(r[P1])
**
@@ -95733,7 +96983,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
break;
}
-/* Opcode: Once P1 P2 * * *
+/* Opcode: Once P1 P2 P3 * *
**
** Fall through to the next instruction the first time this opcode is
** encountered on each invocation of the byte-code program. Jump to P2
@@ -95749,6 +96999,12 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
** whether or not the jump should be taken. The bitmask is necessary
** because the self-altering code trick does not work for recursive
** triggers.
+**
+** The P3 operand is not used directly by this opcode. However P3 is
+** used by the code generator as follows: If this opcode is the start
+** of a subroutine and that subroutine uses a Bloom filter, then P3 will
+** be the register that holds that Bloom filter. See tag-202407032019
+** in the source code for implementation details.
*/
case OP_Once: { /* jump */
u32 iAddr; /* Address of this instruction */
@@ -96794,6 +98050,7 @@ case OP_MakeRecord: {
zHdr += sqlite3PutVarint(zHdr, serial_type);
if( pRec->n ){
assert( pRec->z!=0 );
+ assert( pRec->z!=(const char*)sqlite3CtypeMap );
memcpy(zPayload, pRec->z, pRec->n);
zPayload += pRec->n;
}
@@ -97437,23 +98694,23 @@ case OP_OpenWrite:
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
p->minWriteFileFormat = pDb->pSchema->file_format;
}
+ if( pOp->p5 & OPFLAG_P2ISREG ){
+ assert( p2>0 );
+ assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
+ pIn2 = &aMem[p2];
+ assert( memIsValid(pIn2) );
+ assert( (pIn2->flags & MEM_Int)!=0 );
+ sqlite3VdbeMemIntegerify(pIn2);
+ p2 = (int)pIn2->u.i;
+ /* The p2 value always comes from a prior OP_CreateBtree opcode and
+ ** that opcode will always set the p2 value to 2 or more or else fail.
+ ** If there were a failure, the prepared statement would have halted
+ ** before reaching this instruction. */
+ assert( p2>=2 );
+ }
}else{
wrFlag = 0;
- }
- if( pOp->p5 & OPFLAG_P2ISREG ){
- assert( p2>0 );
- assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
- assert( pOp->opcode==OP_OpenWrite );
- pIn2 = &aMem[p2];
- assert( memIsValid(pIn2) );
- assert( (pIn2->flags & MEM_Int)!=0 );
- sqlite3VdbeMemIntegerify(pIn2);
- p2 = (int)pIn2->u.i;
- /* The p2 value always comes from a prior OP_CreateBtree opcode and
- ** that opcode will always set the p2 value to 2 or more or else fail.
- ** If there were a failure, the prepared statement would have halted
- ** before reaching this instruction. */
- assert( p2>=2 );
+ assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
}
if( pOp->p4type==P4_KEYINFO ){
pKeyInfo = pOp->p4.pKeyInfo;
@@ -97630,8 +98887,13 @@ case OP_OpenEphemeral: { /* ncycle */
}
}
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ assert( p->apCsr[pOp->p1]==pCx );
if( rc ){
+ assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
sqlite3BtreeClose(pCx->ub.pBtx);
+ p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */
+ }else{
+ assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
}
}
}
@@ -98409,6 +99671,7 @@ case OP_Found: { /* jump, in3, ncycle */
r.pKeyInfo = pC->pKeyInfo;
r.default_rc = 0;
#ifdef SQLITE_DEBUG
+ (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */
for(ii=0; ii<r.nField; ii++){
assert( memIsValid(&r.aMem[ii]) );
assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
@@ -99139,7 +100402,7 @@ case OP_RowData: {
/* The OP_RowData opcodes always follow OP_NotExists or
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
** that might invalidate the cursor.
- ** If this where not the case, on of the following assert()s
+ ** If this were not the case, one of the following assert()s
** would fail. Should this ever change (because of changes in the code
** generator) then the fix would be to insert a call to
** sqlite3VdbeCursorMoveto().
@@ -100408,7 +101671,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
*/
case OP_Program: { /* jump0 */
int nMem; /* Number of memory registers for sub-program */
- int nByte; /* Bytes of runtime space required for sub-program */
+ i64 nByte; /* Bytes of runtime space required for sub-program */
Mem *pRt; /* Register to allocate runtime space */
Mem *pMem; /* Used to iterate through memory cells */
Mem *pEnd; /* Last memory cell in new array */
@@ -100459,7 +101722,7 @@ case OP_Program: { /* jump0 */
nByte = ROUND8(sizeof(VdbeFrame))
+ nMem * sizeof(Mem)
+ pProgram->nCsr * sizeof(VdbeCursor*)
- + (pProgram->nOp + 7)/8;
+ + (7 + (i64)pProgram->nOp)/8;
pFrame = sqlite3DbMallocZero(db, nByte);
if( !pFrame ){
goto no_mem;
@@ -100467,7 +101730,7 @@ case OP_Program: { /* jump0 */
sqlite3VdbeMemRelease(pRt);
pRt->flags = MEM_Blob|MEM_Dyn;
pRt->z = (char*)pFrame;
- pRt->n = nByte;
+ pRt->n = (int)nByte;
pRt->xDel = sqlite3VdbeFrameMemDel;
pFrame->v = p;
@@ -100566,12 +101829,14 @@ case OP_Param: { /* out2 */
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
- if( db->flags & SQLITE_DeferFKs ){
- db->nDeferredImmCons += pOp->p2;
- }else if( pOp->p1 ){
+ if( pOp->p1 ){
db->nDeferredCons += pOp->p2;
}else{
- p->nFkConstraint += pOp->p2;
+ if( db->flags & SQLITE_DeferFKs ){
+ db->nDeferredImmCons += pOp->p2;
+ }else{
+ p->nFkConstraint += pOp->p2;
+ }
}
break;
}
@@ -100771,18 +102036,29 @@ case OP_AggInverse:
case OP_AggStep: {
int n;
sqlite3_context *pCtx;
+ u64 nAlloc;
assert( pOp->p4type==P4_FUNCDEF );
n = pOp->p5;
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
- (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
+
+ /* Allocate space for (a) the context object and (n-1) extra pointers
+ ** to append to the sqlite3_context.argv[1] array, and (b) a memory
+ ** cell in which to store the accumulation. Be careful that the memory
+ ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
+ **
+ ** Note: We could avoid this by using a regular memory cell from aMem[] for
+ ** the accumulator, instead of allocating one here. */
+ nAlloc = ROUND8P( SZ_CONTEXT(n) );
+ pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
if( pCtx==0 ) goto no_mem;
- pCtx->pMem = 0;
- pCtx->pOut = (Mem*)&(pCtx->argv[n]);
+ pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
+ assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
+
sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
+ pCtx->pMem = 0;
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
@@ -101435,6 +102711,7 @@ case OP_VFilter: { /* jump, ncycle */
/* Invoke the xFilter method */
apArg = p->apArg;
+ assert( nArg<=p->napArg );
for(i = 0; i<nArg; i++){
apArg[i] = &pArgc[i+1];
}
@@ -101645,6 +102922,7 @@ case OP_VUpdate: {
u8 vtabOnConflict = db->vtabOnConflict;
apArg = p->apArg;
pX = &aMem[pOp->p3];
+ assert( nArg<=p->napArg );
for(i=0; i<nArg; i++){
assert( memIsValid(pX) );
memAboutToChange(p, pX);
@@ -102116,14 +103394,29 @@ case OP_ReleaseReg: {
/* Opcode: Noop * * * * *
**
-** Do nothing. This instruction is often useful as a jump
-** destination.
+** Do nothing. Continue downward to the next opcode.
*/
-/*
-** The magic Explain opcode are only inserted when explain==2 (which
-** is to say when the EXPLAIN QUERY PLAN syntax is used.)
-** This opcode records information from the optimizer. It is the
-** the same as a no-op. This opcodesnever appears in a real VM program.
+/* Opcode: Explain P1 P2 P3 P4 *
+**
+** This is the same as OP_Noop during normal query execution. The
+** purpose of this opcode is to hold information about the query
+** plan for the purpose of EXPLAIN QUERY PLAN output.
+**
+** The P4 value is human-readable text that describes the query plan
+** element. Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1".
+**
+** The P1 value is the ID of the current element and P2 is the parent
+** element for the case of nested query plan elements. If P2 is zero
+** then this element is a top-level element.
+**
+** For loop elements, P3 is the estimated code of each invocation of this
+** element.
+**
+** As with all opcodes, the meanings of the parameters for OP_Explain
+** are subject to change from one release to the next. Applications
+** should not attempt to interpret or use any of the information
+** contained in the OP_Explain opcode. The information provided by this
+** opcode is intended for testing and debugging use only.
*/
default: { /* This is really OP_Noop, OP_Explain */
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
@@ -102206,8 +103499,8 @@ abort_due_to_error:
p->rc = rc;
sqlite3SystemError(db, rc);
testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(rc, "statement aborts at %d: [%s] %s",
- (int)(pOp - aOp), p->zSql, p->zErrMsg);
+ sqlite3_log(rc, "statement aborts at %d: %s; [%s]",
+ (int)(pOp - aOp), p->zErrMsg, p->zSql);
if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
@@ -102416,6 +103709,7 @@ SQLITE_API int sqlite3_blob_open(
char *zErr = 0;
Table *pTab;
Incrblob *pBlob = 0;
+ int iDb;
Parse sParse;
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -102450,13 +103744,21 @@ SQLITE_API int sqlite3_blob_open(
pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
}
+ if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){
+ pTab = 0;
+ sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s",
+ zTable);
+ }
#ifndef SQLITE_OMIT_VIEW
if( pTab && IsView(pTab) ){
pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
}
#endif
- if( !pTab ){
+ if( pTab==0
+ || ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 &&
+ sqlite3OpenTempDatabase(&sParse))
+ ){
if( sParse.zErrMsg ){
sqlite3DbFree(db, zErr);
zErr = sParse.zErrMsg;
@@ -102467,15 +103769,11 @@ SQLITE_API int sqlite3_blob_open(
goto blob_open_out;
}
pBlob->pTab = pTab;
- pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
+ pBlob->zDb = db->aDb[iDb].zDbSName;
/* Now search pTab for the exact column. */
- for(iCol=0; iCol<pTab->nCol; iCol++) {
- if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){
- break;
- }
- }
- if( iCol==pTab->nCol ){
+ iCol = sqlite3ColumnIndex(pTab, zColumn);
+ if( iCol<0 ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
rc = SQLITE_ERROR;
@@ -102555,7 +103853,6 @@ SQLITE_API int sqlite3_blob_open(
{OP_Halt, 0, 0, 0}, /* 5 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
VdbeOp *aOp;
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
@@ -103133,9 +104430,12 @@ struct VdbeSorter {
u8 iPrev; /* Previous thread used to flush PMA */
u8 nTask; /* Size of aTask[] array */
u8 typeMask;
- SortSubtask aTask[1]; /* One or more subtasks */
+ SortSubtask aTask[FLEXARRAY]; /* One or more subtasks */
};
+/* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */
+#define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask))
+
#define SORTER_TYPE_INTEGER 0x01
#define SORTER_TYPE_TEXT 0x02
@@ -103357,13 +104657,14 @@ static int vdbePmaReadBlob(
while( nRem>0 ){
int rc; /* vdbePmaReadBlob() return code */
int nCopy; /* Number of bytes to copy */
- u8 *aNext; /* Pointer to buffer to copy data from */
+ u8 *aNext = 0; /* Pointer to buffer to copy data from */
nCopy = nRem;
if( nRem>p->nBuffer ) nCopy = p->nBuffer;
rc = vdbePmaReadBlob(p, nCopy, &aNext);
if( rc!=SQLITE_OK ) return rc;
assert( aNext!=p->aAlloc );
+ assert( aNext!=0 );
memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
nRem -= nCopy;
}
@@ -103736,7 +105037,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
VdbeSorter *pSorter; /* The new sorter */
KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
- int sz; /* Size of pSorter in bytes */
+ i64 sz; /* Size of pSorter in bytes */
int rc = SQLITE_OK;
#if SQLITE_MAX_WORKER_THREADS==0
# define nWorker 0
@@ -103764,8 +105065,10 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
assert( pCsr->pKeyInfo );
assert( !pCsr->isEphemeral );
assert( pCsr->eCurType==CURTYPE_SORTER );
- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
- sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
+ assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
+ < 0x7fffffff );
+ szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField);
+ sz = SZ_VDBESORTER(nWorker+1);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
pCsr->uc.pSorter = pSorter;
@@ -103977,7 +105280,7 @@ static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){
*/
static MergeEngine *vdbeMergeEngineNew(int nReader){
int N = 2; /* Smallest power of two >= nReader */
- int nByte; /* Total bytes of space to allocate */
+ i64 nByte; /* Total bytes of space to allocate */
MergeEngine *pNew; /* Pointer to allocated object to return */
assert( nReader<=SORTER_MAX_MERGE_COUNT );
@@ -104229,6 +105532,10 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
p->u.pNext = 0;
for(i=0; aSlot[i]; i++){
p = vdbeSorterMerge(pTask, p, aSlot[i]);
+ /* ,--Each aSlot[] holds twice as much as the previous. So we cannot use
+ ** | up all 64 aSlots[] with only a 64-bit address space.
+ ** v */
+ assert( i<ArraySize(aSlot) );
aSlot[i] = 0;
}
aSlot[i] = p;
@@ -106633,7 +107940,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
pSrc = p->pSrc;
if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ if( pItem->fg.isSubquery
+ && sqlite3WalkSelect(pWalker, pItem->u4.pSubq->pSelect)
+ ){
return WRC_Abort;
}
if( pItem->fg.isTabFunc
@@ -106939,7 +108248,7 @@ static void extendFJMatch(
if( pNew ){
pNew->iTable = pMatch->iCursor;
pNew->iColumn = iColumn;
- pNew->y.pTab = pMatch->pTab;
+ pNew->y.pTab = pMatch->pSTab;
assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
ExprSetProperty(pNew, EP_CanBeNull);
*ppList = sqlite3ExprListAppend(pParse, *ppList, pNew);
@@ -107018,7 +108327,6 @@ static int lookupName(
Schema *pSchema = 0; /* Schema of the expression */
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
Table *pTab = 0; /* Table holding the row */
- Column *pCol; /* A column of pTab */
ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */
const char *zCol = pRight->u.zToken;
@@ -107069,11 +108377,10 @@ static int lookupName(
if( pSrcList ){
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
- u8 hCol;
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
assert( pTab!=0 && pTab->zName!=0 );
assert( pTab->nCol>0 || pParse->nErr );
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem));
if( pItem->fg.isNestedFrom ){
/* In this case, pItem is a subquery that has been formed from a
** parenthesized subset of the FROM clause terms. Example:
@@ -107082,8 +108389,12 @@ static int lookupName(
** This pItem -------------^
*/
int hit = 0;
- assert( pItem->pSelect!=0 );
- pEList = pItem->pSelect->pEList;
+ Select *pSel;
+ assert( pItem->fg.isSubquery );
+ assert( pItem->u4.pSubq!=0 );
+ pSel = pItem->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ pEList = pSel->pEList;
assert( pEList!=0 );
assert( pEList->nExpr==pTab->nCol );
for(j=0; j<pEList->nExpr; j++){
@@ -107153,43 +108464,38 @@ static int lookupName(
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
- hCol = sqlite3StrIHash(zCol);
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( pCol->hName==hCol
- && sqlite3StrICmp(pCol->zCnName, zCol)==0
- ){
- if( cnt>0 ){
- if( pItem->fg.isUsing==0
- || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
- ){
- /* Two or more tables have the same column name which is
- ** not joined by USING. This is an error. Signal as much
- ** by clearing pFJMatch and letting cnt go above 1. */
- sqlite3ExprListDelete(db, pFJMatch);
- pFJMatch = 0;
- }else
- if( (pItem->fg.jointype & JT_RIGHT)==0 ){
- /* An INNER or LEFT JOIN. Use the left-most table */
- continue;
- }else
- if( (pItem->fg.jointype & JT_LEFT)==0 ){
- /* A RIGHT JOIN. Use the right-most table */
- cnt = 0;
- sqlite3ExprListDelete(db, pFJMatch);
- pFJMatch = 0;
- }else{
- /* For a FULL JOIN, we must construct a coalesce() func */
- extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
- }
- }
- cnt++;
- pMatch = pItem;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
- if( pItem->fg.isNestedFrom ){
- sqlite3SrcItemColumnUsed(pItem, j);
+ j = sqlite3ColumnIndex(pTab, zCol);
+ if( j>=0 ){
+ if( cnt>0 ){
+ if( pItem->fg.isUsing==0
+ || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
+ ){
+ /* Two or more tables have the same column name which is
+ ** not joined by USING. This is an error. Signal as much
+ ** by clearing pFJMatch and letting cnt go above 1. */
+ sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else
+ if( (pItem->fg.jointype & JT_RIGHT)==0 ){
+ /* An INNER or LEFT JOIN. Use the left-most table */
+ continue;
+ }else
+ if( (pItem->fg.jointype & JT_LEFT)==0 ){
+ /* A RIGHT JOIN. Use the right-most table */
+ cnt = 0;
+ sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else{
+ /* For a FULL JOIN, we must construct a coalesce() func */
+ extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
}
- break;
+ }
+ cnt++;
+ pMatch = pItem;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
+ if( pItem->fg.isNestedFrom ){
+ sqlite3SrcItemColumnUsed(pItem, j);
}
}
if( 0==cnt && VisibleRowid(pTab) ){
@@ -107206,9 +108512,9 @@ static int lookupName(
*/
if( cntTab==0
|| (cntTab==1
- && ALWAYS(pMatch!=0)
- && ALWAYS(pMatch->pTab!=0)
- && (pMatch->pTab->tabFlags & TF_Ephemeral)!=0
+ && pMatch!=0
+ && ALWAYS(pMatch->pSTab!=0)
+ && (pMatch->pSTab->tabFlags & TF_Ephemeral)!=0
&& (pTab->tabFlags & TF_Ephemeral)==0)
){
cntTab = 1;
@@ -107229,7 +108535,7 @@ static int lookupName(
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
assert( ExprUseYTab(pExpr) );
- pExpr->y.pTab = pMatch->pTab;
+ pExpr->y.pTab = pMatch->pSTab;
if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
@@ -107271,7 +108577,7 @@ static int lookupName(
if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
- pTab = pUpsert->pUpsertSrc->a[0].pTab;
+ pTab = pUpsert->pUpsertSrc->a[0].pSTab;
pExpr->iTable = EXCLUDED_TABLE_NUMBER;
}
}
@@ -107279,23 +108585,18 @@ static int lookupName(
if( pTab ){
int iCol;
- u8 hCol = sqlite3StrIHash(zCol);
pSchema = pTab->pSchema;
cntTab++;
- for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
- if( pCol->hName==hCol
- && sqlite3StrICmp(pCol->zCnName, zCol)==0
- ){
- if( iCol==pTab->iPKey ){
- iCol = -1;
- }
- break;
+ iCol = sqlite3ColumnIndex(pTab, zCol);
+ if( iCol>=0 ){
+ if( pTab->iPKey==iCol ) iCol = -1;
+ }else{
+ if( sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
+ iCol = -1;
+ }else{
+ iCol = pTab->nCol;
}
}
- if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
- /* IMP: R-51414-32910 */
- iCol = -1;
- }
if( iCol<pTab->nCol ){
cnt++;
pMatch = 0;
@@ -107354,11 +108655,11 @@ static int lookupName(
&& pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlite3IsRowid(zCol)
- && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
+ && ALWAYS(VisibleRowid(pMatch->pSTab) || pMatch->fg.isNestedFrom)
){
cnt = cntTab;
#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
- if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
+ if( pMatch->pSTab!=0 && IsView(pMatch->pSTab) ){
eNewExprOp = TK_NULL;
}
#endif
@@ -107595,7 +108896,7 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
SrcItem *pItem = &pSrc->a[iSrc];
Table *pTab;
assert( ExprUseYTab(p) );
- pTab = p->y.pTab = pItem->pTab;
+ pTab = p->y.pTab = pItem->pSTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
@@ -107714,7 +109015,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
assert( ExprUseYTab(pExpr) );
- pExpr->y.pTab = pItem->pTab;
+ pExpr->y.pTab = pItem->pSTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn--;
pExpr->affExpr = SQLITE_AFF_INTEGER;
@@ -107839,8 +109140,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
/* Resolve function names
*/
case TK_FUNCTION: {
- ExprList *pList = pExpr->x.pList; /* The argument list */
- int n = pList ? pList->nExpr : 0; /* Number of arguments */
+ ExprList *pList; /* The argument list */
+ int n; /* Number of arguments */
int no_such_func = 0; /* True if no such function exists */
int wrong_num_args = 0; /* True if wrong number of arguments */
int is_agg = 0; /* True if is an aggregate function */
@@ -107853,6 +109154,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
assert( pExpr->pLeft==0 || pExpr->pLeft->op==TK_ORDER );
+ pList = pExpr->x.pList;
+ n = pList ? pList->nExpr : 0;
zId = pExpr->u.zToken;
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
if( pDef==0 ){
@@ -107901,6 +109204,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
}
#endif
+
+ /* If the function may call sqlite3_value_subtype(), then set the
+ ** EP_SubtArg flag on all of its argument expressions. This prevents
+ ** where.c from replacing the expression with a value read from an
+ ** index on the same expression, which will not have the correct
+ ** subtype. Also set the flag if the function expression itself is
+ ** an EP_SubtArg expression. In this case subtypes are required as
+ ** the function may return a value with a subtype back to its
+ ** caller using sqlite3_result_value(). */
+ if( (pDef->funcFlags & SQLITE_SUBTYPE)
+ || ExprHasProperty(pExpr, EP_SubtArg)
+ ){
+ int ii;
+ for(ii=0; ii<n; ii++){
+ ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
+ }
+ }
+
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
/* For the purposes of the EP_ConstFunc flag, date and time
** functions and other functions that change slowly are considered
@@ -107914,13 +109235,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** sqlite_version() that might change over time cannot be used
** in an index or generated column. Curiously, they can be used
** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
- ** all this. */
+ ** allow this. */
sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
}else{
assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
pExpr->op2 = pNC->ncFlags & NC_SelfRef;
- if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
}
if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
&& pParse->nested==0
@@ -107936,6 +109256,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
&& !IN_RENAME_OBJECT
){
+ if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
}
}
@@ -108020,9 +109341,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pWin ){
+ if( pWin && pParse->nErr==0 ){
Select *pSel = pNC->pWinSelect;
- assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
+ assert( ExprUseYWin(pExpr) && pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
if( pParse->db->mallocFailed ) break;
@@ -108229,7 +109550,7 @@ static int resolveOrderByTermToExprList(
int rc; /* Return code from subprocedures */
u8 savedSuppErr; /* Saved value of db->suppressErr */
- assert( sqlite3ExprIsInteger(pE, &i)==0 );
+ assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
pEList = pSelect->pEList;
/* Resolve all names in the ORDER BY term expression
@@ -108328,7 +109649,7 @@ static int resolveCompoundOrderBy(
if( pItem->fg.done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
if( NEVER(pE==0) ) continue;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
return 1;
@@ -108513,7 +109834,7 @@ static int resolveOrderGroupBy(
continue;
}
}
- if( sqlite3ExprIsInteger(pE2, &iCol) ){
+ if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
@@ -108604,7 +109925,11 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** moves the pOrderBy down to the sub-query. It will be moved back
** after the names have been resolved. */
if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
+ Select *pSub;
+ assert( p->pSrc->a[0].fg.isSubquery );
+ assert( p->pSrc->a[0].u4.pSubq!=0 );
+ pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+ assert( pSub!=0 );
assert( p->pSrc->nSrc==1 && p->pOrderBy );
assert( pSub->pPrior && pSub->pOrderBy==0 );
pSub->pOrderBy = p->pOrderBy;
@@ -108616,13 +109941,16 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
- assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
- if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
+ assert( pItem->zName!=0
+ || pItem->fg.isSubquery ); /* Test of tag-20240424-1*/
+ if( pItem->fg.isSubquery
+ && (pItem->u4.pSubq->pSelect->selFlags & SF_Resolved)==0
+ ){
int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
- sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
+ sqlite3ResolveSelectNames(pParse, pItem->u4.pSubq->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr ) return WRC_Abort;
assert( db->mallocFailed==0 );
@@ -108724,7 +110052,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** These integers will be replaced by copies of the corresponding result
** set expressions by the call to resolveOrderGroupBy() below. */
if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
+ Select *pSub;
+ assert( p->pSrc->a[0].fg.isSubquery );
+ pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+ assert( pSub!=0 );
p->pOrderBy = pSub->pOrderBy;
pSub->pOrderBy = 0;
}
@@ -108979,20 +110310,22 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference(
Expr *pExpr, /* Expression to resolve. May be NULL. */
ExprList *pList /* Expression list to resolve. May be NULL. */
){
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
+ SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */
int rc;
+ u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */
assert( type==0 || pTab!=0 );
assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
|| type==NC_GenCol || pTab==0 );
memset(&sNC, 0, sizeof(sNC));
- memset(&sSrc, 0, sizeof(sSrc));
+ pSrc = (SrcList*)srcSpace;
+ memset(pSrc, 0, SZ_SRCLIST_1);
if( pTab ){
- sSrc.nSrc = 1;
- sSrc.a[0].zName = pTab->zName;
- sSrc.a[0].pTab = pTab;
- sSrc.a[0].iCursor = -1;
+ pSrc->nSrc = 1;
+ pSrc->a[0].zName = pTab->zName;
+ pSrc->a[0].pSTab = pTab;
+ pSrc->a[0].iCursor = -1;
if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
/* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
** schema elements */
@@ -109000,7 +110333,7 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference(
}
}
sNC.pParse = pParse;
- sNC.pSrcList = &sSrc;
+ sNC.pSrcList = pSrc;
sNC.ncFlags = type | NC_IsDDL;
if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
@@ -109084,7 +110417,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
- if( op==TK_VECTOR ){
+ if( op==TK_VECTOR
+ || (op==TK_FUNCTION && pExpr->affExpr==SQLITE_AFF_DEFER)
+ ){
assert( ExprUseXList(pExpr) );
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
}
@@ -109096,7 +110431,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
op = pExpr->op;
continue;
}
- if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
+ if( op!=TK_REGISTER ) break;
+ op = pExpr->op2;
+ if( NEVER( op==TK_REGISTER ) ) break;
}
return pExpr->affExpr;
}
@@ -109275,7 +110612,9 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
p = p->pLeft;
continue;
}
- if( op==TK_VECTOR ){
+ if( op==TK_VECTOR
+ || (op==TK_FUNCTION && p->affExpr==SQLITE_AFF_DEFER)
+ ){
assert( ExprUseXList(p) );
p = p->x.pList->a[0].pExpr;
continue;
@@ -109488,7 +110827,7 @@ static int codeCompare(
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
- sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
+ sqlite3VdbeChangeP5(pParse->pVdbe, (u16)p5);
return addr;
}
@@ -110747,7 +112086,7 @@ static Expr *exprDup(
SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){
With *pRet = 0;
if( p ){
- sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
+ sqlite3_int64 nByte = SZ_WITH(p->nCte);
pRet = sqlite3DbMallocZero(db, nByte);
if( pRet ){
int i;
@@ -110858,7 +112197,6 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int
}
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
pItem->fg = pOldItem->fg;
- pItem->fg.done = 0;
pItem->u = pOldItem->u;
}
return pNew;
@@ -110875,26 +112213,39 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
SrcList *pNew;
int i;
- int nByte;
assert( db!=0 );
if( p==0 ) return 0;
- nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
- pNew = sqlite3DbMallocRawNN(db, nByte );
+ pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
SrcItem *pNewItem = &pNew->a[i];
const SrcItem *pOldItem = &p->a[i];
Table *pTab;
- pNewItem->pSchema = pOldItem->pSchema;
- pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
+ pNewItem->fg = pOldItem->fg;
+ if( pOldItem->fg.isSubquery ){
+ Subquery *pNewSubq = sqlite3DbMallocRaw(db, sizeof(Subquery));
+ if( pNewSubq==0 ){
+ assert( db->mallocFailed );
+ pNewItem->fg.isSubquery = 0;
+ }else{
+ memcpy(pNewSubq, pOldItem->u4.pSubq, sizeof(*pNewSubq));
+ pNewSubq->pSelect = sqlite3SelectDup(db, pNewSubq->pSelect, flags);
+ if( pNewSubq->pSelect==0 ){
+ sqlite3DbFree(db, pNewSubq);
+ pNewSubq = 0;
+ pNewItem->fg.isSubquery = 0;
+ }
+ }
+ pNewItem->u4.pSubq = pNewSubq;
+ }else if( pOldItem->fg.fixedSchema ){
+ pNewItem->u4.pSchema = pOldItem->u4.pSchema;
+ }else{
+ pNewItem->u4.zDatabase = sqlite3DbStrDup(db, pOldItem->u4.zDatabase);
+ }
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
- pNewItem->fg = pOldItem->fg;
pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->addrFillSub = pOldItem->addrFillSub;
- pNewItem->regReturn = pOldItem->regReturn;
- pNewItem->regResult = pOldItem->regResult;
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
}else if( pNewItem->fg.isTabFunc ){
@@ -110907,11 +112258,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int fla
if( pNewItem->fg.isCte ){
pNewItem->u2.pCteUse->nUse++;
}
- pTab = pNewItem->pTab = pOldItem->pTab;
+ pTab = pNewItem->pSTab = pOldItem->pSTab;
if( pTab ){
pTab->nTabRef++;
}
- pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
if( pOldItem->fg.isUsing ){
assert( pNewItem->fg.isUsing );
pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing);
@@ -110927,16 +112277,13 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
int i;
assert( db!=0 );
if( p==0 ) return 0;
- assert( p->eU4!=EU4_EXPR );
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
+ pNew = sqlite3DbMallocRawNN(db, SZ_IDLIST(p->nId));
if( pNew==0 ) return 0;
pNew->nId = p->nId;
- pNew->eU4 = p->eU4;
for(i=0; i<p->nId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
const struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
- pNewItem->u4 = pOldItem->u4;
}
return pNew;
}
@@ -110962,7 +112309,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 & ~SF_UsesEphemeral;
+ pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
@@ -110985,7 +112332,6 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla
pp = &pNew->pPrior;
pNext = pNew;
}
-
return pRet;
}
#else
@@ -111015,7 +112361,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
struct ExprList_item *pItem;
ExprList *pList;
- pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
+ pList = sqlite3DbMallocRawNN(db, SZ_EXPRLIST(4));
if( pList==0 ){
sqlite3ExprDelete(db, pExpr);
return 0;
@@ -111035,8 +112381,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow(
struct ExprList_item *pItem;
ExprList *pNew;
pList->nAlloc *= 2;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
+ pNew = sqlite3DbRealloc(db, pList, SZ_EXPRLIST(pList->nAlloc));
if( pNew==0 ){
sqlite3ExprListDelete(db, pList);
sqlite3ExprDelete(db, pExpr);
@@ -111642,7 +112987,7 @@ static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
** (4a) pExpr must come from an ON clause..
** (4b) and specifically the ON clause associated with the LEFT JOIN.
**
-** (5) If pSrc is not the right operand of a LEFT JOIN or the left
+** (5) If pSrc is the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
**
@@ -111800,8 +113145,12 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
+**
+** If the pParse pointer is provided, then allow the expression p to be
+** a parameter (TK_VARIABLE) that is bound to an integer.
+** But if pParse is NULL, then p must be a pure integer literal.
*/
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
int rc = 0;
if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
@@ -111816,18 +113165,38 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
}
switch( p->op ){
case TK_UPLUS: {
- rc = sqlite3ExprIsInteger(p->pLeft, pValue);
+ rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
break;
}
case TK_UMINUS: {
int v = 0;
- if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+ if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
assert( ((unsigned int)v)!=0x80000000 );
*pValue = -v;
rc = 1;
}
break;
}
+ case TK_VARIABLE: {
+ sqlite3_value *pVal;
+ if( pParse==0 ) break;
+ if( NEVER(pParse->pVdbe==0) ) break;
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
+ sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
+ pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
+ SQLITE_AFF_BLOB);
+ if( pVal ){
+ if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
+ sqlite3_int64 vv = sqlite3_value_int64(pVal);
+ if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
+ *pValue = (int)vv;
+ rc = 1;
+ }
+ }
+ sqlite3ValueFree(pVal);
+ }
+ break;
+ }
default: break;
}
return rc;
@@ -111941,13 +113310,7 @@ SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab){
int ii;
assert( VisibleRowid(pTab) );
for(ii=0; ii<ArraySize(azOpt); ii++){
- int iCol;
- for(iCol=0; iCol<pTab->nCol; iCol++){
- if( sqlite3_stricmp(azOpt[ii], pTab->aCol[iCol].zCnName)==0 ) break;
- }
- if( iCol==pTab->nCol ){
- return azOpt[ii];
- }
+ if( sqlite3ColumnIndex(pTab, azOpt[ii])<0 ) return azOpt[ii];
}
return 0;
}
@@ -111981,8 +113344,8 @@ static Select *isCandidateForInOpt(const Expr *pX){
pSrc = p->pSrc;
assert( pSrc!=0 );
if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
- if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
- pTab = pSrc->a[0].pTab;
+ if( pSrc->a[0].fg.isSubquery) return 0;/* FROM is not a subquery or view */
+ pTab = pSrc->a[0].pSTab;
assert( pTab!=0 );
assert( !IsView(pTab) ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
@@ -112165,7 +113528,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
- pTab = p->pSrc->a[0].pTab;
+ pTab = p->pSrc->a[0].pSTab;
/* Code an OP_Transaction and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -112257,6 +113620,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
if( aiMap ) aiMap[i] = j;
}
+ assert( nExpr>0 && nExpr<BMS );
assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
if( colUsed==(MASKBIT(nExpr)-1) ){
/* If we reach this point, that means the index pIdx is usable */
@@ -112350,7 +113714,7 @@ static char *exprINAffinity(Parse *pParse, const Expr *pExpr){
char *zRet;
assert( pExpr->op==TK_IN );
- zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
+ zRet = sqlite3DbMallocRaw(pParse->db, 1+(i64)nVal);
if( zRet ){
int i;
for(i=0; i<nVal; i++){
@@ -112407,6 +113771,50 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
#ifndef SQLITE_OMIT_SUBQUERY
/*
+** Scan all previously generated bytecode looking for an OP_BeginSubrtn
+** that is compatible with pExpr. If found, add the y.sub values
+** to pExpr and return true. If not found, return false.
+*/
+static int findCompatibleInRhsSubrtn(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* IN operator with RHS that we want to reuse */
+ SubrtnSig *pNewSig /* Signature for the IN operator */
+){
+ VdbeOp *pOp, *pEnd;
+ SubrtnSig *pSig;
+ Vdbe *v;
+
+ if( pNewSig==0 ) return 0;
+ if( (pParse->mSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0;
+ assert( pExpr->op==TK_IN );
+ assert( !ExprUseYSub(pExpr) );
+ assert( ExprUseXSelect(pExpr) );
+ assert( pExpr->x.pSelect!=0 );
+ assert( (pExpr->x.pSelect->selFlags & SF_All)==0 );
+ v = pParse->pVdbe;
+ assert( v!=0 );
+ pOp = sqlite3VdbeGetOp(v, 1);
+ pEnd = sqlite3VdbeGetLastOp(v);
+ for(; pOp<pEnd; pOp++){
+ if( pOp->p4type!=P4_SUBRTNSIG ) continue;
+ assert( pOp->opcode==OP_BeginSubrtn );
+ pSig = pOp->p4.pSubrtnSig;
+ assert( pSig!=0 );
+ if( !pSig->bComplete ) continue;
+ if( pNewSig->selId!=pSig->selId ) continue;
+ if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue;
+ pExpr->y.sub.iAddr = pSig->iAddr;
+ pExpr->y.sub.regReturn = pSig->regReturn;
+ pExpr->iTable = pSig->iTable;
+ ExprSetProperty(pExpr, EP_Subrtn);
+ return 1;
+ }
+ return 0;
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
** Generate code that will construct an ephemeral table containing all terms
** in the RHS of an IN operator. The IN operator can be in either of two
** forms:
@@ -112439,6 +113847,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
KeyInfo *pKeyInfo = 0; /* Key information */
int nVal; /* Size of vector pLeft */
Vdbe *v; /* The prepared statement under construction */
+ SubrtnSig *pSig = 0; /* Signature for this subroutine */
v = pParse->pVdbe;
assert( v!=0 );
@@ -112454,11 +113863,27 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
** and reuse it many names.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
- /* Reuse of the RHS is allowed */
- /* If this routine has already been coded, but the previous code
- ** might not have been invoked yet, so invoke it now as a subroutine.
+ /* Reuse of the RHS is allowed
+ **
+ ** Compute a signature for the RHS of the IN operator to facility
+ ** finding and reusing prior instances of the same IN operator.
+ */
+ assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 );
+ if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){
+ pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0]));
+ if( pSig ){
+ pSig->selId = pExpr->x.pSelect->selId;
+ pSig->zAff = exprINAffinity(pParse, pExpr);
+ }
+ }
+
+ /* Check to see if there is a prior materialization of the RHS of
+ ** this IN operator. If there is, then make use of that prior
+ ** materialization rather than recomputing it.
*/
- if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ if( ExprHasProperty(pExpr, EP_Subrtn)
+ || findCompatibleInRhsSubrtn(pParse, pExpr, pSig)
+ ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
@@ -112470,6 +113895,10 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
assert( iTab!=pExpr->iTable );
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
+ if( pSig ){
+ sqlite3DbFree(pParse->db, pSig->zAff);
+ sqlite3DbFree(pParse->db, pSig);
+ }
return;
}
@@ -112480,7 +113909,14 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
-
+ if( pSig ){
+ pSig->bComplete = 0;
+ pSig->iAddr = pExpr->y.sub.iAddr;
+ pSig->regReturn = pExpr->y.sub.regReturn;
+ pSig->iTable = iTab;
+ pParse->mSubrtnSig = 1 << (pSig->selId&7);
+ sqlite3VdbeChangeP4(v, -1, (const char*)pSig, P4_SUBRTNSIG);
+ }
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -112521,15 +113957,31 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
SelectDest dest;
int i;
int rc;
+ int addrBloom = 0;
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
+ if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
+ int regBloom = ++pParse->nMem;
+ addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
+ VdbeComment((v, "Bloom filter"));
+ dest.iSDParm2 = regBloom;
+ }
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
sqlite3DbFree(pParse->db, dest.zAffSdst);
+ if( addrBloom ){
+ /* Remember that location of the Bloom filter in the P3 operand
+ ** of the OP_Once that began this subroutine. tag-202407032019 */
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+ if( dest.iSDParm2==0 ){
+ /* If the Bloom filter won't actually be used, keep it small */
+ sqlite3VdbeGetOp(v, addrBloom)->p1 = 10;
+ }
+ }
if( rc ){
sqlite3KeyInfoUnref(pKeyInfo);
return;
@@ -112595,6 +114047,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
+ if( pSig ) pSig->bComplete = 1;
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
@@ -112827,9 +114280,7 @@ static void sqlite3ExprCodeIN(
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
zAff = exprINAffinity(pParse, pExpr);
nVector = sqlite3ExprVectorSize(pExpr->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(
- pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
- );
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int));
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
/* Attempt to compute the RHS. After this step, if anything other than
@@ -112972,6 +114423,15 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
if( destIfFalse==destIfNull ){
/* Combine Step 3 and Step 5 into a single opcode */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
+ assert( pOp->opcode==OP_Once || pParse->nErr );
+ if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */
+ assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
+ sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
+ rLhs, nVector); VdbeCoverage(v);
+ }
+ }
sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
rLhs, nVector); VdbeCoverage(v);
goto sqlite3ExprCodeIN_finished;
@@ -113254,13 +114714,17 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
** register iReg. The caller must ensure that iReg already contains
** the correct value for the expression.
*/
-static void exprToRegister(Expr *pExpr, int iReg){
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
if( NEVER(p==0) ) return;
- p->op2 = p->op;
- p->op = TK_REGISTER;
- p->iTable = iReg;
- ExprClearProperty(p, EP_Skip);
+ if( p->op==TK_REGISTER ){
+ assert( p->iTable==iReg );
+ }else{
+ p->op2 = p->op;
+ p->op = TK_REGISTER;
+ p->iTable = iReg;
+ ExprClearProperty(p, EP_Skip);
+ }
}
/*
@@ -113431,6 +114895,59 @@ static int exprCodeInlineFunction(
}
/*
+** Expression Node callback for sqlite3ExprCanReturnSubtype().
+**
+** Only a function call is able to return a subtype. So if the node
+** is not a function call, return WRC_Prune immediately.
+**
+** A function call is able to return a subtype if it has the
+** SQLITE_RESULT_SUBTYPE property.
+**
+** Assume that every function is able to pass-through a subtype from
+** one of its argument (using sqlite3_result_value()). Most functions
+** are not this way, but we don't have a mechanism to distinguish those
+** that are from those that are not, so assume they all work this way.
+** That means that if one of its arguments is another function and that
+** other function is able to return a subtype, then this function is
+** able to return a subtype.
+*/
+static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
+ int n;
+ FuncDef *pDef;
+ sqlite3 *db;
+ if( pExpr->op!=TK_FUNCTION ){
+ return WRC_Prune;
+ }
+ assert( ExprUseXList(pExpr) );
+ db = pWalker->pParse->db;
+ n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
+ if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
+ pWalker->eCode = 1;
+ return WRC_Prune;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Return TRUE if expression pExpr is able to return a subtype.
+**
+** A TRUE return does not guarantee that a subtype will be returned.
+** It only indicates that a subtype return is possible. False positives
+** are acceptable as they only disable an optimization. False negatives,
+** on the other hand, can lead to incorrect answers.
+*/
+static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xExprCallback = exprNodeCanReturnSubtype;
+ sqlite3WalkExpr(&w, pExpr);
+ return w.eCode;
+}
+
+
+/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
** return the register into which the value has been read. If pExpr is
@@ -113462,6 +114979,17 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
continue;
}
+
+ /* Functions that might set a subtype should not be replaced by the
+ ** value taken from an expression index if they are themselves an
+ ** argument to another scalar function or aggregate.
+ ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */
+ if( ExprHasProperty(pExpr, EP_SubtArg)
+ && sqlite3ExprCanReturnSubtype(pParse, pExpr)
+ ){
+ continue;
+ }
+
v = pParse->pVdbe;
assert( v!=0 );
if( p->bMaybeNullRow ){
@@ -113490,7 +115018,7 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
/*
-** Expresion pExpr is guaranteed to be a TK_COLUMN or equivalent. This
+** Expression pExpr is guaranteed to be a TK_COLUMN or equivalent. This
** function checks the Parse.pIdxPartExpr list to see if this column
** can be replaced with a constant value. If so, it generates code to
** put the constant value in a register (ideally, but not necessarily,
@@ -114263,7 +115791,7 @@ expr_code_doover:
break;
}
testcase( pX->op==TK_COLUMN );
- exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
testcase( regFree1==0 );
memset(&opCompare, 0, sizeof(opCompare));
opCompare.op = TK_EQ;
@@ -114317,15 +115845,14 @@ expr_code_doover:
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->affExpr==OE_Ignore ){
- sqlite3VdbeAddOp4(
- v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore);
VdbeCoverage(v);
}else{
- sqlite3HaltConstraint(pParse,
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ sqlite3VdbeAddOp3(v, OP_Halt,
pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
- pExpr->affExpr, pExpr->u.zToken, 0, 0);
+ pExpr->affExpr, r1);
}
-
break;
}
#endif
@@ -114614,7 +116141,7 @@ static void exprCodeBetween(
compRight.op = TK_LE;
compRight.pLeft = pDel;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
- exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
@@ -114748,11 +116275,11 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- sqlite3VdbeTypeofColumn(v, r1);
+ assert( regFree1==0 || regFree1==r1 );
+ if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
sqlite3VdbeAddOp2(v, op, r1, dest);
VdbeCoverageIf(v, op==TK_ISNULL);
VdbeCoverageIf(v, op==TK_NOTNULL);
- testcase( regFree1==0 );
break;
}
case TK_BETWEEN: {
@@ -114923,11 +116450,11 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
case TK_ISNULL:
case TK_NOTNULL: {
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- sqlite3VdbeTypeofColumn(v, r1);
+ assert( regFree1==0 || regFree1==r1 );
+ if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
sqlite3VdbeAddOp2(v, op, r1, dest);
testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
- testcase( regFree1==0 );
break;
}
case TK_BETWEEN: {
@@ -114993,16 +116520,23 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i
** same as that currently bound to variable pVar, non-zero is returned.
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
+**
+** If the SQLITE_EnableQPSG flag is set on the database connection, then
+** this routine always returns false.
*/
-static int exprCompareVariable(
+static SQLITE_NOINLINE int exprCompareVariable(
const Parse *pParse,
const Expr *pVar,
const Expr *pExpr
){
- int res = 0;
+ int res = 2;
int iVar;
sqlite3_value *pL, *pR = 0;
+ if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){
+ return 0;
+ }
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2;
sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
if( pR ){
iVar = pVar->iColumn;
@@ -115012,12 +116546,11 @@ static int exprCompareVariable(
if( sqlite3_value_type(pL)==SQLITE_TEXT ){
sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
}
- res = 0==sqlite3MemCompare(pL, pR, 0);
+ res = sqlite3MemCompare(pL, pR, 0) ? 2 : 0;
}
sqlite3ValueFree(pR);
sqlite3ValueFree(pL);
}
-
return res;
}
@@ -115043,12 +116576,10 @@ static int exprCompareVariable(
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
**
-** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
-** pParse->pReprepare can be matched against literals in pB. The
-** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
-** If pParse is NULL (the normal case) then any TK_VARIABLE term in
-** Argument pParse should normally be NULL. If it is not NULL and pA or
-** pB causes a return value of 2.
+** If pParse is not NULL and SQLITE_EnableQPSG is off then TK_VARIABLE
+** terms in pA with bindings in pParse->pReprepare can be matched against
+** literals in pB. The pParse->pVdbe->expmask bitmask is updated for
+** each variable referenced.
*/
SQLITE_PRIVATE int sqlite3ExprCompare(
const Parse *pParse,
@@ -115060,8 +116591,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
- if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
- return 0;
+ if( pParse && pA->op==TK_VARIABLE ){
+ return exprCompareVariable(pParse, pA, pB);
}
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
@@ -115257,17 +116788,69 @@ static int exprImpliesNotNull(
}
/*
+** Return true if the boolean value of the expression is always either
+** FALSE or NULL.
+*/
+static int sqlite3ExprIsNotTrue(Expr *pExpr){
+ int v;
+ 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;
+ return 0;
+}
+
+/*
+** Return true if the expression is one of the following:
+**
+** CASE WHEN x THEN y END
+** CASE WHEN x THEN y ELSE NULL END
+** CASE WHEN x THEN y ELSE false END
+** iif(x,y)
+** iif(x,y,NULL)
+** iif(x,y,false)
+*/
+static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){
+ ExprList *pList;
+ if( pExpr->op==TK_FUNCTION ){
+ const char *z = pExpr->u.zToken;
+ FuncDef *pDef;
+ if( (z[0]!='i' && z[0]!='I') ) return 0;
+ if( pExpr->x.pList==0 ) return 0;
+ pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0);
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ if( pDef==0 ) return 0;
+#else
+ if( NEVER(pDef==0) ) return 0;
+#endif
+ if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0;
+ if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0;
+ }else if( pExpr->op==TK_CASE ){
+ if( pExpr->pLeft!=0 ) return 0;
+ }else{
+ return 0;
+ }
+ pList = pExpr->x.pList;
+ assert( pList!=0 );
+ if( pList->nExpr==2 ) return 1;
+ if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1;
+ return 0;
+}
+
+/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true. Return false if we cannot complete the proof or if pE2 might
** be false. Examples:
**
-** pE1: x==5 pE2: x==5 Result: true
-** pE1: x>0 pE2: x==5 Result: false
-** pE1: x=21 pE2: x=21 OR y=43 Result: true
-** pE1: x!=123 pE2: x IS NOT NULL Result: true
-** pE1: x!=?1 pE2: x IS NOT NULL Result: true
-** pE1: x IS NULL pE2: x IS NOT NULL Result: false
-** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
+** pE1: x==5 pE2: x==5 Result: true
+** pE1: x>0 pE2: x==5 Result: false
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
+** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
+** pE1: iif(x,y) pE2: x Result: true
+** PE1: iif(x,y,0) pE2: x Result: true
**
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
@@ -115301,6 +116884,9 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(
){
return 1;
}
+ if( sqlite3ExprIsIIF(pParse->db, pE1) ){
+ return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab);
+ }
return 0;
}
@@ -115768,7 +117354,9 @@ static void findOrCreateAggInfoColumn(
){
struct AggInfo_col *pCol;
int k;
+ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ assert( mxTerm <= SMXV(i16) );
assert( pAggInfo->iFirstReg==0 );
pCol = pAggInfo->aCol;
for(k=0; k<pAggInfo->nColumn; k++, pCol++){
@@ -115786,6 +117374,10 @@ static void findOrCreateAggInfoColumn(
assert( pParse->db->mallocFailed );
return;
}
+ if( k>mxTerm ){
+ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
+ k = mxTerm;
+ }
pCol = &pAggInfo->aCol[k];
assert( ExprUseYTab(pExpr) );
pCol->pTab = pExpr->y.pTab;
@@ -115819,6 +117411,7 @@ fix_up_expr:
if( pExpr->op==TK_COLUMN ){
pExpr->op = TK_AGG_COLUMN;
}
+ assert( k <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)k;
}
@@ -115903,13 +117496,19 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
+ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ assert( mxTerm <= SMXV(i16) );
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( NEVER(pItem->pFExpr==pExpr) ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
- if( i>=pAggInfo->nFunc ){
+ if( i>mxTerm ){
+ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
+ i = mxTerm;
+ assert( i<pAggInfo->nFunc );
+ }else if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = ENC(pParse->db);
@@ -115963,6 +117562,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pExpr, EP_NoReduce);
+ assert( i <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)i;
pExpr->pAggInfo = pAggInfo;
return WRC_Prune;
@@ -116673,13 +118273,13 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
- pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
+ pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*(u32)nAlloc);
pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
if( !pNew->aCol || !pNew->zName ){
assert( db->mallocFailed );
goto exit_begin_add_column;
}
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
+ memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*(size_t)pNew->nCol);
for(i=0; i<pNew->nCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
@@ -116774,10 +118374,8 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn(
** altered. Set iCol to be the index of the column being renamed */
zOld = sqlite3NameFromToken(db, pOld);
if( !zOld ) goto exit_rename_column;
- for(iCol=0; iCol<pTab->nCol; iCol++){
- if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
- }
- if( iCol==pTab->nCol ){
+ iCol = sqlite3ColumnIndex(pTab, zOld);
+ if( iCol<0 ){
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);
goto exit_rename_column;
}
@@ -117280,6 +118878,7 @@ static int renameParseSql(
int bTemp /* True if SQL is from temp schema */
){
int rc;
+ u64 flags;
sqlite3ParseObjectInit(p, db);
if( zSql==0 ){
@@ -117288,11 +118887,21 @@ static int renameParseSql(
if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
return SQLITE_CORRUPT_BKPT;
}
- db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
+ if( bTemp ){
+ db->init.iDb = 1;
+ }else{
+ int iDb = sqlite3FindDbName(db, zDb);
+ assert( iDb>=0 && iDb<=0xff );
+ db->init.iDb = (u8)iDb;
+ }
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
+ flags = db->flags;
+ testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 );
+ db->flags |= SQLITE_Comments;
rc = sqlite3RunParser(p, zSql);
+ db->flags = flags;
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
@@ -117355,10 +118964,11 @@ static int renameEditSql(
nQuot = sqlite3Strlen30(zQuot)-1;
}
- assert( nQuot>=nNew );
- zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
+ assert( nQuot>=nNew && nSql>=0 && nNew>=0 );
+ zOut = sqlite3DbMallocZero(db, (u64)nSql + pRename->nList*(u64)nQuot + 1);
}else{
- zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
+ assert( nSql>0 );
+ zOut = (char*)sqlite3DbMallocZero(db, (2*(u64)nSql + 1) * 3);
if( zOut ){
zBuf1 = &zOut[nSql*2+1];
zBuf2 = &zOut[nSql*4+2];
@@ -117370,16 +118980,17 @@ static int renameEditSql(
** with the new column name, or with single-quoted versions of themselves.
** All that remains is to construct and return the edited SQL string. */
if( zOut ){
- int nOut = nSql;
- memcpy(zOut, zSql, nSql);
+ i64 nOut = nSql;
+ assert( nSql>0 );
+ memcpy(zOut, zSql, (size_t)nSql);
while( pRename->pList ){
int iOff; /* Offset of token to replace in zOut */
- u32 nReplace;
+ i64 nReplace;
const char *zReplace;
RenameToken *pBest = renameColumnTokenNext(pRename);
if( zNew ){
- if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
+ if( bQuote==0 && sqlite3IsIdChar(*(u8*)pBest->t.z) ){
nReplace = nNew;
zReplace = zNew;
}else{
@@ -117397,14 +119008,15 @@ static int renameEditSql(
memcpy(zBuf1, pBest->t.z, pBest->t.n);
zBuf1[pBest->t.n] = 0;
sqlite3Dequote(zBuf1);
- sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
+ assert( nSql < 0x15555554 /* otherwise malloc would have failed */ );
+ sqlite3_snprintf((int)(nSql*2), zBuf2, "%Q%s", zBuf1,
pBest->t.z[pBest->t.n]=='\'' ? " " : ""
);
zReplace = zBuf2;
nReplace = sqlite3Strlen30(zReplace);
}
- iOff = pBest->t.z - zSql;
+ iOff = (int)(pBest->t.z - zSql);
if( pBest->t.n!=nReplace ){
memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n],
nOut - (iOff + pBest->t.n)
@@ -117430,11 +119042,12 @@ static int renameEditSql(
** Set all pEList->a[].fg.eEName fields in the expression-list to val.
*/
static void renameSetENames(ExprList *pEList, int val){
+ assert( val==ENAME_NAME || val==ENAME_TAB || val==ENAME_SPAN );
if( pEList ){
int i;
for(i=0; i<pEList->nExpr; i++){
assert( val==ENAME_NAME || pEList->a[i].fg.eEName==ENAME_NAME );
- pEList->a[i].fg.eEName = val;
+ pEList->a[i].fg.eEName = val&0x3;
}
}
}
@@ -117508,8 +119121,9 @@ static int renameResolveTrigger(Parse *pParse){
int i;
for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){
SrcItem *p = &pStep->pFrom->a[i];
- if( p->pSelect ){
- sqlite3SelectPrep(pParse, p->pSelect, 0);
+ if( p->fg.isSubquery ){
+ assert( p->u4.pSubq!=0 );
+ sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0);
}
}
}
@@ -117577,8 +119191,12 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
}
if( pStep->pFrom ){
int i;
- for(i=0; i<pStep->pFrom->nSrc; i++){
- sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
+ SrcList *pFrom = pStep->pFrom;
+ for(i=0; i<pFrom->nSrc; i++){
+ if( pFrom->a[i].fg.isSubquery ){
+ assert( pFrom->a[i].u4.pSubq!=0 );
+ sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect);
+ }
}
}
}
@@ -117686,7 +119304,7 @@ static void renameColumnFunc(
if( sParse.pNewTable ){
if( IsView(sParse.pNewTable) ){
Select *pSelect = sParse.pNewTable->u.view.pSelect;
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
@@ -117825,7 +119443,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
}
for(i=0; i<pSrc->nSrc; i++){
SrcItem *pItem = &pSrc->a[i];
- if( pItem->pTab==p->pTab ){
+ if( pItem->pSTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
}
@@ -117904,7 +119522,7 @@ static void renameTableFunc(
sNC.pParse = &sParse;
assert( pSelect->selFlags & SF_View );
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
if( sParse.nErr ){
rc = sParse.rc;
@@ -118077,7 +119695,7 @@ static void renameQuotefixFunc(
if( sParse.pNewTable ){
if( IsView(sParse.pNewTable) ){
Select *pSelect = sParse.pNewTable->u.view.pSelect;
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
@@ -118176,10 +119794,10 @@ static void renameTableTest(
if( zDb && zInput ){
int rc;
Parse sParse;
- int flags = db->flags;
+ u64 flags = db->flags;
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
- db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
+ db->flags = flags;
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
NameContext sNC;
@@ -118671,7 +120289,8 @@ static void openStatTable(
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
);
- aRoot[i] = (u32)pParse->regRoot;
+ assert( pParse->isCreate || pParse->nErr );
+ aRoot[i] = (u32)pParse->u1.cr.regRoot;
aCreateTbl[i] = OPFLAG_P2ISREG;
}
}else{
@@ -118862,7 +120481,7 @@ static void statInit(
int nCol; /* Number of columns in index being sampled */
int nKeyCol; /* Number of key columns */
int nColUp; /* nCol rounded up for alignment */
- int n; /* Bytes of space to allocate */
+ i64 n; /* Bytes of space to allocate */
sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */
#ifdef SQLITE_ENABLE_STAT4
/* Maximum number of samples. 0 if STAT4 data is not collected */
@@ -118898,7 +120517,7 @@ static void statInit(
p->db = db;
p->nEst = sqlite3_value_int64(argv[2]);
p->nRow = 0;
- p->nLimit = sqlite3_value_int64(argv[3]);
+ p->nLimit = sqlite3_value_int(argv[3]);
p->nCol = nCol;
p->nKeyCol = nKeyCol;
p->nSkipAhead = 0;
@@ -120031,16 +121650,6 @@ static void decodeIntArray(
while( z[0]!=0 && z[0]!=' ' ) z++;
while( z[0]==' ' ) z++;
}
-
- /* Set the bLowQual flag if the peak number of rows obtained
- ** from a full equality match is so large that a full table scan
- ** seems likely to be faster than using the index.
- */
- if( aLog[0] > 66 /* Index has more than 100 rows */
- && aLog[0] <= aLog[nOut-1] /* And only a single value seen */
- ){
- pIndex->bLowQual = 1;
- }
}
}
@@ -120253,12 +121862,13 @@ static int loadStatTbl(
while( sqlite3_step(pStmt)==SQLITE_ROW ){
int nIdxCol = 1; /* Number of columns in stat4 records */
- char *zIndex; /* Index name */
- Index *pIdx; /* Pointer to the index object */
- int nSample; /* Number of samples */
- int nByte; /* Bytes of space required */
- int i; /* Bytes of space required */
- tRowcnt *pSpace;
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int nSample; /* Number of samples */
+ i64 nByte; /* Bytes of space required */
+ i64 i; /* Bytes of space required */
+ tRowcnt *pSpace; /* Available allocated memory space */
+ u8 *pPtr; /* Available memory as a u8 for easier manipulation */
zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
@@ -120278,7 +121888,7 @@ static int loadStatTbl(
}
pIdx->nSampleCol = nIdxCol;
pIdx->mxSample = nSample;
- nByte = sizeof(IndexSample) * nSample;
+ nByte = ROUND8(sizeof(IndexSample) * nSample);
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
@@ -120287,7 +121897,10 @@ static int loadStatTbl(
sqlite3_finalize(pStmt);
return SQLITE_NOMEM_BKPT;
}
- pSpace = (tRowcnt*)&pIdx->aSample[nSample];
+ pPtr = (u8*)pIdx->aSample;
+ pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
+ pSpace = (tRowcnt*)pPtr;
+ assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; i<nSample; i++){
@@ -120632,7 +122245,7 @@ static void attachFunc(
if( aNew==0 ) return;
memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
}else{
- aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
+ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(1+(i64)db->nDb));
if( aNew==0 ) return;
}
db->aDb = aNew;
@@ -120651,6 +122264,12 @@ static void attachFunc(
sqlite3_free(zErr);
return;
}
+ if( (db->flags & SQLITE_AttachWrite)==0 ){
+ flags &= ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE);
+ flags |= SQLITE_OPEN_READONLY;
+ }else if( (db->flags & SQLITE_AttachCreate)==0 ){
+ flags &= ~SQLITE_OPEN_CREATE;
+ }
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
@@ -120697,21 +122316,19 @@ static void attachFunc(
sqlite3BtreeEnterAll(db);
db->init.iDb = 0;
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( db->setlkFlags & SQLITE_SETLK_BLOCK_ON_CONNECT ){
+ int val = 1;
+ sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pNew->pBt));
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, &val);
+ }
+#endif
if( !REOPEN_AS_MEMDB(db) ){
rc = sqlite3Init(db, &zErrDyn);
}
sqlite3BtreeLeaveAll(db);
assert( zErrDyn==0 || rc!=SQLITE_OK );
}
-#ifdef SQLITE_USER_AUTHENTICATION
- if( rc==SQLITE_OK && !REOPEN_AS_MEMDB(db) ){
- u8 newAuth = 0;
- rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
- if( newAuth<db->auth.authLevel ){
- rc = SQLITE_AUTH_USER;
- }
- }
-#endif
if( rc ){
if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){
int iDb = db->nDb - 1;
@@ -120955,20 +122572,21 @@ static int fixSelectCb(Walker *p, Select *pSelect){
if( NEVER(pList==0) ) return WRC_Continue;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pFix->bTemp==0 ){
- if( pItem->zDatabase ){
- if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
+ if( pFix->bTemp==0 && pItem->fg.isSubquery==0 ){
+ if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+ if( iDb!=sqlite3FindDbName(db, pItem->u4.zDatabase) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
+ pFix->zType, pFix->pName, pItem->u4.zDatabase);
return WRC_Abort;
}
- sqlite3DbFree(db, pItem->zDatabase);
- pItem->zDatabase = 0;
+ sqlite3DbFree(db, pItem->u4.zDatabase);
pItem->fg.notCte = 1;
+ pItem->fg.hadSchema = 1;
}
- pItem->pSchema = pFix->pSchema;
+ pItem->u4.pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
+ pItem->fg.fixedSchema = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( pList->a[i].fg.isUsing==0
@@ -121208,11 +122826,7 @@ SQLITE_PRIVATE int sqlite3AuthReadCol(
int rc; /* Auth callback return code */
if( db->init.busy ) return SQLITE_OK;
- rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
+ rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
if( rc==SQLITE_DENY ){
char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
@@ -121261,7 +122875,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
assert( pTabList );
for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
- pTab = pTabList->a[iSrc].pTab;
+ pTab = pTabList->a[iSrc].pSTab;
break;
}
}
@@ -121319,11 +122933,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
testcase( zArg3==0 );
testcase( pParse->zAuthContext==0 );
- rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
+ rc = db->xAuth(db->pAuthArg,code,zArg1,zArg2,zArg3,pParse->zAuthContext);
if( rc==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
@@ -121435,6 +123045,7 @@ static SQLITE_NOINLINE void lockTable(
}
}
+ assert( pToplevel->nTableLock < 0x7fff0000 );
nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
pToplevel->aTableLock =
sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
@@ -121535,10 +123146,12 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
if( pParse->bReturning ){
- Returning *pReturning = pParse->u1.pReturning;
+ Returning *pReturning;
int addrRewind;
int reg;
+ assert( !pParse->isCreate );
+ pReturning = pParse->u1.d.pReturning;
if( pReturning->nRetCol ){
sqlite3VdbeAddOp0(v, OP_FkCheck);
addrRewind =
@@ -121556,17 +123169,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
sqlite3VdbeAddOp0(v, OP_Halt);
-#if SQLITE_USER_AUTHENTICATION && !defined(SQLITE_OMIT_SHARED_CACHE)
- if( pParse->nTableLock>0 && db->init.busy==0 ){
- sqlite3UserAuthInit(db);
- if( db->auth.authLevel<UAUTH_User ){
- sqlite3ErrorMsg(pParse, "user not authenticated");
- pParse->rc = SQLITE_AUTH_USER;
- return;
- }
- }
-#endif
-
/* The cookie mask contains one bit for each database file open.
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
** set for each database that is used. Generate code to start a
@@ -121625,7 +123227,9 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
if( pParse->bReturning ){
- Returning *pRet = pParse->u1.pReturning;
+ Returning *pRet;
+ assert( !pParse->isCreate );
+ pRet = pParse->u1.d.pReturning;
if( pRet->nRetCol ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
}
@@ -121695,16 +123299,6 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
pParse->nested--;
}
-#if SQLITE_USER_AUTHENTICATION
-/*
-** Return TRUE if zTable is the name of the system table that stores the
-** list of users and their access credentials.
-*/
-SQLITE_PRIVATE int sqlite3UserAuthTable(const char *zTable){
- return sqlite3_stricmp(zTable, "sqlite_user")==0;
-}
-#endif
-
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
@@ -121723,13 +123317,6 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
/* All mutexes are required for schema access. Make sure we hold them. */
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
-#if SQLITE_USER_AUTHENTICATION
- /* Only the admin user is allowed to know that the sqlite_user table
- ** exists */
- if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
- return 0;
- }
-#endif
if( zDatabase ){
for(i=0; i<db->nDb; i++){
if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
@@ -121864,12 +123451,12 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
SrcItem *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
- if( p->pSchema ){
- int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+ if( p->fg.fixedSchema ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
- zDb = p->zDatabase;
+ assert( !p->fg.isSubquery );
+ zDb = p->u4.zDatabase;
}
return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}
@@ -122457,10 +124044,16 @@ SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){
** find the (first) offset of that column in index pIdx. Or return -1
** if column iCol is not used in index pIdx.
*/
-SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
+SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
int i;
+ i16 iCol16;
+ assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
+ assert( pIdx->nColumn<=SQLITE_MAX_COLUMN+1 );
+ iCol16 = iCol;
for(i=0; i<pIdx->nColumn; i++){
- if( iCol==pIdx->aiColumn[i] ) return i;
+ if( iCol16==pIdx->aiColumn[i] ){
+ return i;
+ }
}
return -1;
}
@@ -122714,8 +124307,9 @@ SQLITE_PRIVATE void sqlite3StartTable(
/* If the file format and encoding in the database have not been set,
** set them now.
*/
- reg1 = pParse->regRowid = ++pParse->nMem;
- reg2 = pParse->regRoot = ++pParse->nMem;
+ assert( pParse->isCreate );
+ reg1 = pParse->u1.cr.regRowid = ++pParse->nMem;
+ reg2 = pParse->u1.cr.regRoot = ++pParse->nMem;
reg3 = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
sqlite3VdbeUsesBtree(v, iDb);
@@ -122730,8 +124324,8 @@ SQLITE_PRIVATE void sqlite3StartTable(
** The record created does not contain anything yet. It will be replaced
** by the real entry in code generated at sqlite3EndTable().
**
- ** The rowid for the new entry is left in register pParse->regRowid.
- ** The root page number of the new table is left in reg pParse->regRoot.
+ ** The rowid for the new entry is left in register pParse->u1.cr.regRowid.
+ ** The root page of the new table is left in reg pParse->u1.cr.regRoot.
** The rowid and root page number values are needed by the code that
** sqlite3EndTable will generate.
*/
@@ -122742,7 +124336,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
#endif
{
assert( !pParse->bReturning );
- pParse->u1.addrCrTab =
+ pParse->u1.cr.addrCrTab =
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlite3OpenSchemaTable(pParse, iDb);
@@ -122820,7 +124414,8 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){
sqlite3ExprListDelete(db, pList);
return;
}
- pParse->u1.pReturning = pRet;
+ assert( !pParse->isCreate );
+ pParse->u1.d.pReturning = pRet;
pRet->pParse = pParse;
pRet->pReturnEL = pList;
sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet);
@@ -122862,7 +124457,6 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
char *zType;
Column *pCol;
sqlite3 *db = pParse->db;
- u8 hName;
Column *aNew;
u8 eType = COLTYPE_CUSTOM;
u8 szEst = 1;
@@ -122916,13 +124510,10 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
memcpy(z, sName.z, sName.n);
z[sName.n] = 0;
sqlite3Dequote(z);
- hName = sqlite3StrIHash(z);
- for(i=0; i<p->nCol; i++){
- if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
- sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
- sqlite3DbFree(db, z);
- return;
- }
+ if( p->nCol && sqlite3ColumnIndex(p, z)>=0 ){
+ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
+ sqlite3DbFree(db, z);
+ return;
}
aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0]));
if( aNew==0 ){
@@ -122933,7 +124524,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zCnName = z;
- pCol->hName = hName;
+ pCol->hName = sqlite3StrIHash(z);
sqlite3ColumnPropertiesFromName(p, pCol);
if( sType.n==0 ){
@@ -122957,9 +124548,14 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
pCol->affinity = sqlite3AffinityType(zType, pCol);
pCol->colFlags |= COLFLAG_HASTYPE;
}
+ if( p->nCol<=0xff ){
+ u8 h = pCol->hName % sizeof(p->aHx);
+ p->aHx[h] = p->nCol;
+ }
p->nCol++;
p->nNVCol++;
- pParse->constraintName.n = 0;
+ assert( pParse->isCreate );
+ pParse->u1.cr.constraintName.n = 0;
}
/*
@@ -123223,15 +124819,11 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
assert( pCExpr!=0 );
sqlite3StringToId(pCExpr);
if( pCExpr->op==TK_ID ){
- const char *zCName;
assert( !ExprHasProperty(pCExpr, EP_IntValue) );
- zCName = pCExpr->u.zToken;
- for(iCol=0; iCol<pTab->nCol; iCol++){
- if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
- pCol = &pTab->aCol[iCol];
- makeColumnPartOfPrimaryKey(pParse, pCol);
- break;
- }
+ iCol = sqlite3ColumnIndex(pTab, pCExpr->u.zToken);
+ if( iCol>=0 ){
+ pCol = &pTab->aCol[iCol];
+ makeColumnPartOfPrimaryKey(pParse, pCol);
}
}
}
@@ -123283,8 +124875,10 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint(
&& !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
){
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
- if( pParse->constraintName.n ){
- sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+ assert( pParse->isCreate );
+ if( pParse->u1.cr.constraintName.n ){
+ sqlite3ExprListSetName(pParse, pTab->pCheck,
+ &pParse->u1.cr.constraintName, 1);
}else{
Token t;
for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
@@ -123479,7 +125073,8 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent){
** from sqliteMalloc() and must be freed by the calling function.
*/
static char *createTableStmt(sqlite3 *db, Table *p){
- int i, k, n;
+ int i, k, len;
+ i64 n;
char *zStmt;
char *zSep, *zSep2, *zEnd;
Column *pCol;
@@ -123503,8 +125098,9 @@ static char *createTableStmt(sqlite3 *db, Table *p){
sqlite3OomFault(db);
return 0;
}
- sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
- k = sqlite3Strlen30(zStmt);
+ assert( n>14 && n<=0x7fffffff );
+ memcpy(zStmt, "CREATE TABLE ", 13);
+ k = 13;
identPut(zStmt, &k, p->zName);
zStmt[k++] = '(';
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
@@ -123516,13 +125112,15 @@ static char *createTableStmt(sqlite3 *db, Table *p){
/* SQLITE_AFF_REAL */ " REAL",
/* SQLITE_AFF_FLEXNUM */ " NUM",
};
- int len;
const char *zType;
- sqlite3_snprintf(n-k, &zStmt[k], zSep);
- k += sqlite3Strlen30(&zStmt[k]);
+ len = sqlite3Strlen30(zSep);
+ assert( k+len<n );
+ memcpy(&zStmt[k], zSep, len);
+ k += len;
zSep = zSep2;
identPut(zStmt, &k, pCol->zCnName);
+ assert( k<n );
assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_BLOB );
@@ -123537,11 +125135,14 @@ static char *createTableStmt(sqlite3 *db, Table *p){
assert( pCol->affinity==SQLITE_AFF_BLOB
|| pCol->affinity==SQLITE_AFF_FLEXNUM
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
+ assert( k+len<n );
memcpy(&zStmt[k], zType, len);
k += len;
assert( k<=n );
}
- sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
+ len = sqlite3Strlen30(zEnd);
+ assert( k+len<n );
+ memcpy(&zStmt[k], zEnd, len+1);
return zStmt;
}
@@ -123549,12 +125150,17 @@ static char *createTableStmt(sqlite3 *db, Table *p){
** Resize an Index object to hold N columns total. Return SQLITE_OK
** on success and SQLITE_NOMEM on an OOM error.
*/
-static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
+static int resizeIndexObject(Parse *pParse, Index *pIdx, int N){
char *zExtra;
- int nByte;
+ u64 nByte;
+ sqlite3 *db;
if( pIdx->nColumn>=N ) return SQLITE_OK;
+ db = pParse->db;
+ assert( N>0 );
+ assert( N <= SQLITE_MAX_COLUMN*2 /* tag-20250221-1 */ );
+ testcase( N==2*pParse->db->aLimit[SQLITE_LIMIT_COLUMN] );
assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
+ nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*(u64)N;
zExtra = sqlite3DbMallocZero(db, nByte);
if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
@@ -123568,7 +125174,7 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
zExtra += sizeof(i16)*N;
memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
pIdx->aSortOrder = (u8*)zExtra;
- pIdx->nColumn = N;
+ pIdx->nColumn = (u16)N; /* See tag-20250221-1 above for proof of safety */
pIdx->isResized = 1;
return SQLITE_OK;
}
@@ -123734,9 +125340,9 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** into BTREE_BLOBKEY.
*/
assert( !pParse->bReturning );
- if( pParse->u1.addrCrTab ){
+ if( pParse->u1.cr.addrCrTab ){
assert( v );
- sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
+ sqlite3VdbeChangeP3(v, pParse->u1.cr.addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
@@ -123822,14 +125428,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pIdx->nColumn = pIdx->nKeyCol;
continue;
}
- if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
+ if( resizeIndexObject(pParse, pIdx, pIdx->nKeyCol+n) ) return;
for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
pIdx->aiColumn[j] = pPk->aiColumn[i];
pIdx->azColl[j] = pPk->azColl[i];
if( pPk->aSortOrder[i] ){
- /* See ticket https://www.sqlite.org/src/info/bba7b69f9849b5bf */
+ /* See ticket https://sqlite.org/src/info/bba7b69f9849b5bf */
pIdx->bAscKeyBug = 1;
}
j++;
@@ -123846,7 +125452,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( !hasColumn(pPk->aiColumn, nPk, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
}
- if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
+ if( resizeIndexObject(pParse, pPk, nPk+nExtra) ) return;
for(i=0, j=nPk; i<pTab->nCol; i++){
if( !hasColumn(pPk->aiColumn, j, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
@@ -124176,7 +125782,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
/* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
** statement to populate the new table. The root-page number for the
- ** new table is in register pParse->regRoot.
+ ** new table is in register pParse->u1.cr.regRoot.
**
** Once the SELECT has been coded by sqlite3Select(), it is in a
** suitable state to query for the column names and types to be used
@@ -124207,7 +125813,8 @@ SQLITE_PRIVATE void sqlite3EndTable(
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
sqlite3MayAbort(pParse);
- sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb);
+ assert( pParse->isCreate );
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->u1.cr.regRoot, iDb);
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
@@ -124252,6 +125859,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
** schema table. We just need to update that slot with all
** the information we've collected.
*/
+ assert( pParse->isCreate );
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE
" SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
@@ -124260,9 +125868,9 @@ SQLITE_PRIVATE void sqlite3EndTable(
zType,
p->zName,
p->zName,
- pParse->regRoot,
+ pParse->u1.cr.regRoot,
zStmt,
- pParse->regRowid
+ pParse->u1.cr.regRowid
);
sqlite3DbFree(db, zStmt);
sqlite3ChangeCookie(pParse, iDb);
@@ -124854,6 +126462,8 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
+ assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
@@ -124862,7 +126472,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
if( pTab==0 ){
if( noErr ){
- sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
goto exit_drop_table;
@@ -125000,7 +126610,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
}else{
nCol = pFromCol->nExpr;
}
- nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
+ nByte = SZ_FKEY(nCol) + pTo->n + 1;
if( pToCol ){
for(i=0; i<pToCol->nExpr; i++){
nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
@@ -125202,7 +126812,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
** not work for UNIQUE constraint indexes on WITHOUT ROWID tables
** with DESC primary keys, since those indexes have there keys in
** a different order from the main table.
- ** See ticket: https://www.sqlite.org/src/info/bba7b69f9849b5bf
+ ** See ticket: https://sqlite.org/src/info/bba7b69f9849b5bf
*/
sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
}
@@ -125226,13 +126836,14 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
*/
SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(
sqlite3 *db, /* Database connection */
- i16 nCol, /* Total number of columns in the index */
+ int nCol, /* Total number of columns in the index */
int nExtra, /* Number of bytes of extra space to alloc */
char **ppExtra /* Pointer to the "extra" space */
){
Index *p; /* Allocated index object */
- int nByte; /* Bytes of space for Index object + arrays */
+ i64 nByte; /* Bytes of space for Index object + arrays */
+ assert( nCol <= 2*db->aLimit[SQLITE_LIMIT_COLUMN] );
nByte = ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */
@@ -125245,8 +126856,9 @@ SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(
p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->aSortOrder = (u8*)pExtra;
- p->nColumn = nCol;
- p->nKeyCol = nCol - 1;
+ assert( nCol>0 );
+ p->nColumn = (u16)nCol;
+ p->nKeyCol = (u16)(nCol - 1);
*ppExtra = ((char*)p) + nByte;
}
return p;
@@ -125386,9 +126998,6 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
&& pTblName!=0
-#if SQLITE_USER_AUTHENTICATION
- && sqlite3UserAuthTable(pTab->zName)==0
-#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
@@ -125587,6 +127196,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
assert( j<=0x7fff );
if( j<0 ){
j = pTab->iPKey;
+ pIndex->bIdxRowid = 1;
}else{
if( pTab->aCol[j].notNull==0 ){
pIndex->uniqNotNull = 0;
@@ -125953,15 +127563,17 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
}
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
assert( pName->nSrc==1 );
+ assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
}
- pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
+ pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].u4.zDatabase);
if( pIndex==0 ){
if( !ifExists ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
- sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
@@ -126058,12 +127670,11 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *
sqlite3 *db = pParse->db;
int i;
if( pList==0 ){
- pList = sqlite3DbMallocZero(db, sizeof(IdList) );
+ pList = sqlite3DbMallocZero(db, SZ_IDLIST(1));
if( pList==0 ) return 0;
}else{
IdList *pNew;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(IdList) + pList->nId*sizeof(pList->a));
+ pNew = sqlite3DbRealloc(db, pList, SZ_IDLIST(pList->nId+1));
if( pNew==0 ){
sqlite3IdListDelete(db, pList);
return 0;
@@ -126085,7 +127696,6 @@ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
int i;
assert( db!=0 );
if( pList==0 ) return;
- assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
for(i=0; i<pList->nId; i++){
sqlite3DbFree(db, pList->a[i].zName);
}
@@ -126163,8 +127773,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
return 0;
}
if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
- pNew = sqlite3DbRealloc(db, pSrc,
- sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
+ pNew = sqlite3DbRealloc(db, pSrc, SZ_SRCLIST(nAlloc));
if( pNew==0 ){
assert( db->mallocFailed );
return 0;
@@ -126239,7 +127848,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
assert( pParse->db!=0 );
db = pParse->db;
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
+ pList = sqlite3DbMallocRawNN(pParse->db, SZ_SRCLIST(1));
if( pList==0 ) return 0;
pList->nAlloc = 1;
pList->nSrc = 1;
@@ -126258,12 +127867,14 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
if( pDatabase && pDatabase->z==0 ){
pDatabase = 0;
}
+ assert( pItem->fg.fixedSchema==0 );
+ assert( pItem->fg.isSubquery==0 );
if( pDatabase ){
pItem->zName = sqlite3NameFromToken(db, pDatabase);
- pItem->zDatabase = sqlite3NameFromToken(db, pTable);
+ pItem->u4.zDatabase = sqlite3NameFromToken(db, pTable);
}else{
pItem->zName = sqlite3NameFromToken(db, pTable);
- pItem->zDatabase = 0;
+ pItem->u4.zDatabase = 0;
}
return pList;
}
@@ -126279,14 +127890,41 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
- if( pItem->pSelect ){
- sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
+ if( pItem->fg.isSubquery ){
+ assert( pItem->u4.pSubq!=0 );
+ assert( pItem->u4.pSubq->pSelect!=0 );
+ assert( pItem->u4.pSubq->pSelect->pSrc!=0 );
+ sqlite3SrcListAssignCursors(pParse, pItem->u4.pSubq->pSelect->pSrc);
}
}
}
}
/*
+** Delete a Subquery object and its substructure.
+*/
+SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3 *db, Subquery *pSubq){
+ assert( pSubq!=0 && pSubq->pSelect!=0 );
+ sqlite3SelectDelete(db, pSubq->pSelect);
+ sqlite3DbFree(db, pSubq);
+}
+
+/*
+** Remove a Subquery from a SrcItem. Return the associated Select object.
+** The returned Select becomes the responsibility of the caller.
+*/
+SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3 *db, SrcItem *pItem){
+ Select *pSel;
+ assert( pItem!=0 );
+ assert( pItem->fg.isSubquery );
+ pSel = pItem->u4.pSubq->pSelect;
+ sqlite3DbFree(db, pItem->u4.pSubq);
+ pItem->u4.pSubq = 0;
+ pItem->fg.isSubquery = 0;
+ return pSel;
+}
+
+/*
** Delete an entire SrcList including all its substructure.
*/
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
@@ -126295,13 +127933,24 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
assert( db!=0 );
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- if( pItem->zDatabase ) sqlite3DbNNFreeNN(db, pItem->zDatabase);
+
+ /* Check invariants on SrcItem */
+ assert( !pItem->fg.isIndexedBy || !pItem->fg.isTabFunc );
+ assert( !pItem->fg.isCte || !pItem->fg.isIndexedBy );
+ assert( !pItem->fg.fixedSchema || !pItem->fg.isSubquery );
+ assert( !pItem->fg.isSubquery || (pItem->u4.pSubq!=0 &&
+ pItem->u4.pSubq->pSelect!=0) );
+
if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName);
if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias);
+ if( pItem->fg.isSubquery ){
+ sqlite3SubqueryDelete(db, pItem->u4.pSubq);
+ }else if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+ sqlite3DbNNFreeNN(db, pItem->u4.zDatabase);
+ }
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
- sqlite3DeleteTable(db, pItem->pTab);
- if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+ sqlite3DeleteTable(db, pItem->pSTab);
if( pItem->fg.isUsing ){
sqlite3IdListDelete(db, pItem->u3.pUsing);
}else if( pItem->u3.pOn ){
@@ -126312,6 +127961,54 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
}
/*
+** Attach a Subquery object to pItem->uv.pSubq. Set the
+** pSelect value but leave all the other values initialized
+** to zero.
+**
+** A copy of the Select object is made if dupSelect is true, and the
+** SrcItem takes responsibility for deleting the copy. If dupSelect is
+** false, ownership of the Select passes to the SrcItem. Either way,
+** the SrcItem will take responsibility for deleting the Select.
+**
+** When dupSelect is zero, that means the Select might get deleted right
+** away if there is an OOM error. Beware.
+**
+** Return non-zero on success. Return zero on an OOM error.
+*/
+SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(
+ Parse *pParse, /* Parsing context */
+ SrcItem *pItem, /* Item to which the subquery is to be attached */
+ Select *pSelect, /* The subquery SELECT. Must be non-NULL */
+ int dupSelect /* If true, attach a copy of pSelect, not pSelect itself.*/
+){
+ Subquery *p;
+ assert( pSelect!=0 );
+ assert( pItem->fg.isSubquery==0 );
+ if( pItem->fg.fixedSchema ){
+ pItem->u4.pSchema = 0;
+ pItem->fg.fixedSchema = 0;
+ }else if( pItem->u4.zDatabase!=0 ){
+ sqlite3DbFree(pParse->db, pItem->u4.zDatabase);
+ pItem->u4.zDatabase = 0;
+ }
+ if( dupSelect ){
+ pSelect = sqlite3SelectDup(pParse->db, pSelect, 0);
+ if( pSelect==0 ) return 0;
+ }
+ p = pItem->u4.pSubq = sqlite3DbMallocRawNN(pParse->db, sizeof(Subquery));
+ if( p==0 ){
+ sqlite3SelectDelete(pParse->db, pSelect);
+ return 0;
+ }
+ pItem->fg.isSubquery = 1;
+ p->pSelect = pSelect;
+ assert( offsetof(Subquery, pSelect)==0 );
+ memset(((char*)p)+sizeof(p->pSelect), 0, sizeof(*p)-sizeof(p->pSelect));
+ return 1;
+}
+
+
+/*
** This routine is called by the parser to add a new term to the
** end of a growing FROM clause. The "p" parameter is the part of
** the FROM clause that has already been constructed. "p" is NULL
@@ -126360,10 +128057,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
if( pAlias->n ){
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
+ assert( pSubquery==0 || pDatabase==0 );
if( pSubquery ){
- pItem->pSelect = pSubquery;
- if( pSubquery->selFlags & SF_NestedFrom ){
- pItem->fg.isNestedFrom = 1;
+ if( sqlite3SrcItemAttachSubquery(pParse, pItem, pSubquery, 0) ){
+ if( pSubquery->selFlags & SF_NestedFrom ){
+ pItem->fg.isNestedFrom = 1;
+ }
}
}
assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
@@ -127035,10 +128734,9 @@ SQLITE_PRIVATE With *sqlite3WithAdd(
}
if( pWith ){
- sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
- pNew = sqlite3DbRealloc(db, pWith, nByte);
+ pNew = sqlite3DbRealloc(db, pWith, SZ_WITH(pWith->nCte+1));
}else{
- pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
+ pNew = sqlite3DbMallocZero(db, SZ_WITH(1));
}
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
@@ -127376,12 +129074,18 @@ static int matchQuality(
u8 enc /* Desired text encoding */
){
int match;
- assert( p->nArg>=-1 );
+ assert( p->nArg>=(-4) && p->nArg!=(-2) );
+ assert( nArg>=(-2) );
/* Wrong number of arguments means "no match" */
if( p->nArg!=nArg ){
- if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
+ if( nArg==(-2) ) return p->xSFunc==0 ? 0 : FUNC_PERFECT_MATCH;
if( p->nArg>=0 ) return 0;
+ /* Special p->nArg values available to built-in functions only:
+ ** -3 1 or more arguments required
+ ** -4 2 or more arguments required
+ */
+ if( p->nArg<(-2) && nArg<(-2-p->nArg) ) return 0;
}
/* Give a better score to a function with a specific number of arguments
@@ -127641,8 +129345,8 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
**
** The following fields are initialized appropriate in pSrc:
**
-** pSrc->a[0].pTab Pointer to the Table object
-** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
+** pSrc->a[0].spTab Pointer to the Table object
+** pSrc->a[0].u2.pIBIndex Pointer to the INDEXED BY index, if there is one
**
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
@@ -127650,8 +129354,8 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
Table *pTab;
assert( pItem && pSrc->nSrc>=1 );
pTab = sqlite3LocateTableItem(pParse, 0, pItem);
- if( pItem->pTab ) sqlite3DeleteTable(pParse->db, pItem->pTab);
- pItem->pTab = pTab;
+ if( pItem->pSTab ) sqlite3DeleteTable(pParse->db, pItem->pSTab);
+ pItem->pSTab = pTab;
pItem->fg.notCte = 1;
if( pTab ){
pTab->nTabRef++;
@@ -127692,6 +129396,7 @@ SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *
** is for a top-level SQL statement.
*/
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
+ assert( IsVirtual(pTab) );
if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
return 1;
}
@@ -127773,7 +129478,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
- pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ assert( pFrom->a[0].fg.fixedSchema==0 && pFrom->a[0].fg.isSubquery==0 );
+ pFrom->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
assert( pFrom->a[0].fg.isUsing==0 );
assert( pFrom->a[0].u3.pOn==0 );
}
@@ -127835,7 +129541,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
** );
*/
- pTab = pSrc->a[0].pTab;
+ pTab = pSrc->a[0].pSTab;
if( HasRowid(pTab) ){
pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
pEList = sqlite3ExprListAppend(
@@ -127868,9 +129574,9 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
- pSrc->a[0].pTab = 0;
+ pSrc->a[0].pSTab = 0;
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
- pSrc->a[0].pTab = pTab;
+ pSrc->a[0].pSTab = pTab;
if( pSrc->a[0].fg.isIndexedBy ){
assert( pSrc->a[0].fg.isCte==0 );
pSrc->a[0].u2.pIBIndex = 0;
@@ -129002,16 +130708,10 @@ static void substrFunc(
int len;
int p0type;
i64 p1, p2;
- int negP2 = 0;
assert( argc==3 || argc==2 );
- if( sqlite3_value_type(argv[1])==SQLITE_NULL
- || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
- ){
- return;
- }
p0type = sqlite3_value_type(argv[0]);
- p1 = sqlite3_value_int(argv[1]);
+ p1 = sqlite3_value_int64(argv[1]);
if( p0type==SQLITE_BLOB ){
len = sqlite3_value_bytes(argv[0]);
z = sqlite3_value_blob(argv[0]);
@@ -129027,28 +130727,31 @@ static void substrFunc(
}
}
}
-#ifdef SQLITE_SUBSTR_COMPATIBILITY
- /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
- ** as substr(X,1,N) - it returns the first N characters of X. This
- ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
- ** from 2009-02-02 for compatibility of applications that exploited the
- ** old buggy behavior. */
- if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */
-#endif
if( argc==3 ){
- p2 = sqlite3_value_int(argv[2]);
- if( p2<0 ){
- p2 = -p2;
- negP2 = 1;
- }
+ 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];
}
+ if( p1==0 ){
+#ifdef SQLITE_SUBSTR_COMPATIBILITY
+ /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
+ ** as substr(X,1,N) - it returns the first N characters of X. This
+ ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
+ ** from 2009-02-02 for compatibility of applications that exploited the
+ ** old buggy behavior. */
+ p1 = 1; /* <rdar://problem/6778339> */
+#endif
+ if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
+ }
if( p1<0 ){
p1 += len;
if( p1<0 ){
- p2 += p1;
- if( p2<0 ) p2 = 0;
+ if( p2<0 ){
+ p2 = 0;
+ }else{
+ p2 += p1;
+ }
p1 = 0;
}
}else if( p1>0 ){
@@ -129056,12 +130759,13 @@ static void substrFunc(
}else if( p2>0 ){
p2--;
}
- if( negP2 ){
- p1 -= p2;
- if( p1<0 ){
- p2 += p1;
- p1 = 0;
+ if( p2<0 ){
+ if( p2<-p1 ){
+ p2 = p1;
+ }else{
+ p2 = -p2;
}
+ p1 -= p2;
}
assert( p1>=0 && p2>=0 );
if( p0type!=SQLITE_BLOB ){
@@ -129075,9 +130779,11 @@ static void substrFunc(
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
SQLITE_UTF8);
}else{
- if( p1+p2>len ){
+ if( p1>=len ){
+ p1 = p2 = 0;
+ }else if( p2>len-p1 ){
p2 = len-p1;
- if( p2<0 ) p2 = 0;
+ assert( p2>0 );
}
sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
}
@@ -129088,13 +130794,13 @@ static void substrFunc(
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- int n = 0;
+ i64 n = 0;
double r;
char *zBuf;
assert( argc==1 || argc==2 );
if( argc==2 ){
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
- n = sqlite3_value_int(argv[1]);
+ n = sqlite3_value_int64(argv[1]);
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
@@ -129109,7 +130815,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}else if( n==0 ){
r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5)));
}else{
- zBuf = sqlite3_mprintf("%!.*f",n,r);
+ zBuf = sqlite3_mprintf("%!.*f",(int)n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
@@ -129738,7 +131444,7 @@ static const char hexdigits[] = {
** Append to pStr text that is the SQL literal representation of the
** value contained in pValue.
*/
-SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
+SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int bEscape){
/* As currently implemented, the string must be initially empty.
** we might relax this requirement in the future, but that will
** require enhancements to the implementation. */
@@ -129786,7 +131492,7 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
}
case SQLITE_TEXT: {
const unsigned char *zArg = sqlite3_value_text(pValue);
- sqlite3_str_appendf(pStr, "%Q", zArg);
+ sqlite3_str_appendf(pStr, bEscape ? "%#Q" : "%Q", zArg);
break;
}
default: {
@@ -129798,6 +131504,105 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
}
/*
+** Return true if z[] begins with N hexadecimal digits, and write
+** a decoding of those digits into *pVal. Or return false if any
+** one of the first N characters in z[] is not a hexadecimal digit.
+*/
+static int isNHex(const char *z, int N, u32 *pVal){
+ int i;
+ int v = 0;
+ for(i=0; i<N; i++){
+ if( !sqlite3Isxdigit(z[i]) ) return 0;
+ v = (v<<4) + sqlite3HexToInt(z[i]);
+ }
+ *pVal = v;
+ return 1;
+}
+
+/*
+** Implementation of the UNISTR() function.
+**
+** This is intended to be a work-alike of the UNISTR() function in
+** PostgreSQL. Quoting from the PG documentation (PostgreSQL 17 -
+** scraped on 2025-02-22):
+**
+** Evaluate escaped Unicode characters in the argument. Unicode
+** characters can be specified as \XXXX (4 hexadecimal digits),
+** \+XXXXXX (6 hexadecimal digits), \uXXXX (4 hexadecimal digits),
+** or \UXXXXXXXX (8 hexadecimal digits). To specify a backslash,
+** write two backslashes. All other characters are taken literally.
+*/
+static void unistrFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ char *zOut;
+ const char *zIn;
+ int nIn;
+ int i, j, n;
+ u32 v;
+
+ assert( argc==1 );
+ UNUSED_PARAMETER( argc );
+ zIn = (const char*)sqlite3_value_text(argv[0]);
+ if( zIn==0 ) return;
+ nIn = sqlite3_value_bytes(argv[0]);
+ zOut = sqlite3_malloc64(nIn+1);
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ i = j = 0;
+ while( i<nIn ){
+ char *z = strchr(&zIn[i],'\\');
+ if( z==0 ){
+ n = nIn - i;
+ memmove(&zOut[j], &zIn[i], n);
+ j += n;
+ break;
+ }
+ n = z - &zIn[i];
+ if( n>0 ){
+ memmove(&zOut[j], &zIn[i], n);
+ j += n;
+ i += n;
+ }
+ if( zIn[i+1]=='\\' ){
+ i += 2;
+ zOut[j++] = '\\';
+ }else if( sqlite3Isxdigit(zIn[i+1]) ){
+ if( !isNHex(&zIn[i+1], 4, &v) ) goto unistr_error;
+ i += 5;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='+' ){
+ if( !isNHex(&zIn[i+2], 6, &v) ) goto unistr_error;
+ i += 8;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='u' ){
+ if( !isNHex(&zIn[i+2], 4, &v) ) goto unistr_error;
+ i += 6;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='U' ){
+ if( !isNHex(&zIn[i+2], 8, &v) ) goto unistr_error;
+ i += 10;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else{
+ goto unistr_error;
+ }
+ }
+ zOut[j] = 0;
+ sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8);
+ return;
+
+unistr_error:
+ sqlite3_free(zOut);
+ sqlite3_result_error(context, "invalid Unicode escape", -1);
+ return;
+}
+
+
+/*
** Implementation of the QUOTE() function.
**
** The quote(X) function returns the text of an SQL literal which is the
@@ -129806,6 +131611,10 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
** as needed. BLOBs are encoded as hexadecimal literals. Strings with
** embedded NUL characters cannot be represented as string literals in SQL
** and hence the returned string literal is truncated prior to the first NUL.
+**
+** If sqlite3_user_data() is non-zero, then the UNISTR_QUOTE() function is
+** implemented instead. The difference is that UNISTR_QUOTE() uses the
+** UNISTR() function to escape control characters.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_str str;
@@ -129813,7 +131622,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
UNUSED_PARAMETER(argc);
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
- sqlite3QuoteValue(&str,argv[0]);
+ 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 ){
@@ -130068,7 +131877,7 @@ static void replaceFunc(
assert( zRep==sqlite3_value_text(argv[2]) );
nOut = nStr + 1;
assert( nOut<SQLITE_MAX_LENGTH );
- zOut = contextMalloc(context, (i64)nOut);
+ zOut = contextMalloc(context, nOut);
if( zOut==0 ){
return;
}
@@ -130212,13 +132021,13 @@ static void concatFuncCore(
int nSep,
const char *zSep
){
- i64 j, k, n = 0;
+ i64 j, n = 0;
int i;
char *z;
for(i=0; i<argc; i++){
n += sqlite3_value_bytes(argv[i]);
}
- n += (argc-1)*nSep;
+ n += (argc-1)*(i64)nSep;
z = sqlite3_malloc64(n+1);
if( z==0 ){
sqlite3_result_error_nomem(context);
@@ -130226,8 +132035,8 @@ static void concatFuncCore(
}
j = 0;
for(i=0; i<argc; i++){
- k = sqlite3_value_bytes(argv[i]);
- if( k>0 ){
+ if( sqlite3_value_type(argv[i])!=SQLITE_NULL ){
+ int k = sqlite3_value_bytes(argv[i]);
const char *v = (const char*)sqlite3_value_text(argv[i]);
if( v!=0 ){
if( j>0 && nSep>0 ){
@@ -130464,7 +132273,7 @@ static void kahanBabuskaNeumaierInit(
** that it returns NULL if it sums over no inputs. TOTAL returns
** 0.0 in that case. In addition, TOTAL always returns a float where
** SUM might return an integer if it never encounters a floating point
-** value. TOTAL never fails, but SUM might through an exception if
+** value. TOTAL never fails, but SUM might throw an exception if
** it overflows an integer.
*/
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
@@ -130516,7 +132325,10 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
assert( p->cnt>0 );
p->cnt--;
if( !p->approx ){
- p->iSum -= sqlite3_value_int64(argv[0]);
+ if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
+ p->ovrfl = 1;
+ p->approx = 1;
+ }
}else if( type==SQLITE_INTEGER ){
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal!=SMALLEST_INT64 ){
@@ -130697,7 +132509,11 @@ static void minMaxFinalize(sqlite3_context *context){
** group_concat(EXPR, ?SEPARATOR?)
** string_agg(EXPR, SEPARATOR)
**
-** The SEPARATOR goes before the EXPR string. This is tragic. The
+** Content is accumulated in GroupConcatCtx.str with the SEPARATOR
+** coming before the EXPR value, except for the first entry which
+** omits the SEPARATOR.
+**
+** It is tragic that the SEPARATOR goes before the EXPR string. The
** groupConcatInverse() implementation would have been easier if the
** SEPARATOR were appended after EXPR. And the order is undocumented,
** so we could change it, in theory. But the old behavior has been
@@ -130801,7 +132617,7 @@ static void groupConcatInverse(
/* pGCC is always non-NULL since groupConcatStep() will have always
** run first to initialize it */
if( ALWAYS(pGCC) ){
- int nVS;
+ int nVS; /* Number of characters to remove */
/* Must call sqlite3_value_text() to convert the argument into text prior
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
(void)sqlite3_value_text(argv[0]);
@@ -131179,7 +132995,13 @@ static void signFunc(
** Implementation of fpdecode(x,y,z) function.
**
** x is a real number that is to be decoded. y is the precision.
-** z is the maximum real precision.
+** z is the maximum real precision. Return a string that shows the
+** results of the sqlite3FpDecode() function.
+**
+** Used for testing and debugging only, specifically testing and debugging
+** of the sqlite3FpDecode() function. This SQL function does not appear
+** in production builds. This function is not an API and is subject to
+** modification or removal in future versions of SQLite.
*/
static void fpdecodeFunc(
sqlite3_context *context,
@@ -131195,6 +133017,7 @@ static void fpdecodeFunc(
x = sqlite3_value_double(argv[0]);
y = sqlite3_value_int(argv[1]);
z = sqlite3_value_int(argv[2]);
+ if( z<=0 ) z = 1;
sqlite3FpDecode(&s, x, y, z);
if( s.isSpecial==2 ){
sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
@@ -131205,6 +133028,82 @@ static void fpdecodeFunc(
}
#endif /* SQLITE_DEBUG */
+#ifdef SQLITE_DEBUG
+/*
+** Implementation of parseuri(uri,flags) function.
+**
+** Required Arguments:
+** "uri" The URI to parse.
+** "flags" Bitmask of flags, as if to sqlite3_open_v2().
+**
+** Additional arguments beyond the first two make calls to
+** sqlite3_uri_key() for integers and sqlite3_uri_parameter for
+** anything else.
+**
+** The result is a string showing the results of calling sqlite3ParseUri().
+**
+** Used for testing and debugging only, specifically testing and debugging
+** of the sqlite3ParseUri() function. This SQL function does not appear
+** in production builds. This function is not an API and is subject to
+** modification or removal in future versions of SQLite.
+*/
+static void parseuriFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3_str *pResult;
+ const char *zVfs;
+ const char *zUri;
+ unsigned int flgs;
+ int rc;
+ sqlite3_vfs *pVfs = 0;
+ char *zFile = 0;
+ char *zErr = 0;
+
+ if( argc<2 ) return;
+ pVfs = sqlite3_vfs_find(0);
+ assert( pVfs );
+ zVfs = pVfs->zName;
+ zUri = (const char*)sqlite3_value_text(argv[0]);
+ if( zUri==0 ) return;
+ flgs = (unsigned int)sqlite3_value_int(argv[1]);
+ rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
+ pResult = sqlite3_str_new(0);
+ if( pResult ){
+ int i;
+ sqlite3_str_appendf(pResult, "rc=%d", rc);
+ sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
+ sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
+ sqlite3_str_appendf(pResult, ", err=%Q", zErr);
+ sqlite3_str_appendf(pResult, ", file=%Q", zFile);
+ if( zFile ){
+ const char *z = zFile;
+ z += sqlite3Strlen30(z)+1;
+ while( z[0] ){
+ sqlite3_str_appendf(pResult, ", %Q", z);
+ z += sqlite3Strlen30(z)+1;
+ }
+ for(i=2; i<argc; i++){
+ const char *zArg;
+ if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
+ int k = sqlite3_value_int(argv[i]);
+ sqlite3_str_appendf(pResult, ", '%d:%q'",k,sqlite3_uri_key(zFile, k));
+ }else if( (zArg = (const char*)sqlite3_value_text(argv[i]))!=0 ){
+ sqlite3_str_appendf(pResult, ", '%q:%q'",
+ zArg, sqlite3_uri_parameter(zFile,zArg));
+ }else{
+ sqlite3_str_appendf(pResult, ", NULL");
+ }
+ }
+ }
+ sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free);
+ }
+ sqlite3_free_filename(zFile);
+ sqlite3_free(zErr);
+}
+#endif /* SQLITE_DEBUG */
+
/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
@@ -131239,9 +133138,6 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
SFUNCTION(load_extension, 1, 0, 0, loadExt ),
SFUNCTION(load_extension, 2, 0, 0, loadExt ),
#endif
-#if SQLITE_USER_AUTHENTICATION
- FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
-#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
@@ -131258,16 +133154,15 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(rtrim, 2, 2, 0, trimFunc ),
FUNCTION(trim, 1, 3, 0, trimFunc ),
FUNCTION(trim, 2, 3, 0, trimFunc ),
- FUNCTION(min, -1, 0, 1, minmaxFunc ),
- FUNCTION(min, 0, 0, 1, 0 ),
+ FUNCTION(min, -3, 0, 1, minmaxFunc ),
WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
- FUNCTION(max, -1, 1, 1, minmaxFunc ),
- FUNCTION(max, 0, 1, 1, 0 ),
+ FUNCTION(max, -3, 1, 1, minmaxFunc ),
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
- FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
+ FUNCTION2(subtype, 1, 0, 0, subtypeFunc,
+ SQLITE_FUNC_TYPEOF|SQLITE_SUBTYPE),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION2(octet_length, 1, 0, 0, bytelengthFunc,SQLITE_FUNC_BYTELEN),
FUNCTION(instr, 2, 0, 0, instrFunc ),
@@ -131278,6 +133173,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(abs, 1, 0, 0, absFunc ),
#ifdef SQLITE_DEBUG
FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ),
+ FUNCTION(parseuri, -1, 0, 0, parseuriFunc ),
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -131288,11 +133184,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(hex, 1, 0, 0, hexFunc ),
FUNCTION(unhex, 1, 0, 0, unhexFunc ),
FUNCTION(unhex, 2, 0, 0, unhexFunc ),
- FUNCTION(concat, -1, 0, 0, concatFunc ),
- FUNCTION(concat, 0, 0, 0, 0 ),
- FUNCTION(concat_ws, -1, 0, 0, concatwsFunc ),
- FUNCTION(concat_ws, 0, 0, 0, 0 ),
- FUNCTION(concat_ws, 1, 0, 0, 0 ),
+ FUNCTION(concat, -3, 0, 0, concatFunc ),
+ FUNCTION(concat_ws, -4, 0, 0, concatwsFunc ),
INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ),
VFUNCTION(random, 0, 0, 0, randomFunc ),
VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
@@ -131300,7 +133193,9 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
FUNCTION(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 ),
VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
VFUNCTION(changes, 0, 0, 0, changes ),
VFUNCTION(total_changes, 0, 0, 0, total_changes ),
@@ -131336,8 +133231,6 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUNCTION(unknown, -1, 0, 0, unknownFunc ),
#endif
- FUNCTION(coalesce, 1, 0, 0, 0 ),
- FUNCTION(coalesce, 0, 0, 0, 0 ),
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
MFUNCTION(ceil, 1, xCeil, ceilingFunc ),
MFUNCTION(ceiling, 1, xCeil, ceilingFunc ),
@@ -131372,11 +133265,12 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
MFUNCTION(sqrt, 1, sqrt, math1Func ),
MFUNCTION(radians, 1, degToRad, math1Func ),
MFUNCTION(degrees, 1, radToDeg, math1Func ),
- FUNCTION(pi, 0, 0, 0, piFunc ),
+ MFUNCTION(pi, 0, 0, piFunc ),
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
FUNCTION(sign, 1, 0, 0, signFunc ),
- INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
- INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
+ INLINE_FUNC(coalesce, -4, INLINEFUNC_coalesce, 0 ),
+ INLINE_FUNC(iif, -4, INLINEFUNC_iif, 0 ),
+ INLINE_FUNC(if, -4, INLINEFUNC_iif, 0 ),
};
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions();
@@ -132451,9 +134345,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
SrcItem *pItem = pSrc->a;
- pItem->pTab = pFKey->pFrom;
+ pItem->pSTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
- pItem->pTab->nTabRef++;
+ pItem->pSTab->nTabRef++;
pItem->iCursor = pParse->nTab++;
if( regNew!=0 ){
@@ -132736,7 +134630,8 @@ static Trigger *fkActionTrigger(
SrcList *pSrc;
Expr *pRaise;
- pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
+ pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"),
+ pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0);
if( pRaise ){
pRaise->affExpr = OE_Abort;
}
@@ -132744,7 +134639,8 @@ static Trigger *fkActionTrigger(
if( pSrc ){
assert( pSrc->nSrc==1 );
pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom);
- pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 );
+ pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
@@ -133478,8 +135374,11 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){
SrcItem *pItem = &pVal->pSrc->a[0];
- sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn);
- sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1);
+ assert( (pItem->fg.isSubquery && pItem->u4.pSubq!=0) || pParse->nErr );
+ if( pItem->fg.isSubquery ){
+ sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->u4.pSubq->regReturn);
+ sqlite3VdbeJumpHere(pParse->pVdbe, pItem->u4.pSubq->addrFillSub - 1);
+ }
}
}
@@ -133583,7 +135482,7 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
f = (f & pLeft->selFlags);
}
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
- pLeft->selFlags &= ~SF_MultiValue;
+ pLeft->selFlags &= ~(u32)SF_MultiValue;
if( pSelect ){
pSelect->op = TK_ALL;
pSelect->pPrior = pLeft;
@@ -133607,6 +135506,7 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
if( pRet ){
SelectDest dest;
+ Subquery *pSubq;
pRet->pSrc->nSrc = 1;
pRet->pPrior = pLeft->pPrior;
pRet->op = pLeft->op;
@@ -133616,28 +135516,32 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
assert( pLeft->pNext==0 );
assert( pRet->pNext==0 );
p = &pRet->pSrc->a[0];
- p->pSelect = pLeft;
p->fg.viaCoroutine = 1;
- p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
- p->regReturn = ++pParse->nMem;
p->iCursor = -1;
+ assert( !p->fg.isIndexedBy && !p->fg.isTabFunc );
p->u1.nRow = 2;
- sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub);
- sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn);
-
- /* Allocate registers for the output of the co-routine. Do so so
- ** that there are two unused registers immediately before those
- ** used by the co-routine. This allows the code in sqlite3Insert()
- ** to use these registers directly, instead of copying the output
- ** of the co-routine to a separate array for processing. */
- dest.iSdst = pParse->nMem + 3;
- dest.nSdst = pLeft->pEList->nExpr;
- pParse->nMem += 2 + dest.nSdst;
-
- pLeft->selFlags |= SF_MultiValue;
- sqlite3Select(pParse, pLeft, &dest);
- p->regResult = dest.iSdst;
- assert( pParse->nErr || dest.iSdst>0 );
+ if( sqlite3SrcItemAttachSubquery(pParse, p, pLeft, 0) ){
+ pSubq = p->u4.pSubq;
+ pSubq->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
+ pSubq->regReturn = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine,
+ pSubq->regReturn, 0, pSubq->addrFillSub);
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn);
+
+ /* Allocate registers for the output of the co-routine. Do so so
+ ** that there are two unused registers immediately before those
+ ** used by the co-routine. This allows the code in sqlite3Insert()
+ ** to use these registers directly, instead of copying the output
+ ** of the co-routine to a separate array for processing. */
+ dest.iSdst = pParse->nMem + 3;
+ dest.nSdst = pLeft->pEList->nExpr;
+ pParse->nMem += 2 + dest.nSdst;
+
+ pLeft->selFlags |= SF_MultiValue;
+ sqlite3Select(pParse, pLeft, &dest);
+ pSubq->regResult = dest.iSdst;
+ assert( pParse->nErr || dest.iSdst>0 );
+ }
pLeft = pRet;
}
}else{
@@ -133647,12 +135551,18 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
}
if( pParse->nErr==0 ){
+ Subquery *pSubq;
assert( p!=0 );
- if( p->pSelect->pEList->nExpr!=pRow->nExpr ){
- sqlite3SelectWrongNumTermsError(pParse, p->pSelect);
+ assert( p->fg.isSubquery );
+ pSubq = p->u4.pSubq;
+ assert( pSubq!=0 );
+ assert( pSubq->pSelect!=0 );
+ assert( pSubq->pSelect->pEList!=0 );
+ if( pSubq->pSelect->pEList->nExpr!=pRow->nExpr ){
+ sqlite3SelectWrongNumTermsError(pParse, pSubq->pSelect);
}else{
- sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0);
- sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn);
+ sqlite3ExprCodeExprList(pParse, pRow, pSubq->regResult, 0, 0);
+ sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, pSubq->regReturn);
}
}
sqlite3ExprListDelete(pParse->db, pRow);
@@ -133806,6 +135716,7 @@ SQLITE_PRIVATE void sqlite3Insert(
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int *aRegIdx = 0; /* One register allocated to each index */
+ int *aTabColMap = 0; /* Mapping from pTab columns to pCol entries */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */
@@ -133950,31 +135861,25 @@ SQLITE_PRIVATE void sqlite3Insert(
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
- assert( pColumn->eU4!=EU4_EXPR );
- pColumn->eU4 = EU4_IDX;
+ aTabColMap = sqlite3DbMallocZero(db, pTab->nCol*sizeof(int));
+ if( aTabColMap==0 ) goto insert_cleanup;
for(i=0; i<pColumn->nId; i++){
- pColumn->a[i].u4.idx = -1;
- }
- for(i=0; i<pColumn->nId; i++){
- for(j=0; j<pTab->nCol; j++){
- if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
- pColumn->a[i].u4.idx = j;
- if( i!=j ) bIdListInOrder = 0;
- if( j==pTab->iPKey ){
- ipkColumn = i; assert( !withoutRowid );
- }
+ j = sqlite3ColumnIndex(pTab, pColumn->a[i].zName);
+ if( j>=0 ){
+ if( aTabColMap[j]==0 ) aTabColMap[j] = i+1;
+ if( i!=j ) bIdListInOrder = 0;
+ if( j==pTab->iPKey ){
+ ipkColumn = i; assert( !withoutRowid );
+ }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
- sqlite3ErrorMsg(pParse,
- "cannot INSERT into generated column \"%s\"",
- pTab->aCol[j].zCnName);
- goto insert_cleanup;
- }
-#endif
- break;
+ if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
+ sqlite3ErrorMsg(pParse,
+ "cannot INSERT into generated column \"%s\"",
+ pTab->aCol[j].zCnName);
+ goto insert_cleanup;
}
- }
- if( j>=pTab->nCol ){
+#endif
+ }else{
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
ipkColumn = i;
bIdListInOrder = 0;
@@ -134003,9 +135908,14 @@ SQLITE_PRIVATE void sqlite3Insert(
&& pSelect->pPrior==0
){
SrcItem *pItem = &pSelect->pSrc->a[0];
- dest.iSDParm = pItem->regReturn;
- regFromSelect = pItem->regResult;
- nColumn = pItem->pSelect->pEList->nExpr;
+ Subquery *pSubq;
+ assert( pItem->fg.isSubquery );
+ pSubq = pItem->u4.pSubq;
+ dest.iSDParm = pSubq->regReturn;
+ regFromSelect = pSubq->regResult;
+ assert( pSubq->pSelect!=0 );
+ assert( pSubq->pSelect->pEList!=0 );
+ nColumn = pSubq->pSelect->pEList->nExpr;
ExplainQueryPlan((pParse, 0, "SCAN %S", pItem));
if( bIdListInOrder && nColumn==pTab->nCol ){
regData = regFromSelect;
@@ -134267,7 +136177,7 @@ SQLITE_PRIVATE void sqlite3Insert(
continue;
}else if( pColumn==0 ){
/* Hidden columns that are not explicitly named in the INSERT
- ** get there default value */
+ ** get their default value */
sqlite3ExprCodeFactorable(pParse,
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
iRegStore);
@@ -134275,9 +136185,9 @@ SQLITE_PRIVATE void sqlite3Insert(
}
}
if( pColumn ){
- assert( pColumn->eU4==EU4_IDX );
- for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){}
- if( j>=pColumn->nId ){
+ j = aTabColMap[i];
+ assert( j>=0 && j<=pColumn->nId );
+ if( j==0 ){
/* A column not named in the insert column list gets its
** default value */
sqlite3ExprCodeFactorable(pParse,
@@ -134285,7 +136195,7 @@ SQLITE_PRIVATE void sqlite3Insert(
iRegStore);
continue;
}
- k = j;
+ k = j - 1;
}else if( nColumn==0 ){
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
sqlite3ExprCodeFactorable(pParse,
@@ -134530,7 +136440,10 @@ insert_cleanup:
sqlite3ExprListDelete(db, pList);
sqlite3UpsertDelete(db, pUpsert);
sqlite3SelectDelete(db, pSelect);
- sqlite3IdListDelete(db, pColumn);
+ if( pColumn ){
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3DbFree(db, aTabColMap);
+ }
if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx);
}
@@ -134989,7 +136902,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** could happen in any order, but they are grouped up front for
** convenience.
**
- ** 2018-08-14: Ticket https://www.sqlite.org/src/info/908f001483982c43
+ ** 2018-08-14: Ticket https://sqlite.org/src/info/908f001483982c43
** The order of constraints used to have OE_Update as (2) and OE_Abort
** and so forth as (1). But apparently PostgreSQL checks the OE_Update
** constraint before any others, so it had to be moved.
@@ -135925,7 +137838,7 @@ static int xferOptimization(
if( pSelect->pSrc->nSrc!=1 ){
return 0; /* FROM clause must have exactly one term */
}
- if( pSelect->pSrc->a[0].pSelect ){
+ if( pSelect->pSrc->a[0].fg.isSubquery ){
return 0; /* FROM clause cannot contain a subquery */
}
if( pSelect->pWhere ){
@@ -136799,6 +138712,8 @@ struct sqlite3_api_routines {
/* Version 3.44.0 and later */
void *(*get_clientdata)(sqlite3*,const char*);
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
+ /* Version 3.50.0 and later */
+ int (*setlk_timeout)(sqlite3*,int,int);
};
/*
@@ -137132,6 +139047,8 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
+/* Version 3.50.0 and later */
+#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -137653,7 +139570,9 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_stmt_explain,
/* Version 3.44.0 and later */
sqlite3_get_clientdata,
- sqlite3_set_clientdata
+ sqlite3_set_clientdata,
+ /* Version 3.50.0 and later */
+ sqlite3_setlk_timeout
};
/* True if x is the directory separator character
@@ -138175,48 +140094,48 @@ static const char *const pragCName[] = {
/* 13 */ "pk",
/* 14 */ "hidden",
/* table_info reuses 8 */
- /* 15 */ "schema", /* Used by: table_list */
- /* 16 */ "name",
+ /* 15 */ "name", /* Used by: function_list */
+ /* 16 */ "builtin",
/* 17 */ "type",
- /* 18 */ "ncol",
- /* 19 */ "wr",
- /* 20 */ "strict",
- /* 21 */ "seqno", /* Used by: index_xinfo */
- /* 22 */ "cid",
- /* 23 */ "name",
- /* 24 */ "desc",
- /* 25 */ "coll",
- /* 26 */ "key",
- /* 27 */ "name", /* Used by: function_list */
- /* 28 */ "builtin",
- /* 29 */ "type",
- /* 30 */ "enc",
- /* 31 */ "narg",
- /* 32 */ "flags",
- /* 33 */ "tbl", /* Used by: stats */
- /* 34 */ "idx",
- /* 35 */ "wdth",
- /* 36 */ "hght",
- /* 37 */ "flgs",
- /* 38 */ "seq", /* Used by: index_list */
- /* 39 */ "name",
- /* 40 */ "unique",
- /* 41 */ "origin",
- /* 42 */ "partial",
+ /* 18 */ "enc",
+ /* 19 */ "narg",
+ /* 20 */ "flags",
+ /* 21 */ "schema", /* Used by: table_list */
+ /* 22 */ "name",
+ /* 23 */ "type",
+ /* 24 */ "ncol",
+ /* 25 */ "wr",
+ /* 26 */ "strict",
+ /* 27 */ "seqno", /* Used by: index_xinfo */
+ /* 28 */ "cid",
+ /* 29 */ "name",
+ /* 30 */ "desc",
+ /* 31 */ "coll",
+ /* 32 */ "key",
+ /* 33 */ "seq", /* Used by: index_list */
+ /* 34 */ "name",
+ /* 35 */ "unique",
+ /* 36 */ "origin",
+ /* 37 */ "partial",
+ /* 38 */ "tbl", /* Used by: stats */
+ /* 39 */ "idx",
+ /* 40 */ "wdth",
+ /* 41 */ "hght",
+ /* 42 */ "flgs",
/* 43 */ "table", /* Used by: foreign_key_check */
/* 44 */ "rowid",
/* 45 */ "parent",
/* 46 */ "fkid",
- /* index_info reuses 21 */
- /* 47 */ "seq", /* Used by: database_list */
- /* 48 */ "name",
- /* 49 */ "file",
- /* 50 */ "busy", /* Used by: wal_checkpoint */
- /* 51 */ "log",
- /* 52 */ "checkpointed",
- /* collation_list reuses 38 */
+ /* 47 */ "busy", /* Used by: wal_checkpoint */
+ /* 48 */ "log",
+ /* 49 */ "checkpointed",
+ /* 50 */ "seq", /* Used by: database_list */
+ /* 51 */ "name",
+ /* 52 */ "file",
+ /* index_info reuses 27 */
/* 53 */ "database", /* Used by: lock_status */
/* 54 */ "status",
+ /* collation_list reuses 33 */
/* 55 */ "cache_size", /* Used by: default_cache_size */
/* module_list pragma_list reuses 9 */
/* 56 */ "timeout", /* Used by: busy_timeout */
@@ -138309,7 +140228,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 38, 2,
+ /* ColNames: */ 33, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -138344,7 +140263,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 47, 3,
+ /* ColNames: */ 50, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -138424,7 +140343,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 27, 6,
+ /* ColNames: */ 15, 6,
/* iArg: */ 0 },
#endif
#endif
@@ -138453,17 +140372,17 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 21, 3,
+ /* ColNames: */ 27, 3,
/* iArg: */ 0 },
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 38, 5,
+ /* ColNames: */ 33, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 21, 6,
+ /* ColNames: */ 27, 6,
/* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
@@ -138642,7 +140561,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 33, 5,
+ /* ColNames: */ 38, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -138661,7 +140580,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "table_list",
/* ePragTyp: */ PragTyp_TABLE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
- /* ColNames: */ 15, 6,
+ /* ColNames: */ 21, 6,
/* iArg: */ 0 },
{/* zName: */ "table_xinfo",
/* ePragTyp: */ PragTyp_TABLE_INFO,
@@ -138738,7 +140657,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
- /* ColNames: */ 50, 3,
+ /* ColNames: */ 47, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -138760,7 +140679,7 @@ static const PragmaName aPragmaName[] = {
** the following macro or to the actual analysis_limit if it is non-zero,
** in order to prevent PRAGMA optimize from running for too long.
**
-** The value of 2000 is chosen emperically so that the worst-case run-time
+** The value of 2000 is chosen empirically so that the worst-case run-time
** for PRAGMA optimize does not exceed 100 milliseconds against a variety
** of test databases on a RaspberryPI-4 compiled using -Os and without
** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
@@ -139868,12 +141787,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
** in auto-commit mode. */
mask &= ~(SQLITE_ForeignKeys);
}
-#if SQLITE_USER_AUTHENTICATION
- if( db->auth.authLevel==UAUTH_User ){
- /* Do not allow non-admin users to modify the schema arbitrarily */
- mask &= ~(SQLITE_WriteSchema);
- }
-#endif
if( sqlite3GetBoolean(zRight, 0) ){
if( (mask & SQLITE_WriteSchema)==0
@@ -139883,7 +141796,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}else{
db->flags &= ~mask;
- if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
+ if( mask==SQLITE_DeferFKs ){
+ db->nDeferredImmCons = 0;
+ db->nDeferredCons = 0;
+ }
if( (mask & SQLITE_WriteSchema)!=0
&& sqlite3_stricmp(zRight, "reset")==0
){
@@ -140009,7 +141925,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
if( zSql ){
sqlite3_stmt *pDummy = 0;
- (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
+ (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG,
+ &pDummy, 0);
(void)sqlite3_finalize(pDummy);
sqlite3DbFree(db, zSql);
}
@@ -140485,11 +142402,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Make sure sufficient number of registers have been allocated */
sqlite3TouchRegister(pParse, 8+cnt);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt);
sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY);
- sqlite3VdbeChangeP5(v, (u8)i);
+ sqlite3VdbeChangeP5(v, (u16)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
@@ -142109,14 +144027,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
#else
encoding = SQLITE_UTF8;
#endif
- if( db->nVdbeActive>0 && encoding!=ENC(db)
- && (db->mDbFlags & DBFLAG_Vacuum)==0
- ){
- rc = SQLITE_LOCKED;
- goto initone_error_out;
- }else{
- sqlite3SetTextEncoding(db, encoding);
- }
+ sqlite3SetTextEncoding(db, encoding);
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){
@@ -142810,12 +144721,24 @@ static int sqlite3Prepare16(
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
return SQLITE_MISUSE_BKPT;
}
+
+ /* Make sure nBytes is non-negative and correct. It should be the
+ ** number of bytes until the end of the input buffer or until the first
+ ** U+0000 character. If the input nBytes is odd, convert it into
+ ** an even number. If the input nBytes is negative, then the input
+ ** must be terminated by at least one U+0000 character */
if( nBytes>=0 ){
int sz;
const char *z = (const char*)zSql;
for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
nBytes = sz;
+ }else{
+ int sz;
+ const char *z = (const char*)zSql;
+ for(sz=0; z[sz]!=0 || z[sz+1]!=0; sz += 2){}
+ nBytes = sz;
}
+
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
@@ -142829,7 +144752,7 @@ static int sqlite3Prepare16(
** the same number of characters into the UTF-16 string.
*/
int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
- *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
+ *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, nBytes, chars_parsed);
}
sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
@@ -143045,7 +144968,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
- if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
@@ -143210,10 +145133,33 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p
*/
SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
int i;
- u8 h = sqlite3StrIHash(zCol);
- Column *pCol;
- for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
- if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
+ u8 h;
+ const Column *aCol;
+ int nCol;
+
+ h = sqlite3StrIHash(zCol);
+ aCol = pTab->aCol;
+ nCol = pTab->nCol;
+
+ /* See if the aHx gives us a lucky match */
+ i = pTab->aHx[h % sizeof(pTab->aHx)];
+ assert( i<nCol );
+ if( aCol[i].hName==h
+ && sqlite3StrICmp(aCol[i].zCnName, zCol)==0
+ ){
+ return i;
+ }
+
+ /* No lucky match from the hash table. Do a full search. */
+ i = 0;
+ while( 1 /*exit-by-break*/ ){
+ if( aCol[i].hName==h
+ && sqlite3StrICmp(aCol[i].zCnName, zCol)==0
+ ){
+ return i;
+ }
+ i++;
+ if( i>=nCol ) break;
}
return -1;
}
@@ -143223,11 +145169,13 @@ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
*/
SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
assert( pItem!=0 );
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
if( pItem->fg.isNestedFrom ){
ExprList *pResults;
- assert( pItem->pSelect!=0 );
- pResults = pItem->pSelect->pEList;
+ assert( pItem->fg.isSubquery );
+ assert( pItem->u4.pSubq!=0 );
+ assert( pItem->u4.pSubq->pSelect!=0 );
+ pResults = pItem->u4.pSubq->pSelect->pEList;
assert( pResults!=0 );
assert( iCol>=0 && iCol<pResults->nExpr );
pResults->a[iCol].fg.bUsed = 1;
@@ -143261,9 +145209,9 @@ static int tableAndColumnIndex(
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=iStart; i<=iEnd; i++){
- iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
+ iCol = sqlite3ColumnIndex(pSrc->a[i].pSTab, zCol);
if( iCol>=0
- && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
+ && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pSTab->aCol[iCol])==0)
){
if( piTab ){
sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
@@ -143392,10 +145340,10 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
- Table *pRightTab = pRight->pTab;
+ Table *pRightTab = pRight->pSTab;
u32 joinType;
- if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
+ if( NEVER(pLeft->pSTab==0 || pRightTab==0) ) continue;
joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON;
/* If this is a NATURAL join, synthesize an appropriate USING clause
@@ -143462,7 +145410,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
}
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
- if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
+ if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 && pParse->nErr==0 ){
/* This branch runs if the query contains one or more RIGHT or FULL
** JOINs. If only a single table on the left side of this join
** contains the zName column, then this branch is a no-op.
@@ -143478,6 +145426,8 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
*/
ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */
static const Token tkCoalesce = { "coalesce", 8 };
+ assert( pE1!=0 );
+ ExprSetProperty(pE1, EP_CanBeNull);
while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
pRight->fg.isSynthUsing)!=0 ){
if( pSrc->a[iLeft].fg.isUsing==0
@@ -143494,7 +145444,13 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
if( pFuncArgs ){
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
+ if( pE1 ){
+ pE1->affExpr = SQLITE_AFF_DEFER;
+ }
}
+ }else if( (pSrc->a[i+1].fg.jointype & JT_LEFT)!=0 && pParse->nErr==0 ){
+ assert( pE1!=0 );
+ ExprSetProperty(pE1, EP_CanBeNull);
}
pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
sqlite3SrcItemColumnUsed(pRight, iRightCol);
@@ -144268,12 +146224,18 @@ static void selectInnerLoop(
** case the order does matter */
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
+ pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
+ if( pDest->iSDParm2 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ regResult, nResultCol);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -144397,8 +146359,8 @@ static void selectInnerLoop(
** X extra columns.
*/
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
- int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
- KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1);
+ KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
if( p ){
p->aSortFlags = (u8*)&p->aColl[N+X];
p->nKeyField = (u16)N;
@@ -144406,7 +146368,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
p->enc = ENC(db);
p->db = db;
p->nRef = 1;
- memset(&p[1], 0, nExtra);
+ memset(p->aColl, 0, nExtra);
}else{
return (KeyInfo*)sqlite3OomFault(db);
}
@@ -144815,8 +146777,12 @@ static const char *columnTypeImpl(
SrcList *pTabList = pNC->pSrcList;
for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
if( j<pTabList->nSrc ){
- pTab = pTabList->a[j].pTab;
- pS = pTabList->a[j].pSelect;
+ pTab = pTabList->a[j].pSTab;
+ if( pTabList->a[j].fg.isSubquery ){
+ pS = pTabList->a[j].u4.pSubq->pSelect;
+ }else{
+ pS = 0;
+ }
}else{
pNC = pNC->pNext;
}
@@ -145383,7 +147349,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
p->iLimit = iLimit = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
- if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
+ if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
@@ -145863,7 +147829,7 @@ static int multiSelect(
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
if( p->pLimit
- && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlite3LogEst((u64)nLimit);
@@ -146103,6 +148069,7 @@ static int multiSelect(
multi_select_end:
pDest->iSdst = dest.iSdst;
pDest->nSdst = dest.nSdst;
+ pDest->iSDParm2 = dest.iSDParm2;
if( pDelete ){
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete);
}
@@ -146207,6 +148174,11 @@ static int generateOutputSubroutine(
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
+ if( pDest->iSDParm2>0 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ pIn->iSdst, pIn->nSdst);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -146785,32 +148757,32 @@ static Expr *substExpr(
if( pSubst->isOuterJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
- if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
- sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
- pExpr->flags & (EP_OuterON|EP_InnerON));
- }
- sqlite3ExprDelete(db, pExpr);
- pExpr = pNew;
- if( pExpr->op==TK_TRUEFALSE ){
- pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
- pExpr->op = TK_INTEGER;
- ExprSetProperty(pExpr, EP_IntValue);
+ if( pNew->op==TK_TRUEFALSE ){
+ pNew->u.iValue = sqlite3ExprTruthValue(pNew);
+ pNew->op = TK_INTEGER;
+ ExprSetProperty(pNew, EP_IntValue);
}
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
{
- CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+ CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew);
CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
pSubst->pCList->a[iColumn].pExpr
);
- if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
- pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+ if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){
+ pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew,
(pColl ? pColl->zName : "BINARY")
);
}
}
- ExprClearProperty(pExpr, EP_Collate);
+ ExprClearProperty(pNew, EP_Collate);
+ if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
+ sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
+ pExpr->flags & (EP_OuterON|EP_InnerON));
+ }
+ sqlite3ExprDelete(db, pExpr);
+ pExpr = pNew;
}
}
}else{
@@ -146863,7 +148835,9 @@ static void substSelect(
pSrc = p->pSrc;
assert( pSrc!=0 );
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- substSelect(pSubst, pItem->pSelect, 1);
+ if( pItem->fg.isSubquery ){
+ substSelect(pSubst, pItem->u4.pSubq->pSelect, 1);
+ }
if( pItem->fg.isTabFunc ){
substExprList(pSubst, pItem->u1.pFuncArg);
}
@@ -146894,7 +148868,7 @@ static void recomputeColumnsUsed(
SrcItem *pSrcItem /* Which FROM clause item to recompute */
){
Walker w;
- if( NEVER(pSrcItem->pTab==0) ) return;
+ if( NEVER(pSrcItem->pSTab==0) ) return;
memset(&w, 0, sizeof(w));
w.xExprCallback = recomputeColumnsUsedExpr;
w.xSelectCallback = sqlite3SelectWalkNoop;
@@ -146934,8 +148908,10 @@ static void srclistRenumberCursors(
aCsrMap[pItem->iCursor+1] = pParse->nTab++;
}
pItem->iCursor = aCsrMap[pItem->iCursor+1];
- for(p=pItem->pSelect; p; p=p->pPrior){
- srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ if( pItem->fg.isSubquery ){
+ for(p=pItem->u4.pSubq->pSelect; p; p=p->pPrior){
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ }
}
}
}
@@ -147082,9 +149058,9 @@ static int compoundHasDifferentAffinities(Select *p){
** from 2015-02-09.)
**
** (3) If the subquery is the right operand of a LEFT JOIN then
-** (3a) the subquery may not be a join and
-** (3b) the FROM clause of the subquery may not contain a virtual
-** table and
+** (3a) the subquery may not be a join
+** (**) Was (3b): "the FROM clause of the subquery may not contain
+** a virtual table"
** (**) Was: "The outer query may not have a GROUP BY." This case
** is now managed correctly
** (3d) the outer query may not be DISTINCT.
@@ -147246,7 +149222,8 @@ static int flattenSubquery(
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
pSubitem = &pSrc->a[iFrom];
iParent = pSubitem->iCursor;
- pSub = pSubitem->pSelect;
+ assert( pSubitem->fg.isSubquery );
+ pSub = pSubitem->u4.pSubq->pSelect;
assert( pSub!=0 );
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -147299,7 +149276,7 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
- || IsVirtual(pSubSrc->a[0].pTab) /* (3b) */
+ /**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
@@ -147385,14 +149362,18 @@ static int flattenSubquery(
pParse->zAuthContext = zSavedAuthContext;
/* Delete the transient structures associated with the subquery */
- pSub1 = pSubitem->pSelect;
- sqlite3DbFree(db, pSubitem->zDatabase);
+
+ if( ALWAYS(pSubitem->fg.isSubquery) ){
+ pSub1 = sqlite3SubqueryDetach(db, pSubitem);
+ }else{
+ pSub1 = 0;
+ }
+ assert( pSubitem->fg.isSubquery==0 );
+ assert( pSubitem->fg.fixedSchema==0 );
sqlite3DbFree(db, pSubitem->zName);
sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
pSubitem->zName = 0;
pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 );
/* If the sub-query is a compound SELECT statement, then (by restrictions
@@ -147433,8 +149414,8 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
- Table *pItemTab = pSubitem->pTab;
- pSubitem->pTab = 0;
+ Table *pItemTab = pSubitem->pSTab;
+ pSubitem->pSTab = 0;
p->pOrderBy = 0;
p->pPrior = 0;
p->pLimit = 0;
@@ -147442,7 +149423,7 @@ static int flattenSubquery(
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->op = TK_ALL;
- pSubitem->pTab = pItemTab;
+ pSubitem->pSTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
@@ -147457,11 +149438,14 @@ static int flattenSubquery(
TREETRACE(0x4,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
- assert( pSubitem->pSelect==0 );
+ assert( pSubitem->fg.isSubquery==0 );
}
sqlite3DbFree(db, aCsrMap);
if( db->mallocFailed ){
- pSubitem->pSelect = pSub1;
+ assert( pSubitem->fg.fixedSchema==0 );
+ assert( pSubitem->fg.isSubquery==0 );
+ assert( pSubitem->u4.zDatabase==0 );
+ sqlite3SrcItemAttachSubquery(pParse, pSubitem, pSub1, 0);
return 1;
}
@@ -147472,8 +149456,8 @@ static int flattenSubquery(
**
** pSubitem->pTab is always non-NULL by test restrictions and tests above.
*/
- if( ALWAYS(pSubitem->pTab!=0) ){
- Table *pTabToDel = pSubitem->pTab;
+ if( ALWAYS(pSubitem->pSTab!=0) ){
+ Table *pTabToDel = pSubitem->pSTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel);
@@ -147481,7 +149465,7 @@ static int flattenSubquery(
}else{
pTabToDel->nTabRef--;
}
- pSubitem->pTab = 0;
+ pSubitem->pSTab = 0;
}
/* The following loop runs once for each term in a compound-subquery
@@ -147535,13 +149519,16 @@ static int flattenSubquery(
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
+ iNewParent = pSubSrc->a[0].iCursor;
for(i=0; i<nSubSrc; i++){
SrcItem *pItem = &pSrc->a[i+iFrom];
- if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
assert( pItem->fg.isTabFunc==0 );
+ assert( pItem->fg.isSubquery
+ || pItem->fg.fixedSchema
+ || pItem->u4.zDatabase==0 );
+ if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
*pItem = pSubSrc->a[i];
pItem->fg.jointype |= ltorj;
- iNewParent = pSubSrc->a[i].iCursor;
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
@@ -147581,6 +149568,7 @@ static int flattenSubquery(
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isOuterJoin>0 ){
+ assert( pSubSrc->nSrc==1 );
sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
}
if( pWhere ){
@@ -147692,7 +149680,8 @@ static void constInsert(
return; /* Already present. Return without doing anything. */
}
}
- if( sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ assert( SQLITE_AFF_NONE<SQLITE_AFF_BLOB );
+ if( sqlite3ExprAffinity(pColumn)<=SQLITE_AFF_BLOB ){
pConst->bHasAffBlob = 1;
}
@@ -147767,7 +149756,8 @@ static int propagateConstantExprRewriteOne(
if( pColumn==pExpr ) continue;
if( pColumn->iTable!=pExpr->iTable ) continue;
if( pColumn->iColumn!=pExpr->iColumn ) continue;
- if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ assert( SQLITE_AFF_NONE<SQLITE_AFF_BLOB );
+ if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)<=SQLITE_AFF_BLOB ){
break;
}
/* A match is found. Add the EP_FixedCol property */
@@ -147957,7 +149947,8 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
**
** NAME AMBIGUITY
**
-** This optimization is called the "WHERE-clause push-down optimization".
+** This optimization is called the "WHERE-clause push-down optimization"
+** or sometimes the "predicate push-down optimization".
**
** Do not confuse this optimization with another unrelated optimization
** with a similar name: The "MySQL push-down optimization" causes WHERE
@@ -148221,10 +150212,10 @@ static int disableUnusedSubqueryResultColumns(SrcItem *pItem){
if( pItem->fg.isCorrelated || pItem->fg.isCte ){
return 0;
}
- assert( pItem->pTab!=0 );
- pTab = pItem->pTab;
- assert( pItem->pSelect!=0 );
- pSub = pItem->pSelect;
+ assert( pItem->pSTab!=0 );
+ pTab = pItem->pSTab;
+ assert( pItem->fg.isSubquery );
+ pSub = pItem->u4.pSubq->pSelect;
assert( pSub->pEList->nExpr==pTab->nCol );
for(pX=pSub; pX; pX=pX->pPrior){
if( (pX->selFlags & (SF_Distinct|SF_Aggregate))!=0 ){
@@ -148353,13 +150344,13 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
if( p->pWhere
|| p->pEList->nExpr!=1
|| p->pSrc->nSrc!=1
- || p->pSrc->a[0].pSelect
+ || p->pSrc->a[0].fg.isSubquery
|| pAggInfo->nFunc!=1
|| p->pHaving
){
return 0;
}
- pTab = p->pSrc->a[0].pTab;
+ pTab = p->pSrc->a[0].pSTab;
assert( pTab!=0 );
assert( !IsView(pTab) );
if( !IsOrdinaryTable(pTab) ) return 0;
@@ -148384,7 +150375,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** pFrom->pIndex and return SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
- Table *pTab = pFrom->pTab;
+ Table *pTab = pFrom->pSTab;
char *zIndexedBy = pFrom->u1.zIndexedBy;
Index *pIdx;
assert( pTab!=0 );
@@ -148419,7 +150410,7 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
** 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://www.sqlite.org/src/info/6709574d2a
+** 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
@@ -148461,7 +150452,11 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
if( pNew==0 ) return WRC_Abort;
memset(&dummy, 0, sizeof(dummy));
pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0);
- if( pNewSrc==0 ) return WRC_Abort;
+ assert( pNewSrc!=0 || pParse->nErr );
+ if( pParse->nErr ){
+ sqlite3SrcListDelete(db, pNewSrc);
+ return WRC_Abort;
+ }
*pNew = *p;
p->pSrc = pNewSrc;
p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0));
@@ -148476,7 +150471,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
#ifndef SQLITE_OMIT_WINDOWFUNC
p->pWinDefn = 0;
#endif
- p->selFlags &= ~SF_Compound;
+ p->selFlags &= ~(u32)SF_Compound;
assert( (p->selFlags & SF_Converted)==0 );
p->selFlags |= SF_Converted;
assert( pNew->pPrior!=0 );
@@ -148516,7 +150511,7 @@ static struct Cte *searchWith(
){
const char *zName = pItem->zName;
With *p;
- assert( pItem->zDatabase==0 );
+ assert( pItem->fg.fixedSchema || pItem->u4.zDatabase==0 );
assert( zName!=0 );
for(p=pWith; p; p=p->pOuter){
int i;
@@ -148586,7 +150581,7 @@ static int resolveFromTermToCte(
Cte *pCte; /* Matched CTE (or NULL if no match) */
With *pWith; /* The matching WITH */
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
if( pParse->pWith==0 ){
/* There are no WITH clauses in the stack. No match is possible */
return 0;
@@ -148596,7 +150591,8 @@ static int resolveFromTermToCte(
** go no further. */
return 0;
}
- if( pFrom->zDatabase!=0 ){
+ assert( pFrom->fg.hadSchema==0 || pFrom->fg.notCte!=0 );
+ if( pFrom->fg.fixedSchema==0 && pFrom->u4.zDatabase!=0 ){
/* The FROM term contains a schema qualifier (ex: main.t1) and so
** it cannot possibly be a CTE reference. */
return 0;
@@ -148632,7 +150628,7 @@ static int resolveFromTermToCte(
}
if( cannotBeFunction(pParse, pFrom) ) return 2;
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return 2;
pCteUse = pCte->pUse;
@@ -148646,26 +150642,29 @@ static int resolveFromTermToCte(
}
pCteUse->eM10d = pCte->eM10d;
}
- pFrom->pTab = pTab;
+ pFrom->pSTab = pTab;
pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
- pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
+ sqlite3SrcItemAttachSubquery(pParse, pFrom, pCte->pSelect, 1);
if( db->mallocFailed ) return 2;
- pFrom->pSelect->selFlags |= SF_CopyCte;
- assert( pFrom->pSelect );
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+ pSel = pFrom->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ pSel->selFlags |= SF_CopyCte;
if( pFrom->fg.isIndexedBy ){
sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
return 2;
}
+ assert( !pFrom->fg.isIndexedBy );
pFrom->fg.isCte = 1;
pFrom->u2.pCteUse = pCteUse;
pCteUse->nUse++;
/* Check if this is a recursive CTE. */
- pRecTerm = pSel = pFrom->pSelect;
+ pRecTerm = pSel;
bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
while( bMayRecursive && pRecTerm->op==pSel->op ){
int i;
@@ -148673,11 +150672,13 @@ static int resolveFromTermToCte(
assert( pRecTerm->pPrior!=0 );
for(i=0; i<pSrc->nSrc; i++){
SrcItem *pItem = &pSrc->a[i];
- if( pItem->zDatabase==0
- && pItem->zName!=0
+ if( pItem->zName!=0
+ && !pItem->fg.hadSchema
+ && ALWAYS( !pItem->fg.isSubquery )
+ && (pItem->fg.fixedSchema || pItem->u4.zDatabase==0)
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
){
- pItem->pTab = pTab;
+ pItem->pSTab = pTab;
pTab->nTabRef++;
pItem->fg.isRecursive = 1;
if( pRecTerm->selFlags & SF_Recursive ){
@@ -148779,11 +150780,14 @@ SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){
** SQLITE_NOMEM.
*/
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
- Select *pSel = pFrom->pSelect;
+ Select *pSel;
Table *pTab;
+ assert( pFrom->fg.isSubquery );
+ assert( pFrom->u4.pSubq!=0 );
+ pSel = pFrom->u4.pSubq->pSelect;
assert( pSel );
- pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
+ pFrom->pSTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
if( pTab==0 ) return SQLITE_NOMEM;
pTab->nTabRef = 1;
if( pFrom->zAlias ){
@@ -148883,7 +150887,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pEList = p->pEList;
if( pParse->pWith && (p->selFlags & SF_View) ){
if( p->pWith==0 ){
- p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
+ p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) );
if( p->pWith==0 ){
return WRC_Abort;
}
@@ -148903,33 +150907,35 @@ static int selectExpander(Walker *pWalker, Select *p){
*/
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab;
- assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
- if( pFrom->pTab ) continue;
+ assert( pFrom->fg.isRecursive==0 || pFrom->pSTab!=0 );
+ if( pFrom->pSTab ) continue;
assert( pFrom->fg.isRecursive==0 );
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
- Select *pSel = pFrom->pSelect;
+ Select *pSel;
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq!=0 );
+ pSel = pFrom->u4.pSubq->pSelect;
/* A sub-query in the FROM clause of a SELECT */
assert( pSel!=0 );
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
#ifndef SQLITE_OMIT_CTE
}else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
if( rc>1 ) return WRC_Abort;
- pTab = pFrom->pTab;
+ pTab = pFrom->pSTab;
assert( pTab!=0 );
#endif
}else{
/* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
+ assert( pFrom->pSTab==0 );
+ pFrom->pSTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
if( pTab->nTabRef>=0xffff ){
sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
pTab->zName);
- pFrom->pTab = 0;
+ pFrom->pSTab = 0;
return WRC_Abort;
}
pTab->nTabRef++;
@@ -148941,7 +150947,7 @@ static int selectExpander(Walker *pWalker, Select *p){
i16 nCol;
u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
- assert( pFrom->pSelect==0 );
+ assert( pFrom->fg.isSubquery==0 );
if( IsView(pTab) ){
if( (db->flags & SQLITE_EnableView)==0
&& pTab->pSchema!=db->aDb[1].pSchema
@@ -148949,7 +150955,7 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName);
}
- pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
+ sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( ALWAYS(IsVirtual(pTab))
@@ -148965,7 +150971,9 @@ static int selectExpander(Walker *pWalker, Select *p){
nCol = pTab->nCol;
pTab->nCol = -1;
pWalker->eCode = 1; /* Turn on Select.selId renumbering */
- sqlite3WalkSelect(pWalker, pFrom->pSelect);
+ if( pFrom->fg.isSubquery ){
+ sqlite3WalkSelect(pWalker, pFrom->u4.pSubq->pSelect);
+ }
pWalker->eCode = eCodeOrig;
pTab->nCol = nCol;
}
@@ -149052,7 +151060,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
int nAdd; /* Number of cols including rowid */
- Table *pTab = pFrom->pTab; /* Table for this data source */
+ Table *pTab = pFrom->pSTab; /* Table for this data source */
ExprList *pNestedFrom; /* Result-set of a nested FROM clause */
char *zTabName; /* AS name for this data source */
const char *zSchemaName = 0; /* Schema name for this data source */
@@ -149063,10 +151071,11 @@ static int selectExpander(Walker *pWalker, Select *p){
zTabName = pTab->zName;
}
if( db->mallocFailed ) break;
- assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
+ assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom) );
if( pFrom->fg.isNestedFrom ){
- assert( pFrom->pSelect!=0 );
- pNestedFrom = pFrom->pSelect->pEList;
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+ assert( pFrom->u4.pSubq->pSelect!=0 );
+ pNestedFrom = pFrom->u4.pSubq->pSelect->pEList;
assert( pNestedFrom!=0 );
assert( pNestedFrom->nExpr==pTab->nCol );
assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
@@ -149305,14 +151314,12 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
assert( (p->selFlags & SF_Resolved) );
pTabList = p->pSrc;
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
+ Table *pTab = pFrom->pSTab;
assert( pTab!=0 );
- if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 && pFrom->fg.isSubquery ){
/* A sub-query in the FROM clause of a SELECT */
- Select *pSel = pFrom->pSelect;
- if( pSel ){
- sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
- }
+ Select *pSel = pFrom->u4.pSubq->pSelect;
+ sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
}
}
}
@@ -149626,6 +151633,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
+ if( pParse->nErr ) return;
pList = pF->pFExpr->x.pList;
if( pF->iOBTab>=0 ){
/* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs
@@ -149666,7 +151674,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nArg);
+ sqlite3VdbeChangeP5(v, (u16)nArg);
sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, iTop);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
@@ -149829,12 +151837,13 @@ static void updateAccumulator(
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nArg);
+ sqlite3VdbeChangeP5(v, (u16)nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
}
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
}
+ if( pParse->nErr ) return;
}
if( regHit==0 && pAggInfo->nAccumulator ){
regHit = regAcc;
@@ -149844,6 +151853,7 @@ static void updateAccumulator(
}
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pCExpr, AggInfoColumnReg(pAggInfo,i));
+ if( pParse->nErr ) return;
}
pAggInfo->directMode = 0;
@@ -149959,25 +151969,28 @@ static SrcItem *isSelfJoinView(
int iFirst, int iEnd /* Range of FROM-clause entries to search. */
){
SrcItem *pItem;
- assert( pThis->pSelect!=0 );
- if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
+ Select *pSel;
+ assert( pThis->fg.isSubquery );
+ pSel = pThis->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ if( pSel->selFlags & SF_PushDown ) return 0;
while( iFirst<iEnd ){
Select *pS1;
pItem = &pTabList->a[iFirst++];
- if( pItem->pSelect==0 ) continue;
+ if( !pItem->fg.isSubquery ) continue;
if( pItem->fg.viaCoroutine ) continue;
if( pItem->zName==0 ) continue;
- assert( pItem->pTab!=0 );
- assert( pThis->pTab!=0 );
- if( pItem->pTab->pSchema!=pThis->pTab->pSchema ) continue;
+ assert( pItem->pSTab!=0 );
+ assert( pThis->pSTab!=0 );
+ if( pItem->pSTab->pSchema!=pThis->pSTab->pSchema ) continue;
if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
- pS1 = pItem->pSelect;
- if( pItem->pTab->pSchema==0 && pThis->pSelect->selId!=pS1->selId ){
+ pS1 = pItem->u4.pSubq->pSelect;
+ if( pItem->pSTab->pSchema==0 && pSel->selId!=pS1->selId ){
/* The query flattener left two different CTE tables with identical
** names in the same FROM clause. */
continue;
}
- if( pItem->pSelect->selFlags & SF_PushDown ){
+ if( pS1->selFlags & SF_PushDown ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -150013,6 +152026,7 @@ static void agginfoFree(sqlite3 *db, void *pArg){
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
** * The outer query is a simple count(*) with no WHERE clause or other
** extraneous syntax.
+** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10)
**
** Return TRUE if the optimization is undertaken.
*/
@@ -150021,6 +152035,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
Expr *pExpr;
Expr *pCount;
sqlite3 *db;
+ SrcItem *pFrom;
if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
if( p->pWhere ) return 0;
@@ -150035,17 +152050,22 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
if( ExprHasProperty(pExpr, EP_WinFunc) ) return 0;/* Not a window function */
- pSub = p->pSrc->a[0].pSelect;
- if( pSub==0 ) return 0; /* The FROM is a subquery */
+ pFrom = p->pSrc->a;
+ if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */
+ pSub = pFrom->u4.pSubq->pSelect;
if( pSub->pPrior==0 ) return 0; /* Must be a compound */
if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */
do{
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
if( pSub->pWhere ) return 0; /* No WHERE clause */
if( pSub->pLimit ) return 0; /* No LIMIT clause */
- if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
+ if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){
+ testcase( pSub->selFlags & SF_Aggregate );
+ testcase( pSub->selFlags & SF_Distinct );
+ return 0; /* Not an aggregate nor DISTINCT */
+ }
assert( pSub->pHaving==0 ); /* Due to the previous */
- pSub = pSub->pPrior; /* Repeat over compound */
+ pSub = pSub->pPrior; /* Repeat over compound */
}while( pSub );
/* If we reach this point then it is OK to perform the transformation */
@@ -150053,17 +152073,16 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
db = pParse->db;
pCount = pExpr;
pExpr = 0;
- pSub = p->pSrc->a[0].pSelect;
- p->pSrc->a[0].pSelect = 0;
+ pSub = sqlite3SubqueryDetach(db, pFrom);
sqlite3SrcListDelete(db, p->pSrc);
- p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
+ p->pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
while( pSub ){
Expr *pTerm;
pPrior = pSub->pPrior;
pSub->pPrior = 0;
pSub->pNext = 0;
pSub->selFlags |= SF_Aggregate;
- pSub->selFlags &= ~SF_Compound;
+ pSub->selFlags &= ~(u32)SF_Compound;
pSub->nSelectRow = 0;
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList);
pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
@@ -150078,7 +152097,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
pSub = pPrior;
}
p->pEList->a[0].pExpr = pExpr;
- p->selFlags &= ~SF_Aggregate;
+ p->selFlags &= ~(u32)SF_Aggregate;
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x200 ){
@@ -150099,12 +152118,12 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
for(i=0; i<pSrc->nSrc; i++){
SrcItem *p1 = &pSrc->a[i];
if( p1==p0 ) continue;
- if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
+ if( p0->pSTab==p1->pSTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
return 1;
}
- if( p1->pSelect
- && (p1->pSelect->selFlags & SF_NestedFrom)!=0
- && sameSrcAlias(p0, p1->pSelect->pSrc)
+ if( p1->fg.isSubquery
+ && (p1->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0
+ && sameSrcAlias(p0, p1->u4.pSubq->pSelect->pSrc)
){
return 1;
}
@@ -150169,13 +152188,13 @@ static int fromClauseTermCanBeCoroutine(
if( i==0 ) break;
i--;
pItem--;
- if( pItem->pSelect!=0 ) return 0; /* (1c-i) */
+ if( pItem->fg.isSubquery ) return 0; /* (1c-i) */
}
return 1;
}
/*
-** Generate code for the SELECT statement given in the p argument.
+** Generate byte-code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
@@ -150186,6 +152205,40 @@ static int fromClauseTermCanBeCoroutine(
**
** This routine does NOT free the Select structure passed in. The
** calling function needs to do that.
+**
+** This is a long function. The following is an outline of the processing
+** steps, with tags referencing various milestones:
+**
+** * Resolve names and similar preparation tag-select-0100
+** * Scan of the FROM clause tag-select-0200
+** + OUTER JOIN strength reduction tag-select-0220
+** + Sub-query ORDER BY removal tag-select-0230
+** + Query flattening tag-select-0240
+** * Separate subroutine for compound-SELECT tag-select-0300
+** * WHERE-clause constant propagation tag-select-0330
+** * Count()-of-VIEW optimization tag-select-0350
+** * Scan of the FROM clause again tag-select-0400
+** + Authorize unreferenced tables tag-select-0410
+** + Predicate push-down optimization tag-select-0420
+** + Omit unused subquery columns optimization tag-select-0440
+** + Generate code to implement subqueries tag-select-0480
+** - Co-routines tag-select-0482
+** - Reuse previously computed CTE tag-select-0484
+** - REuse previously computed VIEW tag-select-0486
+** - Materialize a VIEW or CTE tag-select-0488
+** * DISTINCT ORDER BY -> GROUP BY optimization tag-select-0500
+** * Set up for ORDER BY tag-select-0600
+** * Create output table tag-select-0630
+** * Prepare registers for LIMIT tag-select-0650
+** * Setup for DISTINCT tag-select-0680
+** * Generate code for non-aggregate and non-GROUP BY tag-select-0700
+** * Generate code for aggregate and/or GROUP BY tag-select-0800
+** + GROUP BY queries tag-select-0810
+** + non-GROUP BY queries tag-select-0820
+** - Special case of count() w/o GROUP BY tag-select-0821
+** - General case of non-GROUP BY aggregates tag-select-0822
+** * Sort results, as needed tag-select-0900
+** * Internal self-checks tag-select-1000
*/
SQLITE_PRIVATE int sqlite3Select(
Parse *pParse, /* The parser context */
@@ -150229,6 +152282,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
+ /* tag-select-0100 */
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
@@ -150250,7 +152304,7 @@ SQLITE_PRIVATE int sqlite3Select(
testcase( pParse->earlyCleanup );
p->pOrderBy = 0;
}
- p->selFlags &= ~SF_Distinct;
+ p->selFlags &= ~(u32)SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
@@ -150280,7 +152334,7 @@ SQLITE_PRIVATE int sqlite3Select(
if( sameSrcAlias(p0, p->pSrc) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
- p0->zAlias ? p0->zAlias : p0->pTab->zName
+ p0->zAlias ? p0->zAlias : p0->pSTab->zName
);
goto select_end;
}
@@ -150289,7 +152343,7 @@ SQLITE_PRIVATE int sqlite3Select(
** and leaving this flag set can cause errors if a compound sub-query
** in p->pSrc is flattened into this query and this function called
** again as part of compound SELECT processing. */
- p->selFlags &= ~SF_UFSrcCheck;
+ p->selFlags &= ~(u32)SF_UFSrcCheck;
}
if( pDest->eDest==SRT_Output ){
@@ -150315,12 +152369,13 @@ SQLITE_PRIVATE int sqlite3Select(
/* Try to do various optimizations (flattening subqueries, and strength
** reduction of join operators) in the FROM clause up into the main query
+ ** tag-select-0200
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
SrcItem *pItem = &pTabList->a[i];
- Select *pSub = pItem->pSelect;
- Table *pTab = pItem->pTab;
+ Select *pSub = pItem->fg.isSubquery ? pItem->u4.pSubq->pSelect : 0;
+ Table *pTab = pItem->pSTab;
/* The expander should have already created transient Table objects
** even for FROM clause elements such as subqueries that do not correspond
@@ -150337,6 +152392,7 @@ SQLITE_PRIVATE int sqlite3Select(
** way that the i-th table cannot be the NULL row of a join, then
** perform the appropriate simplification. This is called
** "OUTER JOIN strength reduction" in the SQLite documentation.
+ ** tag-select-0220
*/
if( (pItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0
&& sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor,
@@ -150407,7 +152463,8 @@ SQLITE_PRIVATE int sqlite3Select(
if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
assert( pSub->pGroupBy==0 );
- /* If a FROM-clause subquery has an ORDER BY clause that is not
+ /* tag-select-0230:
+ ** If a FROM-clause subquery has an ORDER BY clause that is not
** really doing anything, then delete it now so that it does not
** interfere with query flattening. See the discussion at
** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a
@@ -150426,13 +152483,16 @@ SQLITE_PRIVATE int sqlite3Select(
** (a) The outer query has a different ORDER BY clause
** (b) The subquery is part of a join
** See forum post 062d576715d277c8
+ ** (6) The subquery is not a recursive CTE. ORDER BY has a different
+ ** meaning for recursive CTEs and this optimization does not
+ ** apply.
**
** Also retain the ORDER BY if the OmitOrderBy optimization is disabled.
*/
if( pSub->pOrderBy!=0
&& (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
&& pSub->pLimit==0 /* Condition (1) */
- && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
+ && (pSub->selFlags & (SF_OrderByReqd|SF_Recursive))==0 /* (2) and (6) */
&& (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
&& OptimizationEnabled(db, SQLITE_OmitOrderBy)
){
@@ -150470,6 +152530,7 @@ SQLITE_PRIVATE int sqlite3Select(
continue;
}
+ /* tag-select-0240 */
if( flattenSubquery(pParse, p, i, isAgg) ){
if( pParse->nErr ) goto select_end;
/* This subquery can be absorbed into its parent. */
@@ -150485,7 +152546,7 @@ SQLITE_PRIVATE int sqlite3Select(
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
- ** procedure.
+ ** procedure. tag-select-0300
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
@@ -150501,9 +152562,9 @@ SQLITE_PRIVATE int sqlite3Select(
#endif
/* Do the WHERE-clause constant propagation optimization if this is
- ** a join. No need to speed time on this operation for non-join queries
+ ** a join. No need to spend time on this operation for non-join queries
** as the equivalent optimization will be handled by query planner in
- ** sqlite3WhereBegin().
+ ** sqlite3WhereBegin(). tag-select-0330
*/
if( p->pWhere!=0
&& p->pWhere->op==TK_AND
@@ -150520,6 +152581,7 @@ SQLITE_PRIVATE int sqlite3Select(
TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n"));
}
+ /* tag-select-0350 */
if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
&& countOfViewOptimization(pParse, p)
){
@@ -150527,20 +152589,26 @@ SQLITE_PRIVATE int sqlite3Select(
pTabList = p->pSrc;
}
- /* For each term in the FROM clause, do two things:
- ** (1) Authorized unreferenced tables
- ** (2) Generate code for all sub-queries
+ /* Loop over all terms in the FROM clause and do two things for each term:
+ **
+ ** (1) Authorize unreferenced tables
+ ** (2) Generate code for all sub-queries
+ **
+ ** tag-select-0400
*/
for(i=0; i<pTabList->nSrc; i++){
SrcItem *pItem = &pTabList->a[i];
SrcItem *pPrior;
SelectDest dest;
+ Subquery *pSubq;
Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
const char *zSavedAuthContext;
#endif
- /* Issue SQLITE_READ authorizations with a fake column name for any
+ /* Authorized unreferenced tables. tag-select-0410
+ **
+ ** Issue SQLITE_READ authorizations with a fake column name for any
** tables that are referenced but from which no values are extracted.
** Examples of where these kinds of null SQLITE_READ authorizations
** would occur:
@@ -150557,17 +152625,28 @@ SQLITE_PRIVATE int sqlite3Select(
** string for the fake column name seems safer.
*/
if( pItem->colUsed==0 && pItem->zName!=0 ){
- sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
+ const char *zDb;
+ if( pItem->fg.fixedSchema ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, pItem->u4.pSchema);
+ zDb = db->aDb[iDb].zDbSName;
+ }else if( pItem->fg.isSubquery ){
+ zDb = 0;
+ }else{
+ zDb = pItem->u4.zDatabase;
+ }
+ sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", zDb);
}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* Generate code for all sub-queries in the FROM clause
*/
- pSub = pItem->pSelect;
- if( pSub==0 || pItem->addrFillSub!=0 ) continue;
+ if( pItem->fg.isSubquery==0 ) continue;
+ pSubq = pItem->u4.pSubq;
+ assert( pSubq!=0 );
+ pSub = pSubq->pSelect;
/* The code for a subquery should only be generated once. */
- assert( pItem->addrFillSub==0 );
+ if( pSubq->addrFillSub!=0 ) continue;
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@@ -150580,6 +152659,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
+ ** This is the "predicate push-down optimization". tag-select-0420
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
&& (pItem->fg.isCte==0
@@ -150593,13 +152673,14 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3TreeViewSelect(0, p, 0);
}
#endif
- assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
+ assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 );
}else{
- TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
+ TREETRACE(0x4000,pParse,p,("WHERE-clause push-down not possible\n"));
}
/* Convert unused result columns of the subquery into simple NULL
** expressions, to avoid unneeded searching and computation.
+ ** tag-select-0440
*/
if( OptimizationEnabled(db, SQLITE_NullUnusedCols)
&& disableUnusedSubqueryResultColumns(pItem)
@@ -150617,32 +152698,33 @@ SQLITE_PRIVATE int sqlite3Select(
zSavedAuthContext = pParse->zAuthContext;
pParse->zAuthContext = pItem->zName;
- /* Generate code to implement the subquery
+ /* Generate byte-code to implement the subquery tag-select-0480
*/
if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){
/* Implement a co-routine that will return a single row of the result
- ** set on each invocation.
+ ** set on each invocation. tag-select-0482
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
- pItem->regReturn = ++pParse->nMem;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
+ pSubq->regReturn = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, pSubq->regReturn, 0, addrTop);
VdbeComment((v, "%!S", pItem));
- pItem->addrFillSub = addrTop;
- sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+ pSubq->addrFillSub = addrTop;
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn);
ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->nRowLogEst = pSub->nSelectRow;
+ pItem->pSTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
- pItem->regResult = dest.iSdst;
- sqlite3VdbeEndCoroutine(v, pItem->regReturn);
+ pSubq->regResult = dest.iSdst;
+ sqlite3VdbeEndCoroutine(v, pSubq->regReturn);
+ VdbeComment((v, "end %!S", pItem));
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
}else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
/* This is a CTE for which materialization code has already been
** generated. Invoke the subroutine to compute the materialization,
- ** the make the pItem->iCursor be a copy of the ephemeral table that
- ** holds the result of the materialization. */
+ ** then make the pItem->iCursor be a copy of the ephemeral table that
+ ** holds the result of the materialization. tag-select-0484 */
CteUse *pCteUse = pItem->u2.pCteUse;
sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
if( pItem->iCursor!=pCteUse->iCur ){
@@ -150652,25 +152734,30 @@ SQLITE_PRIVATE int sqlite3Select(
pSub->nSelectRow = pCteUse->nRowEst;
}else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){
/* This view has already been materialized by a prior entry in
- ** this same FROM clause. Reuse it. */
- if( pPrior->addrFillSub ){
- sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
+ ** this same FROM clause. Reuse it. tag-select-0486 */
+ Subquery *pPriorSubq;
+ assert( pPrior->fg.isSubquery );
+ pPriorSubq = pPrior->u4.pSubq;
+ assert( pPriorSubq!=0 );
+ if( pPriorSubq->addrFillSub ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pPriorSubq->regReturn,
+ pPriorSubq->addrFillSub);
}
sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
- pSub->nSelectRow = pPrior->pSelect->nSelectRow;
+ pSub->nSelectRow = pPriorSubq->pSelect->nSelectRow;
}else{
/* Materialize the view. If the view is not correlated, generate a
** subroutine to do the materialization so that subsequent uses of
- ** the same view can reuse the materialization. */
+ ** the same view can reuse the materialization. tag-select-0488 */
int topAddr;
int onceAddr = 0;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int addrExplain;
#endif
- pItem->regReturn = ++pParse->nMem;
+ pSubq->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
- pItem->addrFillSub = topAddr+1;
+ pSubq->addrFillSub = topAddr+1;
pItem->fg.isMaterialized = 1;
if( pItem->fg.isCorrelated==0 ){
/* If the subquery is not correlated and if we are not inside of
@@ -150685,17 +152772,17 @@ SQLITE_PRIVATE int sqlite3Select(
ExplainQueryPlan2(addrExplain, (pParse, 1, "MATERIALIZE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->nRowLogEst = pSub->nSelectRow;
+ pItem->pSTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
- sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1);
+ sqlite3VdbeAddOp2(v, OP_Return, pSubq->regReturn, topAddr+1);
VdbeComment((v, "end %!S", pItem));
sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1);
sqlite3VdbeJumpHere(v, topAddr);
sqlite3ClearTempRegCache(pParse);
if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
CteUse *pCteUse = pItem->u2.pCteUse;
- pCteUse->addrM9e = pItem->addrFillSub;
- pCteUse->regRtn = pItem->regReturn;
+ pCteUse->addrM9e = pSubq->addrFillSub;
+ pCteUse->regRtn = pSubq->regReturn;
pCteUse->iCur = pItem->iCursor;
pCteUse->nRowEst = pSub->nSelectRow;
}
@@ -150721,7 +152808,9 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
- /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
+ /* tag-select-0500
+ **
+ ** If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
**
@@ -150738,12 +152827,18 @@ SQLITE_PRIVATE int sqlite3Select(
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
+ && OptimizationEnabled(db, SQLITE_GroupByOrder)
#ifndef SQLITE_OMIT_WINDOWFUNC
&& p->pWin==0
#endif
){
- p->selFlags &= ~SF_Distinct;
+ p->selFlags &= ~(u32)SF_Distinct;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
+ if( pGroupBy ){
+ for(i=0; i<pGroupBy->nExpr; i++){
+ pGroupBy->a[i].u.x.iOrderByCol = i+1;
+ }
+ }
p->selFlags |= SF_Aggregate;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
@@ -150765,7 +152860,7 @@ SQLITE_PRIVATE int sqlite3Select(
** If that is the case, then the OP_OpenEphemeral instruction will be
** changed to an OP_Noop once we figure out that the sorting index is
** not needed. The sSort.addrSortIndex variable is used to facilitate
- ** that change.
+ ** that change. tag-select-0600
*/
if( sSort.pOrderBy ){
KeyInfo *pKeyInfo;
@@ -150782,6 +152877,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
/* If the output is destined for a temporary table, open that table.
+ ** tag-select-0630
*/
if( pDest->eDest==SRT_EphemTab ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
@@ -150799,7 +152895,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
}
- /* Set the limiter.
+ /* Set the limiter. tag-select-0650
*/
iEnd = sqlite3VdbeMakeLabel(pParse);
if( (p->selFlags & SF_FixedLimit)==0 ){
@@ -150811,7 +152907,7 @@ SQLITE_PRIVATE int sqlite3Select(
sSort.sortFlags |= SORTFLAG_UseSorter;
}
- /* Open an ephemeral index to use for the distinct set.
+ /* Open an ephemeral index to use for the distinct set. tag-select-0680
*/
if( p->selFlags & SF_Distinct ){
sDistinct.tabTnct = pParse->nTab++;
@@ -150826,7 +152922,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
if( !isAgg && pGroupBy==0 ){
- /* No aggregate functions and no GROUP BY clause */
+ /* No aggregate functions and no GROUP BY clause. tag-select-0700 */
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
| (p->selFlags & SF_FixedLimit);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -150845,6 +152941,12 @@ SQLITE_PRIVATE int sqlite3Select(
if( pWInfo==0 ) goto select_end;
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
+ if( pDest->eDest<=SRT_DistQueue && pDest->eDest>=SRT_DistFifo ){
+ /* TUNING: For a UNION CTE, because UNION is implies DISTINCT,
+ ** reduce the estimated output row count by 8 (LogEst 30).
+ ** Search for tag-20250414a to see other cases */
+ p->nSelectRow -= 30;
+ }
}
if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
@@ -150899,8 +153001,8 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3WhereEnd(pWInfo);
}
}else{
- /* This case when there exist aggregate functions or a GROUP BY clause
- ** or both */
+ /* This case is for when there exist aggregate functions or a GROUP BY
+ ** clause or both. tag-select-0800 */
NameContext sNC; /* Name context for processing aggregate information */
int iAMem; /* First Mem address for storing current GROUP BY */
int iBMem; /* First Mem address for previous GROUP BY */
@@ -151019,7 +153121,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Processing for aggregates with GROUP BY is very different and
- ** much more complex than aggregates without a GROUP BY.
+ ** much more complex than aggregates without a GROUP BY. tag-select-0810
*/
if( pGroupBy ){
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
@@ -151206,12 +153308,29 @@ SQLITE_PRIVATE int sqlite3Select(
sortOut, sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
+ int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
+
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
}else{
pAggInfo->directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
}
+
+ if( iOrderByCol ){
+ Expr *pX = p->pEList->a[iOrderByCol-1].pExpr;
+ Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX);
+ while( ALWAYS(pBase!=0) && pBase->op==TK_IF_NULL_ROW ){
+ pX = pBase->pLeft;
+ pBase = sqlite3ExprSkipCollateAndLikely(pX);
+ }
+ if( ALWAYS(pBase!=0)
+ && pBase->op!=TK_AGG_COLUMN
+ && pBase->op!=TK_REGISTER
+ ){
+ sqlite3ExprToRegister(pX, iAMem+j);
+ }
+ }
}
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
@@ -151227,9 +153346,9 @@ SQLITE_PRIVATE int sqlite3Select(
** and resets the aggregate accumulator registers in preparation
** for the next GROUP BY batch.
*/
- sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output one row"));
+ sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
VdbeComment((v, "check abort flag"));
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
@@ -151303,9 +153422,12 @@ SQLITE_PRIVATE int sqlite3Select(
}
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
+ /* Aggregate functions without GROUP BY. tag-select-0820 */
Table *pTab;
if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
- /* If isSimpleCount() returns a pointer to a Table structure, then
+ /* tag-select-0821
+ **
+ ** If isSimpleCount() returns a pointer to a Table structure, then
** the SQL statement is of the form:
**
** SELECT count(*) FROM <tbl>
@@ -151364,6 +153486,8 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
}else{
+ /* The general case of an aggregate query without GROUP BY
+ ** tag-select-0822 */
int regAcc = 0; /* "populate accumulators" flag */
ExprList *pDistinct = 0;
u16 distFlag = 0;
@@ -151452,7 +153576,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
/* If there is an ORDER BY clause, then we need to sort the results
- ** and send them to the callback one by one.
+ ** and send them to the callback one by one. tag-select-0900
*/
if( sSort.pOrderBy ){
assert( p->pEList==pEList );
@@ -151475,6 +153599,7 @@ select_end:
assert( db->mallocFailed==0 || pParse->nErr!=0 );
sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
+ /* Internal self-checks. tag-select-1000 */
if( pAggInfo && !db->mallocFailed ){
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x20 ){
@@ -151782,7 +153907,8 @@ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
assert( pParse->db->pVtabCtx==0 );
#endif
assert( pParse->bReturning );
- assert( &(pParse->u1.pReturning->retTrig) == pTrig );
+ assert( !pParse->isCreate );
+ assert( &(pParse->u1.d.pReturning->retTrig) == pTrig );
pTrig->table = pTab->zName;
pTrig->pTabSchema = pTab->pSchema;
pTrig->pNext = pList;
@@ -151864,8 +153990,10 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
** name on pTableName if we are reparsing out of the schema table
*/
if( db->init.busy && iDb!=1 ){
- sqlite3DbFree(db, pTableName->a[0].zDatabase);
- pTableName->a[0].zDatabase = 0;
+ assert( pTableName->a[0].fg.fixedSchema==0 );
+ assert( pTableName->a[0].fg.isSubquery==0 );
+ sqlite3DbFree(db, pTableName->a[0].u4.zDatabase);
+ pTableName->a[0].u4.zDatabase = 0;
}
/* If the trigger name was unqualified, and the table is a temp table,
@@ -152343,7 +154471,8 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr)
}
assert( pName->nSrc==1 );
- zDb = pName->a[0].zDatabase;
+ assert( pName->a[0].fg.fixedSchema==0 && pName->a[0].fg.isSubquery==0 );
+ zDb = pName->a[0].u4.zDatabase;
zName = pName->a[0].zName;
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
for(i=OMIT_TEMPDB; i<db->nDb; i++){
@@ -152580,7 +154709,9 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(
Schema *pSchema = pStep->pTrig->pSchema;
pSrc->a[0].zName = zName;
if( pSchema!=db->aDb[1].pSchema ){
- pSrc->a[0].pSchema = pSchema;
+ assert( pSrc->a[0].fg.fixedSchema || pSrc->a[0].u4.zDatabase==0 );
+ pSrc->a[0].u4.pSchema = pSchema;
+ pSrc->a[0].fg.fixedSchema = 1;
}
if( pStep->pFrom ){
SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
@@ -152693,7 +154824,7 @@ static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
pSrc = pSelect->pSrc;
assert( pSrc!=0 );
for(i=0; i<pSrc->nSrc; i++){
- if( pSrc->a[i].pTab==pWalker->u.pTab ){
+ if( pSrc->a[i].pSTab==pWalker->u.pTab ){
testcase( pSelect->selFlags & SF_Correlated );
pSelect->selFlags |= SF_Correlated;
pWalker->eCode = 1;
@@ -152745,7 +154876,8 @@ static void codeReturningTrigger(
ExprList *pNew;
Returning *pReturning;
Select sSelect;
- SrcList sFrom;
+ SrcList *pFrom;
+ u8 fromSpace[SZ_SRCLIST_1];
assert( v!=0 );
if( !pParse->bReturning ){
@@ -152754,19 +154886,21 @@ static void codeReturningTrigger(
return;
}
assert( db->pParse==pParse );
- pReturning = pParse->u1.pReturning;
+ assert( !pParse->isCreate );
+ pReturning = pParse->u1.d.pReturning;
if( pTrigger != &(pReturning->retTrig) ){
/* This RETURNING trigger is for a different statement */
return;
}
memset(&sSelect, 0, sizeof(sSelect));
- memset(&sFrom, 0, sizeof(sFrom));
+ pFrom = (SrcList*)fromSpace;
+ memset(pFrom, 0, SZ_SRCLIST_1);
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
- sSelect.pSrc = &sFrom;
- sFrom.nSrc = 1;
- sFrom.a[0].pTab = pTab;
- sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
- sFrom.a[0].iCursor = -1;
+ sSelect.pSrc = pFrom;
+ pFrom->nSrc = 1;
+ pFrom->a[0].pSTab = pTab;
+ pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */
+ pFrom->a[0].iCursor = -1;
sqlite3SelectPrep(pParse, &sSelect, 0);
if( pParse->nErr==0 ){
assert( db->mallocFailed==0 );
@@ -152984,6 +155118,8 @@ static TriggerPrg *codeRowTrigger(
sSubParse.eTriggerOp = pTrigger->op;
sSubParse.nQueryLoop = pParse->nQueryLoop;
sSubParse.prepFlags = pParse->prepFlags;
+ sSubParse.oldmask = 0;
+ sSubParse.newmask = 0;
v = sqlite3GetVdbe(&sSubParse);
if( v ){
@@ -153116,7 +155252,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
** invocation is disallowed if (a) the sub-program is really a trigger,
** not a foreign key action, and (b) the flag to enable recursive triggers
** is clear. */
- sqlite3VdbeChangeP5(v, (u8)bRecursive);
+ sqlite3VdbeChangeP5(v, (u16)bRecursive);
}
}
@@ -153475,7 +155611,7 @@ static void updateFromSelect(
Expr *pLimit2 = 0;
ExprList *pOrderBy2 = 0;
sqlite3 *db = pParse->db;
- Table *pTab = pTabList->a[0].pTab;
+ Table *pTab = pTabList->a[0].pSTab;
SrcList *pSrc;
Expr *pWhere2;
int eDest;
@@ -153499,8 +155635,8 @@ static void updateFromSelect(
if( pSrc ){
assert( pSrc->a[0].fg.notCte );
pSrc->a[0].iCursor = -1;
- pSrc->a[0].pTab->nTabRef--;
- pSrc->a[0].pTab = 0;
+ pSrc->a[0].pSTab->nTabRef--;
+ pSrc->a[0].pSTab = 0;
}
if( pPk ){
for(i=0; i<pPk->nKeyCol; i++){
@@ -153738,38 +155874,32 @@ SQLITE_PRIVATE void sqlite3Update(
*/
chngRowid = chngPk = 0;
for(i=0; i<pChanges->nExpr; i++){
- u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName);
/* If this is an UPDATE with a FROM clause, do not resolve expressions
** here. The call to sqlite3Select() below will do that. */
if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
- for(j=0; j<pTab->nCol; j++){
- if( pTab->aCol[j].hName==hCol
- && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0
- ){
- if( j==pTab->iPKey ){
- chngRowid = 1;
- pRowidExpr = pChanges->a[i].pExpr;
- iRowidExpr = i;
- }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
- chngPk = 1;
- }
+ j = sqlite3ColumnIndex(pTab, pChanges->a[i].zEName);
+ if( j>=0 ){
+ if( j==pTab->iPKey ){
+ chngRowid = 1;
+ pRowidExpr = pChanges->a[i].pExpr;
+ iRowidExpr = i;
+ }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
+ chngPk = 1;
+ }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
- testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
- testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
- sqlite3ErrorMsg(pParse,
- "cannot UPDATE generated column \"%s\"",
- pTab->aCol[j].zCnName);
- goto update_cleanup;
- }
-#endif
- aXRef[j] = i;
- break;
+ else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
+ testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
+ testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse,
+ "cannot UPDATE generated column \"%s\"",
+ pTab->aCol[j].zCnName);
+ goto update_cleanup;
}
- }
- if( j>=pTab->nCol ){
+#endif
+ aXRef[j] = i;
+ }else{
if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
j = -1;
chngRowid = 1;
@@ -154748,7 +156878,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
int nClause = 0; /* Counter of ON CONFLICT clauses */
assert( pTabList->nSrc==1 );
- assert( pTabList->a[0].pTab!=0 );
+ assert( pTabList->a[0].pSTab!=0 );
assert( pUpsert!=0 );
assert( pUpsert->pUpsertTarget!=0 );
@@ -154767,7 +156897,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
if( rc ) return rc;
/* Check to see if the conflict target matches the rowid. */
- pTab = pTabList->a[0].pTab;
+ pTab = pTabList->a[0].pSTab;
pTarget = pUpsert->pUpsertTarget;
iCursor = pTabList->a[0].iCursor;
if( HasRowid(pTab)
@@ -155092,7 +157222,7 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
#else
/* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
** to VACUUM are silently ignored. This is a back-out of a bug fix that
- ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270).
+ ** occurred on 2016-08-19 (https://sqlite.org/src/info/083f9e6270).
** The buggy behavior is required for binary compatibility with some
** legacy applications. */
iDb = sqlite3FindDb(pParse->db, pNm);
@@ -155138,6 +157268,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
const char *zDbMain; /* Schema name of database to vacuum */
const char *zOut; /* Name of output file */
u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */
+ u64 iRandom; /* Random value used for zDbVacuum[] */
+ char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */
+
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -155168,7 +157301,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
- db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
@@ -155178,27 +157311,29 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
pMain = db->aDb[iDb].pBt;
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
- /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
+ /* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
** (possibly synchronous) transaction opened on the main database before
** sqlite3BtreeCopyFile() is called.
**
** An optimization would be to use a non-journaled pager.
- ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
+ ** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but
** that actually made the VACUUM run slower. Very little journalling
** actually occurs when doing a vacuum since the vacuum_db is initially
** empty. Only the journal header is written. Apparently it takes more
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
+ sqlite3_randomness(sizeof(iRandom),&iRandom);
+ sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom);
nDb = db->nDb;
- rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
+ rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum);
db->openFlags = saved_openFlags;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
assert( (db->nDb-1)==nDb );
pDb = &db->aDb[nDb];
- assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
+ assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
pTemp = pDb->pBt;
if( pOut ){
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
@@ -155275,11 +157410,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
** the contents to the temporary database.
*/
rc = execSqlF(db, pzErrMsg,
- "SELECT'INSERT INTO vacuum_db.'||quote(name)"
+ "SELECT'INSERT INTO %s.'||quote(name)"
"||' SELECT*FROM\"%w\".'||quote(name)"
- "FROM vacuum_db.sqlite_schema "
+ "FROM %s.sqlite_schema "
"WHERE type='table'AND coalesce(rootpage,1)>0",
- zDbMain
+ zDbVacuum, zDbMain, zDbVacuum
);
assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
db->mDbFlags &= ~DBFLAG_Vacuum;
@@ -155291,11 +157426,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
** from the schema table.
*/
rc = execSqlF(db, pzErrMsg,
- "INSERT INTO vacuum_db.sqlite_schema"
+ "INSERT INTO %s.sqlite_schema"
" SELECT*FROM \"%w\".sqlite_schema"
" WHERE type IN('view','trigger')"
" OR(type='table'AND rootpage=0)",
- zDbMain
+ zDbVacuum, zDbMain
);
if( rc ) goto end_of_vacuum;
@@ -155871,11 +158006,12 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
** schema table. We just need to update that slot with all
** the information we've collected.
**
- ** The VM register number pParse->regRowid holds the rowid of an
+ ** The VM register number pParse->u1.cr.regRowid holds the rowid of an
** entry in the sqlite_schema table that was created for this vtab
** by sqlite3StartTable().
*/
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( pParse->isCreate );
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE " "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
@@ -155884,7 +158020,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
pTab->zName,
pTab->zName,
zStmt,
- pParse->regRowid
+ pParse->u1.cr.regRowid
);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(pParse, iDb);
@@ -156222,7 +158358,9 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
z = (const unsigned char*)zCreateTable;
for(i=0; aKeyword[i]; i++){
int tokenType = 0;
- do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
+ do{
+ z += sqlite3GetToken(z, &tokenType);
+ }while( tokenType==TK_SPACE || tokenType==TK_COMMENT );
if( tokenType!=aKeyword[i] ){
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error");
return SQLITE_ERROR;
@@ -156259,6 +158397,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Table *pNew = sParse.pNewTable;
Index *pIdx;
pTab->aCol = pNew->aCol;
+ assert( IsOrdinaryTable(pNew) );
sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
pTab->nNVCol = pTab->nCol = pNew->nCol;
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
@@ -156933,11 +159072,13 @@ struct WhereLoop {
u16 nTop; /* Size of TOP vector */
u16 nDistinctCol; /* Index columns used to sort for DISTINCT */
Index *pIndex; /* Index used, or NULL */
+ ExprList *pOrderBy; /* ORDER BY clause if this is really a subquery */
} btree;
struct { /* Information for virtual tables */
int idxNum; /* Index number */
u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */
u32 bOmitOffset : 1; /* True to let virtual table handle offset */
+ u32 bIdxNumHex : 1; /* Show idxNum as hex in EXPLAIN QUERY PLAN */
i8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
char *idxStr; /* Index identifier string */
@@ -156950,6 +159091,10 @@ struct WhereLoop {
/**** whereLoopXfer() copies fields above ***********************/
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
u16 nLSlot; /* Number of slots allocated for aLTerm[] */
+#ifdef WHERETRACE_ENABLED
+ LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not
+ ** initialized unless pWInfo->bStarUsed */
+#endif
WhereTerm **aLTerm; /* WhereTerms used */
WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */
@@ -156998,7 +159143,7 @@ struct WherePath {
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
LogEst nRow; /* Estimated number of rows generated by this path */
LogEst rCost; /* Total cost of this path */
- LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */
+ LogEst rUnsort; /* Total cost of this path ignoring sorting costs */
i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
};
@@ -157271,8 +159416,13 @@ struct WhereInfo {
unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
- unsigned sorted :1; /* True if really sorted (not just grouped) */
+ unsigned sorted :1; /* True if really sorted (not just grouped) */
+ unsigned bStarDone :1; /* True if check for star-query is complete */
+ unsigned bStarUsed :1; /* True if star-query heuristic is used */
LogEst nRowOut; /* Estimated number of output rows */
+#ifdef WHERETRACE_ENABLED
+ LogEst rTotalCost; /* Total cost of the solution */
+#endif
int iTop; /* The very beginning of the WHERE loop */
int iEndWhere; /* End of the WHERE clause itself */
WhereLoop *pLoops; /* List of all WhereLoop objects */
@@ -157280,10 +159430,15 @@ struct WhereInfo {
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
WhereClause sWC; /* Decomposition of the WHERE clause */
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
+ WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */
};
/*
+** The size (in bytes) of a WhereInfo object that holds N WhereLevels.
+*/
+#define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel))
+
+/*
** Private interfaces - callable only by other where.c routines.
**
** where.c:
@@ -157318,9 +159473,17 @@ SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
const WhereInfo *pWInfo, /* WHERE clause */
const WhereLevel *pLevel /* Bloom filter on this level */
);
+SQLITE_PRIVATE void sqlite3WhereAddExplainText(
+ Parse *pParse, /* Parse context */
+ int addr,
+ SrcList *pTabList, /* Table list this loop refers to */
+ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
+ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
+);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
# define sqlite3WhereExplainBloomFilter(u,v,w) 0
+# define sqlite3WhereAddExplainText(u,v,w,x,y)
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
@@ -157423,7 +159586,8 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */
#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */
#define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */
- /* 0x02000000 -- available for reuse */
+#define WHERE_COROUTINE 0x02000000 /* Implemented by co-routine.
+ ** NB: False-negatives are possible */
#define WHERE_EXPRIDX 0x04000000 /* Uses an index-on-expressions */
#endif /* !defined(SQLITE_WHEREINT_H) */
@@ -157521,38 +159685,38 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
}
/*
-** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
-** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
-** was defined at compile-time. If it is not a no-op, a single OP_Explain
-** opcode is added to the output to describe the table scan strategy in pLevel.
-**
-** If an OP_Explain opcode is added to the VM, its address is returned.
-** Otherwise, if no OP_Explain is coded, zero is returned.
+** This function sets the P4 value of an existing OP_Explain opcode to
+** text describing the loop in pLevel. If the OP_Explain opcode already has
+** a P4 value, it is freed before it is overwritten.
*/
-SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
+SQLITE_PRIVATE void sqlite3WhereAddExplainText(
Parse *pParse, /* Parse context */
+ int addr, /* Address of OP_Explain opcode */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
- int ret = 0;
#if !defined(SQLITE_DEBUG)
if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
#endif
{
+ VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr);
+
SrcItem *pItem = &pTabList->a[pLevel->iFrom];
- Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
u32 flags; /* Flags that describe this loop */
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
char *zMsg; /* Text to add to EQP output */
+#endif
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
+ if( db->mallocFailed ) return;
+
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
- if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
@@ -157568,7 +159732,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
assert( pLoop->u.btree.pIndex!=0 );
pIdx = pLoop->u.btree.pIndex;
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
- if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
+ if( !HasRowid(pItem->pSTab) && IsPrimaryKeyIndex(pIdx) ){
if( isSearch ){
zFmt = "PRIMARY KEY";
}
@@ -157576,7 +159740,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "AUTOMATIC COVERING INDEX";
- }else if( flags & WHERE_IDX_ONLY ){
+ }else if( flags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
zFmt = "COVERING INDEX %s";
}else{
zFmt = "INDEX %s";
@@ -157611,7 +159775,9 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
- sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
+ sqlite3_str_appendall(&str, " VIRTUAL TABLE INDEX ");
+ sqlite3_str_appendf(&str,
+ pLoop->u.vtab.bIdxNumHex ? "0x%x:%s" : "%d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
@@ -157626,10 +159792,50 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
sqlite3_str_append(&str, " (~1 row)", 9);
}
#endif
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
zMsg = sqlite3StrAccumFinish(&str);
sqlite3ExplainBreakpoint("",zMsg);
- ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
- pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
+#endif
+
+ assert( pOp->opcode==OP_Explain );
+ assert( pOp->p4type==P4_DYNAMIC || pOp->p4.z==0 );
+ sqlite3DbFree(db, pOp->p4.z);
+ pOp->p4type = P4_DYNAMIC;
+ pOp->p4.z = sqlite3StrAccumFinish(&str);
+ }
+}
+
+
+/*
+** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
+** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
+** was defined at compile-time. If it is not a no-op, a single OP_Explain
+** opcode is added to the output to describe the table scan strategy in pLevel.
+**
+** If an OP_Explain opcode is added to the VM, its address is returned.
+** Otherwise, if no OP_Explain is coded, zero is returned.
+*/
+SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
+ Parse *pParse, /* Parse context */
+ SrcList *pTabList, /* Table list this loop refers to */
+ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
+ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
+){
+ int ret = 0;
+#if !defined(SQLITE_DEBUG)
+ if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
+#endif
+ {
+ if( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0
+ && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
+ ){
+ Vdbe *v = pParse->pVdbe;
+ int addr = sqlite3VdbeCurrentAddr(v);
+ ret = sqlite3VdbeAddOp3(
+ v, OP_Explain, addr, pParse->addrExplain, pLevel->pWLoop->rRun
+ );
+ sqlite3WhereAddExplainText(pParse, addr, pTabList, pLevel, wctrlFlags);
+ }
}
return ret;
}
@@ -157664,7 +159870,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem);
pLoop = pLevel->pWLoop;
if( pLoop->wsFlags & WHERE_IPK ){
- const Table *pTab = pItem->pTab;
+ const Table *pTab = pItem->pSTab;
if( pTab->iPKey>=0 ){
sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName);
}else{
@@ -157727,8 +159933,11 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
}
}else{
- int addr = pSrclist->a[pLvl->iFrom].addrFillSub;
- VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-1);
+ int addr;
+ VdbeOp *pOp;
+ assert( pSrclist->a[pLvl->iFrom].fg.isSubquery );
+ addr = pSrclist->a[pLvl->iFrom].u4.pSubq->addrFillSub;
+ pOp = sqlite3VdbeGetOp(v, addr-1);
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine );
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr );
sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1);
@@ -157871,11 +160080,44 @@ static void updateRangeAffinityStr(
}
}
+/*
+** The pOrderBy->a[].u.x.iOrderByCol values might be incorrect because
+** columns might have been rearranged in the result set. This routine
+** fixes them up.
+**
+** pEList is the new result set. The pEList->a[].u.x.iOrderByCol values
+** contain the *old* locations of each expression. This is a temporary
+** use of u.x.iOrderByCol, not its intended use. The caller must reset
+** u.x.iOrderByCol back to zero for all entries in pEList before the
+** caller returns.
+**
+** This routine changes pOrderBy->a[].u.x.iOrderByCol values from
+** pEList->a[N].u.x.iOrderByCol into N+1. (The "+1" is because of the 1-based
+** indexing used by iOrderByCol.) Or if no match, iOrderByCol is set to zero.
+*/
+static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){
+ int i, j;
+ if( pOrderBy==0 ) return;
+ for(i=0; i<pOrderBy->nExpr; i++){
+ int t = pOrderBy->a[i].u.x.iOrderByCol;
+ if( t==0 ) continue;
+ for(j=0; j<pEList->nExpr; j++){
+ if( pEList->a[j].u.x.iOrderByCol==t ){
+ pOrderBy->a[i].u.x.iOrderByCol = j+1;
+ break;
+ }
+ }
+ if( j>=pEList->nExpr ){
+ pOrderBy->a[i].u.x.iOrderByCol = 0;
+ }
+ }
+}
+
/*
** pX is an expression of the form: (vector) IN (SELECT ...)
** In other words, it is a vector IN operator with a SELECT clause on the
-** LHS. But not all terms in the vector are indexable and the terms might
+** RHS. But not all terms in the vector are indexable and the terms might
** not be in the correct order for indexing.
**
** This routine makes a copy of the input pX expression and then adjusts
@@ -157934,6 +160176,7 @@ static Expr *removeUnindexableInClauseTerms(
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
+ if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
if( pOrigLhs ){
assert( pOrigLhs->a[iField].pExpr!=0 );
pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
@@ -157947,6 +160190,7 @@ static Expr *removeUnindexableInClauseTerms(
pNew->pLeft->x.pList = pLhs;
}
pSelect->pEList = pRhs;
+ pSelect->selId = ++pParse->nSelect; /* Req'd for SubrtnSig validity */
if( pLhs && pLhs->nExpr==1 ){
/* Take care here not to generate a TK_VECTOR containing only a
** single value. Since the parser never creates such a vector, some
@@ -157956,18 +160200,16 @@ static Expr *removeUnindexableInClauseTerms(
sqlite3ExprDelete(db, pNew->pLeft);
pNew->pLeft = p;
}
- if( pSelect->pOrderBy ){
- /* If the SELECT statement has an ORDER BY clause, zero the
- ** iOrderByCol variables. These are set to non-zero when an
- ** ORDER BY term exactly matches one of the terms of the
- ** result-set. Since the result-set of the SELECT statement may
- ** have been modified or reordered, these variables are no longer
- ** set correctly. Since setting them is just an optimization,
- ** it's easiest just to zero them here. */
- ExprList *pOrderBy = pSelect->pOrderBy;
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].u.x.iOrderByCol = 0;
- }
+
+ /* If either the ORDER BY clause or the GROUP BY clause contains
+ ** references to result-set columns, those references might now be
+ ** obsolete. So fix them up.
+ */
+ assert( pRhs!=0 || db->mallocFailed );
+ if( pRhs ){
+ adjustOrderByCol(pSelect->pOrderBy, pRhs);
+ adjustOrderByCol(pSelect->pGroupBy, pRhs);
+ for(i=0; i<pRhs->nExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0;
}
#if 0
@@ -157982,6 +160224,147 @@ static Expr *removeUnindexableInClauseTerms(
}
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** Generate code for a single X IN (....) term of the WHERE clause.
+**
+** This is a special-case of codeEqualityTerm() that works for IN operators
+** only. It is broken out into a subroutine because this case is
+** uncommon and by splitting it off into a subroutine, the common case
+** runs faster.
+**
+** The current value for the constraint is left in register iTarget.
+** This routine sets up a loop that will iterate over all values of X.
+*/
+static SQLITE_NOINLINE void codeINTerm(
+ Parse *pParse, /* The parsing context */
+ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
+ WhereLevel *pLevel, /* The level of the FROM clause we are working on */
+ int iEq, /* Index of the equality term within this level */
+ int bRev, /* True for reverse-order IN operations */
+ int iTarget /* Attempt to leave results in this register */
+){
+ Expr *pX = pTerm->pExpr;
+ int eType = IN_INDEX_NOOP;
+ int iTab;
+ struct InLoop *pIn;
+ WhereLoop *pLoop = pLevel->pWLoop;
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ int nEq = 0;
+ int *aiMap = 0;
+
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+ && pLoop->u.btree.pIndex!=0
+ && pLoop->u.btree.pIndex->aSortOrder[iEq]
+ ){
+ testcase( iEq==0 );
+ testcase( bRev );
+ bRev = !bRev;
+ }
+ assert( pX->op==TK_IN );
+
+ for(i=0; i<iEq; i++){
+ if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
+ disableTerm(pLevel, pTerm);
+ return;
+ }
+ }
+ for(i=iEq;i<pLoop->nLTerm; i++){
+ assert( pLoop->aLTerm[i]!=0 );
+ if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
+ }
+
+ iTab = 0;
+ if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
+ }else{
+ Expr *pExpr = pTerm->pExpr;
+ if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
+ sqlite3 *db = pParse->db;
+ pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
+ if( !db->mallocFailed ){
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
+ pExpr->iTable = iTab;
+ }
+ sqlite3ExprDelete(db, pX);
+ }else{
+ int n = sqlite3ExprVectorSize(pX->pLeft);
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
+ }
+ pX = pExpr;
+ }
+
+ if( eType==IN_INDEX_INDEX_DESC ){
+ testcase( bRev );
+ bRev = !bRev;
+ }
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
+ VdbeCoverageIf(v, bRev);
+ VdbeCoverageIf(v, !bRev);
+
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+ pLoop->wsFlags |= WHERE_IN_ABLE;
+ if( pLevel->u.in.nIn==0 ){
+ pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
+ }
+ if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
+ pLoop->wsFlags |= WHERE_IN_EARLYOUT;
+ }
+
+ i = pLevel->u.in.nIn;
+ pLevel->u.in.nIn += nEq;
+ pLevel->u.in.aInLoop =
+ sqlite3WhereRealloc(pTerm->pWC->pWInfo,
+ pLevel->u.in.aInLoop,
+ sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
+ pIn = pLevel->u.in.aInLoop;
+ if( pIn ){
+ int iMap = 0; /* Index in aiMap[] */
+ pIn += i;
+ for(i=iEq;i<pLoop->nLTerm; i++){
+ if( pLoop->aLTerm[i]->pExpr==pX ){
+ int iOut = iTarget + i - iEq;
+ if( eType==IN_INDEX_ROWID ){
+ pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
+ }else{
+ int iCol = aiMap ? aiMap[iMap++] : 0;
+ pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
+ }
+ sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
+ if( i==iEq ){
+ pIn->iCur = iTab;
+ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
+ if( iEq>0 ){
+ pIn->iBase = iTarget - i;
+ pIn->nPrefix = i;
+ }else{
+ pIn->nPrefix = 0;
+ }
+ }else{
+ pIn->eEndLoopOp = OP_Noop;
+ }
+ pIn++;
+ }
+ }
+ testcase( iEq>0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
+ && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
+ if( iEq>0
+ && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
+ ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
+ }
+ }else{
+ pLevel->u.in.nIn = 0;
+ }
+ sqlite3DbFree(pParse->db, aiMap);
+}
+#endif
+
+
/*
** Generate code for a single equality term of the WHERE clause. An equality
** term can be either X=expr or X IN (...). pTerm is the term to be
@@ -158006,7 +160389,6 @@ static int codeEqualityTerm(
int iTarget /* Attempt to leave results in this register */
){
Expr *pX = pTerm->pExpr;
- Vdbe *v = pParse->pVdbe;
int iReg; /* Register holding results */
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
@@ -158015,125 +160397,12 @@ static int codeEqualityTerm(
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
}else if( pX->op==TK_ISNULL ){
iReg = iTarget;
- sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
}else{
- int eType = IN_INDEX_NOOP;
- int iTab;
- struct InLoop *pIn;
- WhereLoop *pLoop = pLevel->pWLoop;
- int i;
- int nEq = 0;
- int *aiMap = 0;
-
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
- && pLoop->u.btree.pIndex!=0
- && pLoop->u.btree.pIndex->aSortOrder[iEq]
- ){
- testcase( iEq==0 );
- testcase( bRev );
- bRev = !bRev;
- }
assert( pX->op==TK_IN );
iReg = iTarget;
-
- for(i=0; i<iEq; i++){
- if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
- disableTerm(pLevel, pTerm);
- return iTarget;
- }
- }
- for(i=iEq;i<pLoop->nLTerm; i++){
- assert( pLoop->aLTerm[i]!=0 );
- if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
- }
-
- iTab = 0;
- if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
- }else{
- Expr *pExpr = pTerm->pExpr;
- if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
- sqlite3 *db = pParse->db;
- pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
- if( !db->mallocFailed ){
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
- pExpr->iTable = iTab;
- }
- sqlite3ExprDelete(db, pX);
- }else{
- int n = sqlite3ExprVectorSize(pX->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
- }
- pX = pExpr;
- }
-
- if( eType==IN_INDEX_INDEX_DESC ){
- testcase( bRev );
- bRev = !bRev;
- }
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
- VdbeCoverageIf(v, bRev);
- VdbeCoverageIf(v, !bRev);
-
- assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
- pLoop->wsFlags |= WHERE_IN_ABLE;
- if( pLevel->u.in.nIn==0 ){
- pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
- }
- if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
- pLoop->wsFlags |= WHERE_IN_EARLYOUT;
- }
-
- i = pLevel->u.in.nIn;
- pLevel->u.in.nIn += nEq;
- pLevel->u.in.aInLoop =
- sqlite3WhereRealloc(pTerm->pWC->pWInfo,
- pLevel->u.in.aInLoop,
- sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
- pIn = pLevel->u.in.aInLoop;
- if( pIn ){
- int iMap = 0; /* Index in aiMap[] */
- pIn += i;
- for(i=iEq;i<pLoop->nLTerm; i++){
- if( pLoop->aLTerm[i]->pExpr==pX ){
- int iOut = iReg + i - iEq;
- if( eType==IN_INDEX_ROWID ){
- pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
- }else{
- int iCol = aiMap ? aiMap[iMap++] : 0;
- pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
- }
- sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
- if( i==iEq ){
- pIn->iCur = iTab;
- pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
- if( iEq>0 ){
- pIn->iBase = iReg - i;
- pIn->nPrefix = i;
- }else{
- pIn->nPrefix = 0;
- }
- }else{
- pIn->eEndLoopOp = OP_Noop;
- }
- pIn++;
- }
- }
- testcase( iEq>0
- && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
- && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
- if( iEq>0
- && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
- ){
- sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
- }
- }else{
- pLevel->u.in.nIn = 0;
- }
- sqlite3DbFree(pParse->db, aiMap);
+ codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget);
#endif
}
@@ -158805,7 +161074,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
- VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
+ VdbeModuleComment((v, "Begin WHERE-loop%d: %s",
+ iLevel, pTabItem->pSTab->zName));
#if WHERETRACE_ENABLED /* 0x4001 */
if( sqlite3WhereTrace & 0x1 ){
sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n",
@@ -158860,11 +161130,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->fg.viaCoroutine ){
- int regYield = pTabItem->regReturn;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
+ int regYield;
+ Subquery *pSubq;
+ assert( pTabItem->fg.isSubquery && pTabItem->u4.pSubq!=0 );
+ pSubq = pTabItem->u4.pSubq;
+ regYield = pSubq->regReturn;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub);
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
VdbeCoverage(v);
- VdbeComment((v, "next row of %s", pTabItem->pTab->zName));
+ VdbeComment((v, "next row of %s", pTabItem->pSTab->zName));
pLevel->op = OP_Goto;
}else
@@ -158909,6 +161183,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
+ /* The instruction immediately prior to OP_VFilter must be an OP_Integer
+ ** that sets the "argc" value for xVFilter. This is necessary for
+ ** resolveP2() to work correctly. See tag-20250207a. */
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
pLoop->u.vtab.idxStr,
pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
@@ -159499,12 +161776,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( pLevel->iLeftJoin==0 ){
/* If a partial index is driving the loop, try to eliminate WHERE clause
** terms from the query that must be true due to the WHERE clause of
- ** the partial index.
+ ** the partial index. This optimization does not work on an outer join,
+ ** as shown by:
**
- ** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
- ** for a LEFT JOIN.
+ ** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN)
+ ** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN)
*/
- if( pIdx->pPartIdxWhere ){
+ if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){
whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
}
}else{
@@ -159593,7 +161871,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
- Table *pTab = pTabItem->pTab;
+ Table *pTab = pTabItem->pSTab;
pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
@@ -159611,8 +161889,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int nNotReady; /* The number of notReady tables */
SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
- pOrTab = sqlite3DbMallocRawNN(db,
- sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
+ pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1));
if( pOrTab==0 ) return notReady;
pOrTab->nAlloc = (u8)(nNotReady + 1);
pOrTab->nSrc = pOrTab->nAlloc;
@@ -159663,7 +161940,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
**
** This optimization also only applies if the (x1 OR x2 OR ...) term
** is not contained in the ON clause of a LEFT JOIN.
- ** See ticket http://www.sqlite.org/src/info/f2369304e4
+ ** See ticket http://sqlite.org/src/info/f2369304e4
**
** 2022-02-04: Do not push down slices of a row-value comparison.
** In other words, "w" or "y" may not be a slice of a vector. Otherwise,
@@ -160052,7 +162329,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** least once. This is accomplished by storing the PK for the row in
** both the iMatch index and the regBloom Bloom filter.
*/
- pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab;
+ pTab = pWInfo->pTabList->a[pLevel->iFrom].pSTab;
if( HasRowid(pTab) ){
r = sqlite3GetTempRange(pParse, 2);
sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1);
@@ -160155,11 +162432,12 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
WhereInfo *pSubWInfo;
WhereLoop *pLoop = pLevel->pWLoop;
SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
- SrcList sFrom;
+ SrcList *pFrom;
+ u8 fromSpace[SZ_SRCLIST_1];
Bitmask mAll = 0;
int k;
- ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
+ ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
pRJ->regReturn);
for(k=0; k<iLevel; k++){
@@ -160169,9 +162447,13 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom];
mAll |= pWInfo->a[k].pWLoop->maskSelf;
if( pRight->fg.viaCoroutine ){
+ Subquery *pSubq;
+ assert( pRight->fg.isSubquery && pRight->u4.pSubq!=0 );
+ pSubq = pRight->u4.pSubq;
+ assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 );
sqlite3VdbeAddOp3(
- v, OP_Null, 0, pRight->regResult,
- pRight->regResult + pRight->pSelect->pEList->nExpr-1
+ v, OP_Null, 0, pSubq->regResult,
+ pSubq->regResult + pSubq->pSelect->pEList->nExpr-1
);
}
sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
@@ -160195,13 +162477,14 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
}
}
- sFrom.nSrc = 1;
- sFrom.nAlloc = 1;
- memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
- sFrom.a[0].fg.jointype = 0;
+ pFrom = (SrcList*)fromSpace;
+ pFrom->nSrc = 1;
+ pFrom->nAlloc = 1;
+ memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
+ pFrom->a[0].fg.jointype = 0;
assert( pParse->withinRJSubrtn < 100 );
pParse->withinRJSubrtn++;
- pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
+ pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,
WHERE_RIGHT_JOIN, 0);
if( pSubWInfo ){
int iCur = pLevel->iTabCur;
@@ -160209,7 +162492,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
int nPk;
int jmp;
int addrCont = sqlite3WhereContinueLabel(pSubWInfo);
- Table *pTab = pTabItem->pTab;
+ Table *pTab = pTabItem->pSTab;
if( HasRowid(pTab) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r);
nPk = 1;
@@ -160342,7 +162625,12 @@ static int allowedOp(int op){
assert( TK_LT>TK_EQ && TK_LT<TK_GE );
assert( TK_LE>TK_EQ && TK_LE<TK_GE );
assert( TK_GE==TK_EQ+4 );
- return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
+ assert( TK_IN<TK_EQ );
+ assert( TK_IS<TK_EQ );
+ assert( TK_ISNULL<TK_EQ );
+ if( op>TK_GE ) return 0;
+ if( op>=TK_EQ ) return 1;
+ return op==TK_IN || op==TK_ISNULL || op==TK_IS;
}
/*
@@ -160375,15 +162663,16 @@ static u16 exprCommute(Parse *pParse, Expr *pExpr){
static u16 operatorMask(int op){
u16 c;
assert( allowedOp(op) );
- if( op==TK_IN ){
+ if( op>=TK_EQ ){
+ assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
+ c = (u16)(WO_EQ<<(op-TK_EQ));
+ }else if( op==TK_IN ){
c = WO_IN;
}else if( op==TK_ISNULL ){
c = WO_ISNULL;
- }else if( op==TK_IS ){
- c = WO_IS;
}else{
- assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
- c = (u16)(WO_EQ<<(op-TK_EQ));
+ assert( op==TK_IS );
+ c = WO_IS;
}
assert( op!=TK_ISNULL || c==WO_ISNULL );
assert( op!=TK_IN || c==WO_IN );
@@ -160454,12 +162743,28 @@ static int isLikeOrGlob(
z = (u8*)pRight->u.zToken;
}
if( z ){
-
- /* Count the number of prefix characters prior to the first wildcard */
+ /* Count the number of prefix bytes prior to the first wildcard,
+ ** U+fffd character, or malformed utf-8. If the underlying database
+ ** has a UTF16LE encoding, then only consider ASCII characters. Note that
+ ** the encoding of z[] is UTF8 - we are dealing with only UTF8 here in this
+ ** code, but the database engine itself might be processing content using a
+ ** different encoding. */
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
- if( c==wc[3] && z[cnt]!=0 ) cnt++;
+ if( c==wc[3] && z[cnt]>0 && z[cnt]<0x80 ){
+ cnt++;
+ }else if( c>=0x80 ){
+ const u8 *z2 = z+cnt-1;
+ if( c==0xff || sqlite3Utf8Read(&z2)==0xfffd /* bad utf-8 */
+ || ENC(db)==SQLITE_UTF16LE
+ ){
+ cnt--;
+ break;
+ }else{
+ cnt = (int)(z2-z);
+ }
+ }
}
/* The optimization is possible only if (1) the pattern does not begin
@@ -160470,11 +162775,11 @@ static int isLikeOrGlob(
** range search. The third is because the caller assumes that the pattern
** consists of at least one character after all escapes have been
** removed. */
- if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){
+ if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){
Expr *pPrefix;
/* A "complete" match if the pattern ends with "*" or "%" */
- *pisComplete = c==wc[0] && z[cnt+1]==0;
+ *pisComplete = c==wc[0] && z[cnt+1]==0 && ENC(db)!=SQLITE_UTF16LE;
/* Get the pattern prefix. Remove all escapes from the prefix. */
pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
@@ -160670,6 +162975,13 @@ static int isAuxiliaryVtabOperator(
}
}
}
+ }else if( pExpr->op>=TK_EQ ){
+ /* Comparison operators are a common case. Save a few comparisons for
+ ** that common case by terminating early. */
+ assert( TK_NE < TK_EQ );
+ assert( TK_ISNOT < TK_EQ );
+ assert( TK_NOTNULL < TK_EQ );
+ return 0;
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
int res = 0;
Expr *pLeft = pExpr->pLeft;
@@ -161143,30 +163455,42 @@ static void exprAnalyzeOrTerm(
** 1. The SQLITE_Transitive optimization must be enabled
** 2. Must be either an == or an IS operator
** 3. Not originating in the ON clause of an OUTER JOIN
-** 4. The affinities of A and B must be compatible
-** 5a. Both operands use the same collating sequence OR
-** 5b. The overall collating sequence is BINARY
+** 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
** 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
** returned when it should not be, then incorrect answers might result.
*/
-static int termIsEquivalence(Parse *pParse, Expr *pExpr){
+static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
char aff1, aff2;
CollSeq *pColl;
- if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
- if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
- if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
+ 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) */
+ assert( pSrc!=0 );
+ if( pExpr->op==TK_IS
+ && pSrc->nSrc
+ && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0
+ ){
+ return 0; /* (4) */
+ }
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
- return 0;
+ return 0; /* (5) */
}
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
- if( sqlite3IsBinary(pColl) ) return 1;
- return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
+ if( !sqlite3IsBinary(pColl)
+ && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
+ ){
+ return 0; /* (6) */
+ }
+ return 1;
}
/*
@@ -161186,7 +163510,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
if( ALWAYS(pSrc!=0) ){
int i;
for(i=0; i<pSrc->nSrc; i++){
- mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
+ if( pSrc->a[i].fg.isSubquery ){
+ mask |= exprSelectUsage(pMaskSet, pSrc->a[i].u4.pSubq->pSelect);
+ }
if( pSrc->a[i].fg.isUsing==0 ){
mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn);
}
@@ -161224,7 +163550,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2(
int iCur;
do{
iCur = pFrom->a[j].iCursor;
- for(pIdx=pFrom->a[j].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ for(pIdx=pFrom->a[j].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->aColExpr==0 ) continue;
for(i=0; i<pIdx->nKeyCol; i++){
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
@@ -161268,7 +163594,7 @@ static int exprMightBeIndexed(
for(i=0; i<pFrom->nSrc; i++){
Index *pIdx;
- for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ for(pIdx=pFrom->a[i].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->aColExpr ){
return exprMightBeIndexed2(pFrom,aiCurCol,pExpr,i);
}
@@ -161429,8 +163755,8 @@ static void exprAnalyze(
if( op==TK_IS ) pNew->wtFlags |= TERM_IS;
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_COPIED;
-
- if( termIsEquivalence(pParse, pDup) ){
+ assert( pWInfo->pTabList!=0 );
+ if( termIsEquivalence(pParse, pDup, pWInfo->pTabList) ){
pTerm->eOperator |= WO_EQUIV;
eExtraOp = WO_EQUIV;
}
@@ -161596,9 +163922,8 @@ static void exprAnalyze(
}
if( !db->mallocFailed ){
- u8 c, *pC; /* Last character before the first wildcard */
+ u8 *pC; /* Last character before the first wildcard */
pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
- c = *pC;
if( noCase ){
/* The point is to increment the last character before the first
** wildcard. But if we increment '@', that will push it into the
@@ -161606,10 +163931,17 @@ static void exprAnalyze(
** inequality. To avoid this, make sure to also run the full
** LIKE on all candidate expressions by clearing the isComplete flag
*/
- if( c=='A'-1 ) isComplete = 0;
- c = sqlite3UpperToLower[c];
+ if( *pC=='A'-1 ) isComplete = 0;
+ *pC = sqlite3UpperToLower[*pC];
+ }
+
+ /* Increment the value of the last utf8 character in the prefix. */
+ while( *pC==0xBF && pC>(u8*)pStr2->u.zToken ){
+ *pC = 0x80;
+ pC--;
}
- *pC = c + 1;
+ assert( *pC!=0xFF ); /* isLikeOrGlob() guarantees this */
+ (*pC)++;
}
zCollSeqName = noCase ? "NOCASE" : sqlite3StrBINARY;
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
@@ -161811,7 +164143,7 @@ static void whereAddLimitExpr(
Expr *pNew;
int iVal = 0;
- if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
+ if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
if( pVal==0 ) return;
ExprSetProperty(pVal, EP_IntValue);
@@ -161856,7 +164188,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Selec
assert( p!=0 && p->pLimit!=0 ); /* 1 -- checked by caller */
if( p->pGroupBy==0
&& (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */
- && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab)) /* 3 */
+ && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pSTab)) /* 3 */
){
ExprList *pOrderBy = p->pOrderBy;
int iCsr = p->pSrc->a[0].iCursor;
@@ -162077,7 +164409,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
Expr *pColRef;
Expr *pTerm;
if( pItem->fg.isTabFunc==0 ) return;
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
assert( pTab!=0 );
pArgs = pItem->u1.pFuncArg;
if( pArgs==0 ) return;
@@ -162152,11 +164484,16 @@ struct HiddenIndexInfo {
int eDistinct; /* Value to return from sqlite3_vtab_distinct() */
u32 mIn; /* Mask of terms that are <col> IN (...) */
u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */
- sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST
- ** because extra space is allocated to hold up
- ** to nTerm such values */
+ sqlite3_value *aRhs[FLEXARRAY]; /* RHS values for constraints. MUST BE LAST
+ ** Extra space is allocated to hold up
+ ** to nTerm such values */
};
+/* Size (in bytes) of a HiddenIndeInfo object sufficient to hold as
+** many as N constraints */
+#define SZ_HIDDENINDEXINFO(N) \
+ (offsetof(HiddenIndexInfo,aRhs) + (N)*sizeof(sqlite3_value*))
+
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
@@ -162761,7 +165098,7 @@ static int isDistinctRedundant(
** clause is redundant. */
if( pTabList->nSrc!=1 ) return 0;
iBase = pTabList->a[0].iCursor;
- pTab = pTabList->a[0].pTab;
+ pTab = pTabList->a[0].pSTab;
/* If any of the expressions is an IPK column on table iBase, then return
** true. Note: The (p->iTable==iBase) part of this test may be false if the
@@ -162836,6 +165173,12 @@ static void translateColumnToCopy(
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
if( pParse->db->mallocFailed ) return;
+#ifdef SQLITE_DEBUG
+ if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
+ printf("CHECKING for column-to-copy on cursor %d for %d..%d\n",
+ iTabCur, iStart, iEnd);
+ }
+#endif
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
@@ -162950,13 +165293,52 @@ static int constraintCompatibleWithOuterJoin(
return 0;
}
if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
- && ExprHasProperty(pTerm->pExpr, EP_InnerON)
+ && NEVER(ExprHasProperty(pTerm->pExpr, EP_InnerON))
){
return 0;
}
return 1;
}
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+/*
+** Return true if column iCol of table pTab seem like it might be a
+** good column to use as part of a query-time index.
+**
+** Current algorithm (subject to improvement!):
+**
+** 1. If iCol is already the left-most column of some other index,
+** then return false.
+**
+** 2. If iCol is part of an existing index that has an aiRowLogEst of
+** more than 20, then return false.
+**
+** 3. If no disqualifying conditions above are found, return true.
+**
+** 2025-01-03: I experimented with a new rule that returns false if the
+** the datatype of the column is "BOOLEAN". This did not improve
+** performance on any queries at hand, but it did burn CPU cycles, so the
+** idea was not committed.
+*/
+static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
+ const Table *pTab,
+ int iCol
+){
+ const Index *pIdx;
+ for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
+ int j;
+ for(j=0; j<pIdx->nKeyCol; j++){
+ if( pIdx->aiColumn[j]==iCol ){
+ if( j==0 ) return 0;
+ if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0;
+ break;
+ }
+ }
+ }
+ return 1;
+}
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -162971,6 +165353,8 @@ static int termCanDriveIndex(
const Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
+ int leftCol;
+
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
@@ -162981,11 +165365,12 @@ static int termCanDriveIndex(
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
- if( pTerm->u.x.leftColumn<0 ) return 0;
- aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
+ leftCol = pTerm->u.x.leftColumn;
+ if( leftCol<0 ) return 0;
+ aff = pSrc->pSTab->aCol[leftCol].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
- return 1;
+ return columnIsGoodIndexCandidate(pSrc->pSTab, leftCol);
}
#endif
@@ -163018,7 +165403,7 @@ static void explainAutomaticIndex(
sqlite3_str *pStr = sqlite3_str_new(pParse->db);
sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName);
assert( pIdx->nColumn>1 );
- assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID );
+ assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID || !HasRowid(pTab) );
for(ii=0; ii<(pIdx->nColumn-1); ii++){
const char *zName = 0;
int iCol = pIdx->aiColumn[ii];
@@ -163093,7 +165478,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
nKeyCol = 0;
pTabList = pWC->pWInfo->pTabList;
pSrc = &pTabList->a[pLevel->iFrom];
- pTable = pSrc->pTab;
+ pTable = pSrc->pSTab;
pWCEnd = &pWC->a[pWC->nTerm];
pLoop = pLevel->pWLoop;
idxCols = 0;
@@ -163149,6 +165534,19 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
}else{
extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
}
+ if( !HasRowid(pTable) ){
+ /* For WITHOUT ROWID tables, ensure that all PRIMARY KEY columns are
+ ** either in the idxCols mask or in the extraCols mask */
+ for(i=0; i<pTable->nCol; i++){
+ if( (pTable->aCol[i].colFlags & COLFLAG_PRIMKEY)==0 ) continue;
+ if( i>=BMS-1 ){
+ extraCols |= MASKBIT(BMS-1);
+ break;
+ }
+ if( idxCols & MASKBIT(i) ) continue;
+ extraCols |= MASKBIT(i);
+ }
+ }
mxBitCol = MIN(BMS-1,pTable->nCol);
testcase( pTable->nCol==BMS-1 );
testcase( pTable->nCol==BMS-2 );
@@ -163160,7 +165558,10 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
}
/* Construct the Index object to describe this index */
- pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
+ assert( nKeyCol <= pTable->nCol + MAX(0, pTable->nCol - BMS + 1) );
+ /* ^-- This guarantees that the number of index columns will fit in the u16 */
+ pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+HasRowid(pTable),
+ 0, &zNotUsed);
if( pIdx==0 ) goto end_auto_index_create;
pLoop->u.btree.pIndex = pIdx;
pIdx->zName = "auto-index";
@@ -163216,8 +165617,10 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
}
}
assert( n==nKeyCol );
- pIdx->aiColumn[n] = XN_ROWID;
- pIdx->azColl[n] = sqlite3StrBINARY;
+ if( HasRowid(pTable) ){
+ pIdx->aiColumn[n] = XN_ROWID;
+ pIdx->azColl[n] = sqlite3StrBINARY;
+ }
/* Create the automatic index */
explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp);
@@ -163235,12 +165638,17 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
/* Fill the automatic index with content */
assert( pSrc == &pWC->pWInfo->pTabList->a[pLevel->iFrom] );
if( pSrc->fg.viaCoroutine ){
- int regYield = pSrc->regReturn;
+ int regYield;
+ Subquery *pSubq;
+ assert( pSrc->fg.isSubquery );
+ pSubq = pSrc->u4.pSubq;
+ assert( pSubq!=0 );
+ regYield = pSubq->regReturn;
addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSrc->addrFillSub);
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
VdbeCoverage(v);
- VdbeComment((v, "next row of %s", pSrc->pTab->zName));
+ VdbeComment((v, "next row of %s", pSrc->pSTab->zName));
}else{
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
}
@@ -163262,11 +165670,12 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
if( pSrc->fg.viaCoroutine ){
+ assert( pSrc->fg.isSubquery && pSrc->u4.pSubq!=0 );
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
testcase( pParse->db->mallocFailed );
assert( pLevel->iIdxCur>0 );
translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
- pSrc->regResult, pLevel->iIdxCur);
+ pSrc->u4.pSubq->regResult, pLevel->iIdxCur);
sqlite3VdbeGoto(v, addrTop);
pSrc->fg.viaCoroutine = 0;
}else{
@@ -163357,7 +165766,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
iSrc = pLevel->iFrom;
pItem = &pTabList->a[iSrc];
assert( pItem!=0 );
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
assert( pTab!=0 );
sz = sqlite3LogEstToInt(pTab->nRowLogEst);
if( sz<10000 ){
@@ -163388,7 +165797,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
int r1 = sqlite3GetTempRange(pParse, n);
int jj;
for(jj=0; jj<n; jj++){
- assert( pIdx->pTable==pItem->pTab );
+ assert( pIdx->pTable==pItem->pSTab );
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj);
}
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n);
@@ -163427,6 +165836,20 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
+** Return term iTerm of the WhereClause passed as the first argument. Terms
+** are numbered from 0 upwards, starting with the terms in pWC->a[], then
+** those in pWC->pOuter->a[] (if any), and so on.
+*/
+static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){
+ WhereClause *p;
+ for(p=pWC; p; p=p->pOuter){
+ if( iTerm<p->nTerm ) return &p->a[iTerm];
+ iTerm -= p->nTerm;
+ }
+ return 0;
+}
+
+/*
** Allocate and populate an sqlite3_index_info structure. It is the
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to freeIndexInfo().
@@ -163452,9 +165875,10 @@ static sqlite3_index_info *allocateIndexInfo(
const Table *pTab;
int eDistinct = 0;
ExprList *pOrderBy = pWInfo->pOrderBy;
+ WhereClause *p;
assert( pSrc!=0 );
- pTab = pSrc->pTab;
+ pTab = pSrc->pSTab;
assert( pTab!=0 );
assert( IsVirtual(pTab) );
@@ -163462,28 +165886,30 @@ static sqlite3_index_info *allocateIndexInfo(
** Mark each term with the TERM_OK flag. Set nTerm to the number of
** terms found.
*/
- for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- pTerm->wtFlags &= ~TERM_OK;
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( pTerm->prereqRight & mUnusable ) continue;
- assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
- testcase( pTerm->eOperator & WO_IN );
- testcase( pTerm->eOperator & WO_ISNULL );
- testcase( pTerm->eOperator & WO_IS );
- testcase( pTerm->eOperator & WO_ALL );
- if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
- if( pTerm->wtFlags & TERM_VNULL ) continue;
+ for(p=pWC, nTerm=0; p; p=p->pOuter){
+ for(i=0, pTerm=p->a; i<p->nTerm; i++, pTerm++){
+ pTerm->wtFlags &= ~TERM_OK;
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ if( pTerm->prereqRight & mUnusable ) continue;
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+ testcase( pTerm->eOperator & WO_IN );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ testcase( pTerm->eOperator & WO_IS );
+ testcase( pTerm->eOperator & WO_ALL );
+ if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
- assert( pTerm->u.x.leftColumn>=XN_ROWID );
- assert( pTerm->u.x.leftColumn<pTab->nCol );
- if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
- && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
- ){
- continue;
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
+ assert( pTerm->u.x.leftColumn>=XN_ROWID );
+ assert( pTerm->u.x.leftColumn<pTab->nCol );
+ if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
+ && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
+ ){
+ continue;
+ }
+ nTerm++;
+ pTerm->wtFlags |= TERM_OK;
}
- nTerm++;
- pTerm->wtFlags |= TERM_OK;
}
/* If the ORDER BY clause contains only columns in the current
@@ -163545,8 +165971,8 @@ static sqlite3_index_info *allocateIndexInfo(
*/
pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
+ (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
- + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)
- + sizeof(sqlite3_value*)*nTerm );
+ + sizeof(*pIdxOrderBy)*nOrderBy
+ + SZ_HIDDENINDEXINFO(nTerm) );
if( pIdxInfo==0 ){
sqlite3ErrorMsg(pParse, "out of memory");
return 0;
@@ -163558,53 +165984,69 @@ static sqlite3_index_info *allocateIndexInfo(
pIdxInfo->aConstraint = pIdxCons;
pIdxInfo->aOrderBy = pIdxOrderBy;
pIdxInfo->aConstraintUsage = pUsage;
+ pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
+ if( HasRowid(pTab)==0 ){
+ /* Ensure that all bits associated with PK columns are set. This is to
+ ** ensure they are available for cases like RIGHT joins or OR loops. */
+ Index *pPk = sqlite3PrimaryKeyIndex((Table*)pTab);
+ assert( pPk!=0 );
+ for(i=0; i<pPk->nKeyCol; i++){
+ int iCol = pPk->aiColumn[i];
+ assert( iCol>=0 );
+ if( iCol>=BMS-1 ) iCol = BMS-1;
+ pIdxInfo->colUsed |= MASKBIT(iCol);
+ }
+ }
pHidden->pWC = pWC;
pHidden->pParse = pParse;
pHidden->eDistinct = eDistinct;
pHidden->mIn = 0;
- for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- u16 op;
- if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
- pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
- pIdxCons[j].iTermOffset = i;
- op = pTerm->eOperator & WO_ALL;
- if( op==WO_IN ){
- if( (pTerm->wtFlags & TERM_SLICE)==0 ){
- pHidden->mIn |= SMASKBIT32(j);
- }
- op = WO_EQ;
- }
- if( op==WO_AUX ){
- pIdxCons[j].op = pTerm->eMatchOp;
- }else if( op & (WO_ISNULL|WO_IS) ){
- if( op==WO_ISNULL ){
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
- }else{
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
- }
- }else{
- pIdxCons[j].op = (u8)op;
- /* The direct assignment in the previous line is possible only because
- ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
- ** following asserts verify this fact. */
- assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
- assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
- assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
- assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
- assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
- assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
-
- if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
- && sqlite3ExprIsVector(pTerm->pExpr->pRight)
- ){
- testcase( j!=i );
- if( j<16 ) mNoOmit |= (1 << j);
- if( op==WO_LT ) pIdxCons[j].op = WO_LE;
- if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+ for(p=pWC, i=j=0; p; p=p->pOuter){
+ int nLast = i+p->nTerm;;
+ for(pTerm=p->a; i<nLast; i++, pTerm++){
+ u16 op;
+ if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
+ pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
+ pIdxCons[j].iTermOffset = i;
+ op = pTerm->eOperator & WO_ALL;
+ if( op==WO_IN ){
+ if( (pTerm->wtFlags & TERM_SLICE)==0 ){
+ pHidden->mIn |= SMASKBIT32(j);
+ }
+ op = WO_EQ;
+ }
+ if( op==WO_AUX ){
+ pIdxCons[j].op = pTerm->eMatchOp;
+ }else if( op & (WO_ISNULL|WO_IS) ){
+ if( op==WO_ISNULL ){
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
+ }else{
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
+ }
+ }else{
+ pIdxCons[j].op = (u8)op;
+ /* The direct assignment in the previous line is possible only because
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
+ ** following asserts verify this fact. */
+ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
+ assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
+ assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
+ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
+ assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
+ assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
+
+ if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
+ && sqlite3ExprIsVector(pTerm->pExpr->pRight)
+ ){
+ testcase( j!=i );
+ if( j<16 ) mNoOmit |= (1 << j);
+ if( op==WO_LT ) pIdxCons[j].op = WO_LE;
+ if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+ }
}
- }
- j++;
+ j++;
+ }
}
assert( j==nTerm );
pIdxInfo->nConstraint = j;
@@ -163625,6 +166067,17 @@ static sqlite3_index_info *allocateIndexInfo(
}
/*
+** Free and zero the sqlite3_index_info.idxStr value if needed.
+*/
+static void freeIdxStr(sqlite3_index_info *pIdxInfo){
+ if( pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ }
+}
+
+/*
** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
** and possibly modified by xBestIndex methods.
*/
@@ -163639,6 +166092,7 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
pHidden->aRhs[i] = 0;
}
+ freeIdxStr(pIdxInfo);
sqlite3DbFree(db, pIdxInfo);
}
@@ -163659,9 +166113,11 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
** that this is required.
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
- sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
int rc;
+ sqlite3_vtab *pVtab;
+ assert( IsVirtual(pTab) );
+ pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
whereTraceIndexInfoInputs(p, pTab);
pParse->db->nSchemaLock++;
rc = pVtab->pModule->xBestIndex(pVtab, p);
@@ -164353,7 +166809,7 @@ static int whereInScanEst(
#endif /* SQLITE_ENABLE_STAT4 */
-#ifdef WHERETRACE_ENABLED
+#if defined(WHERETRACE_ENABLED) || defined(SQLITE_DEBUG)
/*
** Print the content of a WhereTerm object
*/
@@ -164397,6 +166853,9 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
+SQLITE_PRIVATE void sqlite3ShowWhereTerm(WhereTerm *pTerm){
+ sqlite3WhereTermPrint(pTerm, 0);
+}
#endif
#ifdef WHERETRACE_ENABLED
@@ -164428,17 +166887,19 @@ SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){
** 1.002.001 t2.t2xy 2 f 010241 N 2 cost 0,56,31
*/
SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){
+ WhereInfo *pWInfo;
if( pWC ){
- WhereInfo *pWInfo = pWC->pWInfo;
+ pWInfo = pWC->pWInfo;
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
- Table *pTab = pItem->pTab;
+ Table *pTab = pItem->pSTab;
Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
sqlite3DebugPrintf(" %12s",
pItem->zAlias ? pItem->zAlias : pTab->zName);
}else{
+ pWInfo = 0;
sqlite3DebugPrintf("%c%2d.%03llx.%03llx %c%d",
p->cId, p->iTab, p->maskSelf, p->prereq & 0xfff, p->cId, p->iTab);
}
@@ -164470,7 +166931,12 @@ SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause
}else{
sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm);
}
- sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
+ if( pWInfo && pWInfo->bStarUsed && p->rStarDelta!=0 ){
+ sqlite3DebugPrintf(" cost %d,%d,%d delta=%d\n",
+ p->rSetup, p->rRun, p->nOut, p->rStarDelta);
+ }else{
+ sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
+ }
if( p->nLTerm && (sqlite3WhereTrace & 0x4000)!=0 ){
int i;
for(i=0; i<p->nLTerm; i++){
@@ -164604,7 +167070,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
** and Y has additional constraints that might speed the search that X lacks
** but the cost of running X is not more than the cost of running Y.
**
-** In other words, return true if the cost relationwship between X and Y
+** In other words, return true if the cost relationship between X and Y
** is inverted and needs to be adjusted.
**
** Case 1:
@@ -164990,7 +167456,7 @@ static void whereLoopOutputAdjust(
Expr *pRight = pTerm->pExpr->pRight;
int k = 0;
testcase( pTerm->pExpr->op==TK_IS );
- if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
+ if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
k = 10;
}else{
k = 20;
@@ -165142,11 +167608,8 @@ static int whereLoopAddBtreeIndex(
assert( pNew->u.btree.nBtm==0 );
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
}
- if( pProbe->bUnordered || pProbe->bLowQual ){
- if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
- if( pProbe->bLowQual && pSrc->fg.isIndexedBy==0 ){
- opMask &= ~(WO_EQ|WO_IN|WO_IS);
- }
+ if( pProbe->bUnordered ){
+ opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
}
assert( pNew->u.btree.nEq<pProbe->nColumn );
@@ -165287,7 +167750,7 @@ static int whereLoopAddBtreeIndex(
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
){
if( iCol==XN_ROWID || pProbe->uniqNotNull
- || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
+ || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ))
){
pNew->wsFlags |= WHERE_ONEROW;
}else{
@@ -165420,7 +167883,7 @@ static int whereLoopAddBtreeIndex(
** 2. Stepping forward in the index pNew->nOut times to find all
** additional matching entries.
*/
- assert( pSrc->pTab->szTabRow>0 );
+ assert( pSrc->pSTab->szTabRow>0 );
if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
/* The pProbe->szIdxRow is low for an IPK table since the interior
** pages are small. Thus szIdxRow gives a good estimate of seek cost.
@@ -165428,7 +167891,7 @@ static int whereLoopAddBtreeIndex(
** under-estimate the scanning cost. */
rCostIdx = pNew->nOut + 16;
}else{
- rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
+ rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pSTab->szTabRow;
}
rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);
@@ -165459,7 +167922,7 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
&& (pNew->u.btree.nEq<pProbe->nKeyCol ||
- pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
+ (pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY && !pProbe->bIdxRowid))
){
if( pNew->u.btree.nEq>3 ){
sqlite3ProgressCheck(pParse);
@@ -165582,13 +168045,13 @@ static int whereUsablePartialIndex(
if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
- if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
+ && !sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, -1)
&& (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
@@ -165893,9 +168356,9 @@ static int whereLoopAddBtree(
pWInfo = pBuilder->pWInfo;
pTabList = pWInfo->pTabList;
pSrc = pTabList->a + pNew->iTab;
- pTab = pSrc->pTab;
+ pTab = pSrc->pSTab;
pWC = pBuilder->pWC;
- assert( !IsVirtual(pSrc->pTab) );
+ assert( !IsVirtual(pSrc->pSTab) );
if( pSrc->fg.isIndexedBy ){
assert( pSrc->fg.isCte==0 );
@@ -165920,7 +168383,7 @@ static int whereLoopAddBtree(
sPk.idxType = SQLITE_IDXTYPE_IPK;
aiRowEstPk[0] = pTab->nRowLogEst;
aiRowEstPk[1] = 0;
- pFirst = pSrc->pTab->pIndex;
+ pFirst = pSrc->pSTab->pIndex;
if( pSrc->fg.notIndexed==0 ){
/* The real indices of the table are only considered if the
** NOT INDEXED qualifier is omitted from the FROM clause */
@@ -165937,7 +168400,6 @@ static int whereLoopAddBtree(
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
&& !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
- && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
&& !pSrc->fg.isRecursive /* Not a recursive common table expression. */
&& (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */
@@ -166010,6 +168472,7 @@ static int whereLoopAddBtree(
pNew->prereq = mPrereq;
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
+ pNew->u.btree.pOrderBy = 0;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
/* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
@@ -166039,6 +168502,10 @@ static int whereLoopAddBtree(
#endif
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
+ if( pSrc->fg.isSubquery ){
+ if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE;
+ pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
+ }
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
@@ -166080,7 +168547,7 @@ static int whereLoopAddBtree(
&& (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
){
WHERETRACE(0x200,
- ("-> %s a covering index according to bitmasks\n",
+ ("-> %s is a covering index according to bitmasks\n",
pProbe->zName, m==0 ? "is" : "is not"));
pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
}
@@ -166241,7 +168708,7 @@ static int whereLoopAddVirtualOne(
** arguments mUsable and mExclude. */
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
for(i=0; i<nConstraint; i++, pIdxCons++){
- WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
+ WhereTerm *pTerm = termFromWhereClause(pWC, pIdxCons->iTermOffset);
pIdxCons->usable = 0;
if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
&& (pTerm->eOperator & mExclude)==0
@@ -166260,11 +168727,10 @@ static int whereLoopAddVirtualOne(
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
pIdxInfo->estimatedRows = 25;
pIdxInfo->idxFlags = 0;
- pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
pHidden->mHandleIn = 0;
/* Invoke the virtual table xBestIndex() method */
- rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
+ rc = vtabBestIndex(pParse, pSrc->pSTab, pIdxInfo);
if( rc ){
if( rc==SQLITE_CONSTRAINT ){
/* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
@@ -166272,6 +168738,7 @@ static int whereLoopAddVirtualOne(
** Make no entries in the loop table.
*/
WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n"));
+ freeIdxStr(pIdxInfo);
return SQLITE_OK;
}
return rc;
@@ -166289,18 +168756,17 @@ static int whereLoopAddVirtualOne(
int j = pIdxCons->iTermOffset;
if( iTerm>=nConstraint
|| j<0
- || j>=pWC->nTerm
+ || (pTerm = termFromWhereClause(pWC, j))==0
|| pNew->aLTerm[iTerm]!=0
|| pIdxCons->usable==0
){
- sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
- testcase( pIdxInfo->needToFreeIdxStr );
+ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName);
+ freeIdxStr(pIdxInfo);
return SQLITE_ERROR;
}
testcase( iTerm==nConstraint-1 );
testcase( j==0 );
testcase( j==pWC->nTerm-1 );
- pTerm = &pWC->a[j];
pNew->prereq |= pTerm->prereqRight;
assert( iTerm<pNew->nLSlot );
pNew->aLTerm[iTerm] = pTerm;
@@ -166345,11 +168811,7 @@ static int whereLoopAddVirtualOne(
** the plan cannot be used. In these cases set variable *pbRetryLimit
** to true to tell the caller to retry with LIMIT and OFFSET
** disabled. */
- if( pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- pIdxInfo->idxStr = 0;
- pIdxInfo->needToFreeIdxStr = 0;
- }
+ freeIdxStr(pIdxInfo);
*pbRetryLimit = 1;
return SQLITE_OK;
}
@@ -166361,8 +168823,8 @@ static int whereLoopAddVirtualOne(
if( pNew->aLTerm[i]==0 ){
/* The non-zero argvIdx values must be contiguous. Raise an
** error if they are not */
- sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
- testcase( pIdxInfo->needToFreeIdxStr );
+ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName);
+ freeIdxStr(pIdxInfo);
return SQLITE_ERROR;
}
}
@@ -166373,6 +168835,7 @@ static int whereLoopAddVirtualOne(
pNew->u.vtab.idxStr = pIdxInfo->idxStr;
pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
pIdxInfo->nOrderBy : 0);
+ pNew->u.vtab.bIdxNumHex = (pIdxInfo->idxFlags&SQLITE_INDEX_SCAN_HEX)!=0;
pNew->rSetup = 0;
pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
@@ -166417,7 +168880,7 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int
if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
CollSeq *pC = 0;
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
- Expr *pX = pHidden->pWC->a[iTerm].pExpr;
+ Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr;
if( pX->pLeft ){
pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
}
@@ -166463,7 +168926,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(
rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */
}else{
if( pH->aRhs[iCons]==0 ){
- WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
+ WhereTerm *pTerm = termFromWhereClause(
+ pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset
+ );
rc = sqlite3ValueFromExpr(
pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
SQLITE_AFF_BLOB, &pH->aRhs[iCons]
@@ -166561,7 +169026,7 @@ static int whereLoopAddVirtual(
pWC = pBuilder->pWC;
pNew = pBuilder->pNew;
pSrc = &pWInfo->pTabList->a[pNew->iTab];
- assert( IsVirtual(pSrc->pTab) );
+ assert( IsVirtual(pSrc->pSTab) );
p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit);
if( p==0 ) return SQLITE_NOMEM_BKPT;
pNew->rSetup = 0;
@@ -166575,7 +169040,7 @@ static int whereLoopAddVirtual(
}
/* First call xBestIndex() with all constraints usable. */
- WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
+ WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pSTab->zName));
WHERETRACE(0x800, (" VirtualOne: all usable\n"));
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry
@@ -166619,9 +169084,8 @@ static int whereLoopAddVirtual(
Bitmask mNext = ALLBITS;
assert( mNext>0 );
for(i=0; i<nConstraint; i++){
- Bitmask mThis = (
- pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
- );
+ int iTerm = p->aConstraint[i].iTermOffset;
+ Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq;
if( mThis>mPrev && mThis<mNext ) mNext = mThis;
}
mPrev = mNext;
@@ -166657,9 +169121,8 @@ static int whereLoopAddVirtual(
}
}
- if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
freeIndexInfo(pParse->db, p);
- WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
+ WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pSTab->zName, rc));
return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -166731,7 +169194,7 @@ static int whereLoopAddOr(
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pItem->pTab) ){
+ if( IsVirtual(pItem->pSTab) ){
rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
}else
#endif
@@ -166845,7 +169308,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
mPrereq = 0;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pItem->pTab) ){
+ if( IsVirtual(pItem->pSTab) ){
SrcItem *p;
for(p=&pItem[1]; p<pEnd; p++){
if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){
@@ -166877,6 +169340,97 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
return rc;
}
+/* Implementation of the order-by-subquery optimization:
+**
+** WhereLoop pLoop, which the iLoop-th term of the nested loop, is really
+** a subquery or CTE that has an ORDER BY clause. See if any of the terms
+** in the subquery ORDER BY clause will satisfy pOrderBy from the outer
+** query. Mark off all satisfied terms (by setting bits in *pOBSat) and
+** return TRUE if they do. If not, return false.
+**
+** Example:
+**
+** CREATE TABLE t1(a,b,c, PRIMARY KEY(a,b));
+** CREATE TABLE t2(x,y);
+** WITH t3(p,q) AS MATERIALIZED (SELECT x+y, x-y FROM t2 ORDER BY x+y)
+** SELECT * FROM t3 JOIN t1 ON a=q ORDER BY p, b;
+**
+** The CTE named "t3" comes out in the natural order of "p", so the first
+** first them of "ORDER BY p,b" is satisfied by a sequential scan of "t3"
+** and sorting only needs to occur on the second term "b".
+**
+** Limitations:
+**
+** (1) The optimization is not applied if the outer ORDER BY contains
+** a COLLATE clause. The optimization might be applied if the
+** outer ORDER BY uses NULLS FIRST, NULLS LAST, ASC, and/or DESC as
+** long as the subquery ORDER BY does the same. But if the
+** outer ORDER BY uses COLLATE, even a redundant COLLATE, the
+** optimization is bypassed.
+**
+** (2) The subquery ORDER BY terms must exactly match subquery result
+** columns, including any COLLATE annotations. This routine relies
+** on iOrderByCol to do matching between order by terms and result
+** columns, and iOrderByCol will not be set if the result column
+** and ORDER BY collations differ.
+**
+** (3) The subquery and outer ORDER BY can be in opposite directions as
+** long as the subquery is materialized. If the subquery is
+** implemented as a co-routine, the sort orders must be in the same
+** direction because there is no way to run a co-routine backwards.
+*/
+static SQLITE_NOINLINE int wherePathMatchSubqueryOB(
+ WhereInfo *pWInfo, /* The WHERE clause */
+ WhereLoop *pLoop, /* The nested loop term that is a subquery */
+ int iLoop, /* Which level of the nested loop. 0==outermost */
+ int iCur, /* Cursor used by the this loop */
+ ExprList *pOrderBy, /* The ORDER BY clause on the whole query */
+ Bitmask *pRevMask, /* When loops need to go in reverse order */
+ Bitmask *pOBSat /* Which terms of pOrderBy are satisfied so far */
+){
+ int iOB; /* Index into pOrderBy->a[] */
+ int jSub; /* Index into pSubOB->a[] */
+ u8 rev = 0; /* True if iOB and jSub sort in opposite directions */
+ u8 revIdx = 0; /* Sort direction for jSub */
+ Expr *pOBExpr; /* Current term of outer ORDER BY */
+ ExprList *pSubOB; /* Complete ORDER BY on the subquery */
+
+ pSubOB = pLoop->u.btree.pOrderBy;
+ assert( pSubOB!=0 );
+ for(iOB=0; (MASKBIT(iOB) & *pOBSat)!=0; iOB++){}
+ for(jSub=0; jSub<pSubOB->nExpr && iOB<pOrderBy->nExpr; jSub++, iOB++){
+ if( pSubOB->a[jSub].u.x.iOrderByCol==0 ) break;
+ pOBExpr = pOrderBy->a[iOB].pExpr;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) break;
+ if( pOBExpr->iTable!=iCur ) break;
+ if( pOBExpr->iColumn!=pSubOB->a[jSub].u.x.iOrderByCol-1 ) break;
+ if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
+ u8 sfOB = pOrderBy->a[iOB].fg.sortFlags; /* sortFlags for iOB */
+ u8 sfSub = pSubOB->a[jSub].fg.sortFlags; /* sortFlags for jSub */
+ if( (sfSub & KEYINFO_ORDER_BIGNULL) != (sfOB & KEYINFO_ORDER_BIGNULL) ){
+ break;
+ }
+ revIdx = sfSub & KEYINFO_ORDER_DESC;
+ if( jSub>0 ){
+ if( (rev^revIdx)!=(sfOB & KEYINFO_ORDER_DESC) ){
+ break;
+ }
+ }else{
+ rev = revIdx ^ (sfOB & KEYINFO_ORDER_DESC);
+ if( rev ){
+ if( (pLoop->wsFlags & WHERE_COROUTINE)!=0 ){
+ /* Cannot run a co-routine in reverse order */
+ break;
+ }
+ *pRevMask |= MASKBIT(iLoop);
+ }
+ }
+ }
+ *pOBSat |= MASKBIT(iOB);
+ }
+ return jSub>0;
+}
+
/*
** Examine a WherePath (with the addition of the extra WhereLoop of the 6th
** parameters) to see if it outputs rows in the requested ORDER BY
@@ -167022,9 +169576,18 @@ static i8 wherePathSatisfiesOrderBy(
if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
if( pLoop->wsFlags & WHERE_IPK ){
+ if( pLoop->u.btree.pOrderBy
+ && OptimizationEnabled(db, SQLITE_OrderBySubq)
+ && wherePathMatchSubqueryOB(pWInfo,pLoop,iLoop,iCur,
+ pOrderBy,pRevMask, &obSat)
+ ){
+ nColumn = 0;
+ isOrderDistinct = 0;
+ }else{
+ nColumn = 1;
+ }
pIndex = 0;
nKeyCol = 0;
- nColumn = 1;
}else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
return 0;
}else{
@@ -167034,7 +169597,7 @@ static i8 wherePathSatisfiesOrderBy(
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
/* All relevant terms of the index must also be non-NULL in order
- ** for isOrderDistinct to be true. So the isOrderDistint value
+ ** for isOrderDistinct to be true. So the isOrderDistinct value
** computed here might be a false positive. Corrections will be
** made at tag-20210426-1 below */
isOrderDistinct = IsUniqueIndex(pIndex)
@@ -167119,7 +169682,7 @@ static i8 wherePathSatisfiesOrderBy(
}
/* Find the ORDER BY term that corresponds to the j-th column
- ** of the index and mark that ORDER BY term off
+ ** of the index and mark that ORDER BY term having been satisfied.
*/
isMatch = 0;
for(i=0; bOnce && i<nOrderBy; i++){
@@ -167327,6 +169890,216 @@ static LogEst whereSortingCost(
}
/*
+** Compute the maximum number of paths in the solver algorithm, for
+** queries that have three or more terms in the FROM clause. Queries with
+** two or fewer FROM clause terms are handled by the caller.
+**
+** Query planning is NP-hard. We must limit the number of paths at
+** each step of the solver search algorithm to avoid exponential behavior.
+**
+** The value returned is a tuning parameter. Currently the value is:
+**
+** 18 for star queries
+** 12 otherwise
+**
+** For the purposes of 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.
+**
+** SIDE EFFECT: (and really the whole point of this subroutine)
+**
+** If pWInfo describes a star-query, then the cost for SCANs of dimension
+** WhereLoops is increased to be slightly larger than the cost of a SCAN
+** in the fact table. Only SCAN costs are increased. SEARCH costs are
+** unchanged. This heuristic helps keep fact tables in outer loops. Without
+** this heuristic, paths with fact tables in outer loops tend to get pruned
+** by the mxChoice limit on the number of paths, resulting in poor query
+** plans. See the starschema1.test test module for examples of queries
+** that need this heuristic to find good query plans.
+**
+** This heuristic can be completely disabled, so that no query is
+** considered a star-query, using SQLITE_TESTCTRL_OPTIMIZATION to
+** disable the SQLITE_StarQuery optimization. In the CLI, the command
+** to do that is: ".testctrl opt -starquery".
+**
+** HISTORICAL NOTES:
+**
+** This optimization was first added on 2024-05-09 by check-in 38db9b5c83d.
+** The original optimization reduced the cost and output size estimate for
+** fact tables to help them move to outer loops. But months later (as people
+** started upgrading) performance regression reports started caming in,
+** including:
+**
+** forum post b18ef983e68d06d1 (2024-12-21)
+** forum post 0025389d0860af82 (2025-01-14)
+** forum post d87570a145599033 (2025-01-17)
+**
+** To address these, the criteria for a star-query was tightened to exclude
+** cases where the fact and dimensions are separated by an outer join, and
+** the affect of star-schema detection was changed to increase the rRun cost
+** on just full table scans of dimension tables, rather than reducing costs
+** in the all access methods of the fact table.
+*/
+static int computeMxChoice(WhereInfo *pWInfo){
+ int nLoop = pWInfo->nLevel; /* Number of terms in the join */
+ WhereLoop *pWLoop; /* For looping over WhereLoops */
+
+#ifdef SQLITE_DEBUG
+ /* The star-query detection code below makes use of the following
+ ** properties of the WhereLoop list, so verify them before
+ ** continuing:
+ ** (1) .maskSelf is the bitmask corresponding to .iTab
+ ** (2) The WhereLoop list is in ascending .iTab order
+ */
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ assert( pWLoop->maskSelf==MASKBIT(pWLoop->iTab) );
+ assert( pWLoop->pNextLoop==0 || pWLoop->iTab<=pWLoop->pNextLoop->iTab );
+ }
+#endif /* SQLITE_DEBUG */
+
+ if( nLoop>=5
+ && !pWInfo->bStarDone
+ && OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery)
+ ){
+ SrcItem *aFromTabs; /* All terms of the FROM clause */
+ int iFromIdx; /* Term of FROM clause is the candidate fact-table */
+ Bitmask m; /* Bitmask for candidate fact-table */
+ Bitmask mSelfJoin = 0; /* Tables that cannot be dimension tables */
+ WhereLoop *pStart; /* Where to start searching for dimension-tables */
+
+ pWInfo->bStarDone = 1; /* Only do this computation once */
+
+ /* Look for fact tables with four or more dimensions where the
+ ** dimension tables are not separately from the fact tables by an outer
+ ** or cross join. Adjust cost weights if found.
+ */
+ assert( !pWInfo->bStarUsed );
+ aFromTabs = pWInfo->pTabList->a;
+ pStart = pWInfo->pLoops;
+ for(iFromIdx=0, m=1; iFromIdx<nLoop; iFromIdx++, m<<=1){
+ int nDep = 0; /* Number of dimension tables */
+ LogEst mxRun; /* Maximum SCAN cost of a fact table */
+ Bitmask mSeen = 0; /* Mask of dimension tables */
+ SrcItem *pFactTab; /* The candidate fact table */
+
+ pFactTab = aFromTabs + iFromIdx;
+ 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 */
+ 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;
+ }
+ if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */
+ && (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */
+ && (pWLoop->maskSelf & mSelfJoin)==0 /* Not a self-join */
+ ){
+ if( aFromTabs[pWLoop->iTab].pSTab==pFactTab->pSTab ){
+ mSelfJoin |= m;
+ }else{
+ nDep++;
+ mSeen |= pWLoop->maskSelf;
+ }
+ }
+ }
+ if( nDep<=3 ) continue;
+
+ /* If we reach this point, it means that pFactTab is a fact table
+ ** with four or more dimensions connected by inner joins. Proceed
+ ** to make cost adjustments. */
+
+#ifdef WHERETRACE_ENABLED
+ /* Make sure rStarDelta values are initialized */
+ if( !pWInfo->bStarUsed ){
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ pWLoop->rStarDelta = 0;
+ }
+ }
+#endif
+ pWInfo->bStarUsed = 1;
+
+ /* Compute the maximum cost of any WhereLoop for the
+ ** fact table plus one epsilon */
+ mxRun = LOGEST_MIN;
+ for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){
+ if( pWLoop->iTab<iFromIdx ) continue;
+ if( pWLoop->iTab>iFromIdx ) break;
+ if( pWLoop->rRun>mxRun ) mxRun = pWLoop->rRun;
+ }
+ if( ALWAYS(mxRun<LOGEST_MAX) ) mxRun++;
+
+ /* Increase the cost of table scans for dimension tables to be
+ ** slightly more than the maximum cost of the fact table */
+ for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){
+ if( (pWLoop->maskSelf & mSeen)==0 ) continue;
+ if( pWLoop->nLTerm ) continue;
+ if( pWLoop->rRun<mxRun ){
+#ifdef WHERETRACE_ENABLED /* 0x80000 */
+ 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
+ );
+ }
+ pWLoop->rStarDelta = mxRun - pWLoop->rRun;
+#endif /* WHERETRACE_ENABLED */
+ pWLoop->rRun = mxRun;
+ }
+ }
+ }
+#ifdef WHERETRACE_ENABLED /* 0x80000 */
+ if( (sqlite3WhereTrace & 0x80000)!=0 && pWInfo->bStarUsed ){
+ sqlite3DebugPrintf("WhereLoops changed by star-query heuristic:\n");
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ if( pWLoop->rStarDelta ){
+ sqlite3WhereLoopPrint(pWLoop, &pWInfo->sWC);
+ }
+ }
+ }
+#endif
+ }
+ return pWInfo->bStarUsed ? 18 : 12;
+}
+
+/*
+** Two WhereLoop objects, pCandidate and pBaseline, are known to have the
+** same cost. Look deep into each to see if pCandidate is even slightly
+** better than pBaseline. Return false if it is, if pCandidate is is preferred.
+** Return true if pBaseline is preferred or if we cannot tell the difference.
+**
+** Result Meaning
+** -------- ----------------------------------------------------------
+** true We cannot tell the difference in pCandidate and pBaseline
+** false pCandidate seems like a better choice than pBaseline
+*/
+static SQLITE_NOINLINE int whereLoopIsNoBetter(
+ const WhereLoop *pCandidate,
+ const WhereLoop *pBaseline
+){
+ if( (pCandidate->wsFlags & WHERE_INDEXED)==0 ) return 1;
+ if( (pBaseline->wsFlags & WHERE_INDEXED)==0 ) return 1;
+ if( pCandidate->u.btree.pIndex->szIdxRow <
+ pBaseline->u.btree.pIndex->szIdxRow ) return 0;
+ return 1;
+}
+
+/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
** attempts to find the lowest cost path that visits each WhereLoop
** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -167347,7 +170120,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
int mxI = 0; /* Index of next entry to replace */
int nOrderBy; /* Number of ORDER BY clause terms */
LogEst mxCost = 0; /* Maximum cost of a set of paths */
- LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */
+ LogEst mxUnsort = 0; /* Maximum unsorted cost of a set of path */
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
WherePath *aFrom; /* All nFrom paths at the previous level */
WherePath *aTo; /* The nTo best paths at the current level */
@@ -167361,13 +170134,27 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pParse = pWInfo->pParse;
nLoop = pWInfo->nLevel;
- /* TUNING: For simple queries, only the best path is tracked.
- ** For 2-way joins, the 5 best paths are followed.
- ** For joins of 3 or more tables, track the 10 best paths */
- mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
- assert( nLoop<=pWInfo->pTabList->nSrc );
WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n",
nRowEst, pParse->nQueryLoop));
+ /* TUNING: mxChoice is the maximum number of possible paths to preserve
+ ** at each step. Based on the number of loops in the FROM clause:
+ **
+ ** nLoop mxChoice
+ ** ----- --------
+ ** 1 1 // the most common case
+ ** 2 5
+ ** 3+ 12 or 18 // see computeMxChoice()
+ */
+ if( nLoop<=1 ){
+ mxChoice = 1;
+ }else if( nLoop==2 ){
+ mxChoice = 5;
+ }else if( pParse->nErr ){
+ mxChoice = 1;
+ }else{
+ mxChoice = computeMxChoice(pWInfo);
+ }
+ assert( nLoop<=pWInfo->pTabList->nSrc );
/* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
** case the purpose of this call is to estimate the number of rows returned
@@ -167432,7 +170219,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
LogEst nOut; /* Rows visited by (pFrom+pWLoop) */
LogEst rCost; /* Cost of path (pFrom+pWLoop) */
- LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */
+ LogEst rUnsort; /* Unsorted cost of (pFrom+pWLoop) */
i8 isOrdered; /* isOrdered for (pFrom+pWLoop) */
Bitmask maskNew; /* Mask of src visited by (..) */
Bitmask revMask; /* Mask of rev-order loops for (..) */
@@ -167450,8 +170237,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
/* At this point, pWLoop is a candidate to be the next loop.
** Compute its cost */
- rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
- rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
+ rUnsort = pWLoop->rRun + pFrom->nRow;
+ if( pWLoop->rSetup ){
+ rUnsort = sqlite3LogEstAdd(pWLoop->rSetup, rUnsort);
+ }
+ rUnsort = sqlite3LogEstAdd(rUnsort, pFrom->rUnsort);
nOut = pFrom->nRow + pWLoop->nOut;
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
isOrdered = pFrom->isOrdered;
@@ -167473,15 +170263,15 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** extra encouragement to the query planner to select a plan
** where the rows emerge in the correct order without any sorting
** required. */
- rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 3;
+ rCost = sqlite3LogEstAdd(rUnsort, aSortCost[isOrdered]) + 3;
WHERETRACE(0x002,
("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy,
- rUnsorted, rCost));
+ rUnsort, rCost));
}else{
- rCost = rUnsorted;
- rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */
+ rCost = rUnsort;
+ rUnsort -= 2; /* TUNING: Slight bias in favor of no-sort plans */
}
/* Check to see if pWLoop should be added to the set of
@@ -167495,6 +170285,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
** of legal values for isOrdered, -1..64.
*/
+ testcase( nTo==0 );
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
if( pTo->maskLoop==maskNew
&& ((pTo->isOrdered^isOrdered)&0x80)==0
@@ -167506,7 +170297,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( jj>=nTo ){
/* None of the existing best-so-far paths match the candidate. */
if( nTo>=mxChoice
- && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
+ && (rCost>mxCost || (rCost==mxCost && rUnsort>=mxUnsort))
){
/* The current candidate is no better than any of the mxChoice
** paths currently in the best-so-far buffer. So discard
@@ -167514,7 +170305,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
}
#endif
@@ -167533,7 +170324,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
}
#endif
@@ -167544,24 +170335,23 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** pTo or if the candidate should be skipped.
**
** The conditional is an expanded vector comparison equivalent to:
- ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted)
+ ** (pTo->rCost,pTo->nRow,pTo->rUnsort) <= (rCost,nOut,rUnsort)
*/
- if( pTo->rCost<rCost
- || (pTo->rCost==rCost
- && (pTo->nRow<nOut
- || (pTo->nRow==nOut && pTo->rUnsorted<=rUnsorted)
- )
- )
+ if( (pTo->rCost<rCost)
+ || (pTo->rCost==rCost && pTo->nRow<nOut)
+ || (pTo->rCost==rCost && pTo->nRow==nOut && pTo->rUnsort<rUnsort)
+ || (pTo->rCost==rCost && pTo->nRow==nOut && pTo->rUnsort==rUnsort
+ && whereLoopIsNoBetter(pWLoop, pTo->aLoop[iLoop]) )
){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
"Skip %s cost=%-3d,%3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+ pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
/* Discard the candidate path from further consideration */
@@ -167575,11 +170365,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
"Update %s cost=%-3d,%3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+ pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
}
@@ -167588,20 +170378,20 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pTo->revLoop = revMask;
pTo->nRow = nOut;
pTo->rCost = rCost;
- pTo->rUnsorted = rUnsorted;
+ pTo->rUnsort = rUnsort;
pTo->isOrdered = isOrdered;
memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
pTo->aLoop[iLoop] = pWLoop;
if( nTo>=mxChoice ){
mxI = 0;
mxCost = aTo[0].rCost;
- mxUnsorted = aTo[0].nRow;
+ mxUnsort = aTo[0].nRow;
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
if( pTo->rCost>mxCost
- || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted)
+ || (pTo->rCost==mxCost && pTo->rUnsort>mxUnsort)
){
mxCost = pTo->rCost;
- mxUnsorted = pTo->rUnsorted;
+ mxUnsort = pTo->rUnsort;
mxI = jj;
}
}
@@ -167611,17 +170401,32 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* >=2 */
if( sqlite3WhereTrace & 0x02 ){
+ LogEst rMin, rFloor = 0;
+ int nDone = 0;
+ int nProgress;
sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
- for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
- sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
- wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
- if( pTo->isOrdered>0 ){
- sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
- }else{
- sqlite3DebugPrintf("\n");
+ do{
+ nProgress = 0;
+ rMin = 0x7fff;
+ for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
+ if( pTo->rCost>rFloor && pTo->rCost<rMin ) rMin = pTo->rCost;
+ }
+ for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
+ if( pTo->rCost==rMin ){
+ sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+ pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
+ if( pTo->isOrdered>0 ){
+ sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
+ }else{
+ sqlite3DebugPrintf("\n");
+ }
+ nDone++;
+ nProgress++;
+ }
}
- }
+ rFloor = rMin;
+ }while( nDone<nTo && nProgress>0 );
}
#endif
@@ -167716,6 +170521,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
}
pWInfo->nRowOut = pFrom->nRow;
+#ifdef WHERETRACE_ENABLED
+ pWInfo->rTotalCost = pFrom->rCost;
+#endif
/* Free temporary memory and return success */
sqlite3StackFreeNN(pParse->db, pSpace);
@@ -167826,7 +170634,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0;
assert( pWInfo->pTabList->nSrc>=1 );
pItem = pWInfo->pTabList->a;
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
if( IsVirtual(pTab) ) return 0;
if( pItem->fg.isIndexedBy || pItem->fg.notIndexed ){
testcase( pItem->fg.isIndexedBy );
@@ -168016,6 +170824,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
WhereTerm *pTerm, *pEnd;
SrcItem *pItem;
WhereLoop *pLoop;
+ Bitmask m1;
pLoop = pWInfo->a[i].pWLoop;
pItem = &pWInfo->pTabList->a[pLoop->iTab];
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
@@ -168036,13 +170845,16 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
}
if( hasRightJoin
&& ExprHasProperty(pTerm->pExpr, EP_InnerON)
- && pTerm->pExpr->w.iJoin==pItem->iCursor
+ && NEVER(pTerm->pExpr->w.iJoin==pItem->iCursor)
){
break; /* restriction (5) */
}
}
if( pTerm<pEnd ) continue;
- WHERETRACE(0xffffffff, ("-> drop loop %c not used\n", pLoop->cId));
+ WHERETRACE(0xffffffff,("-> omit unused FROM-clause term %c\n",pLoop->cId));
+ m1 = MASKBIT(i)-1;
+ testcase( ((pWInfo->revMask>>1) & ~m1)!=0 );
+ pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
notReady &= ~pLoop->maskSelf;
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
@@ -168089,7 +170901,7 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
WhereLoop *pLoop = pWInfo->a[i].pWLoop;
const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ);
SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
- Table *pTab = pItem->pTab;
+ Table *pTab = pItem->pSTab;
if( (pTab->tabFlags & TF_HasStat1)==0 ) break;
pTab->tabFlags |= TF_MaybeReanalyze;
if( i>=1
@@ -168113,58 +170925,6 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
}
/*
-** Expression Node callback for sqlite3ExprCanReturnSubtype().
-**
-** Only a function call is able to return a subtype. So if the node
-** is not a function call, return WRC_Prune immediately.
-**
-** A function call is able to return a subtype if it has the
-** SQLITE_RESULT_SUBTYPE property.
-**
-** Assume that every function is able to pass-through a subtype from
-** one of its argument (using sqlite3_result_value()). Most functions
-** are not this way, but we don't have a mechanism to distinguish those
-** that are from those that are not, so assume they all work this way.
-** That means that if one of its arguments is another function and that
-** other function is able to return a subtype, then this function is
-** able to return a subtype.
-*/
-static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
- int n;
- FuncDef *pDef;
- sqlite3 *db;
- if( pExpr->op!=TK_FUNCTION ){
- return WRC_Prune;
- }
- assert( ExprUseXList(pExpr) );
- db = pWalker->pParse->db;
- n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
- pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
- if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
- pWalker->eCode = 1;
- return WRC_Prune;
- }
- return WRC_Continue;
-}
-
-/*
-** Return TRUE if expression pExpr is able to return a subtype.
-**
-** A TRUE return does not guarantee that a subtype will be returned.
-** It only indicates that a subtype return is possible. False positives
-** are acceptable as they only disable an optimization. False negatives,
-** on the other hand, can lead to incorrect answers.
-*/
-static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
- Walker w;
- memset(&w, 0, sizeof(w));
- w.pParse = pParse;
- w.xExprCallback = exprNodeCanReturnSubtype;
- sqlite3WalkExpr(&w, pExpr);
- return w.eCode;
-}
-
-/*
** The index pIdx is used by a query and contains one or more expressions.
** In other words pIdx is an index on an expression. iIdxCur is the cursor
** number for the index and iDataCur is the cursor number for the corresponding
@@ -168197,12 +170957,6 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
continue;
}
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
- if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
- /* Functions that might set a subtype should not be replaced by the
- ** value taken from an expression index since the index omits the
- ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
- continue;
- }
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
if( p==0 ) break;
p->pIENext = pParse->pIdxEpr;
@@ -168245,8 +170999,8 @@ static SQLITE_NOINLINE void whereReverseScanOrder(WhereInfo *pWInfo){
SrcItem *pItem = &pWInfo->pTabList->a[ii];
if( !pItem->fg.isCte
|| pItem->u2.pCteUse->eM10d!=M10d_Yes
- || NEVER(pItem->pSelect==0)
- || pItem->pSelect->pOrderBy==0
+ || NEVER(pItem->fg.isSubquery==0)
+ || pItem->u4.pSubq->pSelect->pOrderBy==0
){
pWInfo->revMask |= MASKBIT(ii);
}
@@ -168410,10 +171164,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** field (type Bitmask) it must be aligned on an 8-byte boundary on
** some architectures. Hence the ROUND8() below.
*/
- nByteWInfo = ROUND8P(sizeof(WhereInfo));
- if( nTabList>1 ){
- nByteWInfo = ROUND8P(nByteWInfo + (nTabList-1)*sizeof(WhereLevel));
- }
+ nByteWInfo = SZ_WHEREINFO(nTabList);
pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
if( db->mallocFailed ){
sqlite3DbFree(db, pWInfo);
@@ -168625,12 +171376,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( db->mallocFailed ) goto whereBeginError;
if( pWInfo->pOrderBy ){
whereInterstageHeuristic(pWInfo);
- wherePathSolver(pWInfo, pWInfo->nRowOut+1);
+ wherePathSolver(pWInfo, pWInfo->nRowOut<0 ? 1 : pWInfo->nRowOut+1);
if( db->mallocFailed ) goto whereBeginError;
}
/* TUNING: Assume that a DISTINCT clause on a subquery reduces
- ** the output size by a factor of 8 (LogEst -30).
+ ** the output size by a factor of 8 (LogEst -30). Search for
+ ** tag-20250414a to see other cases.
*/
if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){
WHERETRACE(0x0080,("nRowOut reduced from %d to %d due to DISTINCT\n",
@@ -168649,7 +171401,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
assert( db->mallocFailed==0 );
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace ){
- sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
+ sqlite3DebugPrintf("---- Solution cost=%d, nRow=%d",
+ pWInfo->rTotalCost, pWInfo->nRowOut);
if( pWInfo->nOBSat>0 ){
sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
}
@@ -168736,15 +171489,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
- assert( !(wsFlags & WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pTab) );
+ assert( !(wsFlags&WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pSTab) );
if( bOnerow || (
0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
- && !IsVirtual(pTabList->a[0].pTab)
+ && !IsVirtual(pTabList->a[0].pSTab)
&& (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
&& OptimizationEnabled(db, SQLITE_OnePass)
)){
pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
- if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
+ if( HasRowid(pTabList->a[0].pSTab) && (wsFlags & WHERE_IDX_ONLY) ){
if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
bFordelete = OPFLAG_FORDELETE;
}
@@ -168762,7 +171515,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
SrcItem *pTabItem;
pTabItem = &pTabList->a[pLevel->iFrom];
- pTab = pTabItem->pTab;
+ pTab = pTabItem->pSTab;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pLoop = pLevel->pWLoop;
if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){
@@ -168833,7 +171586,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
iIndexCur = pLevel->iTabCur;
op = 0;
}else if( pWInfo->eOnePass!=ONEPASS_OFF ){
- Index *pJ = pTabItem->pTab->pIndex;
+ Index *pJ = pTabItem->pSTab->pIndex;
iIndexCur = iAuxArg;
assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
while( ALWAYS(pJ) && pJ!=pIx ){
@@ -168900,7 +171653,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
pRJ->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
- assert( pTab==pTabItem->pTab );
+ assert( pTab==pTabItem->pSTab );
if( HasRowid(pTab) ){
KeyInfo *pInfo;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1);
@@ -168939,13 +171692,18 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
wsFlags = pLevel->pWLoop->wsFlags;
pSrc = &pTabList->a[pLevel->iFrom];
if( pSrc->fg.isMaterialized ){
- if( pSrc->fg.isCorrelated ){
- sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
+ Subquery *pSubq;
+ int iOnce = 0;
+ assert( pSrc->fg.isSubquery );
+ pSubq = pSrc->u4.pSubq;
+ if( pSrc->fg.isCorrelated==0 ){
+ iOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}else{
- int iOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
- sqlite3VdbeJumpHere(v, iOnce);
+ iOnce = 0;
}
+ sqlite3VdbeAddOp2(v, OP_Gosub, pSubq->regReturn, pSubq->addrFillSub);
+ VdbeComment((v, "materialize %!S", pSrc));
+ if( iOnce ) sqlite3VdbeJumpHere(v, iOnce);
}
assert( pTabList == pWInfo->pTabList );
if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){
@@ -169005,6 +171763,7 @@ whereBeginError:
){
if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return;
sqlite3VdbePrintOp(0, pc, pOp);
+ sqlite3ShowWhereTerm(0); /* So compiler won't complain about unused func */
}
#endif
@@ -169158,9 +171917,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
assert( pLevel->iTabCur==pSrc->iCursor );
if( pSrc->fg.viaCoroutine ){
int m, n;
- n = pSrc->regResult;
- assert( pSrc->pTab!=0 );
- m = pSrc->pTab->nCol;
+ assert( pSrc->fg.isSubquery );
+ n = pSrc->u4.pSubq->regResult;
+ assert( pSrc->pSTab!=0 );
+ m = pSrc->pSTab->nCol;
sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
}
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
@@ -169184,7 +171944,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeJumpHere(v, addr);
}
VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
- pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
+ pWInfo->pTabList->a[pLevel->iFrom].pSTab->zName));
}
assert( pWInfo->nLevel<=pTabList->nSrc );
@@ -169193,7 +171953,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
SrcItem *pTabItem = &pTabList->a[pLevel->iFrom];
- Table *pTab = pTabItem->pTab;
+ Table *pTab = pTabItem->pSTab;
assert( pTab!=0 );
pLoop = pLevel->pWLoop;
@@ -169212,9 +171972,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
*/
if( pTabItem->fg.viaCoroutine ){
testcase( pParse->db->mallocFailed );
- assert( pTabItem->regResult>=0 );
+ assert( pTabItem->fg.isSubquery );
+ assert( pTabItem->u4.pSubq->regResult>=0 );
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
- pTabItem->regResult, 0);
+ pTabItem->u4.pSubq->regResult, 0);
continue;
}
@@ -169302,14 +172063,28 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
- }else{
- /* Unable to translate the table reference into an index
- ** reference. Verify that this is harmless - that the
- ** table being referenced really is open.
- */
+ }else if( pLoop->wsFlags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
if( pLoop->wsFlags & WHERE_IDX_ONLY ){
+ /* An error. pLoop is supposed to be a covering index loop,
+ ** and yet the VM code refers to a column of the table that
+ ** is not part of the index. */
sqlite3ErrorMsg(pParse, "internal query planner error");
pParse->rc = SQLITE_INTERNAL;
+ }else{
+ /* The WHERE_EXPRIDX flag is set by the planner when it is likely
+ ** that pLoop is a covering index loop, but it is not possible
+ ** to be 100% sure. In this case, any OP_Explain opcode
+ ** corresponding to this loop describes the index as a "COVERING
+ ** INDEX". But, pOp proves that pLoop is not actually a covering
+ ** index loop. So clear the WHERE_EXPRIDX flag and rewrite the
+ ** text that accompanies the OP_Explain opcode, if any. */
+ pLoop->wsFlags &= ~WHERE_EXPRIDX;
+ sqlite3WhereAddExplainText(pParse,
+ pLevel->addrBody-1,
+ pTabList,
+ pLevel,
+ pWInfo->wctrlFlags
+ );
}
}
}else if( pOp->opcode==OP_Rowid ){
@@ -170256,7 +173031,7 @@ static ExprList *exprListAppendList(
int iDummy;
Expr *pSub;
pSub = sqlite3ExprSkipCollateAndLikely(pDup);
- if( sqlite3ExprIsInteger(pSub, &iDummy) ){
+ if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){
pSub->op = TK_NULL;
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
pSub->u.zToken = 0;
@@ -170342,7 +173117,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
p->pWhere = 0;
p->pGroupBy = 0;
p->pHaving = 0;
- p->selFlags &= ~SF_Aggregate;
+ p->selFlags &= ~(u32)SF_Aggregate;
p->selFlags |= SF_WinRewrite;
/* Create the ORDER BY clause for the sub-select. This is the concatenation
@@ -170424,9 +173199,10 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
assert( pSub!=0 || p->pSrc==0 ); /* Due to db->mallocFailed test inside
** of sqlite3DbMallocRawNN() called from
** sqlite3SrcListAppend() */
- if( p->pSrc ){
+ if( p->pSrc==0 ){
+ sqlite3SelectDelete(db, pSub);
+ }else if( sqlite3SrcItemAttachSubquery(pParse, &p->pSrc->a[0], pSub, 0) ){
Table *pTab2;
- p->pSrc->a[0].pSelect = pSub;
p->pSrc->a[0].fg.isCorrelated = 1;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
@@ -170440,7 +173216,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
}else{
memcpy(pTab, pTab2, sizeof(Table));
pTab->tabFlags |= TF_Ephemeral;
- p->pSrc->a[0].pTab = pTab;
+ p->pSrc->a[0].pSTab = pTab;
pTab = pTab2;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
@@ -170448,8 +173224,6 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
sqlite3WalkSelect(&w, pSub);
}
- }else{
- sqlite3SelectDelete(db, pSub);
}
if( db->mallocFailed ) rc = SQLITE_NOMEM;
@@ -170736,10 +173510,15 @@ SQLITE_PRIVATE int sqlite3WindowCompare(
** and initialize registers and cursors used by sqlite3WindowCodeStep().
*/
SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
- int nEphExpr = pSelect->pSrc->a[0].pSelect->pEList->nExpr;
- Window *pMWin = pSelect->pWin;
Window *pWin;
- Vdbe *v = sqlite3GetVdbe(pParse);
+ int nEphExpr;
+ Window *pMWin;
+ Vdbe *v;
+
+ assert( pSelect->pSrc->a[0].fg.isSubquery );
+ nEphExpr = pSelect->pSrc->a[0].u4.pSubq->pSelect->pEList->nExpr;
+ pMWin = pSelect->pWin;
+ v = sqlite3GetVdbe(pParse);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr);
sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
@@ -171013,6 +173792,7 @@ static void windowAggStep(
int regArg;
int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
int i;
+ int addrIf = 0;
assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
@@ -171029,6 +173809,18 @@ static void windowAggStep(
}
regArg = reg;
+ if( pWin->pFilter ){
+ int regTmp;
+ assert( ExprUseXList(pWin->pOwner) );
+ assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
+ assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
+ regTmp = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
+ addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
+ VdbeCoverage(v);
+ sqlite3ReleaseTempReg(pParse, regTmp);
+ }
+
if( pMWin->regStartRowid==0
&& (pFunc->funcFlags & SQLITE_FUNC_MINMAX)
&& (pWin->eStart!=TK_UNBOUNDED)
@@ -171048,25 +173840,13 @@ static void windowAggStep(
}
sqlite3VdbeJumpHere(v, addrIsNull);
}else if( pWin->regApp ){
+ assert( pWin->pFilter==0 );
assert( pFunc->zName==nth_valueName
|| pFunc->zName==first_valueName
);
assert( bInverse==0 || bInverse==1 );
sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
}else if( pFunc->xSFunc!=noopStepFunc ){
- int addrIf = 0;
- if( pWin->pFilter ){
- int regTmp;
- assert( ExprUseXList(pWin->pOwner) );
- assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
- assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
- regTmp = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
- addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
- VdbeCoverage(v);
- sqlite3ReleaseTempReg(pParse, regTmp);
- }
-
if( pWin->bExprArgs ){
int iOp = sqlite3VdbeCurrentAddr(v);
int iEnd;
@@ -171093,12 +173873,13 @@ static void windowAggStep(
sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep,
bInverse, regArg, pWin->regAccum);
sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nArg);
+ sqlite3VdbeChangeP5(v, (u16)nArg);
if( pWin->bExprArgs ){
sqlite3ReleaseTempRange(pParse, regArg, nArg);
}
- if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
}
+
+ if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
}
}
@@ -172136,7 +174917,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
Vdbe *v = sqlite3GetVdbe(pParse);
int csrWrite; /* Cursor used to write to eph. table */
int csrInput = p->pSrc->a[0].iCursor; /* Cursor of sub-select */
- int nInput = p->pSrc->a[0].pTab->nCol; /* Number of cols returned by sub */
+ int nInput = p->pSrc->a[0].pSTab->nCol; /* Number of cols returned by sub */
int iInput; /* To iterate through sub cols */
int addrNe; /* Address of OP_Ne */
int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */
@@ -172477,6 +175258,11 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
/* #include "sqliteInt.h" */
/*
+** Verify that the pParse->isCreate field is set
+*/
+#define ASSERT_IS_CREATE assert(pParse->isCreate)
+
+/*
** Disable all error recovery processing in the parser push-down
** automaton.
*/
@@ -172526,12 +175312,23 @@ struct TrigEvent { int a; IdList * b; };
struct FrameBound { int eType; Expr *pExpr; };
/*
+** Generate a syntax error
+*/
+static void parserSyntaxError(Parse *pParse, Token *p){
+ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p);
+}
+
+/*
** Disable lookaside memory allocation for objects that might be
** shared across database connections.
*/
static void disableLookaside(Parse *pParse){
sqlite3 *db = pParse->db;
pParse->disableLookaside++;
+#ifdef SQLITE_DEBUG
+ pParse->isCreate = 1;
+#endif
+ memset(&pParse->u1.cr, 0, sizeof(pParse->u1.cr));
DisableLookaside;
}
@@ -172733,132 +175530,132 @@ static void updateDeleteLimitError(
#define TK_OR 43
#define TK_AND 44
#define TK_IS 45
-#define TK_MATCH 46
-#define TK_LIKE_KW 47
-#define TK_BETWEEN 48
-#define TK_IN 49
-#define TK_ISNULL 50
-#define TK_NOTNULL 51
-#define TK_NE 52
-#define TK_EQ 53
-#define TK_GT 54
-#define TK_LE 55
-#define TK_LT 56
-#define TK_GE 57
-#define TK_ESCAPE 58
-#define TK_ID 59
-#define TK_COLUMNKW 60
-#define TK_DO 61
-#define TK_FOR 62
-#define TK_IGNORE 63
-#define TK_INITIALLY 64
-#define TK_INSTEAD 65
-#define TK_NO 66
-#define TK_KEY 67
-#define TK_OF 68
-#define TK_OFFSET 69
-#define TK_PRAGMA 70
-#define TK_RAISE 71
-#define TK_RECURSIVE 72
-#define TK_REPLACE 73
-#define TK_RESTRICT 74
-#define TK_ROW 75
-#define TK_ROWS 76
-#define TK_TRIGGER 77
-#define TK_VACUUM 78
-#define TK_VIEW 79
-#define TK_VIRTUAL 80
-#define TK_WITH 81
-#define TK_NULLS 82
-#define TK_FIRST 83
-#define TK_LAST 84
-#define TK_CURRENT 85
-#define TK_FOLLOWING 86
-#define TK_PARTITION 87
-#define TK_PRECEDING 88
-#define TK_RANGE 89
-#define TK_UNBOUNDED 90
-#define TK_EXCLUDE 91
-#define TK_GROUPS 92
-#define TK_OTHERS 93
-#define TK_TIES 94
-#define TK_GENERATED 95
-#define TK_ALWAYS 96
-#define TK_MATERIALIZED 97
-#define TK_REINDEX 98
-#define TK_RENAME 99
-#define TK_CTIME_KW 100
-#define TK_ANY 101
-#define TK_BITAND 102
-#define TK_BITOR 103
-#define TK_LSHIFT 104
-#define TK_RSHIFT 105
-#define TK_PLUS 106
-#define TK_MINUS 107
-#define TK_STAR 108
-#define TK_SLASH 109
-#define TK_REM 110
-#define TK_CONCAT 111
-#define TK_PTR 112
-#define TK_COLLATE 113
-#define TK_BITNOT 114
-#define TK_ON 115
-#define TK_INDEXED 116
-#define TK_STRING 117
-#define TK_JOIN_KW 118
-#define TK_CONSTRAINT 119
-#define TK_DEFAULT 120
-#define TK_NULL 121
-#define TK_PRIMARY 122
-#define TK_UNIQUE 123
-#define TK_CHECK 124
-#define TK_REFERENCES 125
-#define TK_AUTOINCR 126
-#define TK_INSERT 127
-#define TK_DELETE 128
-#define TK_UPDATE 129
-#define TK_SET 130
-#define TK_DEFERRABLE 131
-#define TK_FOREIGN 132
-#define TK_DROP 133
-#define TK_UNION 134
-#define TK_ALL 135
-#define TK_EXCEPT 136
-#define TK_INTERSECT 137
-#define TK_SELECT 138
-#define TK_VALUES 139
-#define TK_DISTINCT 140
-#define TK_DOT 141
-#define TK_FROM 142
-#define TK_JOIN 143
-#define TK_USING 144
-#define TK_ORDER 145
-#define TK_GROUP 146
-#define TK_HAVING 147
-#define TK_LIMIT 148
-#define TK_WHERE 149
-#define TK_RETURNING 150
-#define TK_INTO 151
-#define TK_NOTHING 152
-#define TK_FLOAT 153
-#define TK_BLOB 154
-#define TK_INTEGER 155
-#define TK_VARIABLE 156
-#define TK_CASE 157
-#define TK_WHEN 158
-#define TK_THEN 159
-#define TK_ELSE 160
-#define TK_INDEX 161
-#define TK_ALTER 162
-#define TK_ADD 163
-#define TK_WINDOW 164
-#define TK_OVER 165
-#define TK_FILTER 166
-#define TK_COLUMN 167
-#define TK_AGG_FUNCTION 168
-#define TK_AGG_COLUMN 169
-#define TK_TRUEFALSE 170
-#define TK_ISNOT 171
+#define TK_ISNOT 46
+#define TK_MATCH 47
+#define TK_LIKE_KW 48
+#define TK_BETWEEN 49
+#define TK_IN 50
+#define TK_ISNULL 51
+#define TK_NOTNULL 52
+#define TK_NE 53
+#define TK_EQ 54
+#define TK_GT 55
+#define TK_LE 56
+#define TK_LT 57
+#define TK_GE 58
+#define TK_ESCAPE 59
+#define TK_ID 60
+#define TK_COLUMNKW 61
+#define TK_DO 62
+#define TK_FOR 63
+#define TK_IGNORE 64
+#define TK_INITIALLY 65
+#define TK_INSTEAD 66
+#define TK_NO 67
+#define TK_KEY 68
+#define TK_OF 69
+#define TK_OFFSET 70
+#define TK_PRAGMA 71
+#define TK_RAISE 72
+#define TK_RECURSIVE 73
+#define TK_REPLACE 74
+#define TK_RESTRICT 75
+#define TK_ROW 76
+#define TK_ROWS 77
+#define TK_TRIGGER 78
+#define TK_VACUUM 79
+#define TK_VIEW 80
+#define TK_VIRTUAL 81
+#define TK_WITH 82
+#define TK_NULLS 83
+#define TK_FIRST 84
+#define TK_LAST 85
+#define TK_CURRENT 86
+#define TK_FOLLOWING 87
+#define TK_PARTITION 88
+#define TK_PRECEDING 89
+#define TK_RANGE 90
+#define TK_UNBOUNDED 91
+#define TK_EXCLUDE 92
+#define TK_GROUPS 93
+#define TK_OTHERS 94
+#define TK_TIES 95
+#define TK_GENERATED 96
+#define TK_ALWAYS 97
+#define TK_MATERIALIZED 98
+#define TK_REINDEX 99
+#define TK_RENAME 100
+#define TK_CTIME_KW 101
+#define TK_ANY 102
+#define TK_BITAND 103
+#define TK_BITOR 104
+#define TK_LSHIFT 105
+#define TK_RSHIFT 106
+#define TK_PLUS 107
+#define TK_MINUS 108
+#define TK_STAR 109
+#define TK_SLASH 110
+#define TK_REM 111
+#define TK_CONCAT 112
+#define TK_PTR 113
+#define TK_COLLATE 114
+#define TK_BITNOT 115
+#define TK_ON 116
+#define TK_INDEXED 117
+#define TK_STRING 118
+#define TK_JOIN_KW 119
+#define TK_CONSTRAINT 120
+#define TK_DEFAULT 121
+#define TK_NULL 122
+#define TK_PRIMARY 123
+#define TK_UNIQUE 124
+#define TK_CHECK 125
+#define TK_REFERENCES 126
+#define TK_AUTOINCR 127
+#define TK_INSERT 128
+#define TK_DELETE 129
+#define TK_UPDATE 130
+#define TK_SET 131
+#define TK_DEFERRABLE 132
+#define TK_FOREIGN 133
+#define TK_DROP 134
+#define TK_UNION 135
+#define TK_ALL 136
+#define TK_EXCEPT 137
+#define TK_INTERSECT 138
+#define TK_SELECT 139
+#define TK_VALUES 140
+#define TK_DISTINCT 141
+#define TK_DOT 142
+#define TK_FROM 143
+#define TK_JOIN 144
+#define TK_USING 145
+#define TK_ORDER 146
+#define TK_GROUP 147
+#define TK_HAVING 148
+#define TK_LIMIT 149
+#define TK_WHERE 150
+#define TK_RETURNING 151
+#define TK_INTO 152
+#define TK_NOTHING 153
+#define TK_FLOAT 154
+#define TK_BLOB 155
+#define TK_INTEGER 156
+#define TK_VARIABLE 157
+#define TK_CASE 158
+#define TK_WHEN 159
+#define TK_THEN 160
+#define TK_ELSE 161
+#define TK_INDEX 162
+#define TK_ALTER 163
+#define TK_ADD 164
+#define TK_WINDOW 165
+#define TK_OVER 166
+#define TK_FILTER 167
+#define TK_COLUMN 168
+#define TK_AGG_FUNCTION 169
+#define TK_AGG_COLUMN 170
+#define TK_TRUEFALSE 171
#define TK_FUNCTION 172
#define TK_UPLUS 173
#define TK_UMINUS 174
@@ -172872,7 +175669,8 @@ static void updateDeleteLimitError(
#define TK_ERROR 182
#define TK_QNUMBER 183
#define TK_SPACE 184
-#define TK_ILLEGAL 185
+#define TK_COMMENT 185
+#define TK_ILLEGAL 186
#endif
/**************** End token definitions ***************************************/
@@ -172937,31 +175735,31 @@ static void updateDeleteLimitError(
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned short int
-#define YYNOCODE 322
+#define YYNOCODE 323
#define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 101
+#define YYWILDCARD 102
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
- ExprList* yy14;
- With* yy59;
- Cte* yy67;
- Upsert* yy122;
- IdList* yy132;
- int yy144;
- const char* yy168;
- SrcList* yy203;
- Window* yy211;
- OnOrUsing yy269;
- struct TrigEvent yy286;
- struct {int value; int mask;} yy383;
- u32 yy391;
- TriggerStep* yy427;
- Expr* yy454;
- u8 yy462;
- struct FrameBound yy509;
- Select* yy555;
+ u32 yy9;
+ struct TrigEvent yy28;
+ With* yy125;
+ IdList* yy204;
+ struct FrameBound yy205;
+ TriggerStep* yy319;
+ const char* yy342;
+ Cte* yy361;
+ ExprList* yy402;
+ Upsert* yy403;
+ OnOrUsing yy421;
+ u8 yy444;
+ struct {int value; int mask;} yy481;
+ Window* yy483;
+ int yy502;
+ SrcList* yy563;
+ Expr* yy590;
+ Select* yy637;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -172983,7 +175781,7 @@ typedef union {
#define YYNSTATE 583
#define YYNRULE 409
#define YYNRULE_WITH_ACTION 344
-#define YYNTOKEN 186
+#define YYNTOKEN 187
#define YY_MAX_SHIFT 582
#define YY_MIN_SHIFTREDUCE 845
#define YY_MAX_SHIFTREDUCE 1253
@@ -172992,8 +175790,8 @@ typedef union {
#define YY_NO_ACTION 1256
#define YY_MIN_REDUCE 1257
#define YY_MAX_REDUCE 1665
-#define YY_MIN_DSTRCTR 205
-#define YY_MAX_DSTRCTR 319
+#define YY_MIN_DSTRCTR 206
+#define YY_MAX_DSTRCTR 320
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@@ -173076,569 +175874,582 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (2142)
+#define YY_ACTTAB_COUNT (2207)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 576, 128, 125, 232, 1622, 549, 576, 1290, 1281, 576,
- /* 10 */ 328, 576, 1300, 212, 576, 128, 125, 232, 578, 412,
- /* 20 */ 578, 391, 1542, 51, 51, 523, 405, 1293, 529, 51,
- /* 30 */ 51, 983, 51, 51, 81, 81, 1107, 61, 61, 984,
- /* 40 */ 1107, 1292, 380, 135, 136, 90, 1228, 1228, 1063, 1066,
- /* 50 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 1577, 412,
- /* 60 */ 287, 287, 7, 287, 287, 422, 1050, 1050, 1064, 1067,
- /* 70 */ 289, 556, 492, 573, 524, 561, 573, 497, 561, 482,
- /* 80 */ 530, 262, 229, 135, 136, 90, 1228, 1228, 1063, 1066,
- /* 90 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 128, 125,
- /* 100 */ 232, 1506, 132, 132, 132, 132, 131, 131, 130, 130,
- /* 110 */ 130, 129, 126, 450, 1204, 1255, 1, 1, 582, 2,
- /* 120 */ 1259, 1571, 420, 1582, 379, 320, 1174, 153, 1174, 1584,
- /* 130 */ 412, 378, 1582, 543, 1341, 330, 111, 570, 570, 570,
- /* 140 */ 293, 1054, 132, 132, 132, 132, 131, 131, 130, 130,
- /* 150 */ 130, 129, 126, 450, 135, 136, 90, 1228, 1228, 1063,
- /* 160 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 287,
- /* 170 */ 287, 1204, 1205, 1204, 255, 287, 287, 510, 507, 506,
- /* 180 */ 137, 455, 573, 212, 561, 447, 446, 505, 573, 1616,
- /* 190 */ 561, 134, 134, 134, 134, 127, 400, 243, 132, 132,
- /* 200 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450,
- /* 210 */ 282, 471, 345, 132, 132, 132, 132, 131, 131, 130,
- /* 220 */ 130, 130, 129, 126, 450, 574, 155, 936, 936, 454,
- /* 230 */ 227, 521, 1236, 412, 1236, 134, 134, 134, 134, 132,
- /* 240 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126,
- /* 250 */ 450, 130, 130, 130, 129, 126, 450, 135, 136, 90,
- /* 260 */ 1228, 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134,
- /* 270 */ 134, 134, 128, 125, 232, 450, 576, 412, 397, 1249,
- /* 280 */ 180, 92, 93, 132, 132, 132, 132, 131, 131, 130,
- /* 290 */ 130, 130, 129, 126, 450, 381, 387, 1204, 383, 81,
- /* 300 */ 81, 135, 136, 90, 1228, 1228, 1063, 1066, 1053, 1053,
- /* 310 */ 133, 133, 134, 134, 134, 134, 132, 132, 132, 132,
- /* 320 */ 131, 131, 130, 130, 130, 129, 126, 450, 131, 131,
- /* 330 */ 130, 130, 130, 129, 126, 450, 556, 1204, 302, 319,
- /* 340 */ 567, 121, 568, 480, 4, 555, 1149, 1657, 1628, 1657,
- /* 350 */ 45, 128, 125, 232, 1204, 1205, 1204, 1250, 571, 1169,
- /* 360 */ 132, 132, 132, 132, 131, 131, 130, 130, 130, 129,
- /* 370 */ 126, 450, 1169, 287, 287, 1169, 1019, 576, 422, 1019,
- /* 380 */ 412, 451, 1602, 582, 2, 1259, 573, 44, 561, 95,
- /* 390 */ 320, 110, 153, 565, 1204, 1205, 1204, 522, 522, 1341,
- /* 400 */ 81, 81, 7, 44, 135, 136, 90, 1228, 1228, 1063,
- /* 410 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 295,
- /* 420 */ 1149, 1658, 1040, 1658, 1204, 1147, 319, 567, 119, 119,
- /* 430 */ 343, 466, 331, 343, 287, 287, 120, 556, 451, 577,
- /* 440 */ 451, 1169, 1169, 1028, 319, 567, 438, 573, 210, 561,
- /* 450 */ 1339, 1451, 546, 531, 1169, 1169, 1598, 1169, 1169, 416,
- /* 460 */ 319, 567, 243, 132, 132, 132, 132, 131, 131, 130,
- /* 470 */ 130, 130, 129, 126, 450, 1028, 1028, 1030, 1031, 35,
- /* 480 */ 44, 1204, 1205, 1204, 472, 287, 287, 1328, 412, 1307,
- /* 490 */ 372, 1595, 359, 225, 454, 1204, 195, 1328, 573, 1147,
- /* 500 */ 561, 1333, 1333, 274, 576, 1188, 576, 340, 46, 196,
- /* 510 */ 537, 217, 135, 136, 90, 1228, 1228, 1063, 1066, 1053,
- /* 520 */ 1053, 133, 133, 134, 134, 134, 134, 19, 19, 19,
- /* 530 */ 19, 412, 581, 1204, 1259, 511, 1204, 319, 567, 320,
- /* 540 */ 944, 153, 425, 491, 430, 943, 1204, 488, 1341, 1450,
- /* 550 */ 532, 1277, 1204, 1205, 1204, 135, 136, 90, 1228, 1228,
- /* 560 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
- /* 570 */ 575, 132, 132, 132, 132, 131, 131, 130, 130, 130,
- /* 580 */ 129, 126, 450, 287, 287, 528, 287, 287, 372, 1595,
- /* 590 */ 1204, 1205, 1204, 1204, 1205, 1204, 573, 486, 561, 573,
- /* 600 */ 889, 561, 412, 1204, 1205, 1204, 886, 40, 22, 22,
- /* 610 */ 220, 243, 525, 1449, 132, 132, 132, 132, 131, 131,
- /* 620 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
- /* 630 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
- /* 640 */ 134, 412, 180, 454, 1204, 879, 255, 287, 287, 510,
- /* 650 */ 507, 506, 372, 1595, 1568, 1331, 1331, 576, 889, 505,
- /* 660 */ 573, 44, 561, 559, 1207, 135, 136, 90, 1228, 1228,
- /* 670 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
- /* 680 */ 81, 81, 422, 576, 377, 132, 132, 132, 132, 131,
- /* 690 */ 131, 130, 130, 130, 129, 126, 450, 297, 287, 287,
- /* 700 */ 460, 1204, 1205, 1204, 1204, 534, 19, 19, 448, 448,
- /* 710 */ 448, 573, 412, 561, 230, 436, 1187, 535, 319, 567,
- /* 720 */ 363, 432, 1207, 1435, 132, 132, 132, 132, 131, 131,
- /* 730 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
- /* 740 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
- /* 750 */ 134, 412, 211, 949, 1169, 1041, 1110, 1110, 494, 547,
- /* 760 */ 547, 1204, 1205, 1204, 7, 539, 1570, 1169, 376, 576,
- /* 770 */ 1169, 5, 1204, 486, 3, 135, 136, 90, 1228, 1228,
- /* 780 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
- /* 790 */ 576, 513, 19, 19, 427, 132, 132, 132, 132, 131,
- /* 800 */ 131, 130, 130, 130, 129, 126, 450, 305, 1204, 433,
- /* 810 */ 225, 1204, 385, 19, 19, 273, 290, 371, 516, 366,
- /* 820 */ 515, 260, 412, 538, 1568, 549, 1024, 362, 437, 1204,
- /* 830 */ 1205, 1204, 902, 1552, 132, 132, 132, 132, 131, 131,
- /* 840 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
- /* 850 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
- /* 860 */ 134, 412, 1435, 514, 1281, 1204, 1205, 1204, 1204, 1205,
- /* 870 */ 1204, 903, 48, 342, 1568, 1568, 1279, 1627, 1568, 911,
- /* 880 */ 576, 129, 126, 450, 110, 135, 136, 90, 1228, 1228,
- /* 890 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134,
- /* 900 */ 265, 576, 459, 19, 19, 132, 132, 132, 132, 131,
- /* 910 */ 131, 130, 130, 130, 129, 126, 450, 1345, 204, 576,
- /* 920 */ 459, 458, 50, 47, 19, 19, 49, 434, 1105, 573,
- /* 930 */ 497, 561, 412, 428, 108, 1224, 1569, 1554, 376, 205,
- /* 940 */ 550, 550, 81, 81, 132, 132, 132, 132, 131, 131,
- /* 950 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228,
- /* 960 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
- /* 970 */ 134, 480, 576, 1204, 576, 1541, 412, 1435, 969, 315,
- /* 980 */ 1659, 398, 284, 497, 969, 893, 1569, 1569, 376, 376,
- /* 990 */ 1569, 461, 376, 1224, 459, 80, 80, 81, 81, 497,
- /* 1000 */ 374, 114, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133,
- /* 1010 */ 133, 134, 134, 134, 134, 132, 132, 132, 132, 131,
- /* 1020 */ 131, 130, 130, 130, 129, 126, 450, 1204, 1505, 576,
- /* 1030 */ 1204, 1205, 1204, 1366, 316, 486, 281, 281, 497, 431,
- /* 1040 */ 557, 288, 288, 402, 1340, 471, 345, 298, 429, 573,
- /* 1050 */ 576, 561, 81, 81, 573, 374, 561, 971, 386, 132,
- /* 1060 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126,
- /* 1070 */ 450, 231, 117, 81, 81, 287, 287, 231, 287, 287,
- /* 1080 */ 576, 1511, 576, 1336, 1204, 1205, 1204, 139, 573, 556,
- /* 1090 */ 561, 573, 412, 561, 441, 456, 969, 213, 558, 1511,
- /* 1100 */ 1513, 1550, 969, 143, 143, 145, 145, 1368, 314, 478,
- /* 1110 */ 444, 970, 412, 850, 851, 852, 135, 136, 90, 1228,
- /* 1120 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
- /* 1130 */ 134, 357, 412, 397, 1148, 304, 135, 136, 90, 1228,
- /* 1140 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
- /* 1150 */ 134, 1575, 323, 6, 862, 7, 135, 124, 90, 1228,
- /* 1160 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134,
- /* 1170 */ 134, 409, 408, 1511, 212, 132, 132, 132, 132, 131,
- /* 1180 */ 131, 130, 130, 130, 129, 126, 450, 411, 118, 1204,
- /* 1190 */ 116, 10, 352, 265, 355, 132, 132, 132, 132, 131,
- /* 1200 */ 131, 130, 130, 130, 129, 126, 450, 576, 324, 306,
- /* 1210 */ 576, 306, 1250, 469, 158, 132, 132, 132, 132, 131,
- /* 1220 */ 131, 130, 130, 130, 129, 126, 450, 207, 1224, 1126,
- /* 1230 */ 65, 65, 470, 66, 66, 412, 447, 446, 882, 531,
- /* 1240 */ 335, 258, 257, 256, 1127, 1233, 1204, 1205, 1204, 327,
- /* 1250 */ 1235, 874, 159, 576, 16, 480, 1085, 1040, 1234, 1128,
- /* 1260 */ 136, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133, 133,
- /* 1270 */ 134, 134, 134, 134, 1029, 576, 81, 81, 1028, 1040,
- /* 1280 */ 922, 576, 463, 1236, 576, 1236, 1224, 502, 107, 1435,
- /* 1290 */ 923, 6, 576, 410, 1498, 882, 1029, 480, 21, 21,
- /* 1300 */ 1028, 332, 1380, 334, 53, 53, 497, 81, 81, 874,
- /* 1310 */ 1028, 1028, 1030, 445, 259, 19, 19, 533, 132, 132,
- /* 1320 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450,
- /* 1330 */ 551, 301, 1028, 1028, 1030, 107, 532, 545, 121, 568,
- /* 1340 */ 1188, 4, 1126, 1576, 449, 576, 462, 7, 1282, 418,
- /* 1350 */ 462, 350, 1435, 576, 518, 571, 544, 1127, 121, 568,
- /* 1360 */ 442, 4, 1188, 464, 533, 1180, 1223, 9, 67, 67,
- /* 1370 */ 487, 576, 1128, 303, 410, 571, 54, 54, 451, 576,
- /* 1380 */ 123, 944, 576, 417, 576, 333, 943, 1379, 576, 236,
- /* 1390 */ 565, 576, 1574, 564, 68, 68, 7, 576, 451, 362,
- /* 1400 */ 419, 182, 69, 69, 541, 70, 70, 71, 71, 540,
- /* 1410 */ 565, 72, 72, 484, 55, 55, 473, 1180, 296, 1040,
- /* 1420 */ 56, 56, 296, 493, 541, 119, 119, 410, 1573, 542,
- /* 1430 */ 569, 418, 7, 120, 1244, 451, 577, 451, 465, 1040,
- /* 1440 */ 1028, 576, 1557, 552, 476, 119, 119, 527, 259, 121,
- /* 1450 */ 568, 240, 4, 120, 576, 451, 577, 451, 576, 477,
- /* 1460 */ 1028, 576, 156, 576, 57, 57, 571, 576, 286, 229,
- /* 1470 */ 410, 336, 1028, 1028, 1030, 1031, 35, 59, 59, 219,
- /* 1480 */ 983, 60, 60, 220, 73, 73, 74, 74, 984, 451,
- /* 1490 */ 75, 75, 1028, 1028, 1030, 1031, 35, 96, 216, 291,
- /* 1500 */ 552, 565, 1188, 318, 395, 395, 394, 276, 392, 576,
- /* 1510 */ 485, 859, 474, 1311, 410, 541, 576, 417, 1530, 1144,
- /* 1520 */ 540, 399, 1188, 292, 237, 1153, 326, 38, 23, 576,
- /* 1530 */ 1040, 576, 20, 20, 325, 299, 119, 119, 164, 76,
- /* 1540 */ 76, 1529, 121, 568, 120, 4, 451, 577, 451, 203,
- /* 1550 */ 576, 1028, 141, 141, 142, 142, 576, 322, 39, 571,
- /* 1560 */ 341, 1021, 110, 264, 239, 901, 900, 423, 242, 908,
- /* 1570 */ 909, 370, 173, 77, 77, 43, 479, 1310, 264, 62,
- /* 1580 */ 62, 369, 451, 1028, 1028, 1030, 1031, 35, 1601, 1192,
- /* 1590 */ 453, 1092, 238, 291, 565, 163, 1309, 110, 395, 395,
- /* 1600 */ 394, 276, 392, 986, 987, 859, 481, 346, 264, 110,
- /* 1610 */ 1032, 489, 576, 1188, 503, 1088, 261, 261, 237, 576,
- /* 1620 */ 326, 121, 568, 1040, 4, 347, 1376, 413, 325, 119,
- /* 1630 */ 119, 948, 319, 567, 351, 78, 78, 120, 571, 451,
- /* 1640 */ 577, 451, 79, 79, 1028, 354, 356, 576, 360, 1092,
- /* 1650 */ 110, 576, 974, 942, 264, 123, 457, 358, 239, 576,
- /* 1660 */ 519, 451, 939, 1104, 123, 1104, 173, 576, 1032, 43,
- /* 1670 */ 63, 63, 1324, 565, 168, 168, 1028, 1028, 1030, 1031,
- /* 1680 */ 35, 576, 169, 169, 1308, 872, 238, 157, 1589, 576,
- /* 1690 */ 86, 86, 365, 89, 568, 375, 4, 1103, 941, 1103,
- /* 1700 */ 123, 576, 1040, 1389, 64, 64, 1188, 1434, 119, 119,
- /* 1710 */ 571, 576, 82, 82, 563, 576, 120, 165, 451, 577,
- /* 1720 */ 451, 413, 1362, 1028, 144, 144, 319, 567, 576, 1374,
- /* 1730 */ 562, 498, 279, 451, 83, 83, 1439, 576, 166, 166,
- /* 1740 */ 576, 1289, 554, 576, 1280, 565, 576, 12, 576, 1268,
- /* 1750 */ 457, 146, 146, 1267, 576, 1028, 1028, 1030, 1031, 35,
- /* 1760 */ 140, 140, 1269, 167, 167, 1609, 160, 160, 1359, 150,
- /* 1770 */ 150, 149, 149, 311, 1040, 576, 312, 147, 147, 313,
- /* 1780 */ 119, 119, 222, 235, 576, 1188, 396, 576, 120, 576,
- /* 1790 */ 451, 577, 451, 1192, 453, 1028, 508, 291, 148, 148,
- /* 1800 */ 1421, 1612, 395, 395, 394, 276, 392, 85, 85, 859,
- /* 1810 */ 87, 87, 84, 84, 553, 576, 294, 576, 1426, 338,
- /* 1820 */ 339, 1425, 237, 300, 326, 1416, 1409, 1028, 1028, 1030,
- /* 1830 */ 1031, 35, 325, 344, 403, 483, 226, 1307, 52, 52,
- /* 1840 */ 58, 58, 368, 1371, 1502, 566, 1501, 121, 568, 221,
- /* 1850 */ 4, 208, 268, 209, 390, 1244, 1549, 1188, 1372, 1370,
- /* 1860 */ 1369, 1547, 239, 184, 571, 233, 421, 1241, 95, 218,
- /* 1870 */ 173, 1507, 193, 43, 91, 94, 178, 186, 467, 188,
- /* 1880 */ 468, 1422, 13, 189, 190, 191, 501, 451, 245, 108,
- /* 1890 */ 238, 401, 1428, 1427, 1430, 475, 404, 1496, 197, 565,
- /* 1900 */ 14, 490, 249, 101, 1518, 496, 349, 280, 251, 201,
- /* 1910 */ 353, 499, 252, 406, 1270, 253, 517, 1327, 1326, 435,
- /* 1920 */ 1325, 1318, 103, 893, 1296, 413, 227, 407, 1040, 1626,
- /* 1930 */ 319, 567, 1625, 1297, 119, 119, 439, 367, 1317, 1295,
- /* 1940 */ 1624, 526, 120, 440, 451, 577, 451, 1594, 309, 1028,
- /* 1950 */ 310, 373, 266, 267, 457, 1580, 1579, 443, 138, 1394,
- /* 1960 */ 552, 1393, 11, 1483, 384, 115, 317, 1350, 109, 536,
- /* 1970 */ 42, 579, 382, 214, 1349, 388, 1198, 389, 275, 277,
- /* 1980 */ 278, 1028, 1028, 1030, 1031, 35, 580, 1265, 414, 1260,
- /* 1990 */ 170, 415, 183, 1534, 1535, 1533, 171, 154, 307, 1532,
- /* 2000 */ 846, 223, 224, 88, 452, 215, 172, 321, 234, 1102,
- /* 2010 */ 152, 1188, 1100, 329, 185, 174, 1223, 925, 187, 241,
- /* 2020 */ 337, 244, 1116, 192, 175, 176, 424, 426, 97, 194,
- /* 2030 */ 98, 99, 100, 177, 1119, 1115, 246, 247, 161, 24,
- /* 2040 */ 248, 348, 1238, 264, 1108, 250, 495, 199, 198, 15,
- /* 2050 */ 861, 500, 369, 254, 504, 509, 512, 200, 102, 25,
- /* 2060 */ 179, 361, 26, 364, 104, 891, 308, 162, 105, 904,
- /* 2070 */ 520, 106, 1185, 1069, 1155, 17, 228, 27, 1154, 283,
- /* 2080 */ 285, 263, 978, 202, 972, 123, 28, 1175, 29, 30,
- /* 2090 */ 1179, 1171, 31, 1173, 1160, 41, 32, 206, 548, 33,
- /* 2100 */ 110, 1178, 1083, 8, 112, 1070, 113, 1068, 1072, 34,
- /* 2110 */ 1073, 560, 1125, 269, 1124, 270, 36, 18, 1194, 1033,
- /* 2120 */ 873, 151, 122, 37, 393, 271, 272, 572, 181, 1193,
- /* 2130 */ 1256, 1256, 1256, 935, 1256, 1256, 1256, 1256, 1256, 1256,
- /* 2140 */ 1256, 1617,
+ /* 0 */ 130, 127, 234, 282, 282, 1328, 576, 1307, 460, 289,
+ /* 10 */ 289, 576, 1622, 381, 576, 1328, 573, 576, 562, 413,
+ /* 20 */ 1300, 1542, 573, 481, 562, 524, 460, 459, 558, 82,
+ /* 30 */ 82, 983, 294, 375, 51, 51, 498, 61, 61, 984,
+ /* 40 */ 82, 82, 1577, 137, 138, 91, 7, 1228, 1228, 1063,
+ /* 50 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 413,
+ /* 60 */ 288, 288, 182, 288, 288, 481, 536, 288, 288, 130,
+ /* 70 */ 127, 234, 432, 573, 525, 562, 573, 557, 562, 1290,
+ /* 80 */ 573, 421, 562, 137, 138, 91, 559, 1228, 1228, 1063,
+ /* 90 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 296,
+ /* 100 */ 460, 398, 1249, 134, 134, 134, 134, 133, 133, 132,
+ /* 110 */ 132, 132, 131, 128, 451, 451, 1050, 1050, 1064, 1067,
+ /* 120 */ 1255, 1, 1, 582, 2, 1259, 581, 1174, 1259, 1174,
+ /* 130 */ 321, 413, 155, 321, 1584, 155, 379, 112, 481, 1341,
+ /* 140 */ 456, 299, 1341, 134, 134, 134, 134, 133, 133, 132,
+ /* 150 */ 132, 132, 131, 128, 451, 137, 138, 91, 498, 1228,
+ /* 160 */ 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136,
+ /* 170 */ 136, 1204, 862, 1281, 288, 288, 283, 288, 288, 523,
+ /* 180 */ 523, 1250, 139, 578, 7, 578, 1345, 573, 1169, 562,
+ /* 190 */ 573, 1054, 562, 136, 136, 136, 136, 129, 573, 547,
+ /* 200 */ 562, 1169, 245, 1541, 1169, 245, 133, 133, 132, 132,
+ /* 210 */ 132, 131, 128, 451, 302, 134, 134, 134, 134, 133,
+ /* 220 */ 133, 132, 132, 132, 131, 128, 451, 1575, 1204, 1205,
+ /* 230 */ 1204, 7, 470, 550, 455, 413, 550, 455, 130, 127,
+ /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132,
+ /* 250 */ 131, 128, 451, 136, 136, 136, 136, 538, 483, 137,
+ /* 260 */ 138, 91, 1019, 1228, 1228, 1063, 1066, 1053, 1053, 135,
+ /* 270 */ 135, 136, 136, 136, 136, 1085, 576, 1204, 132, 132,
+ /* 280 */ 132, 131, 128, 451, 93, 214, 134, 134, 134, 134,
+ /* 290 */ 133, 133, 132, 132, 132, 131, 128, 451, 401, 19,
+ /* 300 */ 19, 134, 134, 134, 134, 133, 133, 132, 132, 132,
+ /* 310 */ 131, 128, 451, 1498, 426, 267, 344, 467, 332, 134,
+ /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128,
+ /* 330 */ 451, 1281, 576, 6, 1204, 1205, 1204, 257, 576, 413,
+ /* 340 */ 511, 508, 507, 1279, 94, 1019, 464, 1204, 551, 551,
+ /* 350 */ 506, 1224, 1571, 44, 38, 51, 51, 411, 576, 413,
+ /* 360 */ 45, 51, 51, 137, 138, 91, 530, 1228, 1228, 1063,
+ /* 370 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 398,
+ /* 380 */ 1148, 82, 82, 137, 138, 91, 39, 1228, 1228, 1063,
+ /* 390 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 344,
+ /* 400 */ 44, 288, 288, 375, 1204, 1205, 1204, 209, 1204, 1224,
+ /* 410 */ 320, 567, 471, 576, 573, 576, 562, 576, 316, 264,
+ /* 420 */ 231, 46, 160, 134, 134, 134, 134, 133, 133, 132,
+ /* 430 */ 132, 132, 131, 128, 451, 303, 82, 82, 82, 82,
+ /* 440 */ 82, 82, 442, 134, 134, 134, 134, 133, 133, 132,
+ /* 450 */ 132, 132, 131, 128, 451, 1582, 544, 320, 567, 1250,
+ /* 460 */ 874, 1582, 380, 382, 413, 1204, 1205, 1204, 360, 182,
+ /* 470 */ 288, 288, 1576, 557, 1339, 557, 7, 557, 1277, 472,
+ /* 480 */ 346, 526, 531, 573, 556, 562, 439, 1511, 137, 138,
+ /* 490 */ 91, 219, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135,
+ /* 500 */ 136, 136, 136, 136, 465, 1511, 1513, 532, 413, 288,
+ /* 510 */ 288, 423, 512, 288, 288, 411, 288, 288, 874, 130,
+ /* 520 */ 127, 234, 573, 1107, 562, 1204, 573, 1107, 562, 573,
+ /* 530 */ 560, 562, 137, 138, 91, 1293, 1228, 1228, 1063, 1066,
+ /* 540 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 134, 134,
+ /* 550 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451,
+ /* 560 */ 493, 503, 1292, 1204, 257, 288, 288, 511, 508, 507,
+ /* 570 */ 1204, 1628, 1169, 123, 568, 275, 4, 506, 573, 1511,
+ /* 580 */ 562, 331, 1204, 1205, 1204, 1169, 548, 548, 1169, 261,
+ /* 590 */ 571, 7, 134, 134, 134, 134, 133, 133, 132, 132,
+ /* 600 */ 132, 131, 128, 451, 108, 533, 130, 127, 234, 1204,
+ /* 610 */ 448, 447, 413, 1451, 452, 983, 886, 96, 1598, 1233,
+ /* 620 */ 1204, 1205, 1204, 984, 1235, 1450, 565, 1204, 1205, 1204,
+ /* 630 */ 229, 522, 1234, 534, 1333, 1333, 137, 138, 91, 1449,
+ /* 640 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
+ /* 650 */ 136, 136, 373, 1595, 971, 1040, 413, 1236, 418, 1236,
+ /* 660 */ 879, 121, 121, 948, 373, 1595, 1204, 1205, 1204, 122,
+ /* 670 */ 1204, 452, 577, 452, 363, 417, 1028, 882, 373, 1595,
+ /* 680 */ 137, 138, 91, 462, 1228, 1228, 1063, 1066, 1053, 1053,
+ /* 690 */ 135, 135, 136, 136, 136, 136, 134, 134, 134, 134,
+ /* 700 */ 133, 133, 132, 132, 132, 131, 128, 451, 1028, 1028,
+ /* 710 */ 1030, 1031, 35, 570, 570, 570, 197, 423, 1040, 198,
+ /* 720 */ 1204, 123, 568, 1204, 4, 320, 567, 1204, 1205, 1204,
+ /* 730 */ 40, 388, 576, 384, 882, 1029, 423, 1188, 571, 1028,
+ /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
+ /* 750 */ 128, 451, 529, 1568, 1204, 19, 19, 1204, 575, 492,
+ /* 760 */ 413, 157, 452, 489, 1187, 1331, 1331, 5, 1204, 949,
+ /* 770 */ 431, 1028, 1028, 1030, 565, 22, 22, 1204, 1205, 1204,
+ /* 780 */ 1204, 1205, 1204, 477, 137, 138, 91, 212, 1228, 1228,
+ /* 790 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
+ /* 800 */ 1188, 48, 111, 1040, 413, 1204, 213, 970, 1041, 121,
+ /* 810 */ 121, 1204, 1205, 1204, 1204, 1205, 1204, 122, 221, 452,
+ /* 820 */ 577, 452, 44, 487, 1028, 1204, 1205, 1204, 137, 138,
+ /* 830 */ 91, 378, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135,
+ /* 840 */ 136, 136, 136, 136, 134, 134, 134, 134, 133, 133,
+ /* 850 */ 132, 132, 132, 131, 128, 451, 1028, 1028, 1030, 1031,
+ /* 860 */ 35, 461, 1204, 1205, 1204, 1569, 1040, 377, 214, 1149,
+ /* 870 */ 1657, 535, 1657, 437, 902, 320, 567, 1568, 364, 320,
+ /* 880 */ 567, 412, 329, 1029, 519, 1188, 3, 1028, 134, 134,
+ /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451,
+ /* 900 */ 1659, 399, 1169, 307, 893, 307, 515, 576, 413, 214,
+ /* 910 */ 498, 944, 1024, 540, 903, 1169, 943, 392, 1169, 1028,
+ /* 920 */ 1028, 1030, 406, 298, 1204, 50, 1149, 1658, 413, 1658,
+ /* 930 */ 145, 145, 137, 138, 91, 293, 1228, 1228, 1063, 1066,
+ /* 940 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 1188, 1147,
+ /* 950 */ 514, 1568, 137, 138, 91, 1505, 1228, 1228, 1063, 1066,
+ /* 960 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 434, 323,
+ /* 970 */ 435, 539, 111, 1506, 274, 291, 372, 517, 367, 516,
+ /* 980 */ 262, 1204, 1205, 1204, 1574, 481, 363, 576, 7, 1569,
+ /* 990 */ 1568, 377, 134, 134, 134, 134, 133, 133, 132, 132,
+ /* 1000 */ 132, 131, 128, 451, 1568, 576, 1147, 576, 232, 576,
+ /* 1010 */ 19, 19, 134, 134, 134, 134, 133, 133, 132, 132,
+ /* 1020 */ 132, 131, 128, 451, 1169, 433, 576, 1207, 19, 19,
+ /* 1030 */ 19, 19, 19, 19, 1627, 576, 911, 1169, 47, 120,
+ /* 1040 */ 1169, 117, 413, 306, 498, 438, 1125, 206, 336, 19,
+ /* 1050 */ 19, 1435, 49, 449, 449, 449, 1368, 315, 81, 81,
+ /* 1060 */ 576, 304, 413, 1570, 207, 377, 137, 138, 91, 115,
+ /* 1070 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
+ /* 1080 */ 136, 136, 576, 82, 82, 1207, 137, 138, 91, 1340,
+ /* 1090 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136,
+ /* 1100 */ 136, 136, 1569, 386, 377, 82, 82, 463, 1126, 1552,
+ /* 1110 */ 333, 463, 335, 131, 128, 451, 1569, 161, 377, 16,
+ /* 1120 */ 317, 387, 428, 1127, 448, 447, 134, 134, 134, 134,
+ /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 451, 1128, 576,
+ /* 1140 */ 1105, 10, 445, 267, 576, 1554, 134, 134, 134, 134,
+ /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 451, 532, 576,
+ /* 1160 */ 922, 576, 19, 19, 576, 1573, 576, 147, 147, 7,
+ /* 1170 */ 923, 1236, 498, 1236, 576, 487, 413, 552, 285, 1224,
+ /* 1180 */ 969, 215, 82, 82, 66, 66, 1435, 67, 67, 21,
+ /* 1190 */ 21, 1110, 1110, 495, 334, 297, 413, 53, 53, 297,
+ /* 1200 */ 137, 138, 91, 119, 1228, 1228, 1063, 1066, 1053, 1053,
+ /* 1210 */ 135, 135, 136, 136, 136, 136, 413, 1336, 1311, 446,
+ /* 1220 */ 137, 138, 91, 227, 1228, 1228, 1063, 1066, 1053, 1053,
+ /* 1230 */ 135, 135, 136, 136, 136, 136, 574, 1224, 936, 936,
+ /* 1240 */ 137, 126, 91, 141, 1228, 1228, 1063, 1066, 1053, 1053,
+ /* 1250 */ 135, 135, 136, 136, 136, 136, 533, 429, 472, 346,
+ /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
+ /* 1270 */ 128, 451, 576, 457, 233, 343, 1435, 403, 498, 1550,
+ /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
+ /* 1290 */ 128, 451, 576, 324, 576, 82, 82, 487, 576, 969,
+ /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131,
+ /* 1310 */ 128, 451, 288, 288, 546, 68, 68, 54, 54, 553,
+ /* 1320 */ 413, 69, 69, 351, 6, 573, 944, 562, 410, 409,
+ /* 1330 */ 1435, 943, 450, 545, 260, 259, 258, 576, 158, 576,
+ /* 1340 */ 413, 222, 1180, 479, 969, 138, 91, 430, 1228, 1228,
+ /* 1350 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
+ /* 1360 */ 70, 70, 71, 71, 576, 1126, 91, 576, 1228, 1228,
+ /* 1370 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136,
+ /* 1380 */ 1127, 166, 850, 851, 852, 1282, 419, 72, 72, 108,
+ /* 1390 */ 73, 73, 1310, 358, 1180, 1128, 576, 305, 576, 123,
+ /* 1400 */ 568, 494, 4, 488, 134, 134, 134, 134, 133, 133,
+ /* 1410 */ 132, 132, 132, 131, 128, 451, 571, 564, 534, 55,
+ /* 1420 */ 55, 56, 56, 576, 134, 134, 134, 134, 133, 133,
+ /* 1430 */ 132, 132, 132, 131, 128, 451, 576, 1104, 233, 1104,
+ /* 1440 */ 452, 1602, 582, 2, 1259, 576, 57, 57, 576, 321,
+ /* 1450 */ 576, 155, 565, 1435, 485, 353, 576, 356, 1341, 59,
+ /* 1460 */ 59, 576, 44, 969, 569, 419, 576, 238, 60, 60,
+ /* 1470 */ 261, 74, 74, 75, 75, 287, 231, 576, 1366, 76,
+ /* 1480 */ 76, 1040, 420, 184, 20, 20, 576, 121, 121, 77,
+ /* 1490 */ 77, 97, 218, 288, 288, 122, 125, 452, 577, 452,
+ /* 1500 */ 143, 143, 1028, 576, 520, 576, 573, 576, 562, 144,
+ /* 1510 */ 144, 474, 227, 1244, 478, 123, 568, 576, 4, 320,
+ /* 1520 */ 567, 245, 411, 576, 443, 411, 78, 78, 62, 62,
+ /* 1530 */ 79, 79, 571, 319, 1028, 1028, 1030, 1031, 35, 418,
+ /* 1540 */ 63, 63, 576, 290, 411, 9, 80, 80, 1144, 576,
+ /* 1550 */ 400, 576, 486, 455, 576, 1223, 452, 576, 325, 342,
+ /* 1560 */ 576, 111, 576, 1188, 242, 64, 64, 473, 565, 576,
+ /* 1570 */ 23, 576, 170, 170, 171, 171, 576, 87, 87, 328,
+ /* 1580 */ 65, 65, 542, 83, 83, 146, 146, 541, 123, 568,
+ /* 1590 */ 341, 4, 84, 84, 168, 168, 576, 1040, 576, 148,
+ /* 1600 */ 148, 576, 1380, 121, 121, 571, 1021, 576, 266, 576,
+ /* 1610 */ 424, 122, 576, 452, 577, 452, 576, 553, 1028, 142,
+ /* 1620 */ 142, 169, 169, 576, 162, 162, 528, 889, 371, 452,
+ /* 1630 */ 152, 152, 151, 151, 1379, 149, 149, 109, 370, 150,
+ /* 1640 */ 150, 565, 576, 480, 576, 266, 86, 86, 576, 1092,
+ /* 1650 */ 1028, 1028, 1030, 1031, 35, 542, 482, 576, 266, 466,
+ /* 1660 */ 543, 123, 568, 1616, 4, 88, 88, 85, 85, 475,
+ /* 1670 */ 1040, 52, 52, 222, 901, 900, 121, 121, 571, 1188,
+ /* 1680 */ 58, 58, 244, 1032, 122, 889, 452, 577, 452, 908,
+ /* 1690 */ 909, 1028, 300, 347, 504, 111, 263, 361, 165, 111,
+ /* 1700 */ 111, 1088, 452, 263, 974, 1153, 266, 1092, 986, 987,
+ /* 1710 */ 942, 939, 125, 125, 565, 1103, 872, 1103, 159, 941,
+ /* 1720 */ 1309, 125, 1557, 1028, 1028, 1030, 1031, 35, 542, 337,
+ /* 1730 */ 1530, 205, 1529, 541, 499, 1589, 490, 348, 1376, 352,
+ /* 1740 */ 355, 1032, 357, 1040, 359, 1324, 1308, 366, 563, 121,
+ /* 1750 */ 121, 376, 1188, 1389, 1434, 1362, 280, 122, 1374, 452,
+ /* 1760 */ 577, 452, 167, 1439, 1028, 1289, 1280, 1268, 1267, 1269,
+ /* 1770 */ 1609, 1359, 312, 313, 314, 397, 12, 237, 224, 1421,
+ /* 1780 */ 295, 1416, 1409, 1426, 339, 484, 340, 509, 1371, 1612,
+ /* 1790 */ 1372, 1425, 1244, 404, 301, 228, 1028, 1028, 1030, 1031,
+ /* 1800 */ 35, 1601, 1192, 454, 345, 1307, 292, 369, 1502, 1501,
+ /* 1810 */ 270, 396, 396, 395, 277, 393, 1370, 1369, 859, 1549,
+ /* 1820 */ 186, 123, 568, 235, 4, 1188, 391, 210, 211, 223,
+ /* 1830 */ 1547, 239, 1241, 327, 422, 96, 220, 195, 571, 180,
+ /* 1840 */ 188, 326, 468, 469, 190, 191, 502, 192, 193, 566,
+ /* 1850 */ 247, 109, 1430, 491, 199, 251, 102, 281, 402, 476,
+ /* 1860 */ 405, 1496, 452, 497, 253, 1422, 13, 1428, 14, 1427,
+ /* 1870 */ 203, 1507, 241, 500, 565, 354, 407, 92, 95, 1270,
+ /* 1880 */ 175, 254, 518, 43, 1327, 255, 1326, 1325, 436, 1518,
+ /* 1890 */ 350, 1318, 104, 229, 893, 1626, 440, 441, 1625, 408,
+ /* 1900 */ 240, 1296, 268, 1040, 310, 269, 1297, 527, 444, 121,
+ /* 1910 */ 121, 368, 1295, 1594, 1624, 311, 1394, 122, 1317, 452,
+ /* 1920 */ 577, 452, 374, 1580, 1028, 1393, 140, 553, 11, 90,
+ /* 1930 */ 568, 385, 4, 116, 318, 414, 1579, 110, 1483, 537,
+ /* 1940 */ 320, 567, 1350, 555, 42, 579, 571, 1349, 1198, 383,
+ /* 1950 */ 276, 390, 216, 389, 278, 279, 1028, 1028, 1030, 1031,
+ /* 1960 */ 35, 172, 580, 1265, 458, 1260, 415, 416, 185, 156,
+ /* 1970 */ 452, 1534, 1535, 173, 1533, 1532, 89, 308, 225, 226,
+ /* 1980 */ 846, 174, 565, 453, 217, 1188, 322, 236, 1102, 154,
+ /* 1990 */ 1100, 330, 187, 176, 1223, 243, 189, 925, 338, 246,
+ /* 2000 */ 1116, 194, 177, 425, 178, 427, 98, 196, 99, 100,
+ /* 2010 */ 101, 1040, 179, 1119, 1115, 248, 249, 121, 121, 163,
+ /* 2020 */ 24, 250, 349, 1238, 496, 122, 1108, 452, 577, 452,
+ /* 2030 */ 1192, 454, 1028, 266, 292, 200, 252, 201, 861, 396,
+ /* 2040 */ 396, 395, 277, 393, 15, 501, 859, 370, 292, 256,
+ /* 2050 */ 202, 554, 505, 396, 396, 395, 277, 393, 103, 239,
+ /* 2060 */ 859, 327, 25, 26, 1028, 1028, 1030, 1031, 35, 326,
+ /* 2070 */ 362, 510, 891, 239, 365, 327, 513, 904, 105, 309,
+ /* 2080 */ 164, 181, 27, 326, 106, 521, 107, 1185, 1069, 1155,
+ /* 2090 */ 17, 1154, 230, 1188, 284, 286, 265, 204, 125, 1171,
+ /* 2100 */ 241, 28, 978, 972, 29, 41, 1175, 1179, 175, 1173,
+ /* 2110 */ 30, 43, 31, 8, 241, 1178, 32, 1160, 208, 549,
+ /* 2120 */ 33, 111, 175, 1083, 1070, 43, 1068, 1072, 240, 113,
+ /* 2130 */ 114, 34, 561, 118, 1124, 271, 1073, 36, 18, 572,
+ /* 2140 */ 1033, 873, 240, 124, 37, 935, 272, 273, 1617, 183,
+ /* 2150 */ 153, 394, 1194, 1193, 1256, 1256, 1256, 1256, 1256, 1256,
+ /* 2160 */ 1256, 1256, 1256, 414, 1256, 1256, 1256, 1256, 320, 567,
+ /* 2170 */ 1256, 1256, 1256, 1256, 1256, 1256, 1256, 414, 1256, 1256,
+ /* 2180 */ 1256, 1256, 320, 567, 1256, 1256, 1256, 1256, 1256, 1256,
+ /* 2190 */ 1256, 1256, 458, 1256, 1256, 1256, 1256, 1256, 1256, 1256,
+ /* 2200 */ 1256, 1256, 1256, 1256, 1256, 1256, 458,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 194, 276, 277, 278, 216, 194, 194, 217, 194, 194,
- /* 10 */ 194, 194, 224, 194, 194, 276, 277, 278, 204, 19,
- /* 20 */ 206, 202, 297, 217, 218, 205, 207, 217, 205, 217,
- /* 30 */ 218, 31, 217, 218, 217, 218, 29, 217, 218, 39,
- /* 40 */ 33, 217, 220, 43, 44, 45, 46, 47, 48, 49,
- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 312, 19,
- /* 60 */ 240, 241, 316, 240, 241, 194, 46, 47, 48, 49,
- /* 70 */ 22, 254, 65, 253, 254, 255, 253, 194, 255, 194,
- /* 80 */ 263, 258, 259, 43, 44, 45, 46, 47, 48, 49,
- /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 276, 277,
- /* 100 */ 278, 285, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 110 */ 110, 111, 112, 113, 59, 186, 187, 188, 189, 190,
- /* 120 */ 191, 310, 239, 317, 318, 196, 86, 198, 88, 317,
- /* 130 */ 19, 319, 317, 318, 205, 264, 25, 211, 212, 213,
- /* 140 */ 205, 121, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 150 */ 110, 111, 112, 113, 43, 44, 45, 46, 47, 48,
- /* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 240,
- /* 170 */ 241, 116, 117, 118, 119, 240, 241, 122, 123, 124,
- /* 180 */ 69, 298, 253, 194, 255, 106, 107, 132, 253, 141,
- /* 190 */ 255, 54, 55, 56, 57, 58, 207, 268, 102, 103,
- /* 200 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
- /* 210 */ 214, 128, 129, 102, 103, 104, 105, 106, 107, 108,
- /* 220 */ 109, 110, 111, 112, 113, 134, 25, 136, 137, 300,
- /* 230 */ 165, 166, 153, 19, 155, 54, 55, 56, 57, 102,
- /* 240 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- /* 250 */ 113, 108, 109, 110, 111, 112, 113, 43, 44, 45,
- /* 260 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 270 */ 56, 57, 276, 277, 278, 113, 194, 19, 22, 23,
- /* 280 */ 194, 67, 24, 102, 103, 104, 105, 106, 107, 108,
- /* 290 */ 109, 110, 111, 112, 113, 220, 250, 59, 252, 217,
- /* 300 */ 218, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 310 */ 52, 53, 54, 55, 56, 57, 102, 103, 104, 105,
- /* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 106, 107,
- /* 330 */ 108, 109, 110, 111, 112, 113, 254, 59, 205, 138,
- /* 340 */ 139, 19, 20, 194, 22, 263, 22, 23, 231, 25,
- /* 350 */ 72, 276, 277, 278, 116, 117, 118, 101, 36, 76,
- /* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- /* 370 */ 112, 113, 89, 240, 241, 92, 73, 194, 194, 73,
- /* 380 */ 19, 59, 188, 189, 190, 191, 253, 81, 255, 151,
- /* 390 */ 196, 25, 198, 71, 116, 117, 118, 311, 312, 205,
- /* 400 */ 217, 218, 316, 81, 43, 44, 45, 46, 47, 48,
- /* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 270,
- /* 420 */ 22, 23, 100, 25, 59, 101, 138, 139, 106, 107,
- /* 430 */ 127, 128, 129, 127, 240, 241, 114, 254, 116, 117,
- /* 440 */ 118, 76, 76, 121, 138, 139, 263, 253, 264, 255,
- /* 450 */ 205, 275, 87, 19, 89, 89, 194, 92, 92, 199,
- /* 460 */ 138, 139, 268, 102, 103, 104, 105, 106, 107, 108,
- /* 470 */ 109, 110, 111, 112, 113, 153, 154, 155, 156, 157,
- /* 480 */ 81, 116, 117, 118, 129, 240, 241, 224, 19, 226,
- /* 490 */ 314, 315, 23, 25, 300, 59, 22, 234, 253, 101,
- /* 500 */ 255, 236, 237, 26, 194, 183, 194, 152, 72, 22,
- /* 510 */ 145, 150, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 520 */ 51, 52, 53, 54, 55, 56, 57, 217, 218, 217,
- /* 530 */ 218, 19, 189, 59, 191, 23, 59, 138, 139, 196,
- /* 540 */ 135, 198, 232, 283, 232, 140, 59, 287, 205, 275,
- /* 550 */ 116, 205, 116, 117, 118, 43, 44, 45, 46, 47,
- /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 570 */ 194, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- /* 580 */ 111, 112, 113, 240, 241, 194, 240, 241, 314, 315,
- /* 590 */ 116, 117, 118, 116, 117, 118, 253, 194, 255, 253,
- /* 600 */ 59, 255, 19, 116, 117, 118, 23, 22, 217, 218,
- /* 610 */ 142, 268, 205, 275, 102, 103, 104, 105, 106, 107,
- /* 620 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
- /* 630 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 640 */ 57, 19, 194, 300, 59, 23, 119, 240, 241, 122,
- /* 650 */ 123, 124, 314, 315, 194, 236, 237, 194, 117, 132,
- /* 660 */ 253, 81, 255, 205, 59, 43, 44, 45, 46, 47,
- /* 670 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 680 */ 217, 218, 194, 194, 194, 102, 103, 104, 105, 106,
- /* 690 */ 107, 108, 109, 110, 111, 112, 113, 294, 240, 241,
- /* 700 */ 120, 116, 117, 118, 59, 194, 217, 218, 211, 212,
- /* 710 */ 213, 253, 19, 255, 194, 19, 23, 254, 138, 139,
- /* 720 */ 24, 232, 117, 194, 102, 103, 104, 105, 106, 107,
- /* 730 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
- /* 740 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 750 */ 57, 19, 264, 108, 76, 23, 127, 128, 129, 311,
- /* 760 */ 312, 116, 117, 118, 316, 87, 306, 89, 308, 194,
- /* 770 */ 92, 22, 59, 194, 22, 43, 44, 45, 46, 47,
- /* 780 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 790 */ 194, 95, 217, 218, 265, 102, 103, 104, 105, 106,
- /* 800 */ 107, 108, 109, 110, 111, 112, 113, 232, 59, 113,
- /* 810 */ 25, 59, 194, 217, 218, 119, 120, 121, 122, 123,
- /* 820 */ 124, 125, 19, 145, 194, 194, 23, 131, 232, 116,
- /* 830 */ 117, 118, 35, 194, 102, 103, 104, 105, 106, 107,
- /* 840 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
- /* 850 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 860 */ 57, 19, 194, 66, 194, 116, 117, 118, 116, 117,
- /* 870 */ 118, 74, 242, 294, 194, 194, 206, 23, 194, 25,
- /* 880 */ 194, 111, 112, 113, 25, 43, 44, 45, 46, 47,
- /* 890 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 900 */ 24, 194, 194, 217, 218, 102, 103, 104, 105, 106,
- /* 910 */ 107, 108, 109, 110, 111, 112, 113, 241, 232, 194,
- /* 920 */ 212, 213, 242, 242, 217, 218, 242, 130, 11, 253,
- /* 930 */ 194, 255, 19, 265, 149, 59, 306, 194, 308, 232,
- /* 940 */ 309, 310, 217, 218, 102, 103, 104, 105, 106, 107,
- /* 950 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
- /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 970 */ 57, 194, 194, 59, 194, 239, 19, 194, 25, 254,
- /* 980 */ 303, 304, 23, 194, 25, 126, 306, 306, 308, 308,
- /* 990 */ 306, 271, 308, 117, 286, 217, 218, 217, 218, 194,
- /* 1000 */ 194, 159, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 1010 */ 53, 54, 55, 56, 57, 102, 103, 104, 105, 106,
- /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 59, 239, 194,
- /* 1030 */ 116, 117, 118, 260, 254, 194, 240, 241, 194, 233,
- /* 1040 */ 205, 240, 241, 205, 239, 128, 129, 270, 265, 253,
- /* 1050 */ 194, 255, 217, 218, 253, 194, 255, 143, 280, 102,
- /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- /* 1070 */ 113, 118, 159, 217, 218, 240, 241, 118, 240, 241,
- /* 1080 */ 194, 194, 194, 239, 116, 117, 118, 22, 253, 254,
- /* 1090 */ 255, 253, 19, 255, 233, 194, 143, 24, 263, 212,
- /* 1100 */ 213, 194, 143, 217, 218, 217, 218, 261, 262, 271,
- /* 1110 */ 254, 143, 19, 7, 8, 9, 43, 44, 45, 46,
- /* 1120 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 1130 */ 57, 16, 19, 22, 23, 294, 43, 44, 45, 46,
- /* 1140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 1150 */ 57, 312, 194, 214, 21, 316, 43, 44, 45, 46,
- /* 1160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 1170 */ 57, 106, 107, 286, 194, 102, 103, 104, 105, 106,
- /* 1180 */ 107, 108, 109, 110, 111, 112, 113, 207, 158, 59,
- /* 1190 */ 160, 22, 77, 24, 79, 102, 103, 104, 105, 106,
- /* 1200 */ 107, 108, 109, 110, 111, 112, 113, 194, 194, 229,
- /* 1210 */ 194, 231, 101, 80, 22, 102, 103, 104, 105, 106,
- /* 1220 */ 107, 108, 109, 110, 111, 112, 113, 288, 59, 12,
- /* 1230 */ 217, 218, 293, 217, 218, 19, 106, 107, 59, 19,
- /* 1240 */ 16, 127, 128, 129, 27, 115, 116, 117, 118, 194,
- /* 1250 */ 120, 59, 22, 194, 24, 194, 123, 100, 128, 42,
- /* 1260 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 1270 */ 54, 55, 56, 57, 117, 194, 217, 218, 121, 100,
- /* 1280 */ 63, 194, 245, 153, 194, 155, 117, 19, 115, 194,
- /* 1290 */ 73, 214, 194, 256, 161, 116, 117, 194, 217, 218,
- /* 1300 */ 121, 77, 194, 79, 217, 218, 194, 217, 218, 117,
- /* 1310 */ 153, 154, 155, 254, 46, 217, 218, 144, 102, 103,
- /* 1320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
- /* 1330 */ 232, 270, 153, 154, 155, 115, 116, 66, 19, 20,
- /* 1340 */ 183, 22, 12, 312, 254, 194, 262, 316, 209, 210,
- /* 1350 */ 266, 239, 194, 194, 108, 36, 85, 27, 19, 20,
- /* 1360 */ 265, 22, 183, 245, 144, 94, 25, 48, 217, 218,
- /* 1370 */ 293, 194, 42, 270, 256, 36, 217, 218, 59, 194,
- /* 1380 */ 25, 135, 194, 115, 194, 161, 140, 194, 194, 15,
- /* 1390 */ 71, 194, 312, 63, 217, 218, 316, 194, 59, 131,
- /* 1400 */ 301, 302, 217, 218, 85, 217, 218, 217, 218, 90,
- /* 1410 */ 71, 217, 218, 19, 217, 218, 245, 146, 262, 100,
- /* 1420 */ 217, 218, 266, 265, 85, 106, 107, 256, 312, 90,
- /* 1430 */ 209, 210, 316, 114, 60, 116, 117, 118, 194, 100,
- /* 1440 */ 121, 194, 194, 145, 115, 106, 107, 19, 46, 19,
- /* 1450 */ 20, 24, 22, 114, 194, 116, 117, 118, 194, 245,
- /* 1460 */ 121, 194, 164, 194, 217, 218, 36, 194, 258, 259,
- /* 1470 */ 256, 194, 153, 154, 155, 156, 157, 217, 218, 150,
- /* 1480 */ 31, 217, 218, 142, 217, 218, 217, 218, 39, 59,
- /* 1490 */ 217, 218, 153, 154, 155, 156, 157, 149, 150, 5,
- /* 1500 */ 145, 71, 183, 245, 10, 11, 12, 13, 14, 194,
- /* 1510 */ 116, 17, 129, 227, 256, 85, 194, 115, 194, 23,
- /* 1520 */ 90, 25, 183, 99, 30, 97, 32, 22, 22, 194,
- /* 1530 */ 100, 194, 217, 218, 40, 152, 106, 107, 23, 217,
- /* 1540 */ 218, 194, 19, 20, 114, 22, 116, 117, 118, 257,
- /* 1550 */ 194, 121, 217, 218, 217, 218, 194, 133, 53, 36,
- /* 1560 */ 23, 23, 25, 25, 70, 120, 121, 61, 141, 7,
- /* 1570 */ 8, 121, 78, 217, 218, 81, 23, 227, 25, 217,
- /* 1580 */ 218, 131, 59, 153, 154, 155, 156, 157, 0, 1,
- /* 1590 */ 2, 59, 98, 5, 71, 23, 227, 25, 10, 11,
- /* 1600 */ 12, 13, 14, 83, 84, 17, 23, 23, 25, 25,
- /* 1610 */ 59, 194, 194, 183, 23, 23, 25, 25, 30, 194,
- /* 1620 */ 32, 19, 20, 100, 22, 194, 194, 133, 40, 106,
- /* 1630 */ 107, 108, 138, 139, 194, 217, 218, 114, 36, 116,
- /* 1640 */ 117, 118, 217, 218, 121, 194, 194, 194, 23, 117,
- /* 1650 */ 25, 194, 23, 23, 25, 25, 162, 194, 70, 194,
- /* 1660 */ 145, 59, 23, 153, 25, 155, 78, 194, 117, 81,
- /* 1670 */ 217, 218, 194, 71, 217, 218, 153, 154, 155, 156,
- /* 1680 */ 157, 194, 217, 218, 194, 23, 98, 25, 321, 194,
- /* 1690 */ 217, 218, 194, 19, 20, 194, 22, 153, 23, 155,
- /* 1700 */ 25, 194, 100, 194, 217, 218, 183, 194, 106, 107,
- /* 1710 */ 36, 194, 217, 218, 237, 194, 114, 243, 116, 117,
- /* 1720 */ 118, 133, 194, 121, 217, 218, 138, 139, 194, 194,
- /* 1730 */ 194, 290, 289, 59, 217, 218, 194, 194, 217, 218,
- /* 1740 */ 194, 194, 140, 194, 194, 71, 194, 244, 194, 194,
- /* 1750 */ 162, 217, 218, 194, 194, 153, 154, 155, 156, 157,
- /* 1760 */ 217, 218, 194, 217, 218, 194, 217, 218, 257, 217,
- /* 1770 */ 218, 217, 218, 257, 100, 194, 257, 217, 218, 257,
- /* 1780 */ 106, 107, 215, 299, 194, 183, 192, 194, 114, 194,
- /* 1790 */ 116, 117, 118, 1, 2, 121, 221, 5, 217, 218,
- /* 1800 */ 273, 197, 10, 11, 12, 13, 14, 217, 218, 17,
- /* 1810 */ 217, 218, 217, 218, 140, 194, 246, 194, 273, 295,
- /* 1820 */ 247, 273, 30, 247, 32, 269, 269, 153, 154, 155,
- /* 1830 */ 156, 157, 40, 246, 273, 295, 230, 226, 217, 218,
- /* 1840 */ 217, 218, 220, 261, 220, 282, 220, 19, 20, 244,
- /* 1850 */ 22, 250, 141, 250, 246, 60, 201, 183, 261, 261,
- /* 1860 */ 261, 201, 70, 299, 36, 299, 201, 38, 151, 150,
- /* 1870 */ 78, 285, 22, 81, 296, 296, 43, 235, 18, 238,
- /* 1880 */ 201, 274, 272, 238, 238, 238, 18, 59, 200, 149,
- /* 1890 */ 98, 247, 274, 274, 235, 247, 247, 247, 235, 71,
- /* 1900 */ 272, 201, 200, 158, 292, 62, 291, 201, 200, 22,
- /* 1910 */ 201, 222, 200, 222, 201, 200, 115, 219, 219, 64,
- /* 1920 */ 219, 228, 22, 126, 221, 133, 165, 222, 100, 225,
- /* 1930 */ 138, 139, 225, 219, 106, 107, 24, 219, 228, 219,
- /* 1940 */ 219, 307, 114, 113, 116, 117, 118, 315, 284, 121,
- /* 1950 */ 284, 222, 201, 91, 162, 320, 320, 82, 148, 267,
- /* 1960 */ 145, 267, 22, 279, 201, 158, 281, 251, 147, 146,
- /* 1970 */ 25, 203, 250, 249, 251, 248, 13, 247, 195, 195,
- /* 1980 */ 6, 153, 154, 155, 156, 157, 193, 193, 305, 193,
- /* 1990 */ 208, 305, 302, 214, 214, 214, 208, 223, 223, 214,
- /* 2000 */ 4, 215, 215, 214, 3, 22, 208, 163, 15, 23,
- /* 2010 */ 16, 183, 23, 139, 151, 130, 25, 20, 142, 24,
- /* 2020 */ 16, 144, 1, 142, 130, 130, 61, 37, 53, 151,
- /* 2030 */ 53, 53, 53, 130, 116, 1, 34, 141, 5, 22,
- /* 2040 */ 115, 161, 75, 25, 68, 141, 41, 115, 68, 24,
- /* 2050 */ 20, 19, 131, 125, 67, 67, 96, 22, 22, 22,
- /* 2060 */ 37, 23, 22, 24, 22, 59, 67, 23, 149, 28,
- /* 2070 */ 22, 25, 23, 23, 23, 22, 141, 34, 97, 23,
- /* 2080 */ 23, 34, 116, 22, 143, 25, 34, 75, 34, 34,
- /* 2090 */ 75, 88, 34, 86, 23, 22, 34, 25, 24, 34,
- /* 2100 */ 25, 93, 23, 44, 142, 23, 142, 23, 23, 22,
- /* 2110 */ 11, 25, 23, 25, 23, 22, 22, 22, 1, 23,
- /* 2120 */ 23, 23, 22, 22, 15, 141, 141, 25, 25, 1,
- /* 2130 */ 322, 322, 322, 135, 322, 322, 322, 322, 322, 322,
- /* 2140 */ 322, 141, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2150 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2160 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2170 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2180 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2190 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2200 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2210 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2220 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2230 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2240 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2250 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2260 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2270 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2280 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2290 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2300 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2310 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
- /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322,
+ /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 241,
+ /* 10 */ 242, 195, 217, 221, 195, 235, 254, 195, 256, 19,
+ /* 20 */ 225, 298, 254, 195, 256, 206, 213, 214, 206, 218,
+ /* 30 */ 219, 31, 206, 195, 218, 219, 195, 218, 219, 39,
+ /* 40 */ 218, 219, 313, 43, 44, 45, 317, 47, 48, 49,
+ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19,
+ /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 277,
+ /* 70 */ 278, 279, 234, 254, 255, 256, 254, 255, 256, 218,
+ /* 80 */ 254, 240, 256, 43, 44, 45, 264, 47, 48, 49,
+ /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 271,
+ /* 100 */ 287, 22, 23, 103, 104, 105, 106, 107, 108, 109,
+ /* 110 */ 110, 111, 112, 113, 114, 114, 47, 48, 49, 50,
+ /* 120 */ 187, 188, 189, 190, 191, 192, 190, 87, 192, 89,
+ /* 130 */ 197, 19, 199, 197, 318, 199, 320, 25, 195, 206,
+ /* 140 */ 299, 271, 206, 103, 104, 105, 106, 107, 108, 109,
+ /* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 195, 47,
+ /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ /* 170 */ 58, 60, 21, 195, 241, 242, 215, 241, 242, 312,
+ /* 180 */ 313, 102, 70, 205, 317, 207, 242, 254, 77, 256,
+ /* 190 */ 254, 122, 256, 55, 56, 57, 58, 59, 254, 88,
+ /* 200 */ 256, 90, 269, 240, 93, 269, 107, 108, 109, 110,
+ /* 210 */ 111, 112, 113, 114, 271, 103, 104, 105, 106, 107,
+ /* 220 */ 108, 109, 110, 111, 112, 113, 114, 313, 117, 118,
+ /* 230 */ 119, 317, 81, 195, 301, 19, 195, 301, 277, 278,
+ /* 240 */ 279, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 195, 43,
+ /* 260 */ 44, 45, 74, 47, 48, 49, 50, 51, 52, 53,
+ /* 270 */ 54, 55, 56, 57, 58, 124, 195, 60, 109, 110,
+ /* 280 */ 111, 112, 113, 114, 68, 195, 103, 104, 105, 106,
+ /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 208, 218,
+ /* 300 */ 219, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ /* 310 */ 112, 113, 114, 162, 233, 24, 128, 129, 130, 103,
+ /* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ /* 330 */ 114, 195, 195, 215, 117, 118, 119, 120, 195, 19,
+ /* 340 */ 123, 124, 125, 207, 24, 74, 246, 60, 310, 311,
+ /* 350 */ 133, 60, 311, 82, 22, 218, 219, 257, 195, 19,
+ /* 360 */ 73, 218, 219, 43, 44, 45, 206, 47, 48, 49,
+ /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 22,
+ /* 380 */ 23, 218, 219, 43, 44, 45, 54, 47, 48, 49,
+ /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 128,
+ /* 400 */ 82, 241, 242, 195, 117, 118, 119, 289, 60, 118,
+ /* 410 */ 139, 140, 294, 195, 254, 195, 256, 195, 255, 259,
+ /* 420 */ 260, 73, 22, 103, 104, 105, 106, 107, 108, 109,
+ /* 430 */ 110, 111, 112, 113, 114, 206, 218, 219, 218, 219,
+ /* 440 */ 218, 219, 234, 103, 104, 105, 106, 107, 108, 109,
+ /* 450 */ 110, 111, 112, 113, 114, 318, 319, 139, 140, 102,
+ /* 460 */ 60, 318, 319, 221, 19, 117, 118, 119, 23, 195,
+ /* 470 */ 241, 242, 313, 255, 206, 255, 317, 255, 206, 129,
+ /* 480 */ 130, 206, 264, 254, 264, 256, 264, 195, 43, 44,
+ /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54,
+ /* 500 */ 55, 56, 57, 58, 246, 213, 214, 19, 19, 241,
+ /* 510 */ 242, 195, 23, 241, 242, 257, 241, 242, 118, 277,
+ /* 520 */ 278, 279, 254, 29, 256, 60, 254, 33, 256, 254,
+ /* 530 */ 206, 256, 43, 44, 45, 218, 47, 48, 49, 50,
+ /* 540 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104,
+ /* 550 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ /* 560 */ 66, 19, 218, 60, 120, 241, 242, 123, 124, 125,
+ /* 570 */ 60, 232, 77, 19, 20, 26, 22, 133, 254, 287,
+ /* 580 */ 256, 265, 117, 118, 119, 90, 312, 313, 93, 47,
+ /* 590 */ 36, 317, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 600 */ 111, 112, 113, 114, 116, 117, 277, 278, 279, 60,
+ /* 610 */ 107, 108, 19, 276, 60, 31, 23, 152, 195, 116,
+ /* 620 */ 117, 118, 119, 39, 121, 276, 72, 117, 118, 119,
+ /* 630 */ 166, 167, 129, 145, 237, 238, 43, 44, 45, 276,
+ /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 650 */ 57, 58, 315, 316, 144, 101, 19, 154, 116, 156,
+ /* 660 */ 23, 107, 108, 109, 315, 316, 117, 118, 119, 115,
+ /* 670 */ 60, 117, 118, 119, 132, 200, 122, 60, 315, 316,
+ /* 680 */ 43, 44, 45, 272, 47, 48, 49, 50, 51, 52,
+ /* 690 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106,
+ /* 700 */ 107, 108, 109, 110, 111, 112, 113, 114, 154, 155,
+ /* 710 */ 156, 157, 158, 212, 213, 214, 22, 195, 101, 22,
+ /* 720 */ 60, 19, 20, 60, 22, 139, 140, 117, 118, 119,
+ /* 730 */ 22, 251, 195, 253, 117, 118, 195, 183, 36, 122,
+ /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 750 */ 113, 114, 195, 195, 60, 218, 219, 60, 195, 284,
+ /* 760 */ 19, 25, 60, 288, 23, 237, 238, 22, 60, 109,
+ /* 770 */ 233, 154, 155, 156, 72, 218, 219, 117, 118, 119,
+ /* 780 */ 117, 118, 119, 116, 43, 44, 45, 265, 47, 48,
+ /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ /* 800 */ 183, 243, 25, 101, 19, 60, 265, 144, 23, 107,
+ /* 810 */ 108, 117, 118, 119, 117, 118, 119, 115, 151, 117,
+ /* 820 */ 118, 119, 82, 195, 122, 117, 118, 119, 43, 44,
+ /* 830 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54,
+ /* 840 */ 55, 56, 57, 58, 103, 104, 105, 106, 107, 108,
+ /* 850 */ 109, 110, 111, 112, 113, 114, 154, 155, 156, 157,
+ /* 860 */ 158, 121, 117, 118, 119, 307, 101, 309, 195, 22,
+ /* 870 */ 23, 195, 25, 19, 35, 139, 140, 195, 24, 139,
+ /* 880 */ 140, 208, 195, 118, 109, 183, 22, 122, 103, 104,
+ /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ /* 900 */ 304, 305, 77, 230, 127, 232, 67, 195, 19, 195,
+ /* 910 */ 195, 136, 23, 88, 75, 90, 141, 203, 93, 154,
+ /* 920 */ 155, 156, 208, 295, 60, 243, 22, 23, 19, 25,
+ /* 930 */ 218, 219, 43, 44, 45, 100, 47, 48, 49, 50,
+ /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 183, 102,
+ /* 950 */ 96, 195, 43, 44, 45, 240, 47, 48, 49, 50,
+ /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 134,
+ /* 970 */ 131, 146, 25, 286, 120, 121, 122, 123, 124, 125,
+ /* 980 */ 126, 117, 118, 119, 313, 195, 132, 195, 317, 307,
+ /* 990 */ 195, 309, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 1000 */ 111, 112, 113, 114, 195, 195, 102, 195, 195, 195,
+ /* 1010 */ 218, 219, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 1020 */ 111, 112, 113, 114, 77, 233, 195, 60, 218, 219,
+ /* 1030 */ 218, 219, 218, 219, 23, 195, 25, 90, 243, 159,
+ /* 1040 */ 93, 161, 19, 233, 195, 233, 23, 233, 16, 218,
+ /* 1050 */ 219, 195, 243, 212, 213, 214, 262, 263, 218, 219,
+ /* 1060 */ 195, 271, 19, 307, 233, 309, 43, 44, 45, 160,
+ /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 1080 */ 57, 58, 195, 218, 219, 118, 43, 44, 45, 240,
+ /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 1100 */ 57, 58, 307, 195, 309, 218, 219, 263, 12, 195,
+ /* 1110 */ 78, 267, 80, 112, 113, 114, 307, 22, 309, 24,
+ /* 1120 */ 255, 281, 266, 27, 107, 108, 103, 104, 105, 106,
+ /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 195,
+ /* 1140 */ 11, 22, 255, 24, 195, 195, 103, 104, 105, 106,
+ /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 19, 195,
+ /* 1160 */ 64, 195, 218, 219, 195, 313, 195, 218, 219, 317,
+ /* 1170 */ 74, 154, 195, 156, 195, 195, 19, 233, 23, 60,
+ /* 1180 */ 25, 24, 218, 219, 218, 219, 195, 218, 219, 218,
+ /* 1190 */ 219, 128, 129, 130, 162, 263, 19, 218, 219, 267,
+ /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52,
+ /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 240, 228, 255,
+ /* 1220 */ 43, 44, 45, 25, 47, 48, 49, 50, 51, 52,
+ /* 1230 */ 53, 54, 55, 56, 57, 58, 135, 118, 137, 138,
+ /* 1240 */ 43, 44, 45, 22, 47, 48, 49, 50, 51, 52,
+ /* 1250 */ 53, 54, 55, 56, 57, 58, 117, 266, 129, 130,
+ /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 1270 */ 113, 114, 195, 195, 119, 295, 195, 206, 195, 195,
+ /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 1290 */ 113, 114, 195, 195, 195, 218, 219, 195, 195, 144,
+ /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 1310 */ 113, 114, 241, 242, 67, 218, 219, 218, 219, 146,
+ /* 1320 */ 19, 218, 219, 240, 215, 254, 136, 256, 107, 108,
+ /* 1330 */ 195, 141, 255, 86, 128, 129, 130, 195, 165, 195,
+ /* 1340 */ 19, 143, 95, 272, 25, 44, 45, 266, 47, 48,
+ /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ /* 1360 */ 218, 219, 218, 219, 195, 12, 45, 195, 47, 48,
+ /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ /* 1380 */ 27, 23, 7, 8, 9, 210, 211, 218, 219, 116,
+ /* 1390 */ 218, 219, 228, 16, 147, 42, 195, 295, 195, 19,
+ /* 1400 */ 20, 266, 22, 294, 103, 104, 105, 106, 107, 108,
+ /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 218,
+ /* 1420 */ 219, 218, 219, 195, 103, 104, 105, 106, 107, 108,
+ /* 1430 */ 109, 110, 111, 112, 113, 114, 195, 154, 119, 156,
+ /* 1440 */ 60, 189, 190, 191, 192, 195, 218, 219, 195, 197,
+ /* 1450 */ 195, 199, 72, 195, 19, 78, 195, 80, 206, 218,
+ /* 1460 */ 219, 195, 82, 144, 210, 211, 195, 15, 218, 219,
+ /* 1470 */ 47, 218, 219, 218, 219, 259, 260, 195, 261, 218,
+ /* 1480 */ 219, 101, 302, 303, 218, 219, 195, 107, 108, 218,
+ /* 1490 */ 219, 150, 151, 241, 242, 115, 25, 117, 118, 119,
+ /* 1500 */ 218, 219, 122, 195, 146, 195, 254, 195, 256, 218,
+ /* 1510 */ 219, 246, 25, 61, 246, 19, 20, 195, 22, 139,
+ /* 1520 */ 140, 269, 257, 195, 266, 257, 218, 219, 218, 219,
+ /* 1530 */ 218, 219, 36, 246, 154, 155, 156, 157, 158, 116,
+ /* 1540 */ 218, 219, 195, 22, 257, 49, 218, 219, 23, 195,
+ /* 1550 */ 25, 195, 117, 301, 195, 25, 60, 195, 195, 23,
+ /* 1560 */ 195, 25, 195, 183, 24, 218, 219, 130, 72, 195,
+ /* 1570 */ 22, 195, 218, 219, 218, 219, 195, 218, 219, 195,
+ /* 1580 */ 218, 219, 86, 218, 219, 218, 219, 91, 19, 20,
+ /* 1590 */ 153, 22, 218, 219, 218, 219, 195, 101, 195, 218,
+ /* 1600 */ 219, 195, 195, 107, 108, 36, 23, 195, 25, 195,
+ /* 1610 */ 62, 115, 195, 117, 118, 119, 195, 146, 122, 218,
+ /* 1620 */ 219, 218, 219, 195, 218, 219, 19, 60, 122, 60,
+ /* 1630 */ 218, 219, 218, 219, 195, 218, 219, 150, 132, 218,
+ /* 1640 */ 219, 72, 195, 23, 195, 25, 218, 219, 195, 60,
+ /* 1650 */ 154, 155, 156, 157, 158, 86, 23, 195, 25, 195,
+ /* 1660 */ 91, 19, 20, 142, 22, 218, 219, 218, 219, 130,
+ /* 1670 */ 101, 218, 219, 143, 121, 122, 107, 108, 36, 183,
+ /* 1680 */ 218, 219, 142, 60, 115, 118, 117, 118, 119, 7,
+ /* 1690 */ 8, 122, 153, 23, 23, 25, 25, 23, 23, 25,
+ /* 1700 */ 25, 23, 60, 25, 23, 98, 25, 118, 84, 85,
+ /* 1710 */ 23, 23, 25, 25, 72, 154, 23, 156, 25, 23,
+ /* 1720 */ 228, 25, 195, 154, 155, 156, 157, 158, 86, 195,
+ /* 1730 */ 195, 258, 195, 91, 291, 322, 195, 195, 195, 195,
+ /* 1740 */ 195, 118, 195, 101, 195, 195, 195, 195, 238, 107,
+ /* 1750 */ 108, 195, 183, 195, 195, 195, 290, 115, 195, 117,
+ /* 1760 */ 118, 119, 244, 195, 122, 195, 195, 195, 195, 195,
+ /* 1770 */ 195, 258, 258, 258, 258, 193, 245, 300, 216, 274,
+ /* 1780 */ 247, 270, 270, 274, 296, 296, 248, 222, 262, 198,
+ /* 1790 */ 262, 274, 61, 274, 248, 231, 154, 155, 156, 157,
+ /* 1800 */ 158, 0, 1, 2, 247, 227, 5, 221, 221, 221,
+ /* 1810 */ 142, 10, 11, 12, 13, 14, 262, 262, 17, 202,
+ /* 1820 */ 300, 19, 20, 300, 22, 183, 247, 251, 251, 245,
+ /* 1830 */ 202, 30, 38, 32, 202, 152, 151, 22, 36, 43,
+ /* 1840 */ 236, 40, 18, 202, 239, 239, 18, 239, 239, 283,
+ /* 1850 */ 201, 150, 236, 202, 236, 201, 159, 202, 248, 248,
+ /* 1860 */ 248, 248, 60, 63, 201, 275, 273, 275, 273, 275,
+ /* 1870 */ 22, 286, 71, 223, 72, 202, 223, 297, 297, 202,
+ /* 1880 */ 79, 201, 116, 82, 220, 201, 220, 220, 65, 293,
+ /* 1890 */ 292, 229, 22, 166, 127, 226, 24, 114, 226, 223,
+ /* 1900 */ 99, 222, 202, 101, 285, 92, 220, 308, 83, 107,
+ /* 1910 */ 108, 220, 220, 316, 220, 285, 268, 115, 229, 117,
+ /* 1920 */ 118, 119, 223, 321, 122, 268, 149, 146, 22, 19,
+ /* 1930 */ 20, 202, 22, 159, 282, 134, 321, 148, 280, 147,
+ /* 1940 */ 139, 140, 252, 141, 25, 204, 36, 252, 13, 251,
+ /* 1950 */ 196, 248, 250, 249, 196, 6, 154, 155, 156, 157,
+ /* 1960 */ 158, 209, 194, 194, 163, 194, 306, 306, 303, 224,
+ /* 1970 */ 60, 215, 215, 209, 215, 215, 215, 224, 216, 216,
+ /* 1980 */ 4, 209, 72, 3, 22, 183, 164, 15, 23, 16,
+ /* 1990 */ 23, 140, 152, 131, 25, 24, 143, 20, 16, 145,
+ /* 2000 */ 1, 143, 131, 62, 131, 37, 54, 152, 54, 54,
+ /* 2010 */ 54, 101, 131, 117, 1, 34, 142, 107, 108, 5,
+ /* 2020 */ 22, 116, 162, 76, 41, 115, 69, 117, 118, 119,
+ /* 2030 */ 1, 2, 122, 25, 5, 69, 142, 116, 20, 10,
+ /* 2040 */ 11, 12, 13, 14, 24, 19, 17, 132, 5, 126,
+ /* 2050 */ 22, 141, 68, 10, 11, 12, 13, 14, 22, 30,
+ /* 2060 */ 17, 32, 22, 22, 154, 155, 156, 157, 158, 40,
+ /* 2070 */ 23, 68, 60, 30, 24, 32, 97, 28, 22, 68,
+ /* 2080 */ 23, 37, 34, 40, 150, 22, 25, 23, 23, 23,
+ /* 2090 */ 22, 98, 142, 183, 23, 23, 34, 22, 25, 89,
+ /* 2100 */ 71, 34, 117, 144, 34, 22, 76, 76, 79, 87,
+ /* 2110 */ 34, 82, 34, 44, 71, 94, 34, 23, 25, 24,
+ /* 2120 */ 34, 25, 79, 23, 23, 82, 23, 23, 99, 143,
+ /* 2130 */ 143, 22, 25, 25, 23, 22, 11, 22, 22, 25,
+ /* 2140 */ 23, 23, 99, 22, 22, 136, 142, 142, 142, 25,
+ /* 2150 */ 23, 15, 1, 1, 323, 323, 323, 323, 323, 323,
+ /* 2160 */ 323, 323, 323, 134, 323, 323, 323, 323, 139, 140,
+ /* 2170 */ 323, 323, 323, 323, 323, 323, 323, 134, 323, 323,
+ /* 2180 */ 323, 323, 139, 140, 323, 323, 323, 323, 323, 323,
+ /* 2190 */ 323, 323, 163, 323, 323, 323, 323, 323, 323, 323,
+ /* 2200 */ 323, 323, 323, 323, 323, 323, 163, 323, 323, 323,
+ /* 2210 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2220 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2230 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2240 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2250 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2260 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2270 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2280 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2290 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2300 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2310 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2320 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2330 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ /* 2340 */ 323, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2350 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2360 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2370 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2380 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
+ /* 2390 */ 187, 187, 187, 187,
};
#define YY_SHIFT_COUNT (582)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (2128)
+#define YY_SHIFT_MAX (2152)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 1792, 1588, 1494, 322, 322, 399, 306, 1319, 1339, 1430,
- /* 10 */ 1828, 1828, 1828, 580, 399, 399, 399, 399, 399, 0,
- /* 20 */ 0, 214, 1093, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
- /* 30 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1130, 1130,
- /* 40 */ 365, 365, 55, 278, 436, 713, 713, 201, 201, 201,
- /* 50 */ 201, 40, 111, 258, 361, 469, 512, 583, 622, 693,
- /* 60 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093,
- /* 70 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
- /* 80 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1523, 1602,
- /* 90 */ 1674, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
- /* 100 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
- /* 110 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
- /* 120 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
- /* 130 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
- /* 140 */ 137, 181, 181, 181, 181, 181, 181, 181, 96, 222,
- /* 150 */ 143, 477, 713, 1133, 1268, 713, 713, 79, 79, 713,
- /* 160 */ 770, 83, 65, 65, 65, 288, 162, 162, 2142, 2142,
- /* 170 */ 696, 696, 696, 238, 474, 474, 474, 474, 1217, 1217,
- /* 180 */ 678, 477, 324, 398, 713, 713, 713, 713, 713, 713,
- /* 190 */ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713,
- /* 200 */ 713, 713, 713, 1220, 366, 366, 713, 917, 283, 283,
- /* 210 */ 434, 434, 605, 605, 1298, 2142, 2142, 2142, 2142, 2142,
- /* 220 */ 2142, 2142, 1179, 1157, 1157, 487, 527, 585, 645, 749,
- /* 230 */ 914, 968, 752, 713, 713, 713, 713, 713, 713, 713,
- /* 240 */ 713, 713, 713, 303, 713, 713, 713, 713, 713, 713,
- /* 250 */ 713, 713, 713, 713, 713, 713, 797, 797, 797, 713,
- /* 260 */ 713, 713, 959, 713, 713, 713, 1169, 1271, 713, 713,
- /* 270 */ 1330, 713, 713, 713, 713, 713, 713, 713, 713, 629,
- /* 280 */ 7, 91, 876, 876, 876, 876, 953, 91, 91, 1246,
- /* 290 */ 1065, 1106, 1374, 1329, 1348, 468, 1348, 1394, 785, 1329,
- /* 300 */ 1329, 785, 1329, 468, 1394, 859, 854, 1402, 1449, 1449,
- /* 310 */ 1449, 1173, 1173, 1173, 1173, 1355, 1355, 1030, 1341, 405,
- /* 320 */ 1230, 1795, 1795, 1711, 1711, 1829, 1829, 1711, 1717, 1719,
- /* 330 */ 1850, 1833, 1860, 1860, 1860, 1860, 1711, 1868, 1740, 1719,
- /* 340 */ 1719, 1740, 1850, 1833, 1740, 1833, 1740, 1711, 1868, 1745,
- /* 350 */ 1843, 1711, 1868, 1887, 1711, 1868, 1711, 1868, 1887, 1801,
- /* 360 */ 1801, 1801, 1855, 1900, 1900, 1887, 1801, 1797, 1801, 1855,
- /* 370 */ 1801, 1801, 1761, 1912, 1830, 1830, 1887, 1711, 1862, 1862,
- /* 380 */ 1875, 1875, 1810, 1815, 1940, 1711, 1807, 1810, 1821, 1823,
- /* 390 */ 1740, 1945, 1963, 1963, 1974, 1974, 1974, 2142, 2142, 2142,
- /* 400 */ 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
- /* 410 */ 2142, 2142, 20, 1224, 256, 1111, 1115, 1114, 1192, 1496,
- /* 420 */ 1424, 1505, 1427, 355, 1383, 1537, 1506, 1538, 1553, 1583,
- /* 430 */ 1584, 1591, 1625, 541, 1445, 1562, 1450, 1572, 1515, 1428,
- /* 440 */ 1532, 1592, 1629, 1520, 1630, 1639, 1510, 1544, 1662, 1675,
- /* 450 */ 1551, 48, 1996, 2001, 1983, 1844, 1993, 1994, 1986, 1989,
- /* 460 */ 1874, 1863, 1885, 1991, 1991, 1995, 1876, 1997, 1877, 2004,
- /* 470 */ 2021, 1881, 1894, 1991, 1895, 1965, 1990, 1991, 1878, 1975,
- /* 480 */ 1977, 1978, 1979, 1903, 1918, 2002, 1896, 2034, 2033, 2017,
- /* 490 */ 1925, 1880, 1976, 2018, 1980, 1967, 2005, 1904, 1932, 2025,
- /* 500 */ 2030, 2032, 1921, 1928, 2035, 1987, 2036, 2037, 2038, 2040,
- /* 510 */ 1988, 2006, 2039, 1960, 2041, 2042, 1999, 2023, 2044, 2043,
- /* 520 */ 1919, 2048, 2049, 2050, 2046, 2051, 2053, 1981, 1935, 2056,
- /* 530 */ 2057, 1966, 2047, 2061, 1941, 2060, 2052, 2054, 2055, 2058,
- /* 540 */ 2003, 2012, 2007, 2059, 2015, 2008, 2062, 2071, 2073, 2074,
- /* 550 */ 2072, 2075, 2065, 1962, 1964, 2079, 2060, 2082, 2084, 2085,
- /* 560 */ 2087, 2086, 2089, 2088, 2091, 2093, 2099, 2094, 2095, 2096,
- /* 570 */ 2097, 2100, 2101, 2102, 1998, 1984, 1985, 2000, 2103, 2098,
- /* 580 */ 2109, 2117, 2128,
+ /* 0 */ 2029, 1801, 2043, 1380, 1380, 318, 271, 1496, 1569, 1642,
+ /* 10 */ 702, 702, 702, 740, 318, 318, 318, 318, 318, 0,
+ /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702,
+ /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 503, 503,
+ /* 40 */ 111, 111, 217, 287, 348, 610, 610, 736, 736, 736,
+ /* 50 */ 736, 40, 112, 320, 340, 445, 489, 593, 637, 741,
+ /* 60 */ 785, 889, 909, 1023, 1043, 1157, 1177, 1177, 1177, 1177,
+ /* 70 */ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177,
+ /* 80 */ 1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321, 554,
+ /* 90 */ 1802, 1910, 702, 702, 702, 702, 702, 702, 702, 702,
+ /* 100 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
+ /* 110 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
+ /* 120 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
+ /* 130 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
+ /* 140 */ 702, 702, 138, 198, 198, 198, 198, 198, 198, 198,
+ /* 150 */ 183, 99, 169, 549, 610, 151, 542, 610, 610, 1017,
+ /* 160 */ 1017, 610, 1001, 350, 464, 464, 464, 586, 1, 1,
+ /* 170 */ 2207, 2207, 854, 854, 854, 465, 694, 694, 694, 694,
+ /* 180 */ 1096, 1096, 825, 549, 847, 904, 610, 610, 610, 610,
+ /* 190 */ 610, 610, 610, 610, 610, 610, 610, 610, 610, 610,
+ /* 200 */ 610, 610, 610, 610, 610, 488, 947, 947, 610, 1129,
+ /* 210 */ 495, 495, 1139, 1139, 967, 967, 1173, 2207, 2207, 2207,
+ /* 220 */ 2207, 2207, 2207, 2207, 617, 765, 765, 697, 444, 708,
+ /* 230 */ 660, 745, 510, 663, 864, 610, 610, 610, 610, 610,
+ /* 240 */ 610, 610, 610, 610, 610, 188, 610, 610, 610, 610,
+ /* 250 */ 610, 610, 610, 610, 610, 610, 610, 610, 839, 839,
+ /* 260 */ 839, 610, 610, 610, 1155, 610, 610, 610, 1119, 1247,
+ /* 270 */ 610, 1353, 610, 610, 610, 610, 610, 610, 610, 610,
+ /* 280 */ 1063, 494, 1101, 291, 291, 291, 291, 1319, 1101, 1101,
+ /* 290 */ 775, 1221, 1375, 1452, 667, 1341, 1198, 1341, 1435, 1487,
+ /* 300 */ 667, 667, 1487, 667, 1198, 1435, 777, 1011, 1423, 584,
+ /* 310 */ 584, 584, 1273, 1273, 1273, 1273, 1471, 1471, 880, 1530,
+ /* 320 */ 1190, 1095, 1731, 1731, 1668, 1668, 1794, 1794, 1668, 1683,
+ /* 330 */ 1685, 1815, 1796, 1824, 1824, 1824, 1824, 1668, 1828, 1701,
+ /* 340 */ 1685, 1685, 1701, 1815, 1796, 1701, 1796, 1701, 1668, 1828,
+ /* 350 */ 1697, 1800, 1668, 1828, 1848, 1668, 1828, 1668, 1828, 1848,
+ /* 360 */ 1766, 1766, 1766, 1823, 1870, 1870, 1848, 1766, 1767, 1766,
+ /* 370 */ 1823, 1766, 1766, 1727, 1872, 1783, 1783, 1848, 1668, 1813,
+ /* 380 */ 1813, 1825, 1825, 1777, 1781, 1906, 1668, 1774, 1777, 1789,
+ /* 390 */ 1792, 1701, 1919, 1935, 1935, 1949, 1949, 1949, 2207, 2207,
+ /* 400 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207,
+ /* 410 */ 2207, 2207, 2207, 69, 1032, 79, 357, 1377, 1206, 400,
+ /* 420 */ 1525, 835, 332, 1540, 1437, 1539, 1536, 1548, 1583, 1620,
+ /* 430 */ 1633, 1670, 1671, 1674, 1567, 1553, 1682, 1506, 1675, 1358,
+ /* 440 */ 1607, 1589, 1678, 1681, 1624, 1687, 1688, 1283, 1561, 1693,
+ /* 450 */ 1696, 1623, 1521, 1976, 1980, 1962, 1822, 1972, 1973, 1965,
+ /* 460 */ 1967, 1851, 1840, 1862, 1969, 1969, 1971, 1853, 1977, 1854,
+ /* 470 */ 1982, 1999, 1858, 1871, 1969, 1873, 1941, 1968, 1969, 1855,
+ /* 480 */ 1952, 1954, 1955, 1956, 1881, 1896, 1981, 1874, 2013, 2014,
+ /* 490 */ 1998, 1905, 1860, 1957, 2008, 1966, 1947, 1983, 1894, 1921,
+ /* 500 */ 2020, 2018, 2026, 1915, 1923, 2028, 1984, 2036, 2040, 2047,
+ /* 510 */ 2041, 2003, 2012, 2050, 1979, 2049, 2056, 2011, 2044, 2057,
+ /* 520 */ 2048, 1934, 2063, 2064, 2065, 2061, 2066, 2068, 1993, 1950,
+ /* 530 */ 2071, 2072, 1985, 2062, 2075, 1959, 2073, 2067, 2070, 2076,
+ /* 540 */ 2078, 2010, 2030, 2022, 2069, 2031, 2021, 2082, 2094, 2083,
+ /* 550 */ 2095, 2093, 2096, 2086, 1986, 1987, 2100, 2073, 2101, 2103,
+ /* 560 */ 2104, 2109, 2107, 2108, 2111, 2113, 2125, 2115, 2116, 2117,
+ /* 570 */ 2118, 2121, 2122, 2114, 2009, 2004, 2005, 2006, 2124, 2127,
+ /* 580 */ 2136, 2151, 2152,
};
-#define YY_REDUCE_COUNT (411)
-#define YY_REDUCE_MIN (-275)
-#define YY_REDUCE_MAX (1798)
+#define YY_REDUCE_COUNT (412)
+#define YY_REDUCE_MIN (-277)
+#define YY_REDUCE_MAX (1772)
static const short yy_reduce_ofst[] = {
- /* 0 */ -71, 194, 343, 835, -180, -177, 838, -194, -188, -185,
- /* 10 */ -183, 82, 183, -65, 133, 245, 346, 407, 458, -178,
- /* 20 */ 75, -275, -4, 310, 312, 489, 575, 596, 463, 686,
- /* 30 */ 707, 725, 780, 1098, 856, 778, 1059, 1090, 708, 887,
- /* 40 */ 86, 448, 980, 630, 680, 681, 684, 796, 801, 796,
- /* 50 */ 801, -261, -261, -261, -261, -261, -261, -261, -261, -261,
- /* 60 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
- /* 70 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
- /* 80 */ -261, -261, -261, -261, -261, -261, -261, -261, 391, 886,
- /* 90 */ 888, 1013, 1016, 1081, 1087, 1151, 1159, 1177, 1185, 1188,
- /* 100 */ 1190, 1194, 1197, 1203, 1247, 1260, 1264, 1267, 1269, 1273,
- /* 110 */ 1315, 1322, 1335, 1337, 1356, 1362, 1418, 1425, 1453, 1457,
- /* 120 */ 1465, 1473, 1487, 1495, 1507, 1517, 1521, 1534, 1543, 1546,
- /* 130 */ 1549, 1552, 1554, 1560, 1581, 1590, 1593, 1595, 1621, 1623,
- /* 140 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
- /* 150 */ -261, -186, -117, 260, 263, 460, 631, -74, 497, -181,
- /* 160 */ -261, 939, 176, 274, 338, 676, -261, -261, -261, -261,
- /* 170 */ -212, -212, -212, -184, 149, 777, 1061, 1103, 265, 419,
- /* 180 */ -254, 670, 677, 677, -11, -129, 184, 488, 736, 789,
- /* 190 */ 805, 844, 403, 529, 579, 668, 783, 841, 1158, 1112,
- /* 200 */ 806, 861, 1095, 846, 839, 1031, -189, 1077, 1080, 1116,
- /* 210 */ 1084, 1156, 1139, 1221, 46, 1099, 1037, 1118, 1171, 1214,
- /* 220 */ 1210, 1258, -210, -190, -176, -115, 117, 262, 376, 490,
- /* 230 */ 511, 520, 618, 639, 743, 901, 907, 958, 1014, 1055,
- /* 240 */ 1108, 1193, 1244, 720, 1248, 1277, 1324, 1347, 1417, 1431,
- /* 250 */ 1432, 1440, 1451, 1452, 1463, 1478, 1286, 1350, 1369, 1490,
- /* 260 */ 1498, 1501, 773, 1509, 1513, 1528, 1292, 1367, 1535, 1536,
- /* 270 */ 1477, 1542, 376, 1547, 1550, 1555, 1559, 1568, 1571, 1441,
- /* 280 */ 1443, 1474, 1511, 1516, 1519, 1522, 773, 1474, 1474, 1503,
- /* 290 */ 1567, 1594, 1484, 1527, 1556, 1570, 1557, 1524, 1573, 1545,
- /* 300 */ 1548, 1576, 1561, 1587, 1540, 1575, 1606, 1611, 1622, 1624,
- /* 310 */ 1626, 1582, 1597, 1598, 1599, 1601, 1603, 1563, 1608, 1605,
- /* 320 */ 1604, 1564, 1566, 1655, 1660, 1578, 1579, 1665, 1586, 1607,
- /* 330 */ 1610, 1642, 1641, 1645, 1646, 1647, 1679, 1688, 1644, 1618,
- /* 340 */ 1619, 1648, 1628, 1659, 1649, 1663, 1650, 1700, 1702, 1612,
- /* 350 */ 1615, 1706, 1708, 1689, 1709, 1712, 1713, 1715, 1691, 1698,
- /* 360 */ 1699, 1701, 1693, 1704, 1707, 1705, 1714, 1703, 1718, 1710,
- /* 370 */ 1720, 1721, 1632, 1634, 1664, 1666, 1729, 1751, 1635, 1636,
- /* 380 */ 1692, 1694, 1716, 1722, 1684, 1763, 1685, 1723, 1724, 1727,
- /* 390 */ 1730, 1768, 1783, 1784, 1793, 1794, 1796, 1683, 1686, 1690,
- /* 400 */ 1782, 1779, 1780, 1781, 1785, 1788, 1774, 1775, 1786, 1787,
- /* 410 */ 1789, 1798,
+ /* 0 */ -67, 1252, -64, -178, -181, 160, 1071, 143, -184, 137,
+ /* 10 */ 218, 220, 222, -174, 229, 268, 272, 275, 324, -208,
+ /* 20 */ 242, -277, -39, 81, 537, 792, 810, 812, -189, 814,
+ /* 30 */ 831, 163, 865, 944, 887, 840, 964, 1077, -187, 292,
+ /* 40 */ -133, 274, 673, 558, 682, 795, 809, -238, -232, -238,
+ /* 50 */ -232, 329, 329, 329, 329, 329, 329, 329, 329, 329,
+ /* 60 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329,
+ /* 70 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329,
+ /* 80 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 557,
+ /* 90 */ 712, 949, 966, 969, 971, 979, 1097, 1099, 1103, 1142,
+ /* 100 */ 1144, 1169, 1172, 1201, 1203, 1228, 1241, 1250, 1253, 1255,
+ /* 110 */ 1261, 1266, 1271, 1282, 1291, 1308, 1310, 1312, 1322, 1328,
+ /* 120 */ 1347, 1354, 1356, 1359, 1362, 1365, 1367, 1374, 1376, 1381,
+ /* 130 */ 1401, 1403, 1406, 1412, 1414, 1417, 1421, 1428, 1447, 1449,
+ /* 140 */ 1453, 1462, 329, 329, 329, 329, 329, 329, 329, 329,
+ /* 150 */ 329, 329, 329, -22, -159, 475, -220, 756, 38, 501,
+ /* 160 */ 841, 714, 329, 118, 337, 349, 363, -56, 329, 329,
+ /* 170 */ 329, 329, -205, -205, -205, 687, -172, -130, -57, 790,
+ /* 180 */ 397, 528, -271, 136, 596, 596, 90, 316, 522, 541,
+ /* 190 */ -37, 715, 849, 977, 628, 856, 980, 991, 1081, 1102,
+ /* 200 */ 1135, 1083, -162, 208, 1258, 794, -86, 159, 41, 1109,
+ /* 210 */ 671, 852, 844, 932, 1175, 1254, 480, 1180, 100, 258,
+ /* 220 */ 1265, 1268, 1216, 1287, -139, 317, 344, 63, 339, 423,
+ /* 230 */ 563, 636, 676, 813, 908, 914, 950, 1078, 1084, 1098,
+ /* 240 */ 1363, 1384, 1407, 1439, 1464, 411, 1527, 1534, 1535, 1537,
+ /* 250 */ 1541, 1542, 1543, 1544, 1545, 1547, 1549, 1550, 990, 1164,
+ /* 260 */ 1492, 1551, 1552, 1556, 1217, 1558, 1559, 1560, 1473, 1413,
+ /* 270 */ 1563, 1510, 1568, 563, 1570, 1571, 1572, 1573, 1574, 1575,
+ /* 280 */ 1443, 1466, 1518, 1513, 1514, 1515, 1516, 1217, 1518, 1518,
+ /* 290 */ 1531, 1562, 1582, 1477, 1505, 1511, 1533, 1512, 1488, 1538,
+ /* 300 */ 1509, 1517, 1546, 1519, 1557, 1489, 1565, 1564, 1578, 1586,
+ /* 310 */ 1587, 1588, 1526, 1528, 1554, 1555, 1576, 1577, 1566, 1579,
+ /* 320 */ 1584, 1591, 1520, 1523, 1617, 1628, 1580, 1581, 1632, 1585,
+ /* 330 */ 1590, 1593, 1604, 1605, 1606, 1608, 1609, 1641, 1649, 1610,
+ /* 340 */ 1592, 1594, 1611, 1595, 1616, 1612, 1618, 1613, 1651, 1654,
+ /* 350 */ 1596, 1598, 1655, 1663, 1650, 1673, 1680, 1677, 1684, 1653,
+ /* 360 */ 1664, 1666, 1667, 1662, 1669, 1672, 1676, 1686, 1679, 1691,
+ /* 370 */ 1689, 1692, 1694, 1597, 1599, 1619, 1630, 1699, 1700, 1602,
+ /* 380 */ 1615, 1648, 1657, 1690, 1698, 1658, 1729, 1652, 1695, 1702,
+ /* 390 */ 1704, 1703, 1741, 1754, 1758, 1768, 1769, 1771, 1660, 1661,
+ /* 400 */ 1665, 1752, 1756, 1757, 1759, 1760, 1764, 1745, 1753, 1762,
+ /* 410 */ 1763, 1761, 1772,
};
static const YYACTIONTYPE yy_default[] = {
/* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254,
@@ -173647,57 +176458,57 @@ static const YYACTIONTYPE yy_default[] = {
/* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254,
/* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254,
/* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254,
- /* 60 */ 1492, 1493, 1254, 1254, 1254, 1543, 1545, 1508, 1420, 1419,
- /* 70 */ 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, 1486,
- /* 80 */ 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, 1254,
+ /* 60 */ 1492, 1493, 1254, 1254, 1254, 1254, 1543, 1545, 1508, 1420,
+ /* 70 */ 1419, 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488,
+ /* 80 */ 1486, 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254,
/* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 140 */ 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, 1456, 1458,
- /* 150 */ 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, 1254, 1254,
- /* 160 */ 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, 1473, 1472,
- /* 170 */ 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 180 */ 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 140 */ 1254, 1254, 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457,
+ /* 150 */ 1456, 1458, 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254,
+ /* 160 */ 1254, 1254, 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461,
+ /* 170 */ 1473, 1472, 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254,
+ /* 180 */ 1254, 1254, 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 200 */ 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, 1578, 1578,
- /* 210 */ 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, 1358, 1358,
- /* 220 */ 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, 1546, 1254,
- /* 240 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 200 */ 1254, 1254, 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287,
+ /* 210 */ 1578, 1578, 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358,
+ /* 220 */ 1358, 1358, 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548,
+ /* 240 */ 1546, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, 1254, 1254,
- /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, 1254,
- /* 280 */ 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, 1357,
- /* 290 */ 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, 1423,
- /* 300 */ 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, 1397,
- /* 310 */ 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, 1357,
- /* 320 */ 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, 1638,
- /* 330 */ 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, 1638,
- /* 340 */ 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, 1525,
- /* 350 */ 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, 1330,
- /* 360 */ 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, 1319,
- /* 370 */ 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, 1588,
- /* 380 */ 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, 1401,
- /* 390 */ 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, 1558,
- /* 400 */ 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, 1288,
- /* 410 */ 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, 1254,
- /* 420 */ 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1564,
- /* 440 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 450 */ 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, 1254,
- /* 460 */ 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, 1254,
- /* 470 */ 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, 1254,
- /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, 1254,
- /* 490 */ 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, 1254,
+ /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254,
+ /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608,
+ /* 280 */ 1254, 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342,
+ /* 290 */ 1357, 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410,
+ /* 300 */ 1423, 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397,
+ /* 310 */ 1397, 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364,
+ /* 320 */ 1357, 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509,
+ /* 330 */ 1638, 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410,
+ /* 340 */ 1638, 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272,
+ /* 350 */ 1525, 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499,
+ /* 360 */ 1330, 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330,
+ /* 370 */ 1319, 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588,
+ /* 380 */ 1588, 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403,
+ /* 390 */ 1401, 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660,
+ /* 400 */ 1558, 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288,
+ /* 410 */ 1288, 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618,
+ /* 420 */ 1254, 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 440 */ 1564, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 450 */ 1254, 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254,
+ /* 460 */ 1254, 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254,
+ /* 470 */ 1254, 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254,
+ /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254,
+ /* 490 */ 1254, 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254,
/* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 510 */ 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 510 */ 1254, 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 530 */ 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, 1254,
+ /* 530 */ 1254, 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254,
/* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
- /* 550 */ 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, 1254,
- /* 560 */ 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+ /* 550 */ 1254, 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254,
+ /* 560 */ 1254, 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
/* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254,
/* 580 */ 1266, 1254, 1254,
};
@@ -173721,52 +176532,53 @@ static const YYACTIONTYPE yy_default[] = {
static const YYCODETYPE yyFallback[] = {
0, /* $ => nothing */
0, /* SEMI => nothing */
- 59, /* EXPLAIN => ID */
- 59, /* QUERY => ID */
- 59, /* PLAN => ID */
- 59, /* BEGIN => ID */
+ 60, /* EXPLAIN => ID */
+ 60, /* QUERY => ID */
+ 60, /* PLAN => ID */
+ 60, /* BEGIN => ID */
0, /* TRANSACTION => nothing */
- 59, /* DEFERRED => ID */
- 59, /* IMMEDIATE => ID */
- 59, /* EXCLUSIVE => ID */
+ 60, /* DEFERRED => ID */
+ 60, /* IMMEDIATE => ID */
+ 60, /* EXCLUSIVE => ID */
0, /* COMMIT => nothing */
- 59, /* END => ID */
- 59, /* ROLLBACK => ID */
- 59, /* SAVEPOINT => ID */
- 59, /* RELEASE => ID */
+ 60, /* END => ID */
+ 60, /* ROLLBACK => ID */
+ 60, /* SAVEPOINT => ID */
+ 60, /* RELEASE => ID */
0, /* TO => nothing */
0, /* TABLE => nothing */
0, /* CREATE => nothing */
- 59, /* IF => ID */
+ 60, /* IF => ID */
0, /* NOT => nothing */
0, /* EXISTS => nothing */
- 59, /* TEMP => ID */
+ 60, /* TEMP => ID */
0, /* LP => nothing */
0, /* RP => nothing */
0, /* AS => nothing */
0, /* COMMA => nothing */
- 59, /* WITHOUT => ID */
- 59, /* ABORT => ID */
- 59, /* ACTION => ID */
- 59, /* AFTER => ID */
- 59, /* ANALYZE => ID */
- 59, /* ASC => ID */
- 59, /* ATTACH => ID */
- 59, /* BEFORE => ID */
- 59, /* BY => ID */
- 59, /* CASCADE => ID */
- 59, /* CAST => ID */
- 59, /* CONFLICT => ID */
- 59, /* DATABASE => ID */
- 59, /* DESC => ID */
- 59, /* DETACH => ID */
- 59, /* EACH => ID */
- 59, /* FAIL => ID */
+ 60, /* WITHOUT => ID */
+ 60, /* ABORT => ID */
+ 60, /* ACTION => ID */
+ 60, /* AFTER => ID */
+ 60, /* ANALYZE => ID */
+ 60, /* ASC => ID */
+ 60, /* ATTACH => ID */
+ 60, /* BEFORE => ID */
+ 60, /* BY => ID */
+ 60, /* CASCADE => ID */
+ 60, /* CAST => ID */
+ 60, /* CONFLICT => ID */
+ 60, /* DATABASE => ID */
+ 60, /* DESC => ID */
+ 60, /* DETACH => ID */
+ 60, /* EACH => ID */
+ 60, /* FAIL => ID */
0, /* OR => nothing */
0, /* AND => nothing */
0, /* IS => nothing */
- 59, /* MATCH => ID */
- 59, /* LIKE_KW => ID */
+ 0, /* ISNOT => nothing */
+ 60, /* MATCH => ID */
+ 60, /* LIKE_KW => ID */
0, /* BETWEEN => nothing */
0, /* IN => nothing */
0, /* ISNULL => nothing */
@@ -173779,47 +176591,47 @@ static const YYCODETYPE yyFallback[] = {
0, /* GE => nothing */
0, /* ESCAPE => nothing */
0, /* ID => nothing */
- 59, /* COLUMNKW => ID */
- 59, /* DO => ID */
- 59, /* FOR => ID */
- 59, /* IGNORE => ID */
- 59, /* INITIALLY => ID */
- 59, /* INSTEAD => ID */
- 59, /* NO => ID */
- 59, /* KEY => ID */
- 59, /* OF => ID */
- 59, /* OFFSET => ID */
- 59, /* PRAGMA => ID */
- 59, /* RAISE => ID */
- 59, /* RECURSIVE => ID */
- 59, /* REPLACE => ID */
- 59, /* RESTRICT => ID */
- 59, /* ROW => ID */
- 59, /* ROWS => ID */
- 59, /* TRIGGER => ID */
- 59, /* VACUUM => ID */
- 59, /* VIEW => ID */
- 59, /* VIRTUAL => ID */
- 59, /* WITH => ID */
- 59, /* NULLS => ID */
- 59, /* FIRST => ID */
- 59, /* LAST => ID */
- 59, /* CURRENT => ID */
- 59, /* FOLLOWING => ID */
- 59, /* PARTITION => ID */
- 59, /* PRECEDING => ID */
- 59, /* RANGE => ID */
- 59, /* UNBOUNDED => ID */
- 59, /* EXCLUDE => ID */
- 59, /* GROUPS => ID */
- 59, /* OTHERS => ID */
- 59, /* TIES => ID */
- 59, /* GENERATED => ID */
- 59, /* ALWAYS => ID */
- 59, /* MATERIALIZED => ID */
- 59, /* REINDEX => ID */
- 59, /* RENAME => ID */
- 59, /* CTIME_KW => ID */
+ 60, /* COLUMNKW => ID */
+ 60, /* DO => ID */
+ 60, /* FOR => ID */
+ 60, /* IGNORE => ID */
+ 60, /* INITIALLY => ID */
+ 60, /* INSTEAD => ID */
+ 60, /* NO => ID */
+ 60, /* KEY => ID */
+ 60, /* OF => ID */
+ 60, /* OFFSET => ID */
+ 60, /* PRAGMA => ID */
+ 60, /* RAISE => ID */
+ 60, /* RECURSIVE => ID */
+ 60, /* REPLACE => ID */
+ 60, /* RESTRICT => ID */
+ 60, /* ROW => ID */
+ 60, /* ROWS => ID */
+ 60, /* TRIGGER => ID */
+ 60, /* VACUUM => ID */
+ 60, /* VIEW => ID */
+ 60, /* VIRTUAL => ID */
+ 60, /* WITH => ID */
+ 60, /* NULLS => ID */
+ 60, /* FIRST => ID */
+ 60, /* LAST => ID */
+ 60, /* CURRENT => ID */
+ 60, /* FOLLOWING => ID */
+ 60, /* PARTITION => ID */
+ 60, /* PRECEDING => ID */
+ 60, /* RANGE => ID */
+ 60, /* UNBOUNDED => ID */
+ 60, /* EXCLUDE => ID */
+ 60, /* GROUPS => ID */
+ 60, /* OTHERS => ID */
+ 60, /* TIES => ID */
+ 60, /* GENERATED => ID */
+ 60, /* ALWAYS => ID */
+ 60, /* MATERIALIZED => ID */
+ 60, /* REINDEX => ID */
+ 60, /* RENAME => ID */
+ 60, /* CTIME_KW => ID */
0, /* ANY => nothing */
0, /* BITAND => nothing */
0, /* BITOR => nothing */
@@ -173890,7 +176702,6 @@ static const YYCODETYPE yyFallback[] = {
0, /* AGG_FUNCTION => nothing */
0, /* AGG_COLUMN => nothing */
0, /* TRUEFALSE => nothing */
- 0, /* ISNOT => nothing */
0, /* FUNCTION => nothing */
0, /* UPLUS => nothing */
0, /* UMINUS => nothing */
@@ -173904,6 +176715,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* ERROR => nothing */
0, /* QNUMBER => nothing */
0, /* SPACE => nothing */
+ 0, /* COMMENT => nothing */
0, /* ILLEGAL => nothing */
};
#endif /* YYFALLBACK */
@@ -174034,132 +176846,132 @@ static const char *const yyTokenName[] = {
/* 43 */ "OR",
/* 44 */ "AND",
/* 45 */ "IS",
- /* 46 */ "MATCH",
- /* 47 */ "LIKE_KW",
- /* 48 */ "BETWEEN",
- /* 49 */ "IN",
- /* 50 */ "ISNULL",
- /* 51 */ "NOTNULL",
- /* 52 */ "NE",
- /* 53 */ "EQ",
- /* 54 */ "GT",
- /* 55 */ "LE",
- /* 56 */ "LT",
- /* 57 */ "GE",
- /* 58 */ "ESCAPE",
- /* 59 */ "ID",
- /* 60 */ "COLUMNKW",
- /* 61 */ "DO",
- /* 62 */ "FOR",
- /* 63 */ "IGNORE",
- /* 64 */ "INITIALLY",
- /* 65 */ "INSTEAD",
- /* 66 */ "NO",
- /* 67 */ "KEY",
- /* 68 */ "OF",
- /* 69 */ "OFFSET",
- /* 70 */ "PRAGMA",
- /* 71 */ "RAISE",
- /* 72 */ "RECURSIVE",
- /* 73 */ "REPLACE",
- /* 74 */ "RESTRICT",
- /* 75 */ "ROW",
- /* 76 */ "ROWS",
- /* 77 */ "TRIGGER",
- /* 78 */ "VACUUM",
- /* 79 */ "VIEW",
- /* 80 */ "VIRTUAL",
- /* 81 */ "WITH",
- /* 82 */ "NULLS",
- /* 83 */ "FIRST",
- /* 84 */ "LAST",
- /* 85 */ "CURRENT",
- /* 86 */ "FOLLOWING",
- /* 87 */ "PARTITION",
- /* 88 */ "PRECEDING",
- /* 89 */ "RANGE",
- /* 90 */ "UNBOUNDED",
- /* 91 */ "EXCLUDE",
- /* 92 */ "GROUPS",
- /* 93 */ "OTHERS",
- /* 94 */ "TIES",
- /* 95 */ "GENERATED",
- /* 96 */ "ALWAYS",
- /* 97 */ "MATERIALIZED",
- /* 98 */ "REINDEX",
- /* 99 */ "RENAME",
- /* 100 */ "CTIME_KW",
- /* 101 */ "ANY",
- /* 102 */ "BITAND",
- /* 103 */ "BITOR",
- /* 104 */ "LSHIFT",
- /* 105 */ "RSHIFT",
- /* 106 */ "PLUS",
- /* 107 */ "MINUS",
- /* 108 */ "STAR",
- /* 109 */ "SLASH",
- /* 110 */ "REM",
- /* 111 */ "CONCAT",
- /* 112 */ "PTR",
- /* 113 */ "COLLATE",
- /* 114 */ "BITNOT",
- /* 115 */ "ON",
- /* 116 */ "INDEXED",
- /* 117 */ "STRING",
- /* 118 */ "JOIN_KW",
- /* 119 */ "CONSTRAINT",
- /* 120 */ "DEFAULT",
- /* 121 */ "NULL",
- /* 122 */ "PRIMARY",
- /* 123 */ "UNIQUE",
- /* 124 */ "CHECK",
- /* 125 */ "REFERENCES",
- /* 126 */ "AUTOINCR",
- /* 127 */ "INSERT",
- /* 128 */ "DELETE",
- /* 129 */ "UPDATE",
- /* 130 */ "SET",
- /* 131 */ "DEFERRABLE",
- /* 132 */ "FOREIGN",
- /* 133 */ "DROP",
- /* 134 */ "UNION",
- /* 135 */ "ALL",
- /* 136 */ "EXCEPT",
- /* 137 */ "INTERSECT",
- /* 138 */ "SELECT",
- /* 139 */ "VALUES",
- /* 140 */ "DISTINCT",
- /* 141 */ "DOT",
- /* 142 */ "FROM",
- /* 143 */ "JOIN",
- /* 144 */ "USING",
- /* 145 */ "ORDER",
- /* 146 */ "GROUP",
- /* 147 */ "HAVING",
- /* 148 */ "LIMIT",
- /* 149 */ "WHERE",
- /* 150 */ "RETURNING",
- /* 151 */ "INTO",
- /* 152 */ "NOTHING",
- /* 153 */ "FLOAT",
- /* 154 */ "BLOB",
- /* 155 */ "INTEGER",
- /* 156 */ "VARIABLE",
- /* 157 */ "CASE",
- /* 158 */ "WHEN",
- /* 159 */ "THEN",
- /* 160 */ "ELSE",
- /* 161 */ "INDEX",
- /* 162 */ "ALTER",
- /* 163 */ "ADD",
- /* 164 */ "WINDOW",
- /* 165 */ "OVER",
- /* 166 */ "FILTER",
- /* 167 */ "COLUMN",
- /* 168 */ "AGG_FUNCTION",
- /* 169 */ "AGG_COLUMN",
- /* 170 */ "TRUEFALSE",
- /* 171 */ "ISNOT",
+ /* 46 */ "ISNOT",
+ /* 47 */ "MATCH",
+ /* 48 */ "LIKE_KW",
+ /* 49 */ "BETWEEN",
+ /* 50 */ "IN",
+ /* 51 */ "ISNULL",
+ /* 52 */ "NOTNULL",
+ /* 53 */ "NE",
+ /* 54 */ "EQ",
+ /* 55 */ "GT",
+ /* 56 */ "LE",
+ /* 57 */ "LT",
+ /* 58 */ "GE",
+ /* 59 */ "ESCAPE",
+ /* 60 */ "ID",
+ /* 61 */ "COLUMNKW",
+ /* 62 */ "DO",
+ /* 63 */ "FOR",
+ /* 64 */ "IGNORE",
+ /* 65 */ "INITIALLY",
+ /* 66 */ "INSTEAD",
+ /* 67 */ "NO",
+ /* 68 */ "KEY",
+ /* 69 */ "OF",
+ /* 70 */ "OFFSET",
+ /* 71 */ "PRAGMA",
+ /* 72 */ "RAISE",
+ /* 73 */ "RECURSIVE",
+ /* 74 */ "REPLACE",
+ /* 75 */ "RESTRICT",
+ /* 76 */ "ROW",
+ /* 77 */ "ROWS",
+ /* 78 */ "TRIGGER",
+ /* 79 */ "VACUUM",
+ /* 80 */ "VIEW",
+ /* 81 */ "VIRTUAL",
+ /* 82 */ "WITH",
+ /* 83 */ "NULLS",
+ /* 84 */ "FIRST",
+ /* 85 */ "LAST",
+ /* 86 */ "CURRENT",
+ /* 87 */ "FOLLOWING",
+ /* 88 */ "PARTITION",
+ /* 89 */ "PRECEDING",
+ /* 90 */ "RANGE",
+ /* 91 */ "UNBOUNDED",
+ /* 92 */ "EXCLUDE",
+ /* 93 */ "GROUPS",
+ /* 94 */ "OTHERS",
+ /* 95 */ "TIES",
+ /* 96 */ "GENERATED",
+ /* 97 */ "ALWAYS",
+ /* 98 */ "MATERIALIZED",
+ /* 99 */ "REINDEX",
+ /* 100 */ "RENAME",
+ /* 101 */ "CTIME_KW",
+ /* 102 */ "ANY",
+ /* 103 */ "BITAND",
+ /* 104 */ "BITOR",
+ /* 105 */ "LSHIFT",
+ /* 106 */ "RSHIFT",
+ /* 107 */ "PLUS",
+ /* 108 */ "MINUS",
+ /* 109 */ "STAR",
+ /* 110 */ "SLASH",
+ /* 111 */ "REM",
+ /* 112 */ "CONCAT",
+ /* 113 */ "PTR",
+ /* 114 */ "COLLATE",
+ /* 115 */ "BITNOT",
+ /* 116 */ "ON",
+ /* 117 */ "INDEXED",
+ /* 118 */ "STRING",
+ /* 119 */ "JOIN_KW",
+ /* 120 */ "CONSTRAINT",
+ /* 121 */ "DEFAULT",
+ /* 122 */ "NULL",
+ /* 123 */ "PRIMARY",
+ /* 124 */ "UNIQUE",
+ /* 125 */ "CHECK",
+ /* 126 */ "REFERENCES",
+ /* 127 */ "AUTOINCR",
+ /* 128 */ "INSERT",
+ /* 129 */ "DELETE",
+ /* 130 */ "UPDATE",
+ /* 131 */ "SET",
+ /* 132 */ "DEFERRABLE",
+ /* 133 */ "FOREIGN",
+ /* 134 */ "DROP",
+ /* 135 */ "UNION",
+ /* 136 */ "ALL",
+ /* 137 */ "EXCEPT",
+ /* 138 */ "INTERSECT",
+ /* 139 */ "SELECT",
+ /* 140 */ "VALUES",
+ /* 141 */ "DISTINCT",
+ /* 142 */ "DOT",
+ /* 143 */ "FROM",
+ /* 144 */ "JOIN",
+ /* 145 */ "USING",
+ /* 146 */ "ORDER",
+ /* 147 */ "GROUP",
+ /* 148 */ "HAVING",
+ /* 149 */ "LIMIT",
+ /* 150 */ "WHERE",
+ /* 151 */ "RETURNING",
+ /* 152 */ "INTO",
+ /* 153 */ "NOTHING",
+ /* 154 */ "FLOAT",
+ /* 155 */ "BLOB",
+ /* 156 */ "INTEGER",
+ /* 157 */ "VARIABLE",
+ /* 158 */ "CASE",
+ /* 159 */ "WHEN",
+ /* 160 */ "THEN",
+ /* 161 */ "ELSE",
+ /* 162 */ "INDEX",
+ /* 163 */ "ALTER",
+ /* 164 */ "ADD",
+ /* 165 */ "WINDOW",
+ /* 166 */ "OVER",
+ /* 167 */ "FILTER",
+ /* 168 */ "COLUMN",
+ /* 169 */ "AGG_FUNCTION",
+ /* 170 */ "AGG_COLUMN",
+ /* 171 */ "TRUEFALSE",
/* 172 */ "FUNCTION",
/* 173 */ "UPLUS",
/* 174 */ "UMINUS",
@@ -174173,143 +176985,144 @@ static const char *const yyTokenName[] = {
/* 182 */ "ERROR",
/* 183 */ "QNUMBER",
/* 184 */ "SPACE",
- /* 185 */ "ILLEGAL",
- /* 186 */ "input",
- /* 187 */ "cmdlist",
- /* 188 */ "ecmd",
- /* 189 */ "cmdx",
- /* 190 */ "explain",
- /* 191 */ "cmd",
- /* 192 */ "transtype",
- /* 193 */ "trans_opt",
- /* 194 */ "nm",
- /* 195 */ "savepoint_opt",
- /* 196 */ "create_table",
- /* 197 */ "create_table_args",
- /* 198 */ "createkw",
- /* 199 */ "temp",
- /* 200 */ "ifnotexists",
- /* 201 */ "dbnm",
- /* 202 */ "columnlist",
- /* 203 */ "conslist_opt",
- /* 204 */ "table_option_set",
- /* 205 */ "select",
- /* 206 */ "table_option",
- /* 207 */ "columnname",
- /* 208 */ "carglist",
- /* 209 */ "typetoken",
- /* 210 */ "typename",
- /* 211 */ "signed",
- /* 212 */ "plus_num",
- /* 213 */ "minus_num",
- /* 214 */ "scanpt",
- /* 215 */ "scantok",
- /* 216 */ "ccons",
- /* 217 */ "term",
- /* 218 */ "expr",
- /* 219 */ "onconf",
- /* 220 */ "sortorder",
- /* 221 */ "autoinc",
- /* 222 */ "eidlist_opt",
- /* 223 */ "refargs",
- /* 224 */ "defer_subclause",
- /* 225 */ "generated",
- /* 226 */ "refarg",
- /* 227 */ "refact",
- /* 228 */ "init_deferred_pred_opt",
- /* 229 */ "conslist",
- /* 230 */ "tconscomma",
- /* 231 */ "tcons",
- /* 232 */ "sortlist",
- /* 233 */ "eidlist",
- /* 234 */ "defer_subclause_opt",
- /* 235 */ "orconf",
- /* 236 */ "resolvetype",
- /* 237 */ "raisetype",
- /* 238 */ "ifexists",
- /* 239 */ "fullname",
- /* 240 */ "selectnowith",
- /* 241 */ "oneselect",
- /* 242 */ "wqlist",
- /* 243 */ "multiselect_op",
- /* 244 */ "distinct",
- /* 245 */ "selcollist",
- /* 246 */ "from",
- /* 247 */ "where_opt",
- /* 248 */ "groupby_opt",
- /* 249 */ "having_opt",
- /* 250 */ "orderby_opt",
- /* 251 */ "limit_opt",
- /* 252 */ "window_clause",
- /* 253 */ "values",
- /* 254 */ "nexprlist",
- /* 255 */ "mvalues",
- /* 256 */ "sclp",
- /* 257 */ "as",
- /* 258 */ "seltablist",
- /* 259 */ "stl_prefix",
- /* 260 */ "joinop",
- /* 261 */ "on_using",
- /* 262 */ "indexed_by",
- /* 263 */ "exprlist",
- /* 264 */ "xfullname",
- /* 265 */ "idlist",
- /* 266 */ "indexed_opt",
- /* 267 */ "nulls",
- /* 268 */ "with",
- /* 269 */ "where_opt_ret",
- /* 270 */ "setlist",
- /* 271 */ "insert_cmd",
- /* 272 */ "idlist_opt",
- /* 273 */ "upsert",
- /* 274 */ "returning",
- /* 275 */ "filter_over",
- /* 276 */ "likeop",
- /* 277 */ "between_op",
- /* 278 */ "in_op",
- /* 279 */ "paren_exprlist",
- /* 280 */ "case_operand",
- /* 281 */ "case_exprlist",
- /* 282 */ "case_else",
- /* 283 */ "uniqueflag",
- /* 284 */ "collate",
- /* 285 */ "vinto",
- /* 286 */ "nmnum",
- /* 287 */ "trigger_decl",
- /* 288 */ "trigger_cmd_list",
- /* 289 */ "trigger_time",
- /* 290 */ "trigger_event",
- /* 291 */ "foreach_clause",
- /* 292 */ "when_clause",
- /* 293 */ "trigger_cmd",
- /* 294 */ "trnm",
- /* 295 */ "tridxby",
- /* 296 */ "database_kw_opt",
- /* 297 */ "key_opt",
- /* 298 */ "add_column_fullname",
- /* 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",
+ /* 185 */ "COMMENT",
+ /* 186 */ "ILLEGAL",
+ /* 187 */ "input",
+ /* 188 */ "cmdlist",
+ /* 189 */ "ecmd",
+ /* 190 */ "cmdx",
+ /* 191 */ "explain",
+ /* 192 */ "cmd",
+ /* 193 */ "transtype",
+ /* 194 */ "trans_opt",
+ /* 195 */ "nm",
+ /* 196 */ "savepoint_opt",
+ /* 197 */ "create_table",
+ /* 198 */ "create_table_args",
+ /* 199 */ "createkw",
+ /* 200 */ "temp",
+ /* 201 */ "ifnotexists",
+ /* 202 */ "dbnm",
+ /* 203 */ "columnlist",
+ /* 204 */ "conslist_opt",
+ /* 205 */ "table_option_set",
+ /* 206 */ "select",
+ /* 207 */ "table_option",
+ /* 208 */ "columnname",
+ /* 209 */ "carglist",
+ /* 210 */ "typetoken",
+ /* 211 */ "typename",
+ /* 212 */ "signed",
+ /* 213 */ "plus_num",
+ /* 214 */ "minus_num",
+ /* 215 */ "scanpt",
+ /* 216 */ "scantok",
+ /* 217 */ "ccons",
+ /* 218 */ "term",
+ /* 219 */ "expr",
+ /* 220 */ "onconf",
+ /* 221 */ "sortorder",
+ /* 222 */ "autoinc",
+ /* 223 */ "eidlist_opt",
+ /* 224 */ "refargs",
+ /* 225 */ "defer_subclause",
+ /* 226 */ "generated",
+ /* 227 */ "refarg",
+ /* 228 */ "refact",
+ /* 229 */ "init_deferred_pred_opt",
+ /* 230 */ "conslist",
+ /* 231 */ "tconscomma",
+ /* 232 */ "tcons",
+ /* 233 */ "sortlist",
+ /* 234 */ "eidlist",
+ /* 235 */ "defer_subclause_opt",
+ /* 236 */ "orconf",
+ /* 237 */ "resolvetype",
+ /* 238 */ "raisetype",
+ /* 239 */ "ifexists",
+ /* 240 */ "fullname",
+ /* 241 */ "selectnowith",
+ /* 242 */ "oneselect",
+ /* 243 */ "wqlist",
+ /* 244 */ "multiselect_op",
+ /* 245 */ "distinct",
+ /* 246 */ "selcollist",
+ /* 247 */ "from",
+ /* 248 */ "where_opt",
+ /* 249 */ "groupby_opt",
+ /* 250 */ "having_opt",
+ /* 251 */ "orderby_opt",
+ /* 252 */ "limit_opt",
+ /* 253 */ "window_clause",
+ /* 254 */ "values",
+ /* 255 */ "nexprlist",
+ /* 256 */ "mvalues",
+ /* 257 */ "sclp",
+ /* 258 */ "as",
+ /* 259 */ "seltablist",
+ /* 260 */ "stl_prefix",
+ /* 261 */ "joinop",
+ /* 262 */ "on_using",
+ /* 263 */ "indexed_by",
+ /* 264 */ "exprlist",
+ /* 265 */ "xfullname",
+ /* 266 */ "idlist",
+ /* 267 */ "indexed_opt",
+ /* 268 */ "nulls",
+ /* 269 */ "with",
+ /* 270 */ "where_opt_ret",
+ /* 271 */ "setlist",
+ /* 272 */ "insert_cmd",
+ /* 273 */ "idlist_opt",
+ /* 274 */ "upsert",
+ /* 275 */ "returning",
+ /* 276 */ "filter_over",
+ /* 277 */ "likeop",
+ /* 278 */ "between_op",
+ /* 279 */ "in_op",
+ /* 280 */ "paren_exprlist",
+ /* 281 */ "case_operand",
+ /* 282 */ "case_exprlist",
+ /* 283 */ "case_else",
+ /* 284 */ "uniqueflag",
+ /* 285 */ "collate",
+ /* 286 */ "vinto",
+ /* 287 */ "nmnum",
+ /* 288 */ "trigger_decl",
+ /* 289 */ "trigger_cmd_list",
+ /* 290 */ "trigger_time",
+ /* 291 */ "trigger_event",
+ /* 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",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -174597,7 +177410,7 @@ static const char *const yyRuleName[] = {
/* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
/* 278 */ "trigger_cmd ::= scanpt select scanpt",
/* 279 */ "expr ::= RAISE LP IGNORE RP",
- /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP",
/* 281 */ "raisetype ::= ROLLBACK",
/* 282 */ "raisetype ::= ABORT",
/* 283 */ "raisetype ::= FAIL",
@@ -174849,98 +177662,98 @@ static void yy_destructor(
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
- case 205: /* select */
- case 240: /* selectnowith */
- case 241: /* oneselect */
- case 253: /* values */
- case 255: /* mvalues */
+ case 206: /* select */
+ case 241: /* selectnowith */
+ case 242: /* oneselect */
+ case 254: /* values */
+ case 256: /* mvalues */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy555));
-}
- break;
- case 217: /* term */
- case 218: /* expr */
- case 247: /* where_opt */
- case 249: /* having_opt */
- case 269: /* where_opt_ret */
- case 280: /* case_operand */
- case 282: /* case_else */
- case 285: /* vinto */
- case 292: /* when_clause */
- case 297: /* key_opt */
- case 314: /* filter_clause */
+sqlite3SelectDelete(pParse->db, (yypminor->yy637));
+}
+ break;
+ case 218: /* term */
+ case 219: /* expr */
+ case 248: /* where_opt */
+ case 250: /* having_opt */
+ case 270: /* where_opt_ret */
+ case 281: /* case_operand */
+ case 283: /* case_else */
+ case 286: /* vinto */
+ case 293: /* when_clause */
+ case 298: /* key_opt */
+ case 315: /* filter_clause */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy454));
-}
- break;
- case 222: /* eidlist_opt */
- case 232: /* sortlist */
- case 233: /* eidlist */
- case 245: /* selcollist */
- case 248: /* groupby_opt */
- case 250: /* orderby_opt */
- case 254: /* nexprlist */
- case 256: /* sclp */
- case 263: /* exprlist */
- case 270: /* setlist */
- case 279: /* paren_exprlist */
- case 281: /* case_exprlist */
- case 313: /* part_opt */
+sqlite3ExprDelete(pParse->db, (yypminor->yy590));
+}
+ break;
+ case 223: /* eidlist_opt */
+ case 233: /* sortlist */
+ case 234: /* eidlist */
+ case 246: /* selcollist */
+ case 249: /* groupby_opt */
+ case 251: /* orderby_opt */
+ case 255: /* nexprlist */
+ case 257: /* sclp */
+ case 264: /* exprlist */
+ case 271: /* setlist */
+ case 280: /* paren_exprlist */
+ case 282: /* case_exprlist */
+ case 314: /* part_opt */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy14));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy402));
}
break;
- case 239: /* fullname */
- case 246: /* from */
- case 258: /* seltablist */
- case 259: /* stl_prefix */
- case 264: /* xfullname */
+ case 240: /* fullname */
+ case 247: /* from */
+ case 259: /* seltablist */
+ case 260: /* stl_prefix */
+ case 265: /* xfullname */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy203));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy563));
}
break;
- case 242: /* wqlist */
+ case 243: /* wqlist */
{
-sqlite3WithDelete(pParse->db, (yypminor->yy59));
+sqlite3WithDelete(pParse->db, (yypminor->yy125));
}
break;
- case 252: /* window_clause */
- case 309: /* windowdefn_list */
+ case 253: /* window_clause */
+ case 310: /* windowdefn_list */
{
-sqlite3WindowListDelete(pParse->db, (yypminor->yy211));
+sqlite3WindowListDelete(pParse->db, (yypminor->yy483));
}
break;
- case 265: /* idlist */
- case 272: /* idlist_opt */
+ case 266: /* idlist */
+ case 273: /* idlist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy132));
+sqlite3IdListDelete(pParse->db, (yypminor->yy204));
}
break;
- case 275: /* filter_over */
- case 310: /* windowdefn */
- case 311: /* window */
- case 312: /* frame_opt */
- case 315: /* over_clause */
+ case 276: /* filter_over */
+ case 311: /* windowdefn */
+ case 312: /* window */
+ case 313: /* frame_opt */
+ case 316: /* over_clause */
{
-sqlite3WindowDelete(pParse->db, (yypminor->yy211));
+sqlite3WindowDelete(pParse->db, (yypminor->yy483));
}
break;
- case 288: /* trigger_cmd_list */
- case 293: /* trigger_cmd */
+ case 289: /* trigger_cmd_list */
+ case 294: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy319));
}
break;
- case 290: /* trigger_event */
+ case 291: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy286).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy28).b);
}
break;
- case 317: /* frame_bound */
- case 318: /* frame_bound_s */
- case 319: /* frame_bound_e */
+ case 318: /* frame_bound */
+ case 319: /* frame_bound_s */
+ case 320: /* frame_bound_e */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy509).pExpr);
+sqlite3ExprDelete(pParse->db, (yypminor->yy205).pExpr);
}
break;
/********* End destructor definitions *****************************************/
@@ -175242,415 +178055,415 @@ static void yy_shift(
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
- 190, /* (0) explain ::= EXPLAIN */
- 190, /* (1) explain ::= EXPLAIN QUERY PLAN */
- 189, /* (2) cmdx ::= cmd */
- 191, /* (3) cmd ::= BEGIN transtype trans_opt */
- 192, /* (4) transtype ::= */
- 192, /* (5) transtype ::= DEFERRED */
- 192, /* (6) transtype ::= IMMEDIATE */
- 192, /* (7) transtype ::= EXCLUSIVE */
- 191, /* (8) cmd ::= COMMIT|END trans_opt */
- 191, /* (9) cmd ::= ROLLBACK trans_opt */
- 191, /* (10) cmd ::= SAVEPOINT nm */
- 191, /* (11) cmd ::= RELEASE savepoint_opt nm */
- 191, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
- 196, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
- 198, /* (14) createkw ::= CREATE */
- 200, /* (15) ifnotexists ::= */
- 200, /* (16) ifnotexists ::= IF NOT EXISTS */
- 199, /* (17) temp ::= TEMP */
- 199, /* (18) temp ::= */
- 197, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */
- 197, /* (20) create_table_args ::= AS select */
- 204, /* (21) table_option_set ::= */
- 204, /* (22) table_option_set ::= table_option_set COMMA table_option */
- 206, /* (23) table_option ::= WITHOUT nm */
- 206, /* (24) table_option ::= nm */
- 207, /* (25) columnname ::= nm typetoken */
- 209, /* (26) typetoken ::= */
- 209, /* (27) typetoken ::= typename LP signed RP */
- 209, /* (28) typetoken ::= typename LP signed COMMA signed RP */
- 210, /* (29) typename ::= typename ID|STRING */
- 214, /* (30) scanpt ::= */
- 215, /* (31) scantok ::= */
- 216, /* (32) ccons ::= CONSTRAINT nm */
- 216, /* (33) ccons ::= DEFAULT scantok term */
- 216, /* (34) ccons ::= DEFAULT LP expr RP */
- 216, /* (35) ccons ::= DEFAULT PLUS scantok term */
- 216, /* (36) ccons ::= DEFAULT MINUS scantok term */
- 216, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */
- 216, /* (38) ccons ::= NOT NULL onconf */
- 216, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */
- 216, /* (40) ccons ::= UNIQUE onconf */
- 216, /* (41) ccons ::= CHECK LP expr RP */
- 216, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */
- 216, /* (43) ccons ::= defer_subclause */
- 216, /* (44) ccons ::= COLLATE ID|STRING */
- 225, /* (45) generated ::= LP expr RP */
- 225, /* (46) generated ::= LP expr RP ID */
- 221, /* (47) autoinc ::= */
- 221, /* (48) autoinc ::= AUTOINCR */
- 223, /* (49) refargs ::= */
- 223, /* (50) refargs ::= refargs refarg */
- 226, /* (51) refarg ::= MATCH nm */
- 226, /* (52) refarg ::= ON INSERT refact */
- 226, /* (53) refarg ::= ON DELETE refact */
- 226, /* (54) refarg ::= ON UPDATE refact */
- 227, /* (55) refact ::= SET NULL */
- 227, /* (56) refact ::= SET DEFAULT */
- 227, /* (57) refact ::= CASCADE */
- 227, /* (58) refact ::= RESTRICT */
- 227, /* (59) refact ::= NO ACTION */
- 224, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- 224, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- 228, /* (62) init_deferred_pred_opt ::= */
- 228, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- 228, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- 203, /* (65) conslist_opt ::= */
- 230, /* (66) tconscomma ::= COMMA */
- 231, /* (67) tcons ::= CONSTRAINT nm */
- 231, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- 231, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */
- 231, /* (70) tcons ::= CHECK LP expr RP onconf */
- 231, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- 234, /* (72) defer_subclause_opt ::= */
- 219, /* (73) onconf ::= */
- 219, /* (74) onconf ::= ON CONFLICT resolvetype */
- 235, /* (75) orconf ::= */
- 235, /* (76) orconf ::= OR resolvetype */
- 236, /* (77) resolvetype ::= IGNORE */
- 236, /* (78) resolvetype ::= REPLACE */
- 191, /* (79) cmd ::= DROP TABLE ifexists fullname */
- 238, /* (80) ifexists ::= IF EXISTS */
- 238, /* (81) ifexists ::= */
- 191, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- 191, /* (83) cmd ::= DROP VIEW ifexists fullname */
- 191, /* (84) cmd ::= select */
- 205, /* (85) select ::= WITH wqlist selectnowith */
- 205, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */
- 205, /* (87) select ::= selectnowith */
- 240, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */
- 243, /* (89) multiselect_op ::= UNION */
- 243, /* (90) multiselect_op ::= UNION ALL */
- 243, /* (91) multiselect_op ::= EXCEPT|INTERSECT */
- 241, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- 241, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
- 253, /* (94) values ::= VALUES LP nexprlist RP */
- 241, /* (95) oneselect ::= mvalues */
- 255, /* (96) mvalues ::= values COMMA LP nexprlist RP */
- 255, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */
- 244, /* (98) distinct ::= DISTINCT */
- 244, /* (99) distinct ::= ALL */
- 244, /* (100) distinct ::= */
- 256, /* (101) sclp ::= */
- 245, /* (102) selcollist ::= sclp scanpt expr scanpt as */
- 245, /* (103) selcollist ::= sclp scanpt STAR */
- 245, /* (104) selcollist ::= sclp scanpt nm DOT STAR */
- 257, /* (105) as ::= AS nm */
- 257, /* (106) as ::= */
- 246, /* (107) from ::= */
- 246, /* (108) from ::= FROM seltablist */
- 259, /* (109) stl_prefix ::= seltablist joinop */
- 259, /* (110) stl_prefix ::= */
- 258, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */
- 258, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
- 258, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
- 258, /* (114) seltablist ::= stl_prefix LP select RP as on_using */
- 258, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */
- 201, /* (116) dbnm ::= */
- 201, /* (117) dbnm ::= DOT nm */
- 239, /* (118) fullname ::= nm */
- 239, /* (119) fullname ::= nm DOT nm */
- 264, /* (120) xfullname ::= nm */
- 264, /* (121) xfullname ::= nm DOT nm */
- 264, /* (122) xfullname ::= nm DOT nm AS nm */
- 264, /* (123) xfullname ::= nm AS nm */
- 260, /* (124) joinop ::= COMMA|JOIN */
- 260, /* (125) joinop ::= JOIN_KW JOIN */
- 260, /* (126) joinop ::= JOIN_KW nm JOIN */
- 260, /* (127) joinop ::= JOIN_KW nm nm JOIN */
- 261, /* (128) on_using ::= ON expr */
- 261, /* (129) on_using ::= USING LP idlist RP */
- 261, /* (130) on_using ::= */
- 266, /* (131) indexed_opt ::= */
- 262, /* (132) indexed_by ::= INDEXED BY nm */
- 262, /* (133) indexed_by ::= NOT INDEXED */
- 250, /* (134) orderby_opt ::= */
- 250, /* (135) orderby_opt ::= ORDER BY sortlist */
- 232, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */
- 232, /* (137) sortlist ::= expr sortorder nulls */
- 220, /* (138) sortorder ::= ASC */
- 220, /* (139) sortorder ::= DESC */
- 220, /* (140) sortorder ::= */
- 267, /* (141) nulls ::= NULLS FIRST */
- 267, /* (142) nulls ::= NULLS LAST */
- 267, /* (143) nulls ::= */
- 248, /* (144) groupby_opt ::= */
- 248, /* (145) groupby_opt ::= GROUP BY nexprlist */
- 249, /* (146) having_opt ::= */
- 249, /* (147) having_opt ::= HAVING expr */
- 251, /* (148) limit_opt ::= */
- 251, /* (149) limit_opt ::= LIMIT expr */
- 251, /* (150) limit_opt ::= LIMIT expr OFFSET expr */
- 251, /* (151) limit_opt ::= LIMIT expr COMMA expr */
- 191, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
- 247, /* (153) where_opt ::= */
- 247, /* (154) where_opt ::= WHERE expr */
- 269, /* (155) where_opt_ret ::= */
- 269, /* (156) where_opt_ret ::= WHERE expr */
- 269, /* (157) where_opt_ret ::= RETURNING selcollist */
- 269, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */
- 191, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
- 270, /* (160) setlist ::= setlist COMMA nm EQ expr */
- 270, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */
- 270, /* (162) setlist ::= nm EQ expr */
- 270, /* (163) setlist ::= LP idlist RP EQ expr */
- 191, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- 191, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
- 273, /* (166) upsert ::= */
- 273, /* (167) upsert ::= RETURNING selcollist */
- 273, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
- 273, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
- 273, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */
- 273, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
- 274, /* (172) returning ::= RETURNING selcollist */
- 271, /* (173) insert_cmd ::= INSERT orconf */
- 271, /* (174) insert_cmd ::= REPLACE */
- 272, /* (175) idlist_opt ::= */
- 272, /* (176) idlist_opt ::= LP idlist RP */
- 265, /* (177) idlist ::= idlist COMMA nm */
- 265, /* (178) idlist ::= nm */
- 218, /* (179) expr ::= LP expr RP */
- 218, /* (180) expr ::= ID|INDEXED|JOIN_KW */
- 218, /* (181) expr ::= nm DOT nm */
- 218, /* (182) expr ::= nm DOT nm DOT nm */
- 217, /* (183) term ::= NULL|FLOAT|BLOB */
- 217, /* (184) term ::= STRING */
- 217, /* (185) term ::= INTEGER */
- 218, /* (186) expr ::= VARIABLE */
- 218, /* (187) expr ::= expr COLLATE ID|STRING */
- 218, /* (188) expr ::= CAST LP expr AS typetoken RP */
- 218, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */
- 218, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */
- 218, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */
- 218, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */
- 218, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */
- 218, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */
- 217, /* (195) term ::= CTIME_KW */
- 218, /* (196) expr ::= LP nexprlist COMMA expr RP */
- 218, /* (197) expr ::= expr AND expr */
- 218, /* (198) expr ::= expr OR expr */
- 218, /* (199) expr ::= expr LT|GT|GE|LE expr */
- 218, /* (200) expr ::= expr EQ|NE expr */
- 218, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- 218, /* (202) expr ::= expr PLUS|MINUS expr */
- 218, /* (203) expr ::= expr STAR|SLASH|REM expr */
- 218, /* (204) expr ::= expr CONCAT expr */
- 276, /* (205) likeop ::= NOT LIKE_KW|MATCH */
- 218, /* (206) expr ::= expr likeop expr */
- 218, /* (207) expr ::= expr likeop expr ESCAPE expr */
- 218, /* (208) expr ::= expr ISNULL|NOTNULL */
- 218, /* (209) expr ::= expr NOT NULL */
- 218, /* (210) expr ::= expr IS expr */
- 218, /* (211) expr ::= expr IS NOT expr */
- 218, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */
- 218, /* (213) expr ::= expr IS DISTINCT FROM expr */
- 218, /* (214) expr ::= NOT expr */
- 218, /* (215) expr ::= BITNOT expr */
- 218, /* (216) expr ::= PLUS|MINUS expr */
- 218, /* (217) expr ::= expr PTR expr */
- 277, /* (218) between_op ::= BETWEEN */
- 277, /* (219) between_op ::= NOT BETWEEN */
- 218, /* (220) expr ::= expr between_op expr AND expr */
- 278, /* (221) in_op ::= IN */
- 278, /* (222) in_op ::= NOT IN */
- 218, /* (223) expr ::= expr in_op LP exprlist RP */
- 218, /* (224) expr ::= LP select RP */
- 218, /* (225) expr ::= expr in_op LP select RP */
- 218, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */
- 218, /* (227) expr ::= EXISTS LP select RP */
- 218, /* (228) expr ::= CASE case_operand case_exprlist case_else END */
- 281, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- 281, /* (230) case_exprlist ::= WHEN expr THEN expr */
- 282, /* (231) case_else ::= ELSE expr */
- 282, /* (232) case_else ::= */
- 280, /* (233) case_operand ::= */
- 263, /* (234) exprlist ::= */
- 254, /* (235) nexprlist ::= nexprlist COMMA expr */
- 254, /* (236) nexprlist ::= expr */
- 279, /* (237) paren_exprlist ::= */
- 279, /* (238) paren_exprlist ::= LP exprlist RP */
- 191, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- 283, /* (240) uniqueflag ::= UNIQUE */
- 283, /* (241) uniqueflag ::= */
- 222, /* (242) eidlist_opt ::= */
- 222, /* (243) eidlist_opt ::= LP eidlist RP */
- 233, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */
- 233, /* (245) eidlist ::= nm collate sortorder */
- 284, /* (246) collate ::= */
- 284, /* (247) collate ::= COLLATE ID|STRING */
- 191, /* (248) cmd ::= DROP INDEX ifexists fullname */
- 191, /* (249) cmd ::= VACUUM vinto */
- 191, /* (250) cmd ::= VACUUM nm vinto */
- 285, /* (251) vinto ::= INTO expr */
- 285, /* (252) vinto ::= */
- 191, /* (253) cmd ::= PRAGMA nm dbnm */
- 191, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */
- 191, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- 191, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */
- 191, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- 212, /* (258) plus_num ::= PLUS INTEGER|FLOAT */
- 213, /* (259) minus_num ::= MINUS INTEGER|FLOAT */
- 191, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- 287, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- 289, /* (262) trigger_time ::= BEFORE|AFTER */
- 289, /* (263) trigger_time ::= INSTEAD OF */
- 289, /* (264) trigger_time ::= */
- 290, /* (265) trigger_event ::= DELETE|INSERT */
- 290, /* (266) trigger_event ::= UPDATE */
- 290, /* (267) trigger_event ::= UPDATE OF idlist */
- 292, /* (268) when_clause ::= */
- 292, /* (269) when_clause ::= WHEN expr */
- 288, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- 288, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */
- 294, /* (272) trnm ::= nm DOT nm */
- 295, /* (273) tridxby ::= INDEXED BY nm */
- 295, /* (274) tridxby ::= NOT INDEXED */
- 293, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
- 293, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- 293, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- 293, /* (278) trigger_cmd ::= scanpt select scanpt */
- 218, /* (279) expr ::= RAISE LP IGNORE RP */
- 218, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
- 237, /* (281) raisetype ::= ROLLBACK */
- 237, /* (282) raisetype ::= ABORT */
- 237, /* (283) raisetype ::= FAIL */
- 191, /* (284) cmd ::= DROP TRIGGER ifexists fullname */
- 191, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- 191, /* (286) cmd ::= DETACH database_kw_opt expr */
- 297, /* (287) key_opt ::= */
- 297, /* (288) key_opt ::= KEY expr */
- 191, /* (289) cmd ::= REINDEX */
- 191, /* (290) cmd ::= REINDEX nm dbnm */
- 191, /* (291) cmd ::= ANALYZE */
- 191, /* (292) cmd ::= ANALYZE nm dbnm */
- 191, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */
- 191, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- 191, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
- 298, /* (296) add_column_fullname ::= fullname */
- 191, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- 191, /* (298) cmd ::= create_vtab */
- 191, /* (299) cmd ::= create_vtab LP vtabarglist RP */
- 300, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 302, /* (301) vtabarg ::= */
- 303, /* (302) vtabargtoken ::= ANY */
- 303, /* (303) vtabargtoken ::= lp anylist RP */
- 304, /* (304) lp ::= LP */
- 268, /* (305) with ::= WITH wqlist */
- 268, /* (306) with ::= WITH RECURSIVE wqlist */
- 307, /* (307) wqas ::= AS */
- 307, /* (308) wqas ::= AS MATERIALIZED */
- 307, /* (309) wqas ::= AS NOT MATERIALIZED */
- 306, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */
- 308, /* (311) withnm ::= nm */
- 242, /* (312) wqlist ::= wqitem */
- 242, /* (313) wqlist ::= wqlist COMMA wqitem */
- 309, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */
- 310, /* (315) windowdefn ::= nm AS LP window RP */
- 311, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
- 311, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
- 311, /* (318) window ::= ORDER BY sortlist frame_opt */
- 311, /* (319) window ::= nm ORDER BY sortlist frame_opt */
- 311, /* (320) window ::= nm frame_opt */
- 312, /* (321) frame_opt ::= */
- 312, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
- 312, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
- 316, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */
- 318, /* (325) frame_bound_s ::= frame_bound */
- 318, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */
- 319, /* (327) frame_bound_e ::= frame_bound */
- 319, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */
- 317, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */
- 317, /* (330) frame_bound ::= CURRENT ROW */
- 320, /* (331) frame_exclude_opt ::= */
- 320, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */
- 321, /* (333) frame_exclude ::= NO OTHERS */
- 321, /* (334) frame_exclude ::= CURRENT ROW */
- 321, /* (335) frame_exclude ::= GROUP|TIES */
- 252, /* (336) window_clause ::= WINDOW windowdefn_list */
- 275, /* (337) filter_over ::= filter_clause over_clause */
- 275, /* (338) filter_over ::= over_clause */
- 275, /* (339) filter_over ::= filter_clause */
- 315, /* (340) over_clause ::= OVER LP window RP */
- 315, /* (341) over_clause ::= OVER nm */
- 314, /* (342) filter_clause ::= FILTER LP WHERE expr RP */
- 217, /* (343) term ::= QNUMBER */
- 186, /* (344) input ::= cmdlist */
- 187, /* (345) cmdlist ::= cmdlist ecmd */
- 187, /* (346) cmdlist ::= ecmd */
- 188, /* (347) ecmd ::= SEMI */
- 188, /* (348) ecmd ::= cmdx SEMI */
- 188, /* (349) ecmd ::= explain cmdx SEMI */
- 193, /* (350) trans_opt ::= */
- 193, /* (351) trans_opt ::= TRANSACTION */
- 193, /* (352) trans_opt ::= TRANSACTION nm */
- 195, /* (353) savepoint_opt ::= SAVEPOINT */
- 195, /* (354) savepoint_opt ::= */
- 191, /* (355) cmd ::= create_table create_table_args */
- 204, /* (356) table_option_set ::= table_option */
- 202, /* (357) columnlist ::= columnlist COMMA columnname carglist */
- 202, /* (358) columnlist ::= columnname carglist */
- 194, /* (359) nm ::= ID|INDEXED|JOIN_KW */
- 194, /* (360) nm ::= STRING */
- 209, /* (361) typetoken ::= typename */
- 210, /* (362) typename ::= ID|STRING */
- 211, /* (363) signed ::= plus_num */
- 211, /* (364) signed ::= minus_num */
- 208, /* (365) carglist ::= carglist ccons */
- 208, /* (366) carglist ::= */
- 216, /* (367) ccons ::= NULL onconf */
- 216, /* (368) ccons ::= GENERATED ALWAYS AS generated */
- 216, /* (369) ccons ::= AS generated */
- 203, /* (370) conslist_opt ::= COMMA conslist */
- 229, /* (371) conslist ::= conslist tconscomma tcons */
- 229, /* (372) conslist ::= tcons */
- 230, /* (373) tconscomma ::= */
- 234, /* (374) defer_subclause_opt ::= defer_subclause */
- 236, /* (375) resolvetype ::= raisetype */
- 240, /* (376) selectnowith ::= oneselect */
- 241, /* (377) oneselect ::= values */
- 256, /* (378) sclp ::= selcollist COMMA */
- 257, /* (379) as ::= ID|STRING */
- 266, /* (380) indexed_opt ::= indexed_by */
- 274, /* (381) returning ::= */
- 218, /* (382) expr ::= term */
- 276, /* (383) likeop ::= LIKE_KW|MATCH */
- 280, /* (384) case_operand ::= expr */
- 263, /* (385) exprlist ::= nexprlist */
- 286, /* (386) nmnum ::= plus_num */
- 286, /* (387) nmnum ::= nm */
- 286, /* (388) nmnum ::= ON */
- 286, /* (389) nmnum ::= DELETE */
- 286, /* (390) nmnum ::= DEFAULT */
- 212, /* (391) plus_num ::= INTEGER|FLOAT */
- 291, /* (392) foreach_clause ::= */
- 291, /* (393) foreach_clause ::= FOR EACH ROW */
- 294, /* (394) trnm ::= nm */
- 295, /* (395) tridxby ::= */
- 296, /* (396) database_kw_opt ::= DATABASE */
- 296, /* (397) database_kw_opt ::= */
- 299, /* (398) kwcolumn_opt ::= */
- 299, /* (399) kwcolumn_opt ::= COLUMNKW */
- 301, /* (400) vtabarglist ::= vtabarg */
- 301, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */
- 302, /* (402) vtabarg ::= vtabarg vtabargtoken */
- 305, /* (403) anylist ::= */
- 305, /* (404) anylist ::= anylist LP anylist RP */
- 305, /* (405) anylist ::= anylist ANY */
- 268, /* (406) with ::= */
- 309, /* (407) windowdefn_list ::= windowdefn */
- 311, /* (408) window ::= frame_opt */
+ 191, /* (0) explain ::= EXPLAIN */
+ 191, /* (1) explain ::= EXPLAIN QUERY PLAN */
+ 190, /* (2) cmdx ::= cmd */
+ 192, /* (3) cmd ::= BEGIN transtype trans_opt */
+ 193, /* (4) transtype ::= */
+ 193, /* (5) transtype ::= DEFERRED */
+ 193, /* (6) transtype ::= IMMEDIATE */
+ 193, /* (7) transtype ::= EXCLUSIVE */
+ 192, /* (8) cmd ::= COMMIT|END trans_opt */
+ 192, /* (9) cmd ::= ROLLBACK trans_opt */
+ 192, /* (10) cmd ::= SAVEPOINT nm */
+ 192, /* (11) cmd ::= RELEASE savepoint_opt nm */
+ 192, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ 197, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ 199, /* (14) createkw ::= CREATE */
+ 201, /* (15) ifnotexists ::= */
+ 201, /* (16) ifnotexists ::= IF NOT EXISTS */
+ 200, /* (17) temp ::= TEMP */
+ 200, /* (18) temp ::= */
+ 198, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */
+ 198, /* (20) create_table_args ::= AS select */
+ 205, /* (21) table_option_set ::= */
+ 205, /* (22) table_option_set ::= table_option_set COMMA table_option */
+ 207, /* (23) table_option ::= WITHOUT nm */
+ 207, /* (24) table_option ::= nm */
+ 208, /* (25) columnname ::= nm typetoken */
+ 210, /* (26) typetoken ::= */
+ 210, /* (27) typetoken ::= typename LP signed RP */
+ 210, /* (28) typetoken ::= typename LP signed COMMA signed RP */
+ 211, /* (29) typename ::= typename ID|STRING */
+ 215, /* (30) scanpt ::= */
+ 216, /* (31) scantok ::= */
+ 217, /* (32) ccons ::= CONSTRAINT nm */
+ 217, /* (33) ccons ::= DEFAULT scantok term */
+ 217, /* (34) ccons ::= DEFAULT LP expr RP */
+ 217, /* (35) ccons ::= DEFAULT PLUS scantok term */
+ 217, /* (36) ccons ::= DEFAULT MINUS scantok term */
+ 217, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */
+ 217, /* (38) ccons ::= NOT NULL onconf */
+ 217, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ 217, /* (40) ccons ::= UNIQUE onconf */
+ 217, /* (41) ccons ::= CHECK LP expr RP */
+ 217, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */
+ 217, /* (43) ccons ::= defer_subclause */
+ 217, /* (44) ccons ::= COLLATE ID|STRING */
+ 226, /* (45) generated ::= LP expr RP */
+ 226, /* (46) generated ::= LP expr RP ID */
+ 222, /* (47) autoinc ::= */
+ 222, /* (48) autoinc ::= AUTOINCR */
+ 224, /* (49) refargs ::= */
+ 224, /* (50) refargs ::= refargs refarg */
+ 227, /* (51) refarg ::= MATCH nm */
+ 227, /* (52) refarg ::= ON INSERT refact */
+ 227, /* (53) refarg ::= ON DELETE refact */
+ 227, /* (54) refarg ::= ON UPDATE refact */
+ 228, /* (55) refact ::= SET NULL */
+ 228, /* (56) refact ::= SET DEFAULT */
+ 228, /* (57) refact ::= CASCADE */
+ 228, /* (58) refact ::= RESTRICT */
+ 228, /* (59) refact ::= NO ACTION */
+ 225, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ 225, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 229, /* (62) init_deferred_pred_opt ::= */
+ 229, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ 229, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 204, /* (65) conslist_opt ::= */
+ 231, /* (66) tconscomma ::= COMMA */
+ 232, /* (67) tcons ::= CONSTRAINT nm */
+ 232, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ 232, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */
+ 232, /* (70) tcons ::= CHECK LP expr RP onconf */
+ 232, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 235, /* (72) defer_subclause_opt ::= */
+ 220, /* (73) onconf ::= */
+ 220, /* (74) onconf ::= ON CONFLICT resolvetype */
+ 236, /* (75) orconf ::= */
+ 236, /* (76) orconf ::= OR resolvetype */
+ 237, /* (77) resolvetype ::= IGNORE */
+ 237, /* (78) resolvetype ::= REPLACE */
+ 192, /* (79) cmd ::= DROP TABLE ifexists fullname */
+ 239, /* (80) ifexists ::= IF EXISTS */
+ 239, /* (81) ifexists ::= */
+ 192, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ 192, /* (83) cmd ::= DROP VIEW ifexists fullname */
+ 192, /* (84) cmd ::= select */
+ 206, /* (85) select ::= WITH wqlist selectnowith */
+ 206, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */
+ 206, /* (87) select ::= selectnowith */
+ 241, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */
+ 244, /* (89) multiselect_op ::= UNION */
+ 244, /* (90) multiselect_op ::= UNION ALL */
+ 244, /* (91) multiselect_op ::= EXCEPT|INTERSECT */
+ 242, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ 242, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ 254, /* (94) values ::= VALUES LP nexprlist RP */
+ 242, /* (95) oneselect ::= mvalues */
+ 256, /* (96) mvalues ::= values COMMA LP nexprlist RP */
+ 256, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */
+ 245, /* (98) distinct ::= DISTINCT */
+ 245, /* (99) distinct ::= ALL */
+ 245, /* (100) distinct ::= */
+ 257, /* (101) sclp ::= */
+ 246, /* (102) selcollist ::= sclp scanpt expr scanpt as */
+ 246, /* (103) selcollist ::= sclp scanpt STAR */
+ 246, /* (104) selcollist ::= sclp scanpt nm DOT STAR */
+ 258, /* (105) as ::= AS nm */
+ 258, /* (106) as ::= */
+ 247, /* (107) from ::= */
+ 247, /* (108) from ::= FROM seltablist */
+ 260, /* (109) stl_prefix ::= seltablist joinop */
+ 260, /* (110) stl_prefix ::= */
+ 259, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */
+ 259, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
+ 259, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
+ 259, /* (114) seltablist ::= stl_prefix LP select RP as on_using */
+ 259, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */
+ 202, /* (116) dbnm ::= */
+ 202, /* (117) dbnm ::= DOT nm */
+ 240, /* (118) fullname ::= nm */
+ 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 */
+ 261, /* (124) joinop ::= COMMA|JOIN */
+ 261, /* (125) joinop ::= JOIN_KW JOIN */
+ 261, /* (126) joinop ::= JOIN_KW nm JOIN */
+ 261, /* (127) joinop ::= JOIN_KW nm nm JOIN */
+ 262, /* (128) on_using ::= ON expr */
+ 262, /* (129) on_using ::= USING LP idlist RP */
+ 262, /* (130) on_using ::= */
+ 267, /* (131) indexed_opt ::= */
+ 263, /* (132) indexed_by ::= INDEXED BY nm */
+ 263, /* (133) indexed_by ::= NOT INDEXED */
+ 251, /* (134) orderby_opt ::= */
+ 251, /* (135) orderby_opt ::= ORDER BY sortlist */
+ 233, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */
+ 233, /* (137) sortlist ::= expr sortorder nulls */
+ 221, /* (138) sortorder ::= ASC */
+ 221, /* (139) sortorder ::= DESC */
+ 221, /* (140) sortorder ::= */
+ 268, /* (141) nulls ::= NULLS FIRST */
+ 268, /* (142) nulls ::= NULLS LAST */
+ 268, /* (143) nulls ::= */
+ 249, /* (144) groupby_opt ::= */
+ 249, /* (145) groupby_opt ::= GROUP BY nexprlist */
+ 250, /* (146) having_opt ::= */
+ 250, /* (147) having_opt ::= HAVING expr */
+ 252, /* (148) limit_opt ::= */
+ 252, /* (149) limit_opt ::= LIMIT expr */
+ 252, /* (150) limit_opt ::= LIMIT expr OFFSET expr */
+ 252, /* (151) limit_opt ::= LIMIT expr COMMA expr */
+ 192, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
+ 248, /* (153) where_opt ::= */
+ 248, /* (154) where_opt ::= WHERE expr */
+ 270, /* (155) where_opt_ret ::= */
+ 270, /* (156) where_opt_ret ::= WHERE expr */
+ 270, /* (157) where_opt_ret ::= RETURNING selcollist */
+ 270, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */
+ 192, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
+ 271, /* (160) setlist ::= setlist COMMA nm EQ expr */
+ 271, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ 271, /* (162) setlist ::= nm EQ expr */
+ 271, /* (163) setlist ::= LP idlist RP EQ expr */
+ 192, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ 192, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
+ 274, /* (166) upsert ::= */
+ 274, /* (167) upsert ::= RETURNING selcollist */
+ 274, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+ 274, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+ 274, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */
+ 274, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+ 275, /* (172) returning ::= RETURNING selcollist */
+ 272, /* (173) insert_cmd ::= INSERT orconf */
+ 272, /* (174) insert_cmd ::= REPLACE */
+ 273, /* (175) idlist_opt ::= */
+ 273, /* (176) idlist_opt ::= LP idlist RP */
+ 266, /* (177) idlist ::= idlist COMMA nm */
+ 266, /* (178) idlist ::= nm */
+ 219, /* (179) expr ::= LP expr RP */
+ 219, /* (180) expr ::= ID|INDEXED|JOIN_KW */
+ 219, /* (181) expr ::= nm DOT nm */
+ 219, /* (182) expr ::= nm DOT nm DOT nm */
+ 218, /* (183) term ::= NULL|FLOAT|BLOB */
+ 218, /* (184) term ::= STRING */
+ 218, /* (185) term ::= INTEGER */
+ 219, /* (186) expr ::= VARIABLE */
+ 219, /* (187) expr ::= expr COLLATE ID|STRING */
+ 219, /* (188) expr ::= CAST LP expr AS typetoken RP */
+ 219, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */
+ 219, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */
+ 219, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */
+ 219, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */
+ 219, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */
+ 219, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */
+ 218, /* (195) term ::= CTIME_KW */
+ 219, /* (196) expr ::= LP nexprlist COMMA expr RP */
+ 219, /* (197) expr ::= expr AND expr */
+ 219, /* (198) expr ::= expr OR expr */
+ 219, /* (199) expr ::= expr LT|GT|GE|LE expr */
+ 219, /* (200) expr ::= expr EQ|NE expr */
+ 219, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ 219, /* (202) expr ::= expr PLUS|MINUS expr */
+ 219, /* (203) expr ::= expr STAR|SLASH|REM expr */
+ 219, /* (204) expr ::= expr CONCAT expr */
+ 277, /* (205) likeop ::= NOT LIKE_KW|MATCH */
+ 219, /* (206) expr ::= expr likeop expr */
+ 219, /* (207) expr ::= expr likeop expr ESCAPE expr */
+ 219, /* (208) expr ::= expr ISNULL|NOTNULL */
+ 219, /* (209) expr ::= expr NOT NULL */
+ 219, /* (210) expr ::= expr IS expr */
+ 219, /* (211) expr ::= expr IS NOT expr */
+ 219, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */
+ 219, /* (213) expr ::= expr IS DISTINCT FROM expr */
+ 219, /* (214) expr ::= NOT expr */
+ 219, /* (215) expr ::= BITNOT expr */
+ 219, /* (216) expr ::= PLUS|MINUS expr */
+ 219, /* (217) expr ::= expr PTR expr */
+ 278, /* (218) between_op ::= BETWEEN */
+ 278, /* (219) between_op ::= NOT BETWEEN */
+ 219, /* (220) expr ::= expr between_op expr AND expr */
+ 279, /* (221) in_op ::= IN */
+ 279, /* (222) in_op ::= NOT IN */
+ 219, /* (223) expr ::= expr in_op LP exprlist RP */
+ 219, /* (224) expr ::= LP select RP */
+ 219, /* (225) expr ::= expr in_op LP select RP */
+ 219, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */
+ 219, /* (227) expr ::= EXISTS LP select RP */
+ 219, /* (228) expr ::= CASE case_operand case_exprlist case_else END */
+ 282, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ 282, /* (230) case_exprlist ::= WHEN expr THEN expr */
+ 283, /* (231) case_else ::= ELSE expr */
+ 283, /* (232) case_else ::= */
+ 281, /* (233) case_operand ::= */
+ 264, /* (234) exprlist ::= */
+ 255, /* (235) nexprlist ::= nexprlist COMMA expr */
+ 255, /* (236) nexprlist ::= expr */
+ 280, /* (237) paren_exprlist ::= */
+ 280, /* (238) paren_exprlist ::= LP exprlist RP */
+ 192, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ 284, /* (240) uniqueflag ::= UNIQUE */
+ 284, /* (241) uniqueflag ::= */
+ 223, /* (242) eidlist_opt ::= */
+ 223, /* (243) eidlist_opt ::= LP eidlist RP */
+ 234, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */
+ 234, /* (245) eidlist ::= nm collate sortorder */
+ 285, /* (246) collate ::= */
+ 285, /* (247) collate ::= COLLATE ID|STRING */
+ 192, /* (248) cmd ::= DROP INDEX ifexists fullname */
+ 192, /* (249) cmd ::= VACUUM vinto */
+ 192, /* (250) cmd ::= VACUUM nm vinto */
+ 286, /* (251) vinto ::= INTO expr */
+ 286, /* (252) vinto ::= */
+ 192, /* (253) cmd ::= PRAGMA nm dbnm */
+ 192, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ 192, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ 192, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ 192, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ 213, /* (258) plus_num ::= PLUS INTEGER|FLOAT */
+ 214, /* (259) minus_num ::= MINUS INTEGER|FLOAT */
+ 192, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ 288, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ 290, /* (262) trigger_time ::= BEFORE|AFTER */
+ 290, /* (263) trigger_time ::= INSTEAD OF */
+ 290, /* (264) trigger_time ::= */
+ 291, /* (265) trigger_event ::= DELETE|INSERT */
+ 291, /* (266) trigger_event ::= UPDATE */
+ 291, /* (267) trigger_event ::= UPDATE OF idlist */
+ 293, /* (268) when_clause ::= */
+ 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 */
+ 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 */
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
@@ -175936,7 +178749,7 @@ static const signed char yyRuleInfoNRhs[] = {
-6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-3, /* (278) trigger_cmd ::= scanpt select scanpt */
-4, /* (279) expr ::= RAISE LP IGNORE RP */
- -6, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */
+ -6, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */
-1, /* (281) raisetype ::= ROLLBACK */
-1, /* (282) raisetype ::= ABORT */
-1, /* (283) raisetype ::= FAIL */
@@ -176116,16 +178929,16 @@ static YYACTIONTYPE yy_reduce(
{ sqlite3FinishCoding(pParse); }
break;
case 3: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy144);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);}
break;
case 4: /* transtype ::= */
-{yymsp[1].minor.yy144 = TK_DEFERRED;}
+{yymsp[1].minor.yy502 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
case 324: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==324);
-{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/}
+{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 8: /* cmd ::= COMMIT|END trans_opt */
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
@@ -176148,11 +178961,13 @@ static YYACTIONTYPE yy_reduce(
break;
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy144,0,0,yymsp[-2].minor.yy144);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502);
}
break;
case 14: /* createkw ::= CREATE */
-{disableLookaside(pParse);}
+{
+ disableLookaside(pParse);
+}
break;
case 15: /* ifnotexists ::= */
case 18: /* temp ::= */ yytestcase(yyruleno==18);
@@ -176162,38 +178977,38 @@ static YYACTIONTYPE yy_reduce(
case 81: /* ifexists ::= */ yytestcase(yyruleno==81);
case 100: /* distinct ::= */ yytestcase(yyruleno==100);
case 246: /* collate ::= */ yytestcase(yyruleno==246);
-{yymsp[1].minor.yy144 = 0;}
+{yymsp[1].minor.yy502 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
-{yymsp[-2].minor.yy144 = 1;}
+{yymsp[-2].minor.yy502 = 1;}
break;
case 17: /* temp ::= TEMP */
-{yymsp[0].minor.yy144 = pParse->db->init.busy==0;}
+{yymsp[0].minor.yy502 = pParse->db->init.busy==0;}
break;
case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */
{
- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy391,0);
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy9,0);
}
break;
case 20: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy555);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555);
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy637);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637);
}
break;
case 21: /* table_option_set ::= */
-{yymsp[1].minor.yy391 = 0;}
+{yymsp[1].minor.yy9 = 0;}
break;
case 22: /* table_option_set ::= table_option_set COMMA table_option */
-{yylhsminor.yy391 = yymsp[-2].minor.yy391|yymsp[0].minor.yy391;}
- yymsp[-2].minor.yy391 = yylhsminor.yy391;
+{yylhsminor.yy9 = yymsp[-2].minor.yy9|yymsp[0].minor.yy9;}
+ yymsp[-2].minor.yy9 = yylhsminor.yy9;
break;
case 23: /* table_option ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
- yymsp[-1].minor.yy391 = TF_WithoutRowid | TF_NoVisibleRowid;
+ yymsp[-1].minor.yy9 = TF_WithoutRowid | TF_NoVisibleRowid;
}else{
- yymsp[-1].minor.yy391 = 0;
+ yymsp[-1].minor.yy9 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
@@ -176201,13 +179016,13 @@ static YYACTIONTYPE yy_reduce(
case 24: /* table_option ::= nm */
{
if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){
- yylhsminor.yy391 = TF_Strict;
+ yylhsminor.yy9 = TF_Strict;
}else{
- yylhsminor.yy391 = 0;
+ yylhsminor.yy9 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
- yymsp[0].minor.yy391 = yylhsminor.yy391;
+ yymsp[0].minor.yy9 = yylhsminor.yy9;
break;
case 25: /* columnname ::= nm typetoken */
{sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);}
@@ -176233,7 +179048,7 @@ static YYACTIONTYPE yy_reduce(
case 30: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
- yymsp[1].minor.yy168 = yyLookaheadToken.z;
+ yymsp[1].minor.yy342 = yyLookaheadToken.z;
}
break;
case 31: /* scantok ::= */
@@ -176244,20 +179059,20 @@ static YYACTIONTYPE yy_reduce(
break;
case 32: /* ccons ::= CONSTRAINT nm */
case 67: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==67);
-{pParse->constraintName = yymsp[0].minor.yy0;}
+{ASSERT_IS_CREATE; pParse->u1.cr.constraintName = yymsp[0].minor.yy0;}
break;
case 33: /* ccons ::= DEFAULT scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 34: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
case 35: /* ccons ::= DEFAULT PLUS scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 36: /* ccons ::= DEFAULT MINUS scantok term */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy454, 0);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy590, 0);
sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);
}
break;
@@ -176272,151 +179087,155 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 38: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy144);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);}
break;
case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy144,yymsp[0].minor.yy144,yymsp[-2].minor.yy144);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);}
break;
case 40: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy144,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 41: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
break;
case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy144);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy402,yymsp[0].minor.yy502);}
break;
case 43: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy144);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);}
break;
case 44: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 45: /* generated ::= LP expr RP */
-{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy454,0);}
+{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy590,0);}
break;
case 46: /* generated ::= LP expr RP ID */
-{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy454,&yymsp[0].minor.yy0);}
+{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy590,&yymsp[0].minor.yy0);}
break;
case 48: /* autoinc ::= AUTOINCR */
-{yymsp[0].minor.yy144 = 1;}
+{yymsp[0].minor.yy502 = 1;}
break;
case 49: /* refargs ::= */
-{ yymsp[1].minor.yy144 = OE_None*0x0101; /* EV: R-19803-45884 */}
+{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
case 50: /* refargs ::= refargs refarg */
-{ yymsp[-1].minor.yy144 = (yymsp[-1].minor.yy144 & ~yymsp[0].minor.yy383.mask) | yymsp[0].minor.yy383.value; }
+{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy481.mask) | yymsp[0].minor.yy481.value; }
break;
case 51: /* refarg ::= MATCH nm */
-{ yymsp[-1].minor.yy383.value = 0; yymsp[-1].minor.yy383.mask = 0x000000; }
+{ yymsp[-1].minor.yy481.value = 0; yymsp[-1].minor.yy481.mask = 0x000000; }
break;
case 52: /* refarg ::= ON INSERT refact */
-{ yymsp[-2].minor.yy383.value = 0; yymsp[-2].minor.yy383.mask = 0x000000; }
+{ yymsp[-2].minor.yy481.value = 0; yymsp[-2].minor.yy481.mask = 0x000000; }
break;
case 53: /* refarg ::= ON DELETE refact */
-{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144; yymsp[-2].minor.yy383.mask = 0x0000ff; }
+{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy481.mask = 0x0000ff; }
break;
case 54: /* refarg ::= ON UPDATE refact */
-{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144<<8; yymsp[-2].minor.yy383.mask = 0x00ff00; }
+{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy481.mask = 0x00ff00; }
break;
case 55: /* refact ::= SET NULL */
-{ yymsp[-1].minor.yy144 = OE_SetNull; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */}
break;
case 56: /* refact ::= SET DEFAULT */
-{ yymsp[-1].minor.yy144 = OE_SetDflt; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
case 57: /* refact ::= CASCADE */
-{ yymsp[0].minor.yy144 = OE_Cascade; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */}
break;
case 58: /* refact ::= RESTRICT */
-{ yymsp[0].minor.yy144 = OE_Restrict; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */}
break;
case 59: /* refact ::= NO ACTION */
-{ yymsp[-1].minor.yy144 = OE_None; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */}
break;
case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-{yymsp[-2].minor.yy144 = 0;}
+{yymsp[-2].minor.yy502 = 0;}
break;
case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76);
case 173: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==173);
-{yymsp[-1].minor.yy144 = yymsp[0].minor.yy144;}
+{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;}
break;
case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80);
case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219);
case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222);
case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247);
-{yymsp[-1].minor.yy144 = 1;}
+{yymsp[-1].minor.yy502 = 1;}
break;
case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-{yymsp[-1].minor.yy144 = 0;}
+{yymsp[-1].minor.yy502 = 0;}
break;
case 66: /* tconscomma ::= COMMA */
-{pParse->constraintName.n = 0;}
+{ASSERT_IS_CREATE; pParse->u1.cr.constraintName.n = 0;}
break;
case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy144,yymsp[-2].minor.yy144,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);}
break;
case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy144,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy402,yymsp[0].minor.yy502,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 70: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy454,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy590,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
break;
case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy144);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy144);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy402, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy502);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502);
}
break;
case 73: /* onconf ::= */
case 75: /* orconf ::= */ yytestcase(yyruleno==75);
-{yymsp[1].minor.yy144 = OE_Default;}
+{yymsp[1].minor.yy502 = OE_Default;}
break;
case 74: /* onconf ::= ON CONFLICT resolvetype */
-{yymsp[-2].minor.yy144 = yymsp[0].minor.yy144;}
+{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;}
break;
case 77: /* resolvetype ::= IGNORE */
-{yymsp[0].minor.yy144 = OE_Ignore;}
+{yymsp[0].minor.yy502 = OE_Ignore;}
break;
case 78: /* resolvetype ::= REPLACE */
case 174: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==174);
-{yymsp[0].minor.yy144 = OE_Replace;}
+{yymsp[0].minor.yy502 = OE_Replace;}
break;
case 79: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy203, 0, yymsp[-1].minor.yy144);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy563, 0, yymsp[-1].minor.yy502);
}
break;
case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[0].minor.yy555, yymsp[-7].minor.yy144, yymsp[-5].minor.yy144);
+ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[0].minor.yy637, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502);
}
break;
case 83: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy203, 1, yymsp[-1].minor.yy144);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy563, 1, yymsp[-1].minor.yy502);
}
break;
case 84: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy555, &dest);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555);
+ if( (pParse->db->mDbFlags & DBFLAG_EncodingFixed)!=0
+ || sqlite3ReadSchema(pParse)==SQLITE_OK
+ ){
+ sqlite3Select(pParse, yymsp[0].minor.yy637, &dest);
+ }
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637);
}
break;
case 85: /* select ::= WITH wqlist selectnowith */
-{yymsp[-2].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);}
+{yymsp[-2].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);}
break;
case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */
-{yymsp[-3].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);}
+{yymsp[-3].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);}
break;
case 87: /* select ::= selectnowith */
{
- Select *p = yymsp[0].minor.yy555;
+ Select *p = yymsp[0].minor.yy637;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
@@ -176424,8 +179243,8 @@ static YYACTIONTYPE yy_reduce(
break;
case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
- Select *pRhs = yymsp[0].minor.yy555;
- Select *pLhs = yymsp[-2].minor.yy555;
+ Select *pRhs = yymsp[0].minor.yy637;
+ Select *pLhs = yymsp[-2].minor.yy637;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
@@ -176435,60 +179254,60 @@ static YYACTIONTYPE yy_reduce(
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
- pRhs->op = (u8)yymsp[-1].minor.yy144;
+ pRhs->op = (u8)yymsp[-1].minor.yy502;
pRhs->pPrior = pLhs;
- if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
- pRhs->selFlags &= ~SF_MultiValue;
- if( yymsp[-1].minor.yy144!=TK_ALL ) pParse->hasCompound = 1;
+ if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue;
+ pRhs->selFlags &= ~(u32)SF_MultiValue;
+ if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
}
- yymsp[-2].minor.yy555 = pRhs;
+ yymsp[-2].minor.yy637 = pRhs;
}
break;
case 89: /* multiselect_op ::= UNION */
case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91);
-{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-OP*/}
+{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/}
break;
case 90: /* multiselect_op ::= UNION ALL */
-{yymsp[-1].minor.yy144 = TK_ALL;}
+{yymsp[-1].minor.yy502 = TK_ALL;}
break;
case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yymsp[-8].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy203,yymsp[-4].minor.yy454,yymsp[-3].minor.yy14,yymsp[-2].minor.yy454,yymsp[-1].minor.yy14,yymsp[-7].minor.yy144,yymsp[0].minor.yy454);
+ yymsp[-8].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy402,yymsp[-5].minor.yy563,yymsp[-4].minor.yy590,yymsp[-3].minor.yy402,yymsp[-2].minor.yy590,yymsp[-1].minor.yy402,yymsp[-7].minor.yy502,yymsp[0].minor.yy590);
}
break;
case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
{
- yymsp[-9].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy14,yymsp[-6].minor.yy203,yymsp[-5].minor.yy454,yymsp[-4].minor.yy14,yymsp[-3].minor.yy454,yymsp[-1].minor.yy14,yymsp[-8].minor.yy144,yymsp[0].minor.yy454);
- if( yymsp[-9].minor.yy555 ){
- yymsp[-9].minor.yy555->pWinDefn = yymsp[-2].minor.yy211;
+ yymsp[-9].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy402,yymsp[-6].minor.yy563,yymsp[-5].minor.yy590,yymsp[-4].minor.yy402,yymsp[-3].minor.yy590,yymsp[-1].minor.yy402,yymsp[-8].minor.yy502,yymsp[0].minor.yy590);
+ if( yymsp[-9].minor.yy637 ){
+ yymsp[-9].minor.yy637->pWinDefn = yymsp[-2].minor.yy483;
}else{
- sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy211);
+ sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy483);
}
}
break;
case 94: /* values ::= VALUES LP nexprlist RP */
{
- yymsp[-3].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0);
+ yymsp[-3].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values,0);
}
break;
case 95: /* oneselect ::= mvalues */
{
- sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy555);
+ sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy637);
}
break;
case 96: /* mvalues ::= values COMMA LP nexprlist RP */
case 97: /* mvalues ::= mvalues COMMA LP nexprlist RP */ yytestcase(yyruleno==97);
{
- yymsp[-4].minor.yy555 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy555, yymsp[-1].minor.yy14);
+ yymsp[-4].minor.yy637 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy637, yymsp[-1].minor.yy402);
}
break;
case 98: /* distinct ::= DISTINCT */
-{yymsp[0].minor.yy144 = SF_Distinct;}
+{yymsp[0].minor.yy502 = SF_Distinct;}
break;
case 99: /* distinct ::= ALL */
-{yymsp[0].minor.yy144 = SF_All;}
+{yymsp[0].minor.yy502 = SF_All;}
break;
case 101: /* sclp ::= */
case 134: /* orderby_opt ::= */ yytestcase(yyruleno==134);
@@ -176496,20 +179315,20 @@ static YYACTIONTYPE yy_reduce(
case 234: /* exprlist ::= */ yytestcase(yyruleno==234);
case 237: /* paren_exprlist ::= */ yytestcase(yyruleno==237);
case 242: /* eidlist_opt ::= */ yytestcase(yyruleno==242);
-{yymsp[1].minor.yy14 = 0;}
+{yymsp[1].minor.yy402 = 0;}
break;
case 102: /* selcollist ::= sclp scanpt expr scanpt as */
{
- yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[-2].minor.yy454);
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[0].minor.yy0, 1);
- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy14,yymsp[-3].minor.yy168,yymsp[-1].minor.yy168);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[-2].minor.yy590);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy402,yymsp[-3].minor.yy342,yymsp[-1].minor.yy342);
}
break;
case 103: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail));
- yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, p);
+ yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy402, p);
}
break;
case 104: /* selcollist ::= sclp scanpt nm DOT STAR */
@@ -176519,7 +179338,7 @@ static YYACTIONTYPE yy_reduce(
sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail));
pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0);
pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, pDot);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, pDot);
}
break;
case 105: /* as ::= AS nm */
@@ -176530,55 +179349,65 @@ static YYACTIONTYPE yy_reduce(
break;
case 107: /* from ::= */
case 110: /* stl_prefix ::= */ yytestcase(yyruleno==110);
-{yymsp[1].minor.yy203 = 0;}
+{yymsp[1].minor.yy563 = 0;}
break;
case 108: /* from ::= FROM seltablist */
{
- yymsp[-1].minor.yy203 = yymsp[0].minor.yy203;
- sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy203);
+ yymsp[-1].minor.yy563 = yymsp[0].minor.yy563;
+ sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy563);
}
break;
case 109: /* stl_prefix ::= seltablist joinop */
{
- if( ALWAYS(yymsp[-1].minor.yy203 && yymsp[-1].minor.yy203->nSrc>0) ) yymsp[-1].minor.yy203->a[yymsp[-1].minor.yy203->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy144;
+ if( ALWAYS(yymsp[-1].minor.yy563 && yymsp[-1].minor.yy563->nSrc>0) ) yymsp[-1].minor.yy563->a[yymsp[-1].minor.yy563->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502;
}
break;
case 111: /* seltablist ::= stl_prefix nm dbnm as on_using */
{
- yymsp[-4].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy203,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269);
+ yymsp[-4].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy563,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421);
}
break;
case 112: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
{
- yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy269);
- sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-1].minor.yy0);
+ yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy421);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-1].minor.yy0);
}
break;
case 113: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
{
- yymsp[-7].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy203,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269);
- sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy203, yymsp[-3].minor.yy14);
+ yymsp[-7].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy563,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421);
+ sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy563, yymsp[-3].minor.yy402);
}
break;
case 114: /* seltablist ::= stl_prefix LP select RP as on_using */
{
- yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy555,&yymsp[0].minor.yy269);
+ yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy637,&yymsp[0].minor.yy421);
}
break;
case 115: /* seltablist ::= stl_prefix LP seltablist RP as on_using */
{
- if( yymsp[-5].minor.yy203==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy269.pOn==0 && yymsp[0].minor.yy269.pUsing==0 ){
- yymsp[-5].minor.yy203 = yymsp[-3].minor.yy203;
- }else if( ALWAYS(yymsp[-3].minor.yy203!=0) && yymsp[-3].minor.yy203->nSrc==1 ){
- yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269);
- if( yymsp[-5].minor.yy203 ){
- SrcItem *pNew = &yymsp[-5].minor.yy203->a[yymsp[-5].minor.yy203->nSrc-1];
- SrcItem *pOld = yymsp[-3].minor.yy203->a;
+ if( yymsp[-5].minor.yy563==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy421.pOn==0 && yymsp[0].minor.yy421.pUsing==0 ){
+ yymsp[-5].minor.yy563 = yymsp[-3].minor.yy563;
+ }else if( ALWAYS(yymsp[-3].minor.yy563!=0) && yymsp[-3].minor.yy563->nSrc==1 ){
+ yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421);
+ if( yymsp[-5].minor.yy563 ){
+ SrcItem *pNew = &yymsp[-5].minor.yy563->a[yymsp[-5].minor.yy563->nSrc-1];
+ SrcItem *pOld = yymsp[-3].minor.yy563->a;
+ assert( pOld->fg.fixedSchema==0 );
pNew->zName = pOld->zName;
- pNew->zDatabase = pOld->zDatabase;
- pNew->pSelect = pOld->pSelect;
- if( pNew->pSelect && (pNew->pSelect->selFlags & SF_NestedFrom)!=0 ){
- pNew->fg.isNestedFrom = 1;
+ assert( pOld->fg.fixedSchema==0 );
+ if( pOld->fg.isSubquery ){
+ pNew->fg.isSubquery = 1;
+ pNew->u4.pSubq = pOld->u4.pSubq;
+ pOld->u4.pSubq = 0;
+ pOld->fg.isSubquery = 0;
+ assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 );
+ if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){
+ pNew->fg.isNestedFrom = 1;
+ }
+ }else{
+ pNew->u4.zDatabase = pOld->u4.zDatabase;
+ pOld->u4.zDatabase = 0;
}
if( pOld->fg.isTabFunc ){
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
@@ -176586,15 +179415,14 @@ static YYACTIONTYPE yy_reduce(
pOld->fg.isTabFunc = 0;
pNew->fg.isTabFunc = 1;
}
- pOld->zName = pOld->zDatabase = 0;
- pOld->pSelect = 0;
+ pOld->zName = 0;
}
- sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy203);
+ sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy563);
}else{
Select *pSubquery;
- sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy203);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy203,0,0,0,0,SF_NestedFrom,0);
- yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy269);
+ sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy563);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy563,0,0,0,0,SF_NestedFrom,0);
+ yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy421);
}
}
break;
@@ -176604,56 +179432,56 @@ static YYACTIONTYPE yy_reduce(
break;
case 118: /* fullname ::= nm */
{
- yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
- if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[0].minor.yy203 = yylhsminor.yy203;
+ yymsp[0].minor.yy563 = yylhsminor.yy563;
break;
case 119: /* fullname ::= nm DOT nm */
{
- yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[-2].minor.yy203 = yylhsminor.yy203;
+ yymsp[-2].minor.yy563 = yylhsminor.yy563;
break;
case 120: /* xfullname ::= nm */
-{yymsp[0].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
+{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.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{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 */
{
- yymsp[-4].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
- if( yymsp[-4].minor.yy203 ) yymsp[-4].minor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-4].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
+ if( yymsp[-4].minor.yy563 ) yymsp[-4].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 123: /* xfullname ::= nm AS nm */
{
- yymsp[-2].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
- if( yymsp[-2].minor.yy203 ) yymsp[-2].minor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
+ if( yymsp[-2].minor.yy563 ) yymsp[-2].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 124: /* joinop ::= COMMA|JOIN */
-{ yymsp[0].minor.yy144 = JT_INNER; }
+{ yymsp[0].minor.yy502 = JT_INNER; }
break;
case 125: /* joinop ::= JOIN_KW JOIN */
-{yymsp[-1].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
+{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
case 126: /* joinop ::= JOIN_KW nm JOIN */
-{yymsp[-2].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
+{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
case 127: /* joinop ::= JOIN_KW nm nm JOIN */
-{yymsp[-3].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
+{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
case 128: /* on_using ::= ON expr */
-{yymsp[-1].minor.yy269.pOn = yymsp[0].minor.yy454; yymsp[-1].minor.yy269.pUsing = 0;}
+{yymsp[-1].minor.yy421.pOn = yymsp[0].minor.yy590; yymsp[-1].minor.yy421.pUsing = 0;}
break;
case 129: /* on_using ::= USING LP idlist RP */
-{yymsp[-3].minor.yy269.pOn = 0; yymsp[-3].minor.yy269.pUsing = yymsp[-1].minor.yy132;}
+{yymsp[-3].minor.yy421.pOn = 0; yymsp[-3].minor.yy421.pUsing = yymsp[-1].minor.yy204;}
break;
case 130: /* on_using ::= */
-{yymsp[1].minor.yy269.pOn = 0; yymsp[1].minor.yy269.pUsing = 0;}
+{yymsp[1].minor.yy421.pOn = 0; yymsp[1].minor.yy421.pUsing = 0;}
break;
case 132: /* indexed_by ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
@@ -176663,35 +179491,35 @@ static YYACTIONTYPE yy_reduce(
break;
case 135: /* orderby_opt ::= ORDER BY sortlist */
case 145: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==145);
-{yymsp[-2].minor.yy14 = yymsp[0].minor.yy14;}
+{yymsp[-2].minor.yy402 = yymsp[0].minor.yy402;}
break;
case 136: /* sortlist ::= sortlist COMMA expr sortorder nulls */
{
- yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14,yymsp[-2].minor.yy454);
- sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402,yymsp[-2].minor.yy590);
+ sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502);
}
break;
case 137: /* sortlist ::= expr sortorder nulls */
{
- yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy454); /*A-overwrites-Y*/
- sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144);
+ yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy590); /*A-overwrites-Y*/
+ sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502);
}
break;
case 138: /* sortorder ::= ASC */
-{yymsp[0].minor.yy144 = SQLITE_SO_ASC;}
+{yymsp[0].minor.yy502 = SQLITE_SO_ASC;}
break;
case 139: /* sortorder ::= DESC */
-{yymsp[0].minor.yy144 = SQLITE_SO_DESC;}
+{yymsp[0].minor.yy502 = SQLITE_SO_DESC;}
break;
case 140: /* sortorder ::= */
case 143: /* nulls ::= */ yytestcase(yyruleno==143);
-{yymsp[1].minor.yy144 = SQLITE_SO_UNDEFINED;}
+{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;}
break;
case 141: /* nulls ::= NULLS FIRST */
-{yymsp[-1].minor.yy144 = SQLITE_SO_ASC;}
+{yymsp[-1].minor.yy502 = SQLITE_SO_ASC;}
break;
case 142: /* nulls ::= NULLS LAST */
-{yymsp[-1].minor.yy144 = SQLITE_SO_DESC;}
+{yymsp[-1].minor.yy502 = SQLITE_SO_DESC;}
break;
case 146: /* having_opt ::= */
case 148: /* limit_opt ::= */ yytestcase(yyruleno==148);
@@ -176700,42 +179528,42 @@ static YYACTIONTYPE yy_reduce(
case 232: /* case_else ::= */ yytestcase(yyruleno==232);
case 233: /* case_operand ::= */ yytestcase(yyruleno==233);
case 252: /* vinto ::= */ yytestcase(yyruleno==252);
-{yymsp[1].minor.yy454 = 0;}
+{yymsp[1].minor.yy590 = 0;}
break;
case 147: /* having_opt ::= HAVING expr */
case 154: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==154);
case 156: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==156);
case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231);
case 251: /* vinto ::= INTO expr */ yytestcase(yyruleno==251);
-{yymsp[-1].minor.yy454 = yymsp[0].minor.yy454;}
+{yymsp[-1].minor.yy590 = yymsp[0].minor.yy590;}
break;
case 149: /* limit_opt ::= LIMIT expr */
-{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,0);}
+{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,0);}
break;
case 150: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);}
+{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);}
break;
case 151: /* limit_opt ::= LIMIT expr COMMA expr */
-{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,yymsp[-2].minor.yy454);}
+{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,yymsp[-2].minor.yy590);}
break;
case 152: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy203, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy203,yymsp[0].minor.yy454,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy563, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy563,yymsp[0].minor.yy590,0,0);
}
break;
case 157: /* where_opt_ret ::= RETURNING selcollist */
-{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-1].minor.yy454 = 0;}
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-1].minor.yy590 = 0;}
break;
case 158: /* where_opt_ret ::= WHERE expr RETURNING selcollist */
-{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-3].minor.yy454 = yymsp[-2].minor.yy454;}
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-3].minor.yy590 = yymsp[-2].minor.yy590;}
break;
case 159: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-4].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy14,"set list");
- if( yymsp[-1].minor.yy203 ){
- SrcList *pFromClause = yymsp[-1].minor.yy203;
+ sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-4].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy402,"set list");
+ if( yymsp[-1].minor.yy563 ){
+ SrcList *pFromClause = yymsp[-1].minor.yy563;
if( pFromClause->nSrc>1 ){
Select *pSubquery;
Token as;
@@ -176744,90 +179572,90 @@ static YYACTIONTYPE yy_reduce(
as.z = 0;
pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
}
- yymsp[-5].minor.yy203 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy203, pFromClause);
+ yymsp[-5].minor.yy563 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy563, pFromClause);
}
- sqlite3Update(pParse,yymsp[-5].minor.yy203,yymsp[-2].minor.yy14,yymsp[0].minor.yy454,yymsp[-6].minor.yy144,0,0,0);
+ sqlite3Update(pParse,yymsp[-5].minor.yy563,yymsp[-2].minor.yy402,yymsp[0].minor.yy590,yymsp[-6].minor.yy502,0,0,0);
}
break;
case 160: /* setlist ::= setlist COMMA nm EQ expr */
{
- yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy454);
- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, 1);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[0].minor.yy590);
+ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, 1);
}
break;
case 161: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
- yymsp[-6].minor.yy14 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy14, yymsp[-3].minor.yy132, yymsp[0].minor.yy454);
+ yymsp[-6].minor.yy402 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy402, yymsp[-3].minor.yy204, yymsp[0].minor.yy590);
}
break;
case 162: /* setlist ::= nm EQ expr */
{
- yylhsminor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy454);
- sqlite3ExprListSetName(pParse, yylhsminor.yy14, &yymsp[-2].minor.yy0, 1);
+ yylhsminor.yy402 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy590);
+ sqlite3ExprListSetName(pParse, yylhsminor.yy402, &yymsp[-2].minor.yy0, 1);
}
- yymsp[-2].minor.yy14 = yylhsminor.yy14;
+ yymsp[-2].minor.yy402 = yylhsminor.yy402;
break;
case 163: /* setlist ::= LP idlist RP EQ expr */
{
- yymsp[-4].minor.yy14 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy132, yymsp[0].minor.yy454);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy204, yymsp[0].minor.yy590);
}
break;
case 164: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy555, yymsp[-2].minor.yy132, yymsp[-5].minor.yy144, yymsp[0].minor.yy122);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy563, yymsp[-1].minor.yy637, yymsp[-2].minor.yy204, yymsp[-5].minor.yy502, yymsp[0].minor.yy403);
}
break;
case 165: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
{
- sqlite3Insert(pParse, yymsp[-4].minor.yy203, 0, yymsp[-3].minor.yy132, yymsp[-6].minor.yy144, 0);
+ sqlite3Insert(pParse, yymsp[-4].minor.yy563, 0, yymsp[-3].minor.yy204, yymsp[-6].minor.yy502, 0);
}
break;
case 166: /* upsert ::= */
-{ yymsp[1].minor.yy122 = 0; }
+{ yymsp[1].minor.yy403 = 0; }
break;
case 167: /* upsert ::= RETURNING selcollist */
-{ yymsp[-1].minor.yy122 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy14); }
+{ yymsp[-1].minor.yy403 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy402); }
break;
case 168: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
-{ yymsp[-11].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy14,yymsp[-6].minor.yy454,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,yymsp[0].minor.yy122);}
+{ yymsp[-11].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy402,yymsp[-6].minor.yy590,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,yymsp[0].minor.yy403);}
break;
case 169: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
-{ yymsp[-8].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy14,yymsp[-3].minor.yy454,0,0,yymsp[0].minor.yy122); }
+{ yymsp[-8].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy402,yymsp[-3].minor.yy590,0,0,yymsp[0].minor.yy403); }
break;
case 170: /* upsert ::= ON CONFLICT DO NOTHING returning */
-{ yymsp[-4].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
+{ yymsp[-4].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
break;
case 171: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
-{ yymsp[-7].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,0);}
+{ yymsp[-7].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,0);}
break;
case 172: /* returning ::= RETURNING selcollist */
-{sqlite3AddReturning(pParse,yymsp[0].minor.yy14);}
+{sqlite3AddReturning(pParse,yymsp[0].minor.yy402);}
break;
case 175: /* idlist_opt ::= */
-{yymsp[1].minor.yy132 = 0;}
+{yymsp[1].minor.yy204 = 0;}
break;
case 176: /* idlist_opt ::= LP idlist RP */
-{yymsp[-2].minor.yy132 = yymsp[-1].minor.yy132;}
+{yymsp[-2].minor.yy204 = yymsp[-1].minor.yy204;}
break;
case 177: /* idlist ::= idlist COMMA nm */
-{yymsp[-2].minor.yy132 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy132,&yymsp[0].minor.yy0);}
+{yymsp[-2].minor.yy204 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy204,&yymsp[0].minor.yy0);}
break;
case 178: /* idlist ::= nm */
-{yymsp[0].minor.yy132 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+{yymsp[0].minor.yy204 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
case 179: /* expr ::= LP expr RP */
-{yymsp[-2].minor.yy454 = yymsp[-1].minor.yy454;}
+{yymsp[-2].minor.yy590 = yymsp[-1].minor.yy590;}
break;
case 180: /* expr ::= ID|INDEXED|JOIN_KW */
-{yymsp[0].minor.yy454=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy590=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 181: /* expr ::= nm DOT nm */
{
Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0);
Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0);
- yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
+ yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
- yymsp[-2].minor.yy454 = yylhsminor.yy454;
+ yymsp[-2].minor.yy590 = yylhsminor.yy590;
break;
case 182: /* expr ::= nm DOT nm DOT nm */
{
@@ -176838,27 +179666,27 @@ static YYACTIONTYPE yy_reduce(
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, 0, temp1);
}
- yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
+ yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
- yymsp[-4].minor.yy454 = yylhsminor.yy454;
+ yymsp[-4].minor.yy590 = yylhsminor.yy590;
break;
case 183: /* term ::= NULL|FLOAT|BLOB */
case 184: /* term ::= STRING */ yytestcase(yyruleno==184);
-{yymsp[0].minor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 185: /* term ::= INTEGER */
{
- yylhsminor.yy454 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
- if( yylhsminor.yy454 ) yylhsminor.yy454->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail);
+ yylhsminor.yy590 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
+ if( yylhsminor.yy590 ) yylhsminor.yy590->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail);
}
- yymsp[0].minor.yy454 = yylhsminor.yy454;
+ yymsp[0].minor.yy590 = yylhsminor.yy590;
break;
case 186: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
- yymsp[0].minor.yy454 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy454, n);
+ yymsp[0].minor.yy590 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy590, n);
}else{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
@@ -176866,81 +179694,81 @@ static YYACTIONTYPE yy_reduce(
Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
assert( t.n>=2 );
if( pParse->nested==0 ){
- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
- yymsp[0].minor.yy454 = 0;
+ parserSyntaxError(pParse, &t);
+ yymsp[0].minor.yy590 = 0;
}else{
- yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable);
+ yymsp[0].minor.yy590 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
+ if( yymsp[0].minor.yy590 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy590->iTable);
}
}
}
break;
case 187: /* expr ::= expr COLLATE ID|STRING */
{
- yymsp[-2].minor.yy454 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy454, &yymsp[0].minor.yy0, 1);
+ yymsp[-2].minor.yy590 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy590, &yymsp[0].minor.yy0, 1);
}
break;
case 188: /* expr ::= CAST LP expr AS typetoken RP */
{
- yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy454, yymsp[-3].minor.yy454, 0);
+ yymsp[-5].minor.yy590 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy590, yymsp[-3].minor.yy590, 0);
}
break;
case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */
{
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy144);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy502);
}
- yymsp[-4].minor.yy454 = yylhsminor.yy454;
+ yymsp[-4].minor.yy590 = yylhsminor.yy590;
break;
case 190: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */
{
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy14, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy144);
- sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-1].minor.yy14);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy402, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy502);
+ sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-1].minor.yy402);
}
- yymsp[-7].minor.yy454 = yylhsminor.yy454;
+ yymsp[-7].minor.yy590 = yylhsminor.yy590;
break;
case 191: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */
{
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
}
- yymsp[-3].minor.yy454 = yylhsminor.yy454;
+ yymsp[-3].minor.yy590 = yylhsminor.yy590;
break;
case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */
{
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy14, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy144);
- sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy402, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy502);
+ sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483);
}
- yymsp[-5].minor.yy454 = yylhsminor.yy454;
+ yymsp[-5].minor.yy590 = yylhsminor.yy590;
break;
case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */
{
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy14, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy144);
- sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211);
- sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-2].minor.yy14);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy402, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy502);
+ sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483);
+ sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-2].minor.yy402);
}
- yymsp[-8].minor.yy454 = yylhsminor.yy454;
+ yymsp[-8].minor.yy590 = yylhsminor.yy590;
break;
case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */
{
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
- sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
+ sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483);
}
- yymsp[-4].minor.yy454 = yylhsminor.yy454;
+ yymsp[-4].minor.yy590 = yylhsminor.yy590;
break;
case 195: /* term ::= CTIME_KW */
{
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
- yymsp[0].minor.yy454 = yylhsminor.yy454;
+ yymsp[0].minor.yy590 = yylhsminor.yy590;
break;
case 196: /* expr ::= LP nexprlist COMMA expr RP */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454);
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( yymsp[-4].minor.yy454 ){
- yymsp[-4].minor.yy454->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590);
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( yymsp[-4].minor.yy590 ){
+ yymsp[-4].minor.yy590->x.pList = pList;
if( ALWAYS(pList->nExpr) ){
- yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate;
+ yymsp[-4].minor.yy590->flags |= pList->a[0].pExpr->flags & EP_Propagate;
}
}else{
sqlite3ExprListDelete(pParse->db, pList);
@@ -176948,7 +179776,7 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 197: /* expr ::= expr AND expr */
-{yymsp[-2].minor.yy454=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);}
+{yymsp[-2].minor.yy590=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);}
break;
case 198: /* expr ::= expr OR expr */
case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199);
@@ -176957,7 +179785,7 @@ static YYACTIONTYPE yy_reduce(
case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202);
case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203);
case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204);
-{yymsp[-2].minor.yy454=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);}
+{yymsp[-2].minor.yy590=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);}
break;
case 205: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
@@ -176967,11 +179795,11 @@ static YYACTIONTYPE yy_reduce(
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy454);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy454);
- yymsp[-2].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
- if( bNot ) yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy454, 0);
- if( yymsp[-2].minor.yy454 ) yymsp[-2].minor.yy454->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy590);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy590);
+ yymsp[-2].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ if( bNot ) yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy590, 0);
+ if( yymsp[-2].minor.yy590 ) yymsp[-2].minor.yy590->flags |= EP_InfixFunc;
}
break;
case 207: /* expr ::= expr likeop expr ESCAPE expr */
@@ -176979,91 +179807,91 @@ static YYACTIONTYPE yy_reduce(
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy454);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454);
- yymsp[-4].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
- if( bNot ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
- if( yymsp[-4].minor.yy454 ) yymsp[-4].minor.yy454->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy590);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590);
+ yymsp[-4].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
+ if( bNot ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
+ if( yymsp[-4].minor.yy590 ) yymsp[-4].minor.yy590->flags |= EP_InfixFunc;
}
break;
case 208: /* expr ::= expr ISNULL|NOTNULL */
-{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy454,0);}
+{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy590,0);}
break;
case 209: /* expr ::= expr NOT NULL */
-{yymsp[-2].minor.yy454 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy454,0);}
+{yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy590,0);}
break;
case 210: /* expr ::= expr IS expr */
{
- yymsp[-2].minor.yy454 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-2].minor.yy454, TK_ISNULL);
+ yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-2].minor.yy590, TK_ISNULL);
}
break;
case 211: /* expr ::= expr IS NOT expr */
{
- yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy454,yymsp[0].minor.yy454);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-3].minor.yy454, TK_NOTNULL);
+ yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy590,yymsp[0].minor.yy590);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-3].minor.yy590, TK_NOTNULL);
}
break;
case 212: /* expr ::= expr IS NOT DISTINCT FROM expr */
{
- yymsp[-5].minor.yy454 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy454,yymsp[0].minor.yy454);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-5].minor.yy454, TK_ISNULL);
+ yymsp[-5].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy590,yymsp[0].minor.yy590);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-5].minor.yy590, TK_ISNULL);
}
break;
case 213: /* expr ::= expr IS DISTINCT FROM expr */
{
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy454,yymsp[0].minor.yy454);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-4].minor.yy454, TK_NOTNULL);
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy590,yymsp[0].minor.yy590);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-4].minor.yy590, TK_NOTNULL);
}
break;
case 214: /* expr ::= NOT expr */
case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215);
-{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/}
+{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy590, 0);/*A-overwrites-B*/}
break;
case 216: /* expr ::= PLUS|MINUS expr */
{
- Expr *p = yymsp[0].minor.yy454;
+ Expr *p = yymsp[0].minor.yy590;
u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS);
assert( TK_UPLUS>TK_PLUS );
assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) );
if( p && p->op==TK_UPLUS ){
p->op = op;
- yymsp[-1].minor.yy454 = p;
+ yymsp[-1].minor.yy590 = p;
}else{
- yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, op, p, 0);
+ yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, op, p, 0);
/*A-overwrites-B*/
}
}
break;
case 217: /* expr ::= expr PTR expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454);
- pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy454);
- yylhsminor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy590);
+ pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy590);
+ yylhsminor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
}
- yymsp[-2].minor.yy454 = yylhsminor.yy454;
+ yymsp[-2].minor.yy590 = yylhsminor.yy590;
break;
case 218: /* between_op ::= BETWEEN */
case 221: /* in_op ::= IN */ yytestcase(yyruleno==221);
-{yymsp[0].minor.yy144 = 0;}
+{yymsp[0].minor.yy502 = 0;}
break;
case 220: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454);
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0);
- if( yymsp[-4].minor.yy454 ){
- yymsp[-4].minor.yy454->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590);
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy590, 0);
+ if( yymsp[-4].minor.yy590 ){
+ yymsp[-4].minor.yy590->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
+ if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
}
break;
case 223: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy14==0 ){
+ if( yymsp[-1].minor.yy402==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -177072,110 +179900,110 @@ static YYACTIONTYPE yy_reduce(
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy454);
- yymsp[-4].minor.yy454 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy144 ? "true" : "false");
- if( yymsp[-4].minor.yy454 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy454);
- }else{
- Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr;
- if( yymsp[-1].minor.yy14->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy454->op!=TK_VECTOR ){
- yymsp[-1].minor.yy14->a[0].pExpr = 0;
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
+ sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy590);
+ yymsp[-4].minor.yy590 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy502 ? "true" : "false");
+ if( yymsp[-4].minor.yy590 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy590);
+ }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);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy454, pRHS);
- }else if( yymsp[-1].minor.yy14->nExpr==1 && pRHS->op==TK_SELECT ){
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pRHS->x.pSelect);
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy590, pRHS);
+ }else if( yymsp[-1].minor.yy402->nExpr==1 && pRHS->op==TK_SELECT ){
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pRHS->x.pSelect);
pRHS->x.pSelect = 0;
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
- }else{
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
- if( yymsp[-4].minor.yy454==0 ){
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
- }else if( yymsp[-4].minor.yy454->pLeft->op==TK_VECTOR ){
- int nExpr = yymsp[-4].minor.yy454->pLeft->x.pList->nExpr;
- Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy14);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402);
+ }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);
if( pSelectRHS ){
parserDoubleLinkSelect(pParse, pSelectRHS);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelectRHS);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelectRHS);
}
}else{
- yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy14;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454);
+ yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy402;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590);
}
}
- if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
+ if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
}
}
break;
case 224: /* expr ::= LP select RP */
{
- yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy454, yymsp[-1].minor.yy555);
+ yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy590, yymsp[-1].minor.yy637);
}
break;
case 225: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, yymsp[-1].minor.yy555);
- if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, yymsp[-1].minor.yy637);
+ if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
}
break;
case 226: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
- if( yymsp[0].minor.yy14 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy14);
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelect);
- if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
+ if( yymsp[0].minor.yy402 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy402);
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelect);
+ if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0);
}
break;
case 227: /* expr ::= EXISTS LP select RP */
{
Expr *p;
- p = yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy555);
+ p = yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
+ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy637);
}
break;
case 228: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy454, 0);
- if( yymsp[-4].minor.yy454 ){
- yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy454 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454) : yymsp[-2].minor.yy14;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454);
+ yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy590, 0);
+ if( yymsp[-4].minor.yy590 ){
+ yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy590 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590) : yymsp[-2].minor.yy402;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14);
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy402);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590);
}
}
break;
case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy454);
- yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[0].minor.yy454);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[-2].minor.yy590);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[0].minor.yy590);
}
break;
case 230: /* case_exprlist ::= WHEN expr THEN expr */
{
- yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
- yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, yymsp[0].minor.yy454);
+ yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590);
+ yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402, yymsp[0].minor.yy590);
}
break;
case 235: /* nexprlist ::= nexprlist COMMA expr */
-{yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy454);}
+{yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[0].minor.yy590);}
break;
case 236: /* nexprlist ::= expr */
-{yymsp[0].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy454); /*A-overwrites-Y*/}
+{yymsp[0].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy590); /*A-overwrites-Y*/}
break;
case 238: /* paren_exprlist ::= LP exprlist RP */
case 243: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==243);
-{yymsp[-2].minor.yy14 = yymsp[-1].minor.yy14;}
+{yymsp[-2].minor.yy402 = yymsp[-1].minor.yy402;}
break;
case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
- sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy144,
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy454, SQLITE_SO_ASC, yymsp[-8].minor.yy144, SQLITE_IDXTYPE_APPDEF);
+ sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy402, yymsp[-10].minor.yy502,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy590, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
@@ -177183,29 +180011,29 @@ static YYACTIONTYPE yy_reduce(
break;
case 240: /* uniqueflag ::= UNIQUE */
case 282: /* raisetype ::= ABORT */ yytestcase(yyruleno==282);
-{yymsp[0].minor.yy144 = OE_Abort;}
+{yymsp[0].minor.yy502 = OE_Abort;}
break;
case 241: /* uniqueflag ::= */
-{yymsp[1].minor.yy144 = OE_None;}
+{yymsp[1].minor.yy502 = OE_None;}
break;
case 244: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
- yymsp[-4].minor.yy14 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144);
+ yymsp[-4].minor.yy402 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502);
}
break;
case 245: /* eidlist ::= nm collate sortorder */
{
- yymsp[-2].minor.yy14 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); /*A-overwrites-Y*/
+ yymsp[-2].minor.yy402 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/
}
break;
case 248: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy203, yymsp[-1].minor.yy144);}
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy563, yymsp[-1].minor.yy502);}
break;
case 249: /* cmd ::= VACUUM vinto */
-{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy454);}
+{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy590);}
break;
case 250: /* cmd ::= VACUUM nm vinto */
-{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy454);}
+{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy590);}
break;
case 253: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
@@ -177227,50 +180055,54 @@ static YYACTIONTYPE yy_reduce(
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy319, &all);
}
break;
case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy144, yymsp[-4].minor.yy286.a, yymsp[-4].minor.yy286.b, yymsp[-2].minor.yy203, yymsp[0].minor.yy454, yymsp[-10].minor.yy144, yymsp[-8].minor.yy144);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy28.a, yymsp[-4].minor.yy28.b, yymsp[-2].minor.yy563, yymsp[0].minor.yy590, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
+#ifdef SQLITE_DEBUG
+ assert( pParse->isCreate ); /* Set by createkw reduce action */
+ pParse->isCreate = 0; /* But, should not be set for CREATE TRIGGER */
+#endif
}
break;
case 262: /* trigger_time ::= BEFORE|AFTER */
-{ yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/ }
+{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ }
break;
case 263: /* trigger_time ::= INSTEAD OF */
-{ yymsp[-1].minor.yy144 = TK_INSTEAD;}
+{ yymsp[-1].minor.yy502 = TK_INSTEAD;}
break;
case 264: /* trigger_time ::= */
-{ yymsp[1].minor.yy144 = TK_BEFORE; }
+{ yymsp[1].minor.yy502 = TK_BEFORE; }
break;
case 265: /* trigger_event ::= DELETE|INSERT */
case 266: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==266);
-{yymsp[0].minor.yy286.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy286.b = 0;}
+{yymsp[0].minor.yy28.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy28.b = 0;}
break;
case 267: /* trigger_event ::= UPDATE OF idlist */
-{yymsp[-2].minor.yy286.a = TK_UPDATE; yymsp[-2].minor.yy286.b = yymsp[0].minor.yy132;}
+{yymsp[-2].minor.yy28.a = TK_UPDATE; yymsp[-2].minor.yy28.b = yymsp[0].minor.yy204;}
break;
case 268: /* when_clause ::= */
case 287: /* key_opt ::= */ yytestcase(yyruleno==287);
-{ yymsp[1].minor.yy454 = 0; }
+{ yymsp[1].minor.yy590 = 0; }
break;
case 269: /* when_clause ::= WHEN expr */
case 288: /* key_opt ::= KEY expr */ yytestcase(yyruleno==288);
-{ yymsp[-1].minor.yy454 = yymsp[0].minor.yy454; }
+{ yymsp[-1].minor.yy590 = yymsp[0].minor.yy590; }
break;
case 270: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy427!=0 );
- yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427;
- yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427;
+ assert( yymsp[-2].minor.yy319!=0 );
+ yymsp[-2].minor.yy319->pLast->pNext = yymsp[-1].minor.yy319;
+ yymsp[-2].minor.yy319->pLast = yymsp[-1].minor.yy319;
}
break;
case 271: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy427!=0 );
- yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427;
+ assert( yymsp[-1].minor.yy319!=0 );
+ yymsp[-1].minor.yy319->pLast = yymsp[-1].minor.yy319;
}
break;
case 272: /* trnm ::= nm DOT nm */
@@ -177296,58 +180128,58 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 275: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
-{yylhsminor.yy427 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, 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;
+{yylhsminor.yy319 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy563, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590, yymsp[-7].minor.yy502, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy342);}
+ yymsp[-8].minor.yy319 = yylhsminor.yy319;
break;
case 276: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
- yylhsminor.yy427 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy132,yymsp[-2].minor.yy555,yymsp[-6].minor.yy144,yymsp[-1].minor.yy122,yymsp[-7].minor.yy168,yymsp[0].minor.yy168);/*yylhsminor.yy427-overwrites-yymsp[-6].minor.yy144*/
+ yylhsminor.yy319 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy204,yymsp[-2].minor.yy637,yymsp[-6].minor.yy502,yymsp[-1].minor.yy403,yymsp[-7].minor.yy342,yymsp[0].minor.yy342);/*yylhsminor.yy319-overwrites-yymsp[-6].minor.yy502*/
}
- yymsp[-7].minor.yy427 = yylhsminor.yy427;
+ yymsp[-7].minor.yy319 = yylhsminor.yy319;
break;
case 277: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-{yylhsminor.yy427 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy454, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy168);}
- yymsp[-5].minor.yy427 = yylhsminor.yy427;
+{yylhsminor.yy319 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy590, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy342);}
+ yymsp[-5].minor.yy319 = yylhsminor.yy319;
break;
case 278: /* 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;
+{yylhsminor.yy319 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy637, yymsp[-2].minor.yy342, yymsp[0].minor.yy342); /*yylhsminor.yy319-overwrites-yymsp[-1].minor.yy637*/}
+ yymsp[-2].minor.yy319 = yylhsminor.yy319;
break;
case 279: /* expr ::= RAISE LP IGNORE RP */
{
- yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( yymsp[-3].minor.yy454 ){
- yymsp[-3].minor.yy454->affExpr = OE_Ignore;
+ yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
+ if( yymsp[-3].minor.yy590 ){
+ yymsp[-3].minor.yy590->affExpr = OE_Ignore;
}
}
break;
- case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */
{
- yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
- if( yymsp[-5].minor.yy454 ) {
- yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144;
+ yymsp[-5].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy590, 0);
+ if( yymsp[-5].minor.yy590 ) {
+ yymsp[-5].minor.yy590->affExpr = (char)yymsp[-3].minor.yy502;
}
}
break;
case 281: /* raisetype ::= ROLLBACK */
-{yymsp[0].minor.yy144 = OE_Rollback;}
+{yymsp[0].minor.yy502 = OE_Rollback;}
break;
case 283: /* raisetype ::= FAIL */
-{yymsp[0].minor.yy144 = OE_Fail;}
+{yymsp[0].minor.yy502 = OE_Fail;}
break;
case 284: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy203,yymsp[-1].minor.yy144);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy563,yymsp[-1].minor.yy502);
}
break;
case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, yymsp[0].minor.yy454);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy590, yymsp[-1].minor.yy590, yymsp[0].minor.yy590);
}
break;
case 286: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy454);
+ sqlite3Detach(pParse, yymsp[0].minor.yy590);
}
break;
case 289: /* cmd ::= REINDEX */
@@ -177364,7 +180196,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 293: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy203,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy563,&yymsp[0].minor.yy0);
}
break;
case 294: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
@@ -177375,18 +180207,18 @@ static YYACTIONTYPE yy_reduce(
break;
case 295: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
{
- sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0);
+ sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy563, &yymsp[0].minor.yy0);
}
break;
case 296: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy203);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy563);
}
break;
case 297: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
- sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy203, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
+ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy563, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
case 298: /* cmd ::= create_vtab */
@@ -177397,7 +180229,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 300: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy144);
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502);
}
break;
case 301: /* vtabarg ::= */
@@ -177410,20 +180242,20 @@ static YYACTIONTYPE yy_reduce(
break;
case 305: /* with ::= WITH wqlist */
case 306: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==306);
-{ sqlite3WithPush(pParse, yymsp[0].minor.yy59, 1); }
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy125, 1); }
break;
case 307: /* wqas ::= AS */
-{yymsp[0].minor.yy462 = M10d_Any;}
+{yymsp[0].minor.yy444 = M10d_Any;}
break;
case 308: /* wqas ::= AS MATERIALIZED */
-{yymsp[-1].minor.yy462 = M10d_Yes;}
+{yymsp[-1].minor.yy444 = M10d_Yes;}
break;
case 309: /* wqas ::= AS NOT MATERIALIZED */
-{yymsp[-2].minor.yy462 = M10d_No;}
+{yymsp[-2].minor.yy444 = M10d_No;}
break;
case 310: /* wqitem ::= withnm eidlist_opt wqas LP select RP */
{
- yymsp[-5].minor.yy67 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy555, yymsp[-3].minor.yy462); /*A-overwrites-X*/
+ yymsp[-5].minor.yy361 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy637, yymsp[-3].minor.yy444); /*A-overwrites-X*/
}
break;
case 311: /* withnm ::= nm */
@@ -177431,160 +180263,160 @@ static YYACTIONTYPE yy_reduce(
break;
case 312: /* wqlist ::= wqitem */
{
- yymsp[0].minor.yy59 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy67); /*A-overwrites-X*/
+ yymsp[0].minor.yy125 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy361); /*A-overwrites-X*/
}
break;
case 313: /* wqlist ::= wqlist COMMA wqitem */
{
- yymsp[-2].minor.yy59 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy59, yymsp[0].minor.yy67);
+ yymsp[-2].minor.yy125 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy125, yymsp[0].minor.yy361);
}
break;
case 314: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
{
- assert( yymsp[0].minor.yy211!=0 );
- sqlite3WindowChain(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy211);
- yymsp[0].minor.yy211->pNextWin = yymsp[-2].minor.yy211;
- yylhsminor.yy211 = yymsp[0].minor.yy211;
+ assert( yymsp[0].minor.yy483!=0 );
+ sqlite3WindowChain(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy483);
+ yymsp[0].minor.yy483->pNextWin = yymsp[-2].minor.yy483;
+ yylhsminor.yy483 = yymsp[0].minor.yy483;
}
- yymsp[-2].minor.yy211 = yylhsminor.yy211;
+ yymsp[-2].minor.yy483 = yylhsminor.yy483;
break;
case 315: /* windowdefn ::= nm AS LP window RP */
{
- if( ALWAYS(yymsp[-1].minor.yy211) ){
- yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
+ if( ALWAYS(yymsp[-1].minor.yy483) ){
+ yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
}
- yylhsminor.yy211 = yymsp[-1].minor.yy211;
+ yylhsminor.yy483 = yymsp[-1].minor.yy483;
}
- yymsp[-4].minor.yy211 = yylhsminor.yy211;
+ yymsp[-4].minor.yy483 = yylhsminor.yy483;
break;
case 316: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
{
- yymsp[-4].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, 0);
+ yymsp[-4].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, 0);
}
break;
case 317: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
{
- yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, &yymsp[-5].minor.yy0);
+ yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, &yymsp[-5].minor.yy0);
}
- yymsp[-5].minor.yy211 = yylhsminor.yy211;
+ yymsp[-5].minor.yy483 = yylhsminor.yy483;
break;
case 318: /* window ::= ORDER BY sortlist frame_opt */
{
- yymsp[-3].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, 0);
+ yymsp[-3].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, 0);
}
break;
case 319: /* window ::= nm ORDER BY sortlist frame_opt */
{
- yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0);
+ yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0);
}
- yymsp[-4].minor.yy211 = yylhsminor.yy211;
+ yymsp[-4].minor.yy483 = yylhsminor.yy483;
break;
case 320: /* window ::= nm frame_opt */
{
- yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, 0, &yymsp[-1].minor.yy0);
+ yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, 0, &yymsp[-1].minor.yy0);
}
- yymsp[-1].minor.yy211 = yylhsminor.yy211;
+ yymsp[-1].minor.yy483 = yylhsminor.yy483;
break;
case 321: /* frame_opt ::= */
{
- yymsp[1].minor.yy211 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
+ yymsp[1].minor.yy483 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
}
break;
case 322: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
{
- yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy144, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy462);
+ yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy502, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy444);
}
- yymsp[-2].minor.yy211 = yylhsminor.yy211;
+ yymsp[-2].minor.yy483 = yylhsminor.yy483;
break;
case 323: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
{
- yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy144, yymsp[-3].minor.yy509.eType, yymsp[-3].minor.yy509.pExpr, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, yymsp[0].minor.yy462);
+ yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy502, yymsp[-3].minor.yy205.eType, yymsp[-3].minor.yy205.pExpr, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, yymsp[0].minor.yy444);
}
- yymsp[-5].minor.yy211 = yylhsminor.yy211;
+ yymsp[-5].minor.yy483 = yylhsminor.yy483;
break;
case 325: /* frame_bound_s ::= frame_bound */
case 327: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==327);
-{yylhsminor.yy509 = yymsp[0].minor.yy509;}
- yymsp[0].minor.yy509 = yylhsminor.yy509;
+{yylhsminor.yy205 = yymsp[0].minor.yy205;}
+ yymsp[0].minor.yy205 = yylhsminor.yy205;
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.yy509.eType = yymsp[-1].major; yylhsminor.yy509.pExpr = 0;}
- yymsp[-1].minor.yy509 = yylhsminor.yy509;
+{yylhsminor.yy205.eType = yymsp[-1].major; yylhsminor.yy205.pExpr = 0;}
+ yymsp[-1].minor.yy205 = yylhsminor.yy205;
break;
case 329: /* frame_bound ::= expr PRECEDING|FOLLOWING */
-{yylhsminor.yy509.eType = yymsp[0].major; yylhsminor.yy509.pExpr = yymsp[-1].minor.yy454;}
- yymsp[-1].minor.yy509 = yylhsminor.yy509;
+{yylhsminor.yy205.eType = yymsp[0].major; yylhsminor.yy205.pExpr = yymsp[-1].minor.yy590;}
+ yymsp[-1].minor.yy205 = yylhsminor.yy205;
break;
case 331: /* frame_exclude_opt ::= */
-{yymsp[1].minor.yy462 = 0;}
+{yymsp[1].minor.yy444 = 0;}
break;
case 332: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
-{yymsp[-1].minor.yy462 = yymsp[0].minor.yy462;}
+{yymsp[-1].minor.yy444 = yymsp[0].minor.yy444;}
break;
case 333: /* frame_exclude ::= NO OTHERS */
case 334: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==334);
-{yymsp[-1].minor.yy462 = yymsp[-1].major; /*A-overwrites-X*/}
+{yymsp[-1].minor.yy444 = yymsp[-1].major; /*A-overwrites-X*/}
break;
case 335: /* frame_exclude ::= GROUP|TIES */
-{yymsp[0].minor.yy462 = yymsp[0].major; /*A-overwrites-X*/}
+{yymsp[0].minor.yy444 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 336: /* window_clause ::= WINDOW windowdefn_list */
-{ yymsp[-1].minor.yy211 = yymsp[0].minor.yy211; }
+{ yymsp[-1].minor.yy483 = yymsp[0].minor.yy483; }
break;
case 337: /* filter_over ::= filter_clause over_clause */
{
- if( yymsp[0].minor.yy211 ){
- yymsp[0].minor.yy211->pFilter = yymsp[-1].minor.yy454;
+ if( yymsp[0].minor.yy483 ){
+ yymsp[0].minor.yy483->pFilter = yymsp[-1].minor.yy590;
}else{
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590);
}
- yylhsminor.yy211 = yymsp[0].minor.yy211;
+ yylhsminor.yy483 = yymsp[0].minor.yy483;
}
- yymsp[-1].minor.yy211 = yylhsminor.yy211;
+ yymsp[-1].minor.yy483 = yylhsminor.yy483;
break;
case 338: /* filter_over ::= over_clause */
{
- yylhsminor.yy211 = yymsp[0].minor.yy211;
+ yylhsminor.yy483 = yymsp[0].minor.yy483;
}
- yymsp[0].minor.yy211 = yylhsminor.yy211;
+ yymsp[0].minor.yy483 = yylhsminor.yy483;
break;
case 339: /* filter_over ::= filter_clause */
{
- yylhsminor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yylhsminor.yy211 ){
- yylhsminor.yy211->eFrmType = TK_FILTER;
- yylhsminor.yy211->pFilter = yymsp[0].minor.yy454;
+ yylhsminor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yylhsminor.yy483 ){
+ yylhsminor.yy483->eFrmType = TK_FILTER;
+ yylhsminor.yy483->pFilter = yymsp[0].minor.yy590;
}else{
- sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy454);
+ sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy590);
}
}
- yymsp[0].minor.yy211 = yylhsminor.yy211;
+ yymsp[0].minor.yy483 = yylhsminor.yy483;
break;
case 340: /* over_clause ::= OVER LP window RP */
{
- yymsp[-3].minor.yy211 = yymsp[-1].minor.yy211;
- assert( yymsp[-3].minor.yy211!=0 );
+ yymsp[-3].minor.yy483 = yymsp[-1].minor.yy483;
+ assert( yymsp[-3].minor.yy483!=0 );
}
break;
case 341: /* over_clause ::= OVER nm */
{
- yymsp[-1].minor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yymsp[-1].minor.yy211 ){
- yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
+ yymsp[-1].minor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yymsp[-1].minor.yy483 ){
+ yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
}
}
break;
case 342: /* filter_clause ::= FILTER LP WHERE expr RP */
-{ yymsp[-4].minor.yy454 = yymsp[-1].minor.yy454; }
+{ yymsp[-4].minor.yy590 = yymsp[-1].minor.yy590; }
break;
case 343: /* term ::= QNUMBER */
{
- yylhsminor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0);
- sqlite3DequoteNumber(pParse, yylhsminor.yy454);
+ yylhsminor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0);
+ sqlite3DequoteNumber(pParse, yylhsminor.yy590);
}
- yymsp[0].minor.yy454 = yylhsminor.yy454;
+ yymsp[0].minor.yy590 = yylhsminor.yy590;
break;
default:
/* (344) input ::= cmdlist */ yytestcase(yyruleno==344);
@@ -177714,7 +180546,7 @@ static void yy_syntax_error(
UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
if( TOKEN.z[0] ){
- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
+ parserSyntaxError(pParse, &TOKEN);
}else{
sqlite3ErrorMsg(pParse, "incomplete input");
}
@@ -178765,7 +181597,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
case CC_MINUS: {
if( z[1]=='-' ){
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
- *tokenType = TK_SPACE; /* IMP: R-22934-25134 */
+ *tokenType = TK_COMMENT;
return i;
}else if( z[1]=='>' ){
*tokenType = TK_PTR;
@@ -178801,7 +181633,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
- *tokenType = TK_SPACE; /* IMP: R-22934-25134 */
+ *tokenType = TK_COMMENT;
return i;
}
case CC_PERCENT: {
@@ -179130,12 +181962,12 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){
if( tokenType>=TK_WINDOW ){
assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER
|| tokenType==TK_ILLEGAL || tokenType==TK_WINDOW
- || tokenType==TK_QNUMBER
+ || tokenType==TK_QNUMBER || tokenType==TK_COMMENT
);
#else
if( tokenType>=TK_SPACE ){
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL
- || tokenType==TK_QNUMBER
+ || tokenType==TK_QNUMBER || tokenType==TK_COMMENT
);
#endif /* SQLITE_OMIT_WINDOWFUNC */
if( AtomicLoad(&db->u1.isInterrupted) ){
@@ -179169,6 +182001,13 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){
assert( n==6 );
tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
#endif /* SQLITE_OMIT_WINDOWFUNC */
+ }else if( tokenType==TK_COMMENT
+ && (db->init.busy || (db->flags & SQLITE_Comments)!=0)
+ ){
+ /* Ignore SQL comments if either (1) we are reparsing the schema or
+ ** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */
+ zSql += n;
+ continue;
}else if( tokenType!=TK_QNUMBER ){
Token x;
x.z = zSql;
@@ -179205,7 +182044,9 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){
if( pParse->zErrMsg==0 ){
pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
}
- sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
+ if( (pParse->prepFlags & SQLITE_PREPARE_DONT_LOG)==0 ){
+ sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
+ }
nErr++;
}
pParse->zTail = zSql;
@@ -179273,6 +182114,7 @@ SQLITE_PRIVATE char *sqlite3Normalize(
n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
if( NEVER(n<=0) ) break;
switch( tokenType ){
+ case TK_COMMENT:
case TK_SPACE: {
break;
}
@@ -179915,32 +182757,6 @@ SQLITE_API char *sqlite3_temp_directory = 0;
SQLITE_API char *sqlite3_data_directory = 0;
/*
-** Determine whether or not high-precision (long double) floating point
-** math works correctly on CPU currently running.
-*/
-static SQLITE_NOINLINE int hasHighPrecisionDouble(int rc){
- if( sizeof(LONGDOUBLE_TYPE)<=8 ){
- /* If the size of "long double" is not more than 8, then
- ** high-precision math is not possible. */
- return 0;
- }else{
- /* Just because sizeof(long double)>8 does not mean that the underlying
- ** hardware actually supports high-precision floating point. For example,
- ** clearing the 0x100 bit in the floating-point control word on Intel
- ** processors will make long double work like double, even though long
- ** double takes up more space. The only way to determine if long double
- ** actually works is to run an experiment. */
- LONGDOUBLE_TYPE a, b, c;
- rc++;
- a = 1.0+rc*0.1;
- b = 1.0e+18+rc*25.0;
- c = a+b;
- return b!=c;
- }
-}
-
-
-/*
** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
@@ -180084,6 +182900,14 @@ SQLITE_API int sqlite3_initialize(void){
if( rc==SQLITE_OK ){
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
+#ifdef SQLITE_EXTRA_INIT_MUTEXED
+ {
+ int SQLITE_EXTRA_INIT_MUTEXED(const char*);
+ rc = SQLITE_EXTRA_INIT_MUTEXED(0);
+ }
+#endif
+ }
+ if( rc==SQLITE_OK ){
sqlite3MemoryBarrier();
sqlite3GlobalConfig.isInit = 1;
#ifdef SQLITE_EXTRA_INIT
@@ -180134,13 +182958,6 @@ SQLITE_API int sqlite3_initialize(void){
rc = SQLITE_EXTRA_INIT(0);
}
#endif
-
- /* Experimentally determine if high-precision floating point is
- ** available. */
-#ifndef SQLITE_OMIT_WSD
- sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc);
-#endif
-
return rc;
}
@@ -180547,17 +183364,22 @@ SQLITE_API int sqlite3_config(int op, ...){
** If lookaside is already active, return SQLITE_BUSY.
**
** The sz parameter is the number of bytes in each lookaside slot.
-** The cnt parameter is the number of slots. If pStart is NULL the
-** space for the lookaside memory is obtained from sqlite3_malloc().
-** If pStart is not NULL then it is sz*cnt bytes of memory to use for
-** the lookaside memory.
+** The cnt parameter is the number of slots. If pBuf is NULL the
+** space for the lookaside memory is obtained from sqlite3_malloc()
+** or similar. If pBuf is not NULL then it is sz*cnt bytes of memory
+** to use for the lookaside memory.
*/
-static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
+static int setupLookaside(
+ sqlite3 *db, /* Database connection being configured */
+ void *pBuf, /* Memory to use for lookaside. May be NULL */
+ int sz, /* Desired size of each lookaside memory slot */
+ int cnt /* Number of slots to allocate */
+){
#ifndef SQLITE_OMIT_LOOKASIDE
- void *pStart;
- sqlite3_int64 szAlloc = sz*(sqlite3_int64)cnt;
- int nBig; /* Number of full-size slots */
- int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */
+ void *pStart; /* Start of the lookaside buffer */
+ sqlite3_int64 szAlloc; /* Total space set aside for lookaside memory */
+ int nBig; /* Number of full-size slots */
+ int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */
if( sqlite3LookasideUsed(db,0)>0 ){
return SQLITE_BUSY;
@@ -180570,17 +183392,22 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
sqlite3_free(db->lookaside.pStart);
}
/* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
- ** than a pointer to be useful.
+ ** than a pointer and small enough to fit in a u16.
*/
- sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */
+ sz = ROUNDDOWN8(sz);
if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
- if( cnt<0 ) cnt = 0;
- if( sz==0 || cnt==0 ){
+ if( sz>65528 ) sz = 65528;
+ /* Count must be at least 1 to be useful, but not so large as to use
+ ** more than 0x7fff0000 total bytes for lookaside. */
+ if( cnt<1 ) cnt = 0;
+ if( sz>0 && cnt>(0x7fff0000/sz) ) cnt = 0x7fff0000/sz;
+ szAlloc = (i64)sz*(i64)cnt;
+ if( szAlloc==0 ){
sz = 0;
pStart = 0;
}else if( pBuf==0 ){
sqlite3BeginBenignMalloc();
- pStart = sqlite3Malloc( szAlloc ); /* IMP: R-61949-35727 */
+ pStart = sqlite3Malloc( szAlloc );
sqlite3EndBenignMalloc();
if( pStart ) szAlloc = sqlite3MallocSize(pStart);
}else{
@@ -180589,10 +183416,10 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
if( sz>=LOOKASIDE_SMALL*3 ){
nBig = szAlloc/(3*LOOKASIDE_SMALL+sz);
- nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
+ nSm = (szAlloc - (i64)sz*(i64)nBig)/LOOKASIDE_SMALL;
}else if( sz>=LOOKASIDE_SMALL*2 ){
nBig = szAlloc/(LOOKASIDE_SMALL+sz);
- nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
+ nSm = (szAlloc - (i64)sz*(i64)nBig)/LOOKASIDE_SMALL;
}else
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
if( sz>0 ){
@@ -180747,7 +183574,7 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
default: {
static const struct {
int op; /* The opcode */
- u32 mask; /* Mask of the bit in sqlite3.flags to set/clear */
+ u64 mask; /* Mask of the bit in sqlite3.flags to set/clear */
} aFlagOp[] = {
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
@@ -180768,6 +183595,9 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_TRUSTED_SCHEMA, SQLITE_TrustedSchema },
{ SQLITE_DBCONFIG_STMT_SCANSTATUS, SQLITE_StmtScanStatus },
{ SQLITE_DBCONFIG_REVERSE_SCANORDER, SQLITE_ReverseOrder },
+ { SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE, SQLITE_AttachCreate },
+ { SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE, SQLITE_AttachWrite },
+ { SQLITE_DBCONFIG_ENABLE_COMMENTS, SQLITE_Comments },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
@@ -181211,10 +184041,6 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
sqlite3ValueFree(db->pErr);
sqlite3CloseExtensions(db);
-#if SQLITE_USER_AUTHENTICATION
- sqlite3_free(db->auth.zAuthUser);
- sqlite3_free(db->auth.zAuthPW);
-#endif
db->eOpenState = SQLITE_STATE_ERROR;
@@ -181558,6 +184384,9 @@ SQLITE_API int sqlite3_busy_handler(
db->busyHandler.pBusyArg = pArg;
db->busyHandler.nBusy = 0;
db->busyTimeout = 0;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ db->setlkTimeout = 0;
+#endif
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -181607,6 +184436,9 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
(void*)db);
db->busyTimeout = ms;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ db->setlkTimeout = ms;
+#endif
}else{
sqlite3_busy_handler(db, 0, 0);
}
@@ -181614,6 +184446,40 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
}
/*
+** Set the setlk timeout value.
+*/
+SQLITE_API int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int iDb;
+ int bBOC = ((flags & SQLITE_SETLK_BLOCK_ON_CONNECT) ? 1 : 0);
+#endif
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+#endif
+ if( ms<-1 ) return SQLITE_RANGE;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3_mutex_enter(db->mutex);
+ db->setlkTimeout = ms;
+ db->setlkFlags = flags;
+ sqlite3BtreeEnterAll(db);
+ for(iDb=0; iDb<db->nDb; iDb++){
+ Btree *pBt = db->aDb[iDb].pBt;
+ if( pBt ){
+ sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt));
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC);
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+ sqlite3_mutex_leave(db->mutex);
+#endif
+#if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ UNUSED_PARAMETER(db);
+ UNUSED_PARAMETER(flags);
+#endif
+ return SQLITE_OK;
+}
+
+/*
** Cause any pending operation to stop at its earliest opportunity.
*/
SQLITE_API void sqlite3_interrupt(sqlite3 *db){
@@ -181681,7 +184547,8 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
- SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE);
+ SQLITE_SUBTYPE|SQLITE_INNOCUOUS|
+ SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1);
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
/* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
@@ -182648,8 +185515,8 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_VDBE_OP<40
# error SQLITE_MAX_VDBE_OP must be at least 40
#endif
-#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127
-# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127
+#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>32767
+# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 32767
#endif
#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
# error SQLITE_MAX_ATTACHED must be between 0 and 125
@@ -182716,8 +185583,8 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
- }else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){
- newLimit = 1;
+ }else if( newLimit<SQLITE_MIN_LENGTH && limitId==SQLITE_LIMIT_LENGTH ){
+ newLimit = SQLITE_MIN_LENGTH;
}
db->aLimit[limitId] = newLimit;
}
@@ -183112,6 +185979,9 @@ static int openDatabase(
| SQLITE_EnableTrigger
| SQLITE_EnableView
| SQLITE_CacheSpill
+ | SQLITE_AttachCreate
+ | SQLITE_AttachWrite
+ | SQLITE_Comments
#if !defined(SQLITE_TRUSTED_SCHEMA) || SQLITE_TRUSTED_SCHEMA+0!=0
| SQLITE_TrustedSchema
#endif
@@ -183236,6 +186106,7 @@ static int openDatabase(
if( ((1<<(flags&7)) & 0x46)==0 ){
rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */
}else{
+ if( zFilename==0 ) zFilename = ":memory:";
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
}
if( rc!=SQLITE_OK ){
@@ -183573,7 +186444,7 @@ SQLITE_API int sqlite3_set_clientdata(
return SQLITE_OK;
}else{
size_t n = strlen(zName);
- p = sqlite3_malloc64( sizeof(DbClientData)+n+1 );
+ p = sqlite3_malloc64( SZ_DBCLIENTDATA(n+1) );
if( p==0 ){
if( xDestructor ) xDestructor(pData);
sqlite3_mutex_leave(db->mutex);
@@ -183727,13 +186598,10 @@ SQLITE_API int sqlite3_table_column_metadata(
if( zColumnName==0 ){
/* Query for existence of table only */
}else{
- for(iCol=0; iCol<pTab->nCol; iCol++){
+ iCol = sqlite3ColumnIndex(pTab, zColumnName);
+ if( iCol>=0 ){
pCol = &pTab->aCol[iCol];
- if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){
- break;
- }
- }
- if( iCol==pTab->nCol ){
+ }else{
if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
iCol = pTab->iPKey;
pCol = iCol>=0 ? &pTab->aCol[iCol] : 0;
@@ -183942,8 +186810,8 @@ SQLITE_API int sqlite3_test_control(int op, ...){
/* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b);
**
** If b is true, then activate the SQLITE_FkNoAction setting. If b is
- ** false then clearn that setting. If the SQLITE_FkNoAction setting is
- ** abled, all foreign key ON DELETE and ON UPDATE actions behave as if
+ ** false then clear that setting. If the SQLITE_FkNoAction setting is
+ ** enabled, all foreign key ON DELETE and ON UPDATE actions behave as if
** they were NO ACTION, regardless of how they are defined.
**
** NB: One must usually run "PRAGMA writable_schema=RESET" after
@@ -184061,7 +186929,6 @@ SQLITE_API int sqlite3_test_control(int op, ...){
** issue "defined but not used" warnings. */
if( x==9999 ){
sqlite3ShowExpr(0);
- sqlite3ShowExpr(0);
sqlite3ShowExprList(0);
sqlite3ShowIdList(0);
sqlite3ShowSrcList(0);
@@ -184148,6 +187015,18 @@ SQLITE_API int sqlite3_test_control(int op, ...){
break;
}
+ /* sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, sqlite3 *db, int *N)
+ **
+ ** Write the current optimization settings into *N. A zero bit means that
+ ** the optimization is on, and a 1 bit means that the optimization is off.
+ */
+ case SQLITE_TESTCTRL_GETOPT: {
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ int *pN = va_arg(ap, int*);
+ *pN = db->dbOptFlags;
+ break;
+ }
+
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
**
** If parameter onoff is 1, subsequent calls to localtime() fail.
@@ -184379,24 +187258,6 @@ SQLITE_API int sqlite3_test_control(int op, ...){
break;
}
-#if !defined(SQLITE_OMIT_WSD)
- /* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X);
- **
- ** X<0 Make no changes to the bUseLongDouble. Just report value.
- ** X==0 Disable bUseLongDouble
- ** X==1 Enable bUseLongDouble
- ** X>=2 Set bUseLongDouble to its default value for this platform
- */
- case SQLITE_TESTCTRL_USELONGDOUBLE: {
- int b = va_arg(ap, int);
- if( b>=2 ) b = hasHighPrecisionDouble(b);
- if( b>=0 ) sqlite3Config.bUseLongDouble = b>0;
- rc = sqlite3Config.bUseLongDouble!=0;
- break;
- }
-#endif
-
-
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
**
@@ -184704,7 +187565,11 @@ SQLITE_API int sqlite3_snapshot_get(
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
+ Pager *pPager = sqlite3BtreePager(pBt);
+ i64 dummy = 0;
+ sqlite3PagerSnapshotOpen(pPager, (sqlite3_snapshot*)&dummy);
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
+ sqlite3PagerSnapshotOpen(pPager, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
}
@@ -185293,7 +188158,7 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory. A "position" is an index of a token in the token stream
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
-** in the same logical place as the position element, and act as sentinals
+** in the same logical place as the position element, and act as sentinels
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
** The positions numbers are not stored literally but rather as two more
** than the difference from the prior position, or the just the position plus
@@ -185512,6 +188377,13 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
#ifndef _FTSINT_H
#define _FTSINT_H
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+/* #include <stddef.h> */
+/* #include <stdio.h> */
+/* #include <string.h> */
+/* #include <stdarg.h> */
+
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
@@ -185981,6 +188853,19 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
#define deliberate_fall_through
+/*
+** Macros needed to provide flexible arrays in a portable way
+*/
+#ifndef offsetof
+# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
+
+
#endif /* SQLITE_AMALGAMATION */
#ifdef SQLITE_DEBUG
@@ -186085,7 +188970,7 @@ struct Fts3Table {
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- /* True to disable the incremental doclist optimization. This is controled
+ /* True to disable the incremental doclist optimization. This is controlled
** by special insert command 'test-no-incr-doclist'. */
int bNoIncrDoclist;
@@ -186137,7 +189022,7 @@ struct Fts3Cursor {
/*
** The Fts3Cursor.eSearch member is always set to one of the following.
-** Actualy, Fts3Cursor.eSearch can be greater than or equal to
+** Actually, Fts3Cursor.eSearch can be greater than or equal to
** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
** of the column to be searched. For example, in
**
@@ -186210,9 +189095,13 @@ struct Fts3Phrase {
*/
int nToken; /* Number of tokens in the phrase */
int iColumn; /* Index of column this phrase must match */
- Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
+ Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */
};
+/* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */
+#define SZ_FTS3PHRASE(N) \
+ (offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken))
+
/*
** A tree of these objects forms the RHS of a MATCH operator.
**
@@ -186419,6 +189308,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
+SQLITE_PRIVATE int sqlite3Fts3MsrCancel(Fts3Cursor*, Fts3Expr*);
/* fts3_tokenize_vtab.c */
SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
@@ -186445,12 +189335,6 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
# define SQLITE_CORE 1
#endif
-/* #include <assert.h> */
-/* #include <stdlib.h> */
-/* #include <stddef.h> */
-/* #include <stdio.h> */
-/* #include <string.h> */
-/* #include <stdarg.h> */
/* #include "fts3.h" */
#ifndef SQLITE_CORE
@@ -188494,10 +191378,15 @@ static int fts3PoslistPhraseMerge(
if( *p1==POS_COLUMN ){
p1++;
p1 += fts3GetVarint32(p1, &iCol1);
+ /* iCol1==0 indicates corruption. Column 0 does not have a POS_COLUMN
+ ** entry, so this is actually end-of-doclist. */
+ if( iCol1==0 ) return 0;
}
if( *p2==POS_COLUMN ){
p2++;
p2 += fts3GetVarint32(p2, &iCol2);
+ /* As above, iCol2==0 indicates corruption. */
+ if( iCol2==0 ) return 0;
}
while( 1 ){
@@ -188784,7 +191673,7 @@ static int fts3DoclistOrMerge(
** sizes of the two inputs, plus enough space for exactly one of the input
** docids to grow.
**
- ** A symetric argument may be made if the doclists are in descending
+ ** A symmetric argument may be made if the doclists are in descending
** order.
*/
aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
@@ -190583,7 +193472,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
nDistance = iPrev - nMaxUndeferred;
}
- aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING);
+ aOut = (char *)sqlite3Fts3MallocZero(((i64)nPoslist)+FTS3_BUFFER_PADDING);
if( !aOut ){
sqlite3_free(aPoslist);
return SQLITE_NOMEM;
@@ -190882,7 +193771,7 @@ static int incrPhraseTokenNext(
**
** * does not contain any deferred tokens.
**
-** Advance it to the next matching documnent in the database and populate
+** Advance it to the next matching document in the database and populate
** the Fts3Doclist.pList and nList fields.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
@@ -191668,7 +194557,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
- aTmp = sqlite3_malloc64(nTmp*2);
+ aTmp = sqlite3_malloc64(nTmp*2 + FTS3_VARINT_MAX);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
@@ -191889,7 +194778,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
}
/*
-** Restart interation for expression pExpr so that the next call to
+** Restart iteration for expression pExpr so that the next call to
** fts3EvalNext() visits the first row. Do not allow incremental
** loading or merging of phrase doclists for this iteration.
**
@@ -191933,6 +194822,24 @@ static void fts3EvalRestart(
}
/*
+** Expression node pExpr is an MSR phrase. This function restarts pExpr
+** so that it is a regular phrase query, not an MSR. SQLITE_OK is returned
+** if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3Fts3MsrCancel(Fts3Cursor *pCsr, Fts3Expr *pExpr){
+ int rc = SQLITE_OK;
+ if( pExpr->bEof==0 ){
+ i64 iDocid = pExpr->iDocid;
+ fts3EvalRestart(pCsr, pExpr, &rc);
+ while( rc==SQLITE_OK && pExpr->iDocid!=iDocid ){
+ fts3EvalNextRow(pCsr, pExpr, &rc);
+ if( pExpr->bEof ) rc = FTS_CORRUPT_VTAB;
+ }
+ }
+ return rc;
+}
+
+/*
** After allocating the Fts3Expr.aMI[] array for each phrase in the
** expression rooted at pExpr, the cursor iterates through all rows matched
** by pExpr, calling this function for each row. This function increments
@@ -192319,7 +195226,7 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
}
#endif
-#if !SQLITE_CORE
+#if !defined(SQLITE_CORE)
/*
** Initialize API pointer table, if required.
*/
@@ -193064,6 +195971,23 @@ SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
/*
+** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis
+** is defined, search for '(' and ')' as well. Return the index of the first
+** such character in the buffer. If there is no such character, return -1.
+*/
+static int findBarredChar(const char *z, int n){
+ int ii;
+ for(ii=0; ii<n; ii++){
+ if( (z[ii]=='"')
+ || (sqlite3_fts3_enable_parentheses && (z[ii]=='(' || z[ii]==')'))
+ ){
+ return ii;
+ }
+ }
+ return -1;
+}
+
+/*
** Extract the next token from buffer z (length n) using the tokenizer
** and other information (column names etc.) in pParse. Create an Fts3Expr
** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
@@ -193087,16 +196011,9 @@ static int getNextToken(
int rc;
sqlite3_tokenizer_cursor *pCursor;
Fts3Expr *pRet = 0;
- int i = 0;
-
- /* Set variable i to the maximum number of bytes of input to tokenize. */
- for(i=0; i<n; i++){
- if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
- if( z[i]=='"' ) break;
- }
- *pnConsumed = i;
- rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
+ *pnConsumed = n;
+ rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
@@ -193104,7 +196021,18 @@ static int getNextToken(
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
- nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
+ /* Check that this tokenization did not gobble up any " characters. Or,
+ ** if enable_parenthesis is true, that it did not gobble up any
+ ** open or close parenthesis characters either. If it did, call
+ ** getNextToken() again, but pass only that part of the input buffer
+ ** up to the first such character. */
+ int iBarred = findBarredChar(z, iEnd);
+ if( iBarred>=0 ){
+ pModule->xClose(pCursor);
+ return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed);
+ }
+
+ nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken;
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
if( !pRet ){
rc = SQLITE_NOMEM;
@@ -193114,7 +196042,7 @@ static int getNextToken(
pRet->pPhrase->nToken = 1;
pRet->pPhrase->iColumn = iCol;
pRet->pPhrase->aToken[0].n = nToken;
- pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
+ pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1];
memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
if( iEnd<n && z[iEnd]=='*' ){
@@ -193138,7 +196066,11 @@ static int getNextToken(
}
*pnConsumed = iEnd;
- }else if( i && rc==SQLITE_DONE ){
+ }else if( n && rc==SQLITE_DONE ){
+ int iBarred = findBarredChar(z, n);
+ if( iBarred>=0 ){
+ *pnConsumed = iBarred;
+ }
rc = SQLITE_OK;
}
@@ -193185,9 +196117,9 @@ static int getNextString(
Fts3Expr *p = 0;
sqlite3_tokenizer_cursor *pCursor = 0;
char *zTemp = 0;
- int nTemp = 0;
+ i64 nTemp = 0;
- const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
+ const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1);
int nToken = 0;
/* The final Fts3Expr data structure, including the Fts3Phrase,
@@ -193221,10 +196153,11 @@ static int getNextString(
Fts3PhraseToken *pToken;
p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
- if( !p ) goto no_mem;
-
zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
- if( !zTemp ) goto no_mem;
+ if( !zTemp || !p ){
+ rc = SQLITE_NOMEM;
+ goto getnextstring_out;
+ }
assert( nToken==ii );
pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
@@ -193239,9 +196172,6 @@ static int getNextString(
nToken = ii+1;
}
}
-
- pModule->xClose(pCursor);
- pCursor = 0;
}
if( rc==SQLITE_DONE ){
@@ -193249,7 +196179,10 @@ static int getNextString(
char *zBuf = 0;
p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
- if( !p ) goto no_mem;
+ if( !p ){
+ rc = SQLITE_NOMEM;
+ goto getnextstring_out;
+ }
memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
p->eType = FTSQUERY_PHRASE;
p->pPhrase = (Fts3Phrase *)&p[1];
@@ -193257,11 +196190,9 @@ static int getNextString(
p->pPhrase->nToken = nToken;
zBuf = (char *)&p->pPhrase->aToken[nToken];
+ assert( nTemp==0 || zTemp );
if( zTemp ){
memcpy(zBuf, zTemp, nTemp);
- sqlite3_free(zTemp);
- }else{
- assert( nTemp==0 );
}
for(jj=0; jj<p->pPhrase->nToken; jj++){
@@ -193271,17 +196202,17 @@ static int getNextString(
rc = SQLITE_OK;
}
- *ppExpr = p;
- return rc;
-no_mem:
-
+ getnextstring_out:
if( pCursor ){
pModule->xClose(pCursor);
}
sqlite3_free(zTemp);
- sqlite3_free(p);
- *ppExpr = 0;
- return SQLITE_NOMEM;
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(p);
+ p = 0;
+ }
+ *ppExpr = p;
+ return rc;
}
/*
@@ -193560,7 +196491,7 @@ static int fts3ExprParse(
/* The isRequirePhrase variable is set to true if a phrase or
** an expression contained in parenthesis is required. If a
- ** binary operator (AND, OR, NOT or NEAR) is encounted when
+ ** binary operator (AND, OR, NOT or NEAR) is encountered when
** isRequirePhrase is set, this is a syntax error.
*/
if( !isPhrase && isRequirePhrase ){
@@ -194142,7 +197073,6 @@ static void fts3ExprTestCommon(
}
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
- sqlite3Fts3ExprFree(pExpr);
sqlite3_result_error(context, "Error parsing expression", -1);
}else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
sqlite3_result_error_nomem(context);
@@ -194385,7 +197315,7 @@ static void fts3HashInsertElement(
}
-/* Resize the hash table so that it cantains "new_size" buckets.
+/* Resize the hash table so that it contains "new_size" buckets.
** "new_size" must be a power of 2. The hash table might fail
** to resize if sqliteMalloc() fails.
**
@@ -194840,7 +197770,7 @@ static int star_oh(const char *z){
/*
** If the word ends with zFrom and xCond() is true for the stem
-** of the word that preceeds the zFrom ending, then change the
+** of the word that precedes the zFrom ending, then change the
** ending to zTo.
**
** The input word *pz and zFrom are both in reverse order. zTo
@@ -195475,11 +198405,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
/* #include <string.h> */
/*
@@ -196355,7 +199281,7 @@ static int fts3tokFilterMethod(
fts3tokResetCursor(pCsr);
if( idxNum==1 ){
const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
- int nByte = sqlite3_value_bytes(apVal[0]);
+ sqlite3_int64 nByte = sqlite3_value_bytes(apVal[0]);
pCsr->zInput = sqlite3_malloc64(nByte+1);
if( pCsr->zInput==0 ){
rc = SQLITE_NOMEM;
@@ -200427,7 +203353,7 @@ static int fts3IncrmergePush(
**
** It is assumed that the buffer associated with pNode is already large
** enough to accommodate the new entry. The buffer associated with pPrev
-** is extended by this function if requrired.
+** is extended by this function if required.
**
** If an error (i.e. OOM condition) occurs, an SQLite error code is
** returned. Otherwise, SQLITE_OK.
@@ -202090,7 +205016,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(
/*
** SQLite value pRowid contains the rowid of a row that may or may not be
** present in the FTS3 table. If it is, delete it and adjust the contents
-** of subsiduary data structures accordingly.
+** of subsidiary data structures accordingly.
*/
static int fts3DeleteByRowid(
Fts3Table *p,
@@ -202416,9 +205342,13 @@ struct MatchinfoBuffer {
int nElem;
int bGlobal; /* Set if global data is loaded */
char *zMatchinfo;
- u32 aMatchinfo[1];
+ u32 aMI[FLEXARRAY];
};
+/* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */
+#define SZ_MATCHINFOBUFFER(N) \
+ (offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64))
+
/*
** The snippet() and offsets() functions both return text values. An instance
@@ -202443,13 +205373,13 @@ struct StrBuffer {
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
- + sizeof(MatchinfoBuffer);
+ + SZ_MATCHINFOBUFFER(1);
sqlite3_int64 nStr = strlen(zMatchinfo);
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
if( pRet ){
- pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
- pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
+ pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet;
+ pRet->aMI[1+nElem] = pRet->aMI[0]
+ sizeof(u32)*((int)nElem+1);
pRet->nElem = (int)nElem;
pRet->zMatchinfo = ((char*)pRet) + nByte;
@@ -202463,10 +205393,10 @@ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
static void fts3MIBufferFree(void *p){
MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
- assert( (u32*)p==&pBuf->aMatchinfo[1]
- || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
+ assert( (u32*)p==&pBuf->aMI[1]
+ || (u32*)p==&pBuf->aMI[pBuf->nElem+2]
);
- if( (u32*)p==&pBuf->aMatchinfo[1] ){
+ if( (u32*)p==&pBuf->aMI[1] ){
pBuf->aRef[1] = 0;
}else{
pBuf->aRef[2] = 0;
@@ -202483,18 +205413,18 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
if( p->aRef[1]==0 ){
p->aRef[1] = 1;
- aOut = &p->aMatchinfo[1];
+ aOut = &p->aMI[1];
xRet = fts3MIBufferFree;
}
else if( p->aRef[2]==0 ){
p->aRef[2] = 1;
- aOut = &p->aMatchinfo[p->nElem+2];
+ aOut = &p->aMI[p->nElem+2];
xRet = fts3MIBufferFree;
}else{
aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
if( aOut ){
xRet = sqlite3_free;
- if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
+ if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32));
}
}
@@ -202504,7 +205434,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
p->bGlobal = 1;
- memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
+ memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32));
}
/*
@@ -202706,6 +205636,7 @@ static int fts3SnippetNextCandidate(SnippetIter *pIter){
return 1;
}
+ assert( pIter->nSnippet>=0 );
pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1;
for(i=0; i<pIter->nPhrase; i++){
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
@@ -202918,7 +205849,7 @@ static int fts3StringAppend(
}
/* If there is insufficient space allocated at StrBuffer.z, use realloc()
- ** to grow the buffer until so that it is big enough to accomadate the
+ ** to grow the buffer until so that it is big enough to accommodate the
** appended data.
*/
if( pStr->n+nAppend+1>=pStr->nAlloc ){
@@ -203330,16 +206261,16 @@ static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
break;
case FTS3_MATCHINFO_LHITS:
- nVal = pInfo->nCol * pInfo->nPhrase;
+ nVal = (size_t)pInfo->nCol * pInfo->nPhrase;
break;
case FTS3_MATCHINFO_LHITS_BM:
- nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
+ nVal = (size_t)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
break;
default:
assert( cArg==FTS3_MATCHINFO_HITS );
- nVal = pInfo->nCol * pInfo->nPhrase * 3;
+ nVal = (size_t)pInfo->nCol * pInfo->nPhrase * 3;
break;
}
@@ -203894,6 +206825,22 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
}
/*
+** If expression pExpr is a phrase expression that uses an MSR query,
+** restart it as a regular, non-incremental query. Return SQLITE_OK
+** if successful, or an SQLite error code otherwise.
+*/
+static int fts3ExprRestartIfCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
+ TermOffsetCtx *p = (TermOffsetCtx*)ctx;
+ int rc = SQLITE_OK;
+ UNUSED_PARAMETER(iPhrase);
+ if( pExpr->pPhrase && pExpr->pPhrase->bIncr ){
+ rc = sqlite3Fts3MsrCancel(p->pCsr, pExpr);
+ pExpr->pPhrase->bIncr = 0;
+ }
+ return rc;
+}
+
+/*
** Implementation of offsets() function.
*/
SQLITE_PRIVATE void sqlite3Fts3Offsets(
@@ -203929,6 +206876,12 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
sCtx.iDocid = pCsr->iPrevId;
sCtx.pCsr = pCsr;
+ /* If a query restart will be required, do it here, rather than later of
+ ** after pointers to poslist buffers that may be invalidated by a restart
+ ** have been saved. */
+ rc = sqlite3Fts3ExprIterate(pCsr->pExpr, fts3ExprRestartIfCb, (void*)&sCtx);
+ if( rc!=SQLITE_OK ) goto offsets_out;
+
/* Loop through the table columns, appending offset information to
** string-buffer res for each column.
*/
@@ -204875,8 +207828,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
** Beginning with version 3.45.0 (circa 2024-01-01), these routines also
** accept BLOB values that have JSON encoded using a binary representation
** called "JSONB". The name JSONB comes from PostgreSQL, however the on-disk
-** format SQLite JSONB is completely different and incompatible with
-** PostgreSQL JSONB.
+** format for SQLite-JSONB is completely different and incompatible with
+** PostgreSQL-JSONB.
**
** Decoding and interpreting JSONB is still O(N) where N is the size of
** the input, the same as text JSON. However, the constant of proportionality
@@ -204933,7 +207886,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
**
** The payload size need not be expressed in its minimal form. For example,
** if the payload size is 10, the size can be expressed in any of 5 different
-** ways: (1) (X>>4)==10, (2) (X>>4)==12 following by on 0x0a byte,
+** ways: (1) (X>>4)==10, (2) (X>>4)==12 following by one 0x0a byte,
** (3) (X>>4)==13 followed by 0x00 and 0x0a, (4) (X>>4)==14 followed by
** 0x00 0x00 0x00 0x0a, or (5) (X>>4)==15 followed by 7 bytes of 0x00 and
** a single byte of 0x0a. The shorter forms are preferred, of course, but
@@ -204943,7 +207896,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
** the size when it becomes known, resulting in a non-minimal encoding.
**
** The value (X>>4)==15 is not actually used in the current implementation
-** (as SQLite is currently unable handle BLOBs larger than about 2GB)
+** (as SQLite is currently unable to handle BLOBs larger than about 2GB)
** but is included in the design to allow for future enhancements.
**
** The payload follows the header. NULL, TRUE, and FALSE have no payload and
@@ -205003,23 +207956,47 @@ static const char * const jsonbType[] = {
** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
*/
static const char jsonIsSpace[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#ifdef SQLITE_ASCII
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */
+#endif
+#ifdef SQLITE_EBCDIC
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */
+#endif
+
};
#define jsonIsspace(x) (jsonIsSpace[(unsigned char)x])
@@ -205027,7 +208004,13 @@ static const char jsonIsSpace[] = {
** The set of all space characters recognized by jsonIsspace().
** Useful as the second argument to strspn().
*/
+#ifdef SQLITE_ASCII
static const char jsonSpaces[] = "\011\012\015\040";
+#endif
+#ifdef SQLITE_EBCDIC
+static const char jsonSpaces[] = "\005\045\015\100";
+#endif
+
/*
** Characters that are special to JSON. Control characters,
@@ -205036,23 +208019,46 @@ static const char jsonSpaces[] = "\011\012\015\040";
** it in the set of special characters.
*/
static const char jsonIsOk[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#ifdef SQLITE_ASCII
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
+ 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* 2 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 3 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 5 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */
+#endif
+#ifdef SQLITE_EBCDIC
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 3 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 5 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, /* 7 */
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */
+#endif
};
/* Objects */
@@ -205197,7 +208203,7 @@ struct JsonParse {
** Forward references
**************************************************************************/
static void jsonReturnStringAsBlob(JsonString*);
-static int jsonFuncArgMightBeBinary(sqlite3_value *pJson);
+static int jsonArgIsJsonb(sqlite3_value *pJson, JsonParse *p);
static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*);
static void jsonReturnParse(sqlite3_context*,JsonParse*);
static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
@@ -205271,7 +208277,7 @@ static int jsonCacheInsert(
** most-recently used entry if it isn't so already.
**
** The JsonParse object returned still belongs to the Cache and might
-** be deleted at any moment. If the caller whants the JsonParse to
+** be deleted at any moment. If the caller wants the JsonParse to
** linger, it needs to increment the nPJRef reference counter.
*/
static JsonParse *jsonCacheSearch(
@@ -205615,11 +208621,9 @@ static void jsonAppendSqlValue(
break;
}
default: {
- if( jsonFuncArgMightBeBinary(pValue) ){
- JsonParse px;
- memset(&px, 0, sizeof(px));
- px.aBlob = (u8*)sqlite3_value_blob(pValue);
- px.nBlob = sqlite3_value_bytes(pValue);
+ JsonParse px;
+ memset(&px, 0, sizeof(px));
+ if( jsonArgIsJsonb(pValue, &px) ){
jsonTranslateBlobToText(&px, 0, p);
}else if( p->eErr==0 ){
sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
@@ -205938,7 +208942,7 @@ static void jsonWrongNumArgs(
*/
static int jsonBlobExpand(JsonParse *pParse, u32 N){
u8 *aNew;
- u32 t;
+ u64 t;
assert( N>pParse->nBlobAlloc );
if( pParse->nBlobAlloc==0 ){
t = 100;
@@ -205948,8 +208952,9 @@ static int jsonBlobExpand(JsonParse *pParse, u32 N){
if( t<N ) t = N+100;
aNew = sqlite3DbRealloc(pParse->db, pParse->aBlob, t);
if( aNew==0 ){ pParse->oom = 1; return 1; }
+ assert( t<0x7fffffff );
pParse->aBlob = aNew;
- pParse->nBlobAlloc = t;
+ pParse->nBlobAlloc = (u32)t;
return 0;
}
@@ -206016,7 +209021,7 @@ static SQLITE_NOINLINE void jsonBlobExpandAndAppendNode(
}
-/* Append an node type byte together with the payload size and
+/* Append a node type byte together with the payload size and
** possibly also the payload.
**
** If aPayload is not NULL, then it is a pointer to the payload which
@@ -206085,8 +209090,10 @@ static int jsonBlobChangePayloadSize(
nExtra = 1;
}else if( szType==13 ){
nExtra = 2;
- }else{
+ }else if( szType==14 ){
nExtra = 4;
+ }else{
+ nExtra = 8;
}
if( szPayload<=11 ){
nNeeded = 0;
@@ -206556,7 +209563,12 @@ json_parse_restart:
|| c=='n' || c=='r' || c=='t'
|| (c=='u' && jsonIs4Hex(&z[j+1])) ){
if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ;
- }else if( c=='\'' || c=='0' || c=='v' || c=='\n'
+ }else if( c=='\'' || c=='v' || c=='\n'
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
+ || (c=='0') /* Legacy bug compatible */
+#else
+ || (c=='0' && !sqlite3Isdigit(z[j+1])) /* Correct implementation */
+#endif
|| (0xe2==(u8)c && 0x80==(u8)z[j+1]
&& (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]))
|| (c=='x' && jsonIs2Hex(&z[j+1])) ){
@@ -206906,10 +209918,7 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
u8 x;
u32 sz;
u32 n;
- if( NEVER(i>pParse->nBlob) ){
- *pSz = 0;
- return 0;
- }
+ assert( i<=pParse->nBlob );
x = pParse->aBlob[i]>>4;
if( x<=11 ){
sz = x;
@@ -206946,15 +209955,15 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
*pSz = 0;
return 0;
}
- sz = (pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
+ sz = ((u32)pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
(pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
n = 9;
}
if( (i64)i+sz+n > pParse->nBlob
&& (i64)i+sz+n > pParse->nBlob-pParse->delta
){
- sz = 0;
- n = 0;
+ *pSz = 0;
+ return 0;
}
*pSz = sz;
return n;
@@ -207051,9 +210060,12 @@ static u32 jsonTranslateBlobToText(
}
case JSONB_TEXT:
case JSONB_TEXTJ: {
- jsonAppendChar(pOut, '"');
- jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz);
- jsonAppendChar(pOut, '"');
+ if( pOut->nUsed+sz+2<=pOut->nAlloc || jsonStringGrow(pOut, sz+2)==0 ){
+ pOut->zBuf[pOut->nUsed] = '"';
+ memcpy(pOut->zBuf+pOut->nUsed+1,(const char*)&pParse->aBlob[i+n],sz);
+ pOut->zBuf[pOut->nUsed+sz+1] = '"';
+ pOut->nUsed += sz+2;
+ }
break;
}
case JSONB_TEXT5: {
@@ -207292,33 +210304,6 @@ static u32 jsonTranslateBlobToPrettyText(
return i;
}
-
-/* Return true if the input pJson
-**
-** For performance reasons, this routine does not do a detailed check of the
-** input BLOB to ensure that it is well-formed. Hence, false positives are
-** possible. False negatives should never occur, however.
-*/
-static int jsonFuncArgMightBeBinary(sqlite3_value *pJson){
- u32 sz, n;
- const u8 *aBlob;
- int nBlob;
- JsonParse s;
- if( sqlite3_value_type(pJson)!=SQLITE_BLOB ) return 0;
- aBlob = sqlite3_value_blob(pJson);
- nBlob = sqlite3_value_bytes(pJson);
- if( nBlob<1 ) return 0;
- if( NEVER(aBlob==0) || (aBlob[0] & 0x0f)>JSONB_OBJECT ) return 0;
- memset(&s, 0, sizeof(s));
- s.aBlob = (u8*)aBlob;
- s.nBlob = nBlob;
- n = jsonbPayloadSize(&s, 0, &sz);
- if( n==0 ) return 0;
- if( sz+n!=(u32)nBlob ) return 0;
- if( (aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0 ) return 0;
- return sz+n==(u32)nBlob;
-}
-
/*
** Given that a JSONB_ARRAY object starts at offset i, return
** the number of entries in that array.
@@ -207352,6 +210337,82 @@ static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){
}
/*
+** If the JSONB at aIns[0..nIns-1] can be expanded (by denormalizing the
+** size field) by d bytes, then write the expansion into aOut[] and
+** return true. In this way, an overwrite happens without changing the
+** size of the JSONB, which reduces memcpy() operations and also make it
+** faster and easier to update the B-Tree entry that contains the JSONB
+** in the database.
+**
+** If the expansion of aIns[] by d bytes cannot be (easily) accomplished
+** then return false.
+**
+** The d parameter is guaranteed to be between 1 and 8.
+**
+** This routine is an optimization. A correct answer is obtained if it
+** always leaves the output unchanged and returns false.
+*/
+static int jsonBlobOverwrite(
+ u8 *aOut, /* Overwrite here */
+ const u8 *aIns, /* New content */
+ u32 nIns, /* Bytes of new content */
+ u32 d /* Need to expand new content by this much */
+){
+ u32 szPayload; /* Bytes of payload */
+ u32 i; /* New header size, after expansion & a loop counter */
+ u8 szHdr; /* Size of header before expansion */
+
+ /* Lookup table for finding the upper 4 bits of the first byte of the
+ ** expanded aIns[], based on the size of the expanded aIns[] header:
+ **
+ ** 2 3 4 5 6 7 8 9 */
+ static const u8 aType[] = { 0xc0, 0xd0, 0, 0xe0, 0, 0, 0, 0xf0 };
+
+ if( (aIns[0]&0x0f)<=2 ) return 0; /* Cannot enlarge NULL, true, false */
+ switch( aIns[0]>>4 ){
+ default: { /* aIns[] header size 1 */
+ if( ((1<<d)&0x116)==0 ) return 0; /* d must be 1, 2, 4, or 8 */
+ i = d + 1; /* New hdr sz: 2, 3, 5, or 9 */
+ szHdr = 1;
+ break;
+ }
+ case 12: { /* aIns[] header size is 2 */
+ if( ((1<<d)&0x8a)==0) return 0; /* d must be 1, 3, or 7 */
+ i = d + 2; /* New hdr sz: 2, 5, or 9 */
+ szHdr = 2;
+ break;
+ }
+ case 13: { /* aIns[] header size is 3 */
+ if( d!=2 && d!=6 ) return 0; /* d must be 2 or 6 */
+ i = d + 3; /* New hdr sz: 5 or 9 */
+ szHdr = 3;
+ break;
+ }
+ case 14: { /* aIns[] header size is 5 */
+ if( d!=4 ) return 0; /* d must be 4 */
+ i = 9; /* New hdr sz: 9 */
+ szHdr = 5;
+ break;
+ }
+ case 15: { /* aIns[] header size is 9 */
+ return 0; /* No solution */
+ }
+ }
+ assert( i>=2 && i<=9 && aType[i-2]!=0 );
+ aOut[0] = (aIns[0] & 0x0f) | aType[i-2];
+ memcpy(&aOut[i], &aIns[szHdr], nIns-szHdr);
+ szPayload = nIns - szHdr;
+ while( 1/*edit-by-break*/ ){
+ i--;
+ aOut[i] = szPayload & 0xff;
+ if( i==1 ) break;
+ szPayload >>= 8;
+ }
+ assert( (szPayload>>8)==0 );
+ return 1;
+}
+
+/*
** Modify the JSONB blob at pParse->aBlob by removing nDel bytes of
** content beginning at iDel, and replacing them with nIns bytes of
** content given by aIns.
@@ -207372,6 +210433,11 @@ static void jsonBlobEdit(
u32 nIns /* Bytes of content to insert */
){
i64 d = (i64)nIns - (i64)nDel;
+ if( d<0 && d>=(-8) && aIns!=0
+ && jsonBlobOverwrite(&pParse->aBlob[iDel], aIns, nIns, (int)-d)
+ ){
+ return;
+ }
if( d!=0 ){
if( pParse->nBlob + d > pParse->nBlobAlloc ){
jsonBlobExpand(pParse, pParse->nBlob+d);
@@ -207383,7 +210449,9 @@ static void jsonBlobEdit(
pParse->nBlob += d;
pParse->delta += d;
}
- if( nIns && aIns ) memcpy(&pParse->aBlob[iDel], aIns, nIns);
+ if( nIns && aIns ){
+ memcpy(&pParse->aBlob[iDel], aIns, nIns);
+ }
}
/*
@@ -207468,7 +210536,21 @@ static u32 jsonUnescapeOneChar(const char *z, u32 n, u32 *piOut){
case 'r': { *piOut = '\r'; return 2; }
case 't': { *piOut = '\t'; return 2; }
case 'v': { *piOut = '\v'; return 2; }
- case '0': { *piOut = 0; return 2; }
+ case '0': {
+ /* JSON5 requires that the \0 escape not be followed by a digit.
+ ** But SQLite did not enforce this restriction in versions 3.42.0
+ ** through 3.49.2. That was a bug. But some applications might have
+ ** come to depend on that bug. Use the SQLITE_BUG_COMPATIBLE_20250510
+ ** option to restore the old buggy behavior. */
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
+ /* Legacy bug-compatible behavior */
+ *piOut = 0;
+#else
+ /* Correct behavior */
+ *piOut = (n>2 && sqlite3Isdigit(z[2])) ? JSON_INVALID_CHAR : 0;
+#endif
+ return 2;
+ }
case '\'':
case '"':
case '/':
@@ -207699,7 +210781,9 @@ static u32 jsonLookupStep(
zPath++;
if( zPath[0]=='"' ){
zKey = zPath + 1;
- for(i=1; zPath[i] && zPath[i]!='"'; i++){}
+ for(i=1; zPath[i] && zPath[i]!='"'; i++){
+ if( zPath[i]=='\\' && zPath[i+1]!=0 ) i++;
+ }
nKey = i-1;
if( zPath[i] ){
i++;
@@ -207966,7 +211050,7 @@ static void jsonReturnFromBlob(
char *zOut;
u32 nOut = sz;
z = (const char*)&pParse->aBlob[i+n];
- zOut = sqlite3DbMallocRaw(db, nOut+1);
+ zOut = sqlite3DbMallocRaw(db, ((u64)nOut)+1);
if( zOut==0 ) goto returnfromblob_oom;
for(iIn=iOut=0; iIn<sz; iIn++){
char c = z[iIn];
@@ -208061,10 +211145,7 @@ static int jsonFunctionArgToBlob(
return 0;
}
case SQLITE_BLOB: {
- if( jsonFuncArgMightBeBinary(pArg) ){
- pParse->aBlob = (u8*)sqlite3_value_blob(pArg);
- pParse->nBlob = sqlite3_value_bytes(pArg);
- }else{
+ if( !jsonArgIsJsonb(pArg, pParse) ){
sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1);
return 1;
}
@@ -208144,7 +211225,7 @@ static char *jsonBadPathError(
}
/* argv[0] is a BLOB that seems likely to be a JSONB. Subsequent
-** arguments come in parse where each pair contains a JSON path and
+** arguments come in pairs where each pair contains a JSON path and
** content to insert or set at that patch. Do the updates
** and return the result.
**
@@ -208215,27 +211296,46 @@ jsonInsertIntoBlob_patherror:
/*
** If pArg is a blob that seems like a JSONB blob, then initialize
** p to point to that JSONB and return TRUE. If pArg does not seem like
-** a JSONB blob, then return FALSE;
-**
-** This routine is only called if it is already known that pArg is a
-** blob. The only open question is whether or not the blob appears
-** to be a JSONB blob.
+** a JSONB blob, then return FALSE.
+**
+** For small BLOBs (having no more than 7 bytes of payload) a full
+** validity check is done. So for small BLOBs this routine only returns
+** true if the value is guaranteed to be a valid JSONB. For larger BLOBs
+** (8 byte or more of payload) only the size of the outermost element is
+** checked to verify that the BLOB is superficially valid JSONB.
+**
+** A full JSONB validation is done on smaller BLOBs because those BLOBs might
+** also be text JSON that has been incorrectly cast into a BLOB.
+** (See tag-20240123-a and https://sqlite.org/forum/forumpost/012136abd5)
+** If the BLOB is 9 bytes are larger, then it is not possible for the
+** superficial size check done here to pass if the input is really text
+** JSON so we do not need to look deeper in that case.
+**
+** Why we only need to do full JSONB validation for smaller BLOBs:
+**
+** The first byte of valid JSON text must be one of: '{', '[', '"', ' ', '\n',
+** '\r', '\t', '-', or a digit '0' through '9'. Of these, only a subset
+** can also be the first byte of JSONB: '{', '[', and digits '3'
+** through '9'. In every one of those cases, the payload size is 7 bytes
+** or less. So if we do full JSONB validation for every BLOB where the
+** payload is less than 7 bytes, we will never get a false positive for
+** JSONB on an input that is really text JSON.
*/
static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){
u32 n, sz = 0;
+ u8 c;
+ if( sqlite3_value_type(pArg)!=SQLITE_BLOB ) return 0;
p->aBlob = (u8*)sqlite3_value_blob(pArg);
p->nBlob = (u32)sqlite3_value_bytes(pArg);
- if( p->nBlob==0 ){
- p->aBlob = 0;
- return 0;
- }
- if( NEVER(p->aBlob==0) ){
- return 0;
- }
- if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT
+ if( p->nBlob>0
+ && ALWAYS(p->aBlob!=0)
+ && ((c = p->aBlob[0]) & 0x0f)<=JSONB_OBJECT
&& (n = jsonbPayloadSize(p, 0, &sz))>0
&& sz+n==p->nBlob
- && ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0)
+ && ((c & 0x0f)>JSONB_FALSE || sz==0)
+ && (sz>7
+ || (c!=0x7b && c!=0x5b && !sqlite3Isdigit(c))
+ || jsonbValidityCheck(p, 0, p->nBlob, 1)==0)
){
return 1;
}
@@ -208313,7 +211413,7 @@ rebuild_from_cache:
** JSON functions were suppose to work. From the beginning, blob was
** reserved for expansion and a blob value should have raised an error.
** But it did not, due to a bug. And many applications came to depend
- ** upon this buggy behavior, espeically when using the CLI and reading
+ ** upon this buggy behavior, especially when using the CLI and reading
** JSON text using readfile(), which returns a blob. For this reason
** we will continue to support the bug moving forward.
** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
@@ -208709,10 +211809,16 @@ static void jsonExtractFunc(
** NUMBER ==> $[NUMBER] // PG compatible
** LABEL ==> $.LABEL // PG compatible
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
+ **
+ ** Updated 2024-05-27: If the NUMBER is negative, then PG counts from
+ ** the right of the array. Hence for negative NUMBER:
+ **
+ ** NUMBER ==> $[#NUMBER] // PG compatible
*/
jsonStringInit(&jx, ctx);
if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
jsonAppendRawNZ(&jx, "[", 1);
+ if( zPath[0]=='-' ) jsonAppendRawNZ(&jx,"#",1);
jsonAppendRaw(&jx, zPath, nPath);
jsonAppendRawNZ(&jx, "]", 2);
}else if( jsonAllAlphanum(zPath, nPath) ){
@@ -209322,21 +212428,17 @@ static void jsonValidFunc(
return;
}
case SQLITE_BLOB: {
- if( jsonFuncArgMightBeBinary(argv[0]) ){
+ JsonParse py;
+ memset(&py, 0, sizeof(py));
+ if( jsonArgIsJsonb(argv[0], &py) ){
if( flags & 0x04 ){
/* Superficial checking only - accomplished by the
- ** jsonFuncArgMightBeBinary() call above. */
+ ** jsonArgIsJsonb() call above. */
res = 1;
}else if( flags & 0x08 ){
/* Strict checking. Check by translating BLOB->TEXT->BLOB. If
** no errors occur, call that a "strict check". */
- JsonParse px;
- u32 iErr;
- memset(&px, 0, sizeof(px));
- px.aBlob = (u8*)sqlite3_value_blob(argv[0]);
- px.nBlob = sqlite3_value_bytes(argv[0]);
- iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
- res = iErr==0;
+ res = 0==jsonbValidityCheck(&py, 0, py.nBlob, 1);
}
break;
}
@@ -209394,9 +212496,7 @@ static void jsonErrorFunc(
UNUSED_PARAMETER(argc);
memset(&s, 0, sizeof(s));
s.db = sqlite3_context_db_handle(ctx);
- if( jsonFuncArgMightBeBinary(argv[0]) ){
- s.aBlob = (u8*)sqlite3_value_blob(argv[0]);
- s.nBlob = sqlite3_value_bytes(argv[0]);
+ if( jsonArgIsJsonb(argv[0], &s) ){
iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1);
}else{
s.zJson = (char*)sqlite3_value_text(argv[0]);
@@ -209557,18 +212657,20 @@ static void jsonObjectStep(
UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
+ z = (const char*)sqlite3_value_text(argv[0]);
+ n = sqlite3Strlen30(z);
if( pStr->zBuf==0 ){
jsonStringInit(pStr, ctx);
jsonAppendChar(pStr, '{');
- }else if( pStr->nUsed>1 ){
+ }else if( pStr->nUsed>1 && z!=0 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
- z = (const char*)sqlite3_value_text(argv[0]);
- n = sqlite3Strlen30(z);
- jsonAppendString(pStr, z, n);
- jsonAppendChar(pStr, ':');
- jsonAppendSqlValue(pStr, argv[1]);
+ if( z!=0 ){
+ jsonAppendString(pStr, z, n);
+ jsonAppendChar(pStr, ':');
+ jsonAppendSqlValue(pStr, argv[1]);
+ }
}
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
@@ -210081,9 +213183,8 @@ static int jsonEachFilter(
memset(&p->sParse, 0, sizeof(p->sParse));
p->sParse.nJPRef = 1;
p->sParse.db = p->db;
- if( jsonFuncArgMightBeBinary(argv[0]) ){
- p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
- p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
+ if( jsonArgIsJsonb(argv[0], &p->sParse) ){
+ /* We have JSONB */
}else{
p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
p->sParse.nJson = sqlite3_value_bytes(argv[0]);
@@ -210377,6 +213478,8 @@ SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3 *db){
#endif
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
+/* #include <stddef.h> */
+
/*
** If building separately, we will need some setup that is normally
** found in sqliteInt.h
@@ -210407,6 +213510,14 @@ typedef unsigned int u32;
# define ALWAYS(X) (X)
# define NEVER(X) (X)
#endif
+#ifndef offsetof
+#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
#endif /* !defined(SQLITE_AMALGAMATION) */
/* Macro to check for 4-byte alignment. Only used inside of assert() */
@@ -210727,9 +213838,13 @@ struct RtreeMatchArg {
RtreeGeomCallback cb; /* Info about the callback functions */
int nParam; /* Number of parameters to the SQL function */
sqlite3_value **apSqlParam; /* Original SQL parameter values */
- RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
+ RtreeDValue aParam[FLEXARRAY]; /* Values for parameters to the SQL function */
};
+/* Size of an RtreeMatchArg object with N parameters */
+#define SZ_RTREEMATCHARG(N) \
+ (offsetof(RtreeMatchArg,aParam)+(N)*sizeof(RtreeDValue))
+
#ifndef MAX
# define MAX(x,y) ((x) < (y) ? (y) : (x))
#endif
@@ -212418,7 +215533,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
}
/*
-** Return the N-dimensional volumn of the cell stored in *p.
+** Return the N-dimensional volume of the cell stored in *p.
*/
static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
RtreeDValue area = (RtreeDValue)1;
@@ -214088,8 +217203,8 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
sqlite3_str_append(pOut, "}", 1);
}
errCode = sqlite3_str_errcode(pOut);
- sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
sqlite3_result_error_code(ctx, errCode);
+ sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
}
/* This routine implements an SQL function that returns the "depth" parameter
@@ -214184,7 +217299,7 @@ static sqlite3_stmt *rtreeCheckPrepare(
/*
** The second and subsequent arguments to this function are a printf()
** style format string and arguments. This function formats the string and
-** appends it to the report being accumuated in pCheck.
+** appends it to the report being accumulated in pCheck.
*/
static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
va_list ap;
@@ -215372,7 +218487,7 @@ static void geopolyBBoxFinal(
** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2).
** Returns:
**
-** +2 x0,y0 is on the line segement
+** +2 x0,y0 is on the line segment
**
** +1 x0,y0 is beneath line segment
**
@@ -215478,7 +218593,7 @@ static void geopolyWithinFunc(
sqlite3_free(p2);
}
-/* Objects used by the overlap algorihm. */
+/* Objects used by the overlap algorithm. */
typedef struct GeoEvent GeoEvent;
typedef struct GeoSegment GeoSegment;
typedef struct GeoOverlap GeoOverlap;
@@ -216525,8 +219640,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
sqlite3_int64 nBlob;
int memErr = 0;
- nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
- + nArg*sizeof(sqlite3_value*);
+ nBlob = SZ_RTREEMATCHARG(nArg) + nArg*sizeof(sqlite3_value*);
pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
if( !pBlob ){
sqlite3_result_error_nomem(ctx);
@@ -216605,7 +219719,7 @@ SQLITE_API int sqlite3_rtree_query_callback(
);
}
-#if !SQLITE_CORE
+#ifndef SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
@@ -217196,7 +220310,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
return rc;
}
-#if !SQLITE_CORE
+#ifndef SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
@@ -217621,7 +220735,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(
**
** "RBU" stands for "Resumable Bulk Update". As in a large database update
** transmitted via a wireless network to a mobile device. A transaction
-** applied using this extension is hence refered to as an "RBU update".
+** applied using this extension is hence referred to as an "RBU update".
**
**
** LIMITATIONS
@@ -217918,7 +221032,7 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
** new RBU vacuum operation.
**
-** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
+** As with sqlite3rbu_open(), Zipvfs users should refer to the comment
** describing the sqlite3rbu_create_vfs() API function below for
** a description of the complications associated with using RBU with
** zipvfs databases.
@@ -218014,7 +221128,7 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu);
**
** If the RBU update has been completely applied, mark the RBU database
** as fully applied. Otherwise, assuming no error has occurred, save the
-** current state of the RBU update appliation to the RBU database.
+** current state of the RBU update application to the RBU database.
**
** If an error has already occurred as part of an sqlite3rbu_step()
** or sqlite3rbu_open() call, or if one occurs within this function, an
@@ -218454,6 +221568,27 @@ struct RbuFrame {
u32 iWalFrame;
};
+#ifndef UNUSED_PARAMETER
+/*
+** The following macros are used to suppress compiler warnings and to
+** make it clear to human readers when a function parameter is deliberately
+** left unused within the body of a function. This usually happens when
+** a function is called via a function pointer. For example the
+** implementation of an SQL aggregate step callback may not use the
+** parameter indicating the number of arguments passed to the aggregate,
+** if it knows that this is enforced elsewhere.
+**
+** When a function parameter is not used at all within the body of a function,
+** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
+** However, these macros may also be used to suppress warnings related to
+** parameters that may or may not be used depending on compilation options.
+** For example those parameters only used in assert() statements. In these
+** cases the parameters are named as per the usual conventions.
+*/
+#define UNUSED_PARAMETER(x) (void)(x)
+#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
+#endif
+
/*
** RBU handle.
**
@@ -218505,7 +221640,7 @@ struct sqlite3rbu {
int rc; /* Value returned by last rbu_step() call */
char *zErrmsg; /* Error message if rc!=SQLITE_OK */
int nStep; /* Rows processed for current object */
- int nProgress; /* Rows processed for all objects */
+ sqlite3_int64 nProgress; /* Rows processed for all objects */
RbuObjIter objiter; /* Iterator for skipping through tbl/idx */
const char *zVfsName; /* Name of automatically created rbu vfs */
rbu_file *pTargetFd; /* File handle open on target db */
@@ -218622,7 +221757,7 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
v = (v<<6) + c;
}
z--;
- *pLen -= z - zStart;
+ *pLen -= (int)(z - zStart);
*pz = (char*)z;
return v;
}
@@ -218807,6 +221942,7 @@ static void rbuFossilDeltaFunc(
char *aOut;
assert( argc==2 );
+ UNUSED_PARAMETER(argc);
nOrig = sqlite3_value_bytes(argv[0]);
aOrig = (const char*)sqlite3_value_blob(argv[0]);
@@ -220386,13 +223522,13 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
else if( c==')' ){
nParen--;
if( nParen==0 ){
- int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
+ int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
i++;
break;
}
}else if( c==',' && nParen==1 ){
- int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
+ int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
}else if( c=='"' || c=='\'' || c=='`' ){
@@ -221082,6 +224218,8 @@ static void rbuFileSuffix3(const char *zBase, char *z){
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4);
}
+#else
+ UNUSED_PARAMETER2(zBase,z);
#endif
}
@@ -221666,7 +224804,7 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){
"(%d, %Q), "
"(%d, %Q), "
"(%d, %d), "
- "(%d, %d), "
+ "(%d, %lld), "
"(%d, %lld), "
"(%d, %lld), "
"(%d, %lld), "
@@ -222024,6 +225162,7 @@ static void rbuIndexCntFunc(
sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);
assert( nVal==1 );
+ UNUSED_PARAMETER(nVal);
rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
@@ -222299,7 +225438,7 @@ SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
){
if( zTarget==0 ){ return rbuMisuseError(); }
if( zState ){
- int n = strlen(zState);
+ size_t n = strlen(zState);
if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
return rbuMisuseError();
}
@@ -222516,6 +225655,7 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){
*/
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
int rc = SQLITE_OK;
+ UNUSED_PARAMETER(pArg);
#if defined(_WIN32_WCE)
{
LPWSTR zWideOld;
@@ -222914,7 +226054,7 @@ static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
/* If this is an RBU vacuum operation and this is the target database,
** pretend that it has at least one page. Otherwise, SQLite will not
- ** check for the existance of a *-wal file. rbuVfsRead() contains
+ ** check for the existence of a *-wal file. rbuVfsRead() contains
** similar logic. */
if( rc==SQLITE_OK && *pSize==0
&& p->pRbu && rbuIsVacuum(p->pRbu)
@@ -223420,6 +226560,9 @@ static int rbuVfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
** No-op.
*/
static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(a);
+ UNUSED_PARAMETER(b);
return 0;
}
@@ -223818,6 +226961,7 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->orderByConsumed = 1;
pIdxInfo->idxNum |= 0x08;
}
+ pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_HEX;
return SQLITE_OK;
}
@@ -224475,7 +227619,13 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; }
**
** The data field of sqlite_dbpage table can be updated. The new
** value must be a BLOB which is the correct page size, otherwise the
-** update fails. Rows may not be deleted or inserted.
+** update fails. INSERT operations also work, and operate as if they
+** where REPLACE. The size of the database can be extended by INSERT-ing
+** new pages on the end.
+**
+** Rows may not be deleted. However, doing an INSERT to page number N
+** with NULL page data causes the N-th page and all subsequent pages to be
+** deleted and the database to be truncated.
*/
/* #include "sqliteInt.h" ** Requires access to internal data structures ** */
@@ -224498,6 +227648,8 @@ struct DbpageCursor {
struct DbpageTable {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* The database */
+ int iDbTrunc; /* Database to truncate */
+ Pgno pgnoTrunc; /* Size to truncate to */
};
/* Columns */
@@ -224506,7 +227658,6 @@ struct DbpageTable {
#define DBPAGE_COLUMN_SCHEMA 2
-
/*
** Connect to or create a dbpagevfs virtual table.
*/
@@ -224757,6 +227908,24 @@ static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
return SQLITE_OK;
}
+/*
+** Open write transactions. Since we do not know in advance which database
+** files will be written by the sqlite_dbpage virtual table, start a write
+** transaction on them all.
+**
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
+*/
+static int dbpageBeginTrans(DbpageTable *pTab){
+ sqlite3 *db = pTab->db;
+ int rc = SQLITE_OK;
+ int i;
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
+ }
+ return rc;
+}
+
static int dbpageUpdate(
sqlite3_vtab *pVtab,
int argc,
@@ -224768,11 +227937,11 @@ static int dbpageUpdate(
DbPage *pDbPage = 0;
int rc = SQLITE_OK;
char *zErr = 0;
- const char *zSchema;
int iDb;
Btree *pBt;
Pager *pPager;
int szPage;
+ int isInsert;
(void)pRowid;
if( pTab->db->flags & SQLITE_Defensive ){
@@ -224783,21 +227952,29 @@ static int dbpageUpdate(
zErr = "cannot delete";
goto update_fail;
}
- pgno = sqlite3_value_int(argv[0]);
- if( sqlite3_value_type(argv[0])==SQLITE_NULL
- || (Pgno)sqlite3_value_int(argv[1])!=pgno
- ){
- zErr = "cannot insert";
- goto update_fail;
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
+ pgno = (Pgno)sqlite3_value_int(argv[2]);
+ isInsert = 1;
+ }else{
+ pgno = sqlite3_value_int(argv[0]);
+ if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
+ zErr = "cannot insert";
+ goto update_fail;
+ }
+ isInsert = 0;
}
- zSchema = (const char*)sqlite3_value_text(argv[4]);
- iDb = ALWAYS(zSchema) ? sqlite3FindDbName(pTab->db, zSchema) : -1;
- if( NEVER(iDb<0) ){
- zErr = "no such schema";
- goto update_fail;
+ if( sqlite3_value_type(argv[4])==SQLITE_NULL ){
+ iDb = 0;
+ }else{
+ const char *zSchema = (const char*)sqlite3_value_text(argv[4]);
+ iDb = sqlite3FindDbName(pTab->db, zSchema);
+ if( iDb<0 ){
+ zErr = "no such schema";
+ goto update_fail;
+ }
}
pBt = pTab->db->aDb[iDb].pBt;
- if( NEVER(pgno<1) || NEVER(pBt==0) || NEVER(pgno>sqlite3BtreeLastPage(pBt)) ){
+ if( pgno<1 || NEVER(pBt==0) ){
zErr = "bad page number";
goto update_fail;
}
@@ -224805,51 +227982,83 @@ static int dbpageUpdate(
if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
|| sqlite3_value_bytes(argv[3])!=szPage
){
- zErr = "bad page value";
+ if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert && pgno>1 ){
+ /* "INSERT INTO dbpage($PGNO,NULL)" causes page number $PGNO and
+ ** all subsequent pages to be deleted. */
+ pTab->iDbTrunc = iDb;
+ pTab->pgnoTrunc = pgno-1;
+ pgno = 1;
+ }else{
+ zErr = "bad page value";
+ goto update_fail;
+ }
+ }
+
+ if( dbpageBeginTrans(pTab)!=SQLITE_OK ){
+ zErr = "failed to open transaction";
goto update_fail;
}
+
pPager = sqlite3BtreePager(pBt);
rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
if( rc==SQLITE_OK ){
const void *pData = sqlite3_value_blob(argv[3]);
- assert( pData!=0 || pTab->db->mallocFailed );
- if( pData
- && (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
- ){
- memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);
+ if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
+ unsigned char *aPage = sqlite3PagerGetData(pDbPage);
+ memcpy(aPage, pData, szPage);
+ pTab->pgnoTrunc = 0;
}
+ }else{
+ pTab->pgnoTrunc = 0;
}
sqlite3PagerUnref(pDbPage);
return rc;
update_fail:
+ pTab->pgnoTrunc = 0;
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
return SQLITE_ERROR;
}
-/* Since we do not know in advance which database files will be
-** written by the sqlite_dbpage virtual table, start a write transaction
-** on them all.
-*/
static int dbpageBegin(sqlite3_vtab *pVtab){
DbpageTable *pTab = (DbpageTable *)pVtab;
- sqlite3 *db = pTab->db;
- int i;
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
+ pTab->pgnoTrunc = 0;
+ return SQLITE_OK;
+}
+
+/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
+*/
+static int dbpageSync(sqlite3_vtab *pVtab){
+ DbpageTable *pTab = (DbpageTable *)pVtab;
+ if( pTab->pgnoTrunc>0 ){
+ Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt;
+ Pager *pPager = sqlite3BtreePager(pBt);
+ sqlite3BtreeEnter(pBt);
+ if( pTab->pgnoTrunc<sqlite3BtreeLastPage(pBt) ){
+ sqlite3PagerTruncateImage(pPager, pTab->pgnoTrunc);
+ }
+ sqlite3BtreeLeave(pBt);
}
+ pTab->pgnoTrunc = 0;
return SQLITE_OK;
}
+/* Cancel any pending truncate.
+*/
+static int dbpageRollbackTo(sqlite3_vtab *pVtab, int notUsed1){
+ DbpageTable *pTab = (DbpageTable *)pVtab;
+ pTab->pgnoTrunc = 0;
+ (void)notUsed1;
+ return SQLITE_OK;
+}
/*
** Invoke this routine to register the "dbpage" virtual table module
*/
SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){
static sqlite3_module dbpage_module = {
- 0, /* iVersion */
+ 2, /* iVersion */
dbpageConnect, /* xCreate */
dbpageConnect, /* xConnect */
dbpageBestIndex, /* xBestIndex */
@@ -224864,14 +228073,14 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){
dbpageRowid, /* xRowid - read data */
dbpageUpdate, /* xUpdate */
dbpageBegin, /* xBegin */
- 0, /* xSync */
+ dbpageSync, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0, /* xRollbackTo */
+ dbpageRollbackTo, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
@@ -224959,6 +228168,10 @@ struct SessionBuffer {
** input data. Input data may be supplied either as a single large buffer
** (e.g. sqlite3changeset_start()) or using a stream function (e.g.
** sqlite3changeset_start_strm()).
+**
+** bNoDiscard:
+** If true, then the only time data is discarded is as a result of explicit
+** sessionDiscardData() calls. Not within every sessionInputBuffer() call.
*/
struct SessionInput {
int bNoDiscard; /* If true, do not discard in InputBuffer() */
@@ -225020,11 +228233,13 @@ struct sqlite3_changeset_iter {
struct SessionTable {
SessionTable *pNext;
char *zName; /* Local name of table */
- int nCol; /* Number of columns in table zName */
+ int nCol; /* Number of non-hidden columns */
+ int nTotalCol; /* Number of columns including hidden */
int bStat1; /* True if this is sqlite_stat1 */
int bRowid; /* True if this table uses rowid for PK */
const char **azCol; /* Column names */
const char **azDflt; /* Default value expressions */
+ int *aiIdx; /* Index to pass to xNew/xOld */
u8 *abPK; /* Array of primary key flags */
int nEntry; /* Total number of entries in hash table */
int nChange; /* Size of apChange[] array */
@@ -225427,22 +228642,22 @@ static int sessionPreupdateHash(
unsigned int h = 0; /* Hash value to return */
int i; /* Used to iterate through columns */
+ assert( pTab->nTotalCol==pSession->hook.xCount(pSession->hook.pCtx) );
if( pTab->bRowid ){
- assert( pTab->nCol-1==pSession->hook.xCount(pSession->hook.pCtx) );
h = sessionHashAppendI64(h, iRowid);
}else{
assert( *pbNullPK==0 );
- assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) );
for(i=0; i<pTab->nCol; i++){
if( pTab->abPK[i] ){
int rc;
int eType;
sqlite3_value *pVal;
+ int iIdx = pTab->aiIdx[i];
if( bNew ){
- rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal);
+ rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal);
}else{
- rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal);
+ rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal);
}
if( rc!=SQLITE_OK ) return rc;
@@ -225779,6 +228994,7 @@ static int sessionPreupdateEqual(
sqlite3_value *pVal; /* Value returned by preupdate_new/old */
int rc; /* Error code from preupdate_new/old */
int eType = *a++; /* Type of value from change record */
+ int iIdx = pTab->aiIdx[iCol];
/* The following calls to preupdate_new() and preupdate_old() can not
** fail. This is because they cache their return values, and by the
@@ -225787,10 +229003,10 @@ static int sessionPreupdateEqual(
** this (that the method has already been called). */
if( op==SQLITE_INSERT ){
/* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */
- rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal);
+ rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal);
}else{
/* assert( db->pPreUpdate->pUnpacked ); */
- rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal);
+ rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal);
}
assert( rc==SQLITE_OK );
(void)rc; /* Suppress warning about unused variable */
@@ -225915,9 +229131,11 @@ static int sessionTableInfo(
const char *zDb, /* Name of attached database (e.g. "main") */
const char *zThis, /* Table name */
int *pnCol, /* OUT: number of columns */
+ int *pnTotalCol, /* OUT: number of hidden columns */
const char **pzTab, /* OUT: Copy of zThis */
const char ***pazCol, /* OUT: Array of column names for table */
const char ***pazDflt, /* OUT: Array of default value expressions */
+ int **paiIdx, /* OUT: Array of xNew/xOld indexes */
u8 **pabPK, /* OUT: Array of booleans - true for PK col */
int *pbRowid /* OUT: True if only PK is a rowid */
){
@@ -225932,6 +229150,7 @@ static int sessionTableInfo(
char **azCol = 0;
char **azDflt = 0;
u8 *abPK = 0;
+ int *aiIdx = 0;
int bRowid = 0; /* Set to true to use rowid as PK */
assert( pazCol && pabPK );
@@ -225939,6 +229158,8 @@ static int sessionTableInfo(
*pazCol = 0;
*pabPK = 0;
*pnCol = 0;
+ if( pnTotalCol ) *pnTotalCol = 0;
+ if( paiIdx ) *paiIdx = 0;
if( pzTab ) *pzTab = 0;
if( pazDflt ) *pazDflt = 0;
@@ -225948,9 +229169,9 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
/* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */
zPragma = sqlite3_mprintf(
- "SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
- "SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
- "SELECT 2, 'stat', '', 0, '', 0"
+ "SELECT 0, 'tbl', '', 0, '', 1, 0 UNION ALL "
+ "SELECT 1, 'idx', '', 0, '', 2, 0 UNION ALL "
+ "SELECT 2, 'stat', '', 0, '', 0, 0"
);
}else if( rc==SQLITE_ERROR ){
zPragma = sqlite3_mprintf("");
@@ -225958,7 +229179,7 @@ static int sessionTableInfo(
return rc;
}
}else{
- zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
+ zPragma = sqlite3_mprintf("PRAGMA '%q'.table_xinfo('%q')", zDb, zThis);
}
if( !zPragma ){
return SQLITE_NOMEM;
@@ -225975,7 +229196,9 @@ static int sessionTableInfo(
while( SQLITE_ROW==sqlite3_step(pStmt) ){
nByte += sqlite3_column_bytes(pStmt, 1); /* name */
nByte += sqlite3_column_bytes(pStmt, 4); /* dflt_value */
- nDbCol++;
+ if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */
+ nDbCol++;
+ }
if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; /* pk */
}
if( nDbCol==0 ) bRowid = 0;
@@ -225984,7 +229207,7 @@ static int sessionTableInfo(
rc = sqlite3_reset(pStmt);
if( rc==SQLITE_OK ){
- nByte += nDbCol * (sizeof(const char *)*2 + sizeof(u8) + 1 + 1);
+ nByte += nDbCol * (sizeof(const char *)*2 +sizeof(int)+sizeof(u8) + 1 + 1);
pAlloc = sessionMalloc64(pSession, nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
@@ -225995,8 +229218,8 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
azCol = (char **)pAlloc;
azDflt = (char**)&azCol[nDbCol];
- pAlloc = (u8 *)&azDflt[nDbCol];
- abPK = (u8 *)pAlloc;
+ aiIdx = (int*)&azDflt[nDbCol];
+ abPK = (u8 *)&aiIdx[nDbCol];
pAlloc = &abPK[nDbCol];
if( pzTab ){
memcpy(pAlloc, zThis, nThis+1);
@@ -226011,27 +229234,32 @@ static int sessionTableInfo(
azCol[i] = (char*)pAlloc;
pAlloc += nName+1;
abPK[i] = 1;
+ aiIdx[i] = -1;
i++;
}
while( SQLITE_ROW==sqlite3_step(pStmt) ){
- int nName = sqlite3_column_bytes(pStmt, 1);
- int nDflt = sqlite3_column_bytes(pStmt, 4);
- const unsigned char *zName = sqlite3_column_text(pStmt, 1);
- const unsigned char *zDflt = sqlite3_column_text(pStmt, 4);
-
- if( zName==0 ) break;
- memcpy(pAlloc, zName, nName+1);
- azCol[i] = (char *)pAlloc;
- pAlloc += nName+1;
- if( zDflt ){
- memcpy(pAlloc, zDflt, nDflt+1);
- azDflt[i] = (char *)pAlloc;
- pAlloc += nDflt+1;
- }else{
- azDflt[i] = 0;
+ if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */
+ int nName = sqlite3_column_bytes(pStmt, 1);
+ int nDflt = sqlite3_column_bytes(pStmt, 4);
+ const unsigned char *zName = sqlite3_column_text(pStmt, 1);
+ const unsigned char *zDflt = sqlite3_column_text(pStmt, 4);
+
+ if( zName==0 ) break;
+ memcpy(pAlloc, zName, nName+1);
+ azCol[i] = (char *)pAlloc;
+ pAlloc += nName+1;
+ if( zDflt ){
+ memcpy(pAlloc, zDflt, nDflt+1);
+ azDflt[i] = (char *)pAlloc;
+ pAlloc += nDflt+1;
+ }else{
+ azDflt[i] = 0;
+ }
+ abPK[i] = sqlite3_column_int(pStmt, 5);
+ aiIdx[i] = sqlite3_column_int(pStmt, 0);
+ i++;
}
- abPK[i] = sqlite3_column_int(pStmt, 5);
- i++;
+ if( pnTotalCol ) (*pnTotalCol)++;
}
rc = sqlite3_reset(pStmt);
}
@@ -226044,6 +229272,7 @@ static int sessionTableInfo(
if( pazDflt ) *pazDflt = (const char**)azDflt;
*pabPK = abPK;
*pnCol = nDbCol;
+ if( paiIdx ) *paiIdx = aiIdx;
}else{
sessionFree(pSession, azCol);
}
@@ -226055,7 +229284,7 @@ static int sessionTableInfo(
/*
** This function is called to initialize the SessionTable.nCol, azCol[]
** abPK[] and azDflt[] members of SessionTable object pTab. If these
-** fields are already initilialized, this function is a no-op.
+** fields are already initialized, this function is a no-op.
**
** If an error occurs, an error code is stored in sqlite3_session.rc and
** non-zero returned. Or, if no error occurs but the table has no primary
@@ -226074,8 +229303,11 @@ static int sessionInitTable(
if( pTab->nCol==0 ){
u8 *abPK;
assert( pTab->azCol==0 || pTab->abPK==0 );
+ sqlite3_free(pTab->azCol);
+ pTab->abPK = 0;
rc = sessionTableInfo(pSession, db, zDb,
- pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->azDflt, &abPK,
+ pTab->zName, &pTab->nCol, &pTab->nTotalCol, 0, &pTab->azCol,
+ &pTab->azDflt, &pTab->aiIdx, &abPK,
((pSession==0 || pSession->bImplicitPK) ? &pTab->bRowid : 0)
);
if( rc==SQLITE_OK ){
@@ -226110,15 +229342,17 @@ static int sessionInitTable(
*/
static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){
int nCol = 0;
+ int nTotalCol = 0;
const char **azCol = 0;
const char **azDflt = 0;
+ int *aiIdx = 0;
u8 *abPK = 0;
int bRowid = 0;
assert( pSession->rc==SQLITE_OK );
pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
- pTab->zName, &nCol, 0, &azCol, &azDflt, &abPK,
+ pTab->zName, &nCol, &nTotalCol, 0, &azCol, &azDflt, &aiIdx, &abPK,
(pSession->bImplicitPK ? &bRowid : 0)
);
if( pSession->rc==SQLITE_OK ){
@@ -226141,8 +229375,10 @@ static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){
const char **a = pTab->azCol;
pTab->azCol = azCol;
pTab->nCol = nCol;
+ pTab->nTotalCol = nTotalCol;
pTab->azDflt = azDflt;
pTab->abPK = abPK;
+ pTab->aiIdx = aiIdx;
azCol = a;
}
if( pSession->bEnableSize ){
@@ -226460,7 +229696,7 @@ static int sessionUpdateMaxSize(
int ii;
for(ii=0; ii<pTab->nCol; ii++){
sqlite3_value *p = 0;
- pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
+ pSession->hook.xNew(pSession->hook.pCtx, pTab->aiIdx[ii], &p);
sessionSerializeValue(0, p, &nNew);
}
}
@@ -226480,8 +229716,9 @@ static int sessionUpdateMaxSize(
int bChanged = 1;
int nOld = 0;
int eType;
+ int iIdx = pTab->aiIdx[ii];
sqlite3_value *p = 0;
- pSession->hook.xNew(pSession->hook.pCtx, ii-pTab->bRowid, &p);
+ pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p);
if( p==0 ){
return SQLITE_NOMEM;
}
@@ -226578,11 +229815,11 @@ static void sessionPreupdateOneChange(
/* Check the number of columns in this xPreUpdate call matches the
** number of columns in the table. */
nExpect = pSession->hook.xCount(pSession->hook.pCtx);
- if( (pTab->nCol-pTab->bRowid)<nExpect ){
+ if( pTab->nTotalCol<nExpect ){
if( sessionReinitTable(pSession, pTab) ) return;
if( sessionUpdateChanges(pSession, pTab) ) return;
}
- if( (pTab->nCol-pTab->bRowid)!=nExpect ){
+ if( pTab->nTotalCol!=nExpect ){
pSession->rc = SQLITE_SCHEMA;
return;
}
@@ -226639,19 +229876,23 @@ static void sessionPreupdateOneChange(
/* Figure out how large an allocation is required */
nByte = sizeof(SessionChange);
- for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
+ for(i=pTab->bRowid; i<pTab->nCol; i++){
+ int iIdx = pTab->aiIdx[i];
sqlite3_value *p = 0;
if( op!=SQLITE_INSERT ){
- TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p);
- assert( trc==SQLITE_OK );
+ /* This may fail if the column has a non-NULL default and was added
+ ** using ALTER TABLE ADD COLUMN after this record was created. */
+ rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p);
}else if( pTab->abPK[i] ){
- TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p);
+ TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx,iIdx,&p);
assert( trc==SQLITE_OK );
}
- /* This may fail if SQLite value p contains a utf-16 string that must
- ** be converted to utf-8 and an OOM error occurs while doing so. */
- rc = sessionSerializeValue(0, p, &nByte);
+ if( rc==SQLITE_OK ){
+ /* This may fail if SQLite value p contains a utf-16 string that must
+ ** be converted to utf-8 and an OOM error occurs while doing so. */
+ rc = sessionSerializeValue(0, p, &nByte);
+ }
if( rc!=SQLITE_OK ) goto error_out;
}
if( pTab->bRowid ){
@@ -226678,12 +229919,13 @@ static void sessionPreupdateOneChange(
sessionPutI64(&pC->aRecord[1], iRowid);
nByte = 9;
}
- for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
+ for(i=pTab->bRowid; i<pTab->nCol; i++){
sqlite3_value *p = 0;
+ int iIdx = pTab->aiIdx[i];
if( op!=SQLITE_INSERT ){
- pSession->hook.xOld(pSession->hook.pCtx, i, &p);
+ pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p);
}else if( pTab->abPK[i] ){
- pSession->hook.xNew(pSession->hook.pCtx, i, &p);
+ pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p);
}
sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
}
@@ -227070,7 +230312,9 @@ SQLITE_API int sqlite3session_diff(
SessionTable *pTo; /* Table zTbl */
/* Locate and if necessary initialize the target table object */
+ pSession->bAutoAttach++;
rc = sessionFindTable(pSession, zTbl, &pTo);
+ pSession->bAutoAttach--;
if( pTo==0 ) goto diff_out;
if( sessionInitTable(pSession, pTo, pSession->db, pSession->zDb) ){
rc = pSession->rc;
@@ -227081,16 +230325,43 @@ SQLITE_API int sqlite3session_diff(
if( rc==SQLITE_OK ){
int bHasPk = 0;
int bMismatch = 0;
- int nCol; /* Columns in zFrom.zTbl */
+ int nCol = 0; /* Columns in zFrom.zTbl */
int bRowid = 0;
- u8 *abPK;
+ u8 *abPK = 0;
const char **azCol = 0;
- rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, 0, &abPK,
- pSession->bImplicitPK ? &bRowid : 0
- );
+ char *zDbExists = 0;
+
+ /* Check that database zFrom is attached. */
+ zDbExists = sqlite3_mprintf("SELECT * FROM %Q.sqlite_schema", zFrom);
+ if( zDbExists==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_stmt *pDbExists = 0;
+ rc = sqlite3_prepare_v2(db, zDbExists, -1, &pDbExists, 0);
+ if( rc==SQLITE_ERROR ){
+ rc = SQLITE_OK;
+ nCol = -1;
+ }
+ sqlite3_finalize(pDbExists);
+ sqlite3_free(zDbExists);
+ }
+
+ if( rc==SQLITE_OK && nCol==0 ){
+ rc = sessionTableInfo(0, db, zFrom, zTbl,
+ &nCol, 0, 0, &azCol, 0, 0, &abPK,
+ pSession->bImplicitPK ? &bRowid : 0
+ );
+ }
if( rc==SQLITE_OK ){
if( pTo->nCol!=nCol ){
- bMismatch = 1;
+ if( nCol<=0 ){
+ rc = SQLITE_SCHEMA;
+ if( pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("no such table: %s.%s", zFrom, zTbl);
+ }
+ }else{
+ bMismatch = 1;
+ }
}else{
int i;
for(i=0; i<nCol; i++){
@@ -227409,9 +230680,11 @@ static void sessionAppendIdent(
char *zOut = (char *)&p->aBuf[p->nBuf];
const char *zIn = zStr;
*zOut++ = '"';
- while( *zIn ){
- if( *zIn=='"' ) *zOut++ = '"';
- *zOut++ = *(zIn++);
+ if( zIn!=0 ){
+ while( *zIn ){
+ if( *zIn=='"' ) *zOut++ = '"';
+ *zOut++ = *(zIn++);
+ }
}
*zOut++ = '"';
p->nBuf = (int)((u8 *)zOut - p->aBuf);
@@ -227662,10 +230935,10 @@ static int sessionSelectStmt(
int rc = SQLITE_OK;
char *zSql = 0;
const char *zSep = "";
- const char *zCols = bRowid ? SESSIONS_ROWID ", *" : "*";
int nSql = -1;
int i;
+ SessionBuffer cols = {0, 0, 0};
SessionBuffer nooptest = {0, 0, 0};
SessionBuffer pkfield = {0, 0, 0};
SessionBuffer pkvar = {0, 0, 0};
@@ -227678,9 +230951,16 @@ static int sessionSelectStmt(
sessionAppendStr(&pkvar,
"?1, (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", &rc
);
- zCols = "tbl, ?2, stat";
+ sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
}else{
+ #if 0
+ if( bRowid ){
+ sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
+ }
+ #endif
for(i=0; i<nCol; i++){
+ if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
+ sessionAppendIdent(&cols, azCol[i], &rc);
if( abPK[i] ){
sessionAppendStr(&pkfield, zSep, &rc);
sessionAppendStr(&pkvar, zSep, &rc);
@@ -227698,7 +230978,7 @@ static int sessionSelectStmt(
if( rc==SQLITE_OK ){
zSql = sqlite3_mprintf(
"SELECT %s%s FROM %Q.%Q WHERE (%s) IS (%s)",
- zCols, (bIgnoreNoop ? (char*)nooptest.aBuf : ""),
+ (char*)cols.aBuf, (bIgnoreNoop ? (char*)nooptest.aBuf : ""),
zDb, zTab, (char*)pkfield.aBuf, (char*)pkvar.aBuf
);
if( zSql==0 ) rc = SQLITE_NOMEM;
@@ -227741,6 +231021,7 @@ static int sessionSelectStmt(
sqlite3_free(nooptest.aBuf);
sqlite3_free(pkfield.aBuf);
sqlite3_free(pkvar.aBuf);
+ sqlite3_free(cols.aBuf);
return rc;
}
@@ -227856,7 +231137,7 @@ static int sessionGenerateChangeset(
){
sqlite3 *db = pSession->db; /* Source database handle */
SessionTable *pTab; /* Used to iterate through attached tables */
- SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
+ SessionBuffer buf = {0,0,0}; /* Buffer in which to accumulate changeset */
int rc; /* Return code */
assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
@@ -228209,14 +231490,15 @@ SQLITE_API int sqlite3changeset_start_v2_strm(
** object and the buffer is full, discard some data to free up space.
*/
static void sessionDiscardData(SessionInput *pIn){
- if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){
- int nMove = pIn->buf.nBuf - pIn->iNext;
+ if( pIn->xInput && pIn->iCurrent>=sessions_strm_chunk_size ){
+ int nMove = pIn->buf.nBuf - pIn->iCurrent;
assert( nMove>=0 );
if( nMove>0 ){
- memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove);
+ memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iCurrent], nMove);
}
- pIn->buf.nBuf -= pIn->iNext;
- pIn->iNext = 0;
+ pIn->buf.nBuf -= pIn->iCurrent;
+ pIn->iNext -= pIn->iCurrent;
+ pIn->iCurrent = 0;
pIn->nData = pIn->buf.nBuf;
}
}
@@ -228570,8 +231852,8 @@ static int sessionChangesetNextOne(
p->rc = sessionInputBuffer(&p->in, 2);
if( p->rc!=SQLITE_OK ) return p->rc;
- sessionDiscardData(&p->in);
p->in.iCurrent = p->in.iNext;
+ sessionDiscardData(&p->in);
/* If the iterator is already at the end of the changeset, return DONE. */
if( p->in.iNext>=p->in.nData ){
@@ -230009,15 +233291,21 @@ static int sessionChangesetApply(
int nTab = 0; /* Result of sqlite3Strlen30(zTab) */
SessionApplyCtx sApply; /* changeset_apply() context object */
int bPatchset;
+ u64 savedFlag = db->flags & SQLITE_FkNoAction;
assert( xConflict!=0 );
+ sqlite3_mutex_enter(sqlite3_db_mutex(db));
+ if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){
+ db->flags |= ((u64)SQLITE_FkNoAction);
+ db->aDb[0].pSchema->schema_cookie -= 32;
+ }
+
pIter->in.bNoDiscard = 1;
memset(&sApply, 0, sizeof(sApply));
sApply.bRebase = (ppRebase && pnRebase);
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
- sqlite3_mutex_enter(sqlite3_db_mutex(db));
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
}
@@ -230075,7 +233363,8 @@ static int sessionChangesetApply(
sqlite3changeset_pk(pIter, &abPK, 0);
rc = sessionTableInfo(0, db, "main", zNew,
- &sApply.nCol, &zTab, &sApply.azCol, 0, &sApply.abPK, &sApply.bRowid
+ &sApply.nCol, 0, &zTab, &sApply.azCol, 0, 0,
+ &sApply.abPK, &sApply.bRowid
);
if( rc!=SQLITE_OK ) break;
for(i=0; i<sApply.nCol; i++){
@@ -230155,12 +233444,17 @@ static int sessionChangesetApply(
}
}
}
- sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
+
+ {
+ int rc2 = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
if( rc==SQLITE_OK ){
rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
- }else{
+ }
+ if( rc!=SQLITE_OK ){
sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
}
@@ -230179,6 +233473,12 @@ static int sessionChangesetApply(
sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlite3_free((char*)sApply.constraints.aBuf);
sqlite3_free((char*)sApply.rebase.aBuf);
+
+ if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
+ assert( db->flags & SQLITE_FkNoAction );
+ db->flags &= ~((u64)SQLITE_FkNoAction);
+ db->aDb[0].pSchema->schema_cookie -= 32;
+ }
sqlite3_mutex_leave(sqlite3_db_mutex(db));
return rc;
}
@@ -230207,12 +233507,6 @@ SQLITE_API int sqlite3changeset_apply_v2(
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
- u64 savedFlag = db->flags & SQLITE_FkNoAction;
-
- if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){
- db->flags |= ((u64)SQLITE_FkNoAction);
- db->aDb[0].pSchema->schema_cookie -= 32;
- }
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
@@ -230220,11 +233514,6 @@ SQLITE_API int sqlite3changeset_apply_v2(
);
}
- if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
- assert( db->flags & SQLITE_FkNoAction );
- db->flags &= ~((u64)SQLITE_FkNoAction);
- db->aDb[0].pSchema->schema_cookie -= 32;
- }
return rc;
}
@@ -230545,6 +233834,9 @@ static int sessionChangesetExtendRecord(
sessionAppendBlob(pOut, aRec, nRec, &rc);
if( rc==SQLITE_OK && pTab->pDfltStmt==0 ){
rc = sessionPrepareDfltStmt(pGrp->db, pTab, &pTab->pDfltStmt);
+ if( rc==SQLITE_OK && SQLITE_ROW!=sqlite3_step(pTab->pDfltStmt) ){
+ rc = sqlite3_errcode(pGrp->db);
+ }
}
for(ii=nCol; rc==SQLITE_OK && ii<pTab->nCol; ii++){
int eType = sqlite3_column_type(pTab->pDfltStmt, ii);
@@ -230561,6 +233853,7 @@ static int sessionChangesetExtendRecord(
}
if( SQLITE_OK==sessionBufferGrow(pOut, 8, &rc) ){
sessionPutI64(&pOut->aBuf[pOut->nBuf], iVal);
+ pOut->nBuf += 8;
}
break;
}
@@ -230700,6 +233993,8 @@ static int sessionOneChangeToHash(
u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;
+ assert( nRec>0 );
+
/* Ensure that only changesets, or only patchsets, but not a mixture
** of both, are being combined. It is an error to try to combine a
** changeset and a patchset. */
@@ -230777,6 +234072,7 @@ static int sessionChangesetToHash(
int nRec;
int rc = SQLITE_OK;
+ pIter->in.bNoDiscard = 1;
while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
rc = sessionOneChangeToHash(pGrp, pIter, bRebase);
if( rc!=SQLITE_OK ) break;
@@ -230916,14 +234212,19 @@ SQLITE_API int sqlite3changegroup_add_change(
sqlite3_changegroup *pGrp,
sqlite3_changeset_iter *pIter
){
+ int rc = SQLITE_OK;
+
if( pIter->in.iCurrent==pIter->in.iNext
|| pIter->rc!=SQLITE_OK
|| pIter->bInvert
){
/* Iterator does not point to any valid entry or is an INVERT iterator. */
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ }else{
+ pIter->in.bNoDiscard = 1;
+ rc = sessionOneChangeToHash(pGrp, pIter, 0);
}
- return sessionOneChangeToHash(pGrp, pIter, 0);
+ return rc;
}
/*
@@ -231408,7 +234709,27 @@ SQLITE_API int sqlite3session_config(int op, void *pArg){
/************** End of sqlite3session.c **************************************/
/************** Begin file fts5.c ********************************************/
-
+/*
+** This, the "fts5.c" source file, is a composite file that is itself
+** assembled from the following files:
+**
+** fts5.h
+** fts5Int.h
+** fts5parse.h <--- Generated from fts5parse.y by Lemon
+** fts5parse.c <--- Generated from fts5parse.y by Lemon
+** fts5_aux.c
+** fts5_buffer.c
+** fts5_config.c
+** fts5_expr.c
+** fts5_hash.c
+** fts5_index.c
+** fts5_main.c
+** fts5_storage.c
+** fts5_tokenize.c
+** fts5_unicode2.c
+** fts5_varint.c
+** fts5_vocab.c
+*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5)
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
@@ -231418,6 +234739,12 @@ SQLITE_API int sqlite3session_config(int op, void *pArg){
# undef NDEBUG
#endif
+#ifdef HAVE_STDINT_H
+/* #include <stdint.h> */
+#endif
+#ifdef HAVE_INTTYPES_H
+/* #include <inttypes.h> */
+#endif
/*
** 2014 May 31
**
@@ -231658,6 +234985,10 @@ struct Fts5PhraseIter {
** (i.e. if it is a contentless table), then this API always iterates
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
+** In all cases, matches are visited in (column ASC, offset ASC) order.
+** i.e. all those in column 0, sorted by offset, followed by those in
+** column 1, etc.
+**
** xPhraseNext()
** See xPhraseFirst above.
**
@@ -231714,19 +235045,57 @@ struct Fts5PhraseIter {
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
** output variable (*ppToken) is set to point to a buffer containing the
** matching document token, and (*pnToken) to the size of that buffer in
-** bytes. This API is not available if the specified token matches a
-** prefix query term. In that case both output variables are always set
-** to 0.
+** bytes.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
+** This API may be slow in some cases if the token identified by parameters
+** iIdx and iToken matched a prefix token in the query. In most cases, the
+** first call to this API for each prefix token in the query is forced
+** to scan the portion of the full-text index that matches the prefix
+** token to collect the extra data required by this API. If the prefix
+** token matches a large number of token instances in the document set,
+** this may be a performance problem.
+**
+** If the user knows in advance that a query may use this API for a
+** prefix token, FTS5 may be configured to collect all required data as part
+** of the initial querying of the full-text index, avoiding the second scan
+** entirely. This also causes prefix queries that do not use this API to
+** run more slowly and use more memory. FTS5 may be configured in this way
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
+** option, or on a per-query basis using the
+** [fts5_insttoken | fts5_insttoken()] user function.
+**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
+**
+** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of columns in the table, SQLITE_RANGE is returned.
+**
+** Otherwise, this function attempts to retrieve the locale associated
+** with column iCol of the current row. Usually, there is no associated
+** locale, and output parameters (*pzLocale) and (*pnLocale) are set
+** to NULL and 0, respectively. However, if the fts5_locale() function
+** was used to associate a locale with the value when it was inserted
+** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+** buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+** is set to the size in bytes of the buffer, not including the
+** nul-terminator.
+**
+** If successful, SQLITE_OK is returned. Or, if an error occurs, an
+** SQLite error code is returned. The final value of the output parameters
+** is undefined in this case.
+**
+** xTokenize_v2:
+** Tokenize text using the tokenizer belonging to the FTS5 table. This
+** API is the same as the xTokenize() API, except that it allows a tokenizer
+** locale to be specified.
*/
struct Fts5ExtensionApi {
- int iVersion; /* Currently always set to 3 */
+ int iVersion; /* Currently always set to 4 */
void *(*xUserData)(Fts5Context*);
@@ -231768,6 +235137,15 @@ struct Fts5ExtensionApi {
const char **ppToken, int *pnToken
);
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+
+ /* Below this point are iVersion>=4 only */
+ int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+ int (*xTokenize_v2)(Fts5Context*,
+ const char *pText, int nText, /* Text to tokenize */
+ const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
+ void *pCtx, /* Context passed to xToken() */
+ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
+ );
};
/*
@@ -231788,7 +235166,7 @@ struct Fts5ExtensionApi {
** A tokenizer instance is required to actually tokenize text.
**
** The first argument passed to this function is a copy of the (void*)
-** pointer provided by the application when the fts5_tokenizer object
+** pointer provided by the application when the fts5_tokenizer_v2 object
** was registered with FTS5 (the third argument to xCreateTokenizer()).
** The second and third arguments are an array of nul-terminated strings
** containing the tokenizer arguments, if any, specified following the
@@ -231812,7 +235190,7 @@ struct Fts5ExtensionApi {
** argument passed to this function is a pointer to an Fts5Tokenizer object
** returned by an earlier call to xCreate().
**
-** The second argument indicates the reason that FTS5 is requesting
+** The third argument indicates the reason that FTS5 is requesting
** tokenization of the supplied text. This is always one of the following
** four values:
**
@@ -231836,6 +235214,13 @@ struct Fts5ExtensionApi {
** on a columnsize=0 database.
** </ul>
**
+** The sixth and seventh arguments passed to xTokenize() - pLocale and
+** nLocale - are a pointer to a buffer containing the locale to use for
+** tokenization (e.g. "en_US") and its size in bytes, respectively. The
+** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+** which case nLocale is always 0) to indicate that the tokenizer should
+** use its default locale.
+**
** For each token in the input string, the supplied callback xToken() must
** be invoked. The first argument to it should be a copy of the pointer
** passed as the second argument to xTokenize(). The third and fourth
@@ -231859,6 +235244,30 @@ struct Fts5ExtensionApi {
** may abandon the tokenization and return any error code other than
** SQLITE_OK or SQLITE_DONE.
**
+** If the tokenizer is registered using an fts5_tokenizer_v2 object,
+** then the xTokenize() method has two additional arguments - pLocale
+** and nLocale. These specify the locale that the tokenizer should use
+** for the current request. If pLocale and nLocale are both 0, then the
+** tokenizer should use its default locale. Otherwise, pLocale points to
+** an nLocale byte buffer containing the name of the locale to use as utf-8
+** text. pLocale is not nul-terminated.
+**
+** FTS5_TOKENIZER
+**
+** There is also an fts5_tokenizer object. This is an older, deprecated,
+** version of fts5_tokenizer_v2. It is similar except that:
+**
+** <ul>
+** <li> There is no "iVersion" field, and
+** <li> The xTokenize() method does not take a locale argument.
+** </ul>
+**
+** Legacy fts5_tokenizer tokenizers must be registered using the
+** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+**
+** Tokenizer implementations registered using either API may be retrieved
+** using both xFindTokenizer() and xFindTokenizer_v2().
+**
** SYNONYM SUPPORT
**
** Custom tokenizers may also support synonyms. Consider a case in which a
@@ -231967,6 +235376,33 @@ struct Fts5ExtensionApi {
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
+typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+struct fts5_tokenizer_v2 {
+ int iVersion; /* Currently always 2 */
+
+ int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+ void (*xDelete)(Fts5Tokenizer*);
+ int (*xTokenize)(Fts5Tokenizer*,
+ void *pCtx,
+ int flags, /* Mask of FTS5_TOKENIZE_* flags */
+ const char *pText, int nText,
+ const char *pLocale, int nLocale,
+ int (*xToken)(
+ void *pCtx, /* Copy of 2nd argument to xTokenize() */
+ int tflags, /* Mask of FTS5_TOKEN_* flags */
+ const char *pToken, /* Pointer to buffer containing token */
+ int nToken, /* Size of token in bytes */
+ int iStart, /* Byte offset of token within input text */
+ int iEnd /* Byte offset of end of token within input text */
+ )
+ );
+};
+
+/*
+** New code should use the fts5_tokenizer_v2 type to define tokenizer
+** implementations. The following type is included for legacy applications
+** that still use it.
+*/
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
@@ -231986,6 +235422,7 @@ struct fts5_tokenizer {
);
};
+
/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY 0x0001
#define FTS5_TOKENIZE_PREFIX 0x0002
@@ -232005,7 +235442,7 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
- int iVersion; /* Currently always set to 2 */
+ int iVersion; /* Currently always set to 3 */
/* Create a new tokenizer */
int (*xCreateTokenizer)(
@@ -232032,6 +235469,25 @@ struct fts5_api {
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
+
+ /* APIs below this point are only available if iVersion>=3 */
+
+ /* Create a new tokenizer */
+ int (*xCreateTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void *pUserData,
+ fts5_tokenizer_v2 *pTokenizer,
+ void (*xDestroy)(void*)
+ );
+
+ /* Find an existing tokenizer */
+ int (*xFindTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void **ppUserData,
+ fts5_tokenizer_v2 **ppTokenizer
+ );
};
/*
@@ -232066,6 +235522,7 @@ SQLITE_EXTENSION_INIT1
/* #include <string.h> */
/* #include <assert.h> */
+/* #include <stddef.h> */
#ifndef SQLITE_AMALGAMATION
@@ -232105,6 +235562,34 @@ typedef sqlite3_uint64 u64;
# define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
+/* The uptr type is an unsigned integer large enough to hold a pointer
+*/
+#if defined(HAVE_STDINT_H)
+ typedef uintptr_t uptr;
+#elif SQLITE_PTRSIZE==4
+ typedef u32 uptr;
+#else
+ typedef u64 uptr;
+#endif
+
+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
+#else
+# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
+#endif
+
+/*
+** Macros needed to provide flexible arrays in a portable way
+*/
+#ifndef offsetof
+# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
+
#endif
/* Truncate very long tokens to this many bytes. Hard limit is
@@ -232177,10 +235662,11 @@ typedef struct Fts5Colset Fts5Colset;
*/
struct Fts5Colset {
int nCol;
- int aiCol[1];
+ int aiCol[FLEXARRAY];
};
-
+/* Size (int bytes) of a complete Fts5Colset object with N columns. */
+#define SZ_FTS5COLSET(N) (sizeof(i64)*((N+2)/2))
/**************************************************************************
** Interface to code in fts5_config.c. fts5_config.c contains contains code
@@ -232188,6 +235674,18 @@ struct Fts5Colset {
*/
typedef struct Fts5Config Fts5Config;
+typedef struct Fts5TokenizerConfig Fts5TokenizerConfig;
+
+struct Fts5TokenizerConfig {
+ Fts5Tokenizer *pTok;
+ fts5_tokenizer_v2 *pApi2;
+ fts5_tokenizer *pApi1;
+ const char **azArg;
+ int nArg;
+ int ePattern; /* FTS_PATTERN_XXX constant */
+ const char *pLocale; /* Current locale to use */
+ int nLocale; /* Size of pLocale in bytes */
+};
/*
** An instance of the following structure encodes all information that can
@@ -232227,9 +235725,12 @@ typedef struct Fts5Config Fts5Config;
**
** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
**
+** bLocale:
+** Set to true if locale=1 was specified when the table was created.
*/
struct Fts5Config {
sqlite3 *db; /* Database handle */
+ Fts5Global *pGlobal; /* Global fts5 object for handle db */
char *zDb; /* Database holding FTS index (e.g. "main") */
char *zName; /* Name of FTS index */
int nCol; /* Number of columns */
@@ -232239,16 +235740,17 @@ struct Fts5Config {
int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */
int eContent; /* An FTS5_CONTENT value */
int bContentlessDelete; /* "contentless_delete=" option (dflt==0) */
+ int bContentlessUnindexed; /* "contentless_unindexed=" option (dflt=0) */
char *zContent; /* content table */
char *zContentRowid; /* "content_rowid=" option value */
int bColumnsize; /* "columnsize=" option value (dflt==1) */
int bTokendata; /* "tokendata=" option value (dflt==0) */
+ int bLocale; /* "locale=" option value (dflt==0) */
int eDetail; /* FTS5_DETAIL_XXX value */
char *zContentExprlist;
- Fts5Tokenizer *pTok;
- fts5_tokenizer *pTokApi;
+ Fts5TokenizerConfig t;
int bLock; /* True when table is preparing statement */
- int ePattern; /* FTS_PATTERN_XXX constant */
+
/* Values loaded from the %_config table */
int iVersion; /* fts5 file format 'version' */
@@ -232261,7 +235763,8 @@ struct Fts5Config {
char *zRank; /* Name of rank function */
char *zRankArgs; /* Arguments to rank function */
int bSecureDelete; /* 'secure-delete' */
- int nDeleteMerge; /* 'deletemerge' */
+ int nDeleteMerge; /* 'deletemerge' */
+ int bPrefixInsttoken; /* 'prefix-insttoken' */
/* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
char **pzErrmsg;
@@ -232277,9 +235780,10 @@ struct Fts5Config {
#define FTS5_CURRENT_VERSION 4
#define FTS5_CURRENT_VERSION_SECUREDELETE 5
-#define FTS5_CONTENT_NORMAL 0
-#define FTS5_CONTENT_NONE 1
-#define FTS5_CONTENT_EXTERNAL 2
+#define FTS5_CONTENT_NORMAL 0
+#define FTS5_CONTENT_NONE 1
+#define FTS5_CONTENT_EXTERNAL 2
+#define FTS5_CONTENT_UNINDEXED 3
#define FTS5_DETAIL_FULL 0
#define FTS5_DETAIL_NONE 1
@@ -232314,6 +235818,8 @@ static int sqlite3Fts5ConfigSetValue(Fts5Config*, const char*, sqlite3_value*, i
static int sqlite3Fts5ConfigParseRank(const char*, char**, char**);
+static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...);
+
/*
** End of interface to code in fts5_config.c.
**************************************************************************/
@@ -232358,7 +235864,7 @@ static char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
static void sqlite3Fts5Put32(u8*, int);
static int sqlite3Fts5Get32(const u8*);
-#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
+#define FTS5_POS2COLUMN(iPos) (int)((iPos >> 32) & 0x7FFFFFFF)
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)
typedef struct Fts5PoslistReader Fts5PoslistReader;
@@ -232515,7 +236021,14 @@ static int sqlite3Fts5StructureTest(Fts5Index*, void*);
/*
** Used by xInstToken():
*/
-static int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*);
+static int sqlite3Fts5IterToken(
+ Fts5IndexIter *pIndexIter,
+ const char *pToken, int nToken,
+ i64 iRowid,
+ int iCol,
+ int iOff,
+ const char **ppOut, int *pnOut
+);
/*
** Insert or remove data to or from the index. Each time a document is
@@ -232643,18 +236156,20 @@ struct Fts5Table {
Fts5Index *pIndex; /* Full-text index */
};
-static int sqlite3Fts5GetTokenizer(
- Fts5Global*,
- const char **azArg,
- int nArg,
- Fts5Config*,
- char **pzErr
-);
+static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);
static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
static int sqlite3Fts5FlushToDisk(Fts5Table*);
+static void sqlite3Fts5ClearLocale(Fts5Config *pConfig);
+static void sqlite3Fts5SetLocale(Fts5Config *pConfig, const char *pLoc, int nLoc);
+
+static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal);
+static int sqlite3Fts5DecodeLocaleValue(sqlite3_value *pVal,
+ const char **ppText, int *pnText, const char **ppLoc, int *pnLoc
+);
+
/*
** End of interface to code in fts5.c.
**************************************************************************/
@@ -232734,8 +236249,8 @@ static int sqlite3Fts5StorageRename(Fts5Storage*, const char *zName);
static int sqlite3Fts5DropAll(Fts5Config*);
static int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);
-static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
-static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
+static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**, int);
+static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, int, sqlite3_value**, i64*);
static int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg);
@@ -232760,6 +236275,9 @@ static int sqlite3Fts5StorageOptimize(Fts5Storage *p);
static int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge);
static int sqlite3Fts5StorageReset(Fts5Storage *p);
+static void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage*);
+static int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel);
+
/*
** End of interface to code in fts5_storage.c.
**************************************************************************/
@@ -232912,6 +236430,7 @@ static int sqlite3Fts5TokenizerPattern(
int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
Fts5Tokenizer *pTok
);
+static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*);
/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/
@@ -232976,7 +236495,7 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
**
** The "lemon" program processes an LALR(1) input grammar file, then uses
** this template to construct a parser. The "lemon" program inserts text
-** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
+** 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
@@ -234689,6 +238208,7 @@ static int fts5HighlightCb(
return rc;
}
+
/*
** Implementation of highlight() function.
*/
@@ -234719,12 +238239,19 @@ static void fts5HighlightFunction(
sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
rc = SQLITE_OK;
}else if( ctx.zIn ){
+ const char *pLoc = 0; /* Locale of column iCol */
+ int nLoc = 0; /* Size of pLoc in bytes */
if( rc==SQLITE_OK ){
rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
}
if( rc==SQLITE_OK ){
- rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
+ rc = pApi->xColumnLocale(pFts, iCol, &pLoc, &nLoc);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pApi->xTokenize_v2(
+ pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx, fts5HighlightCb
+ );
}
if( ctx.bOpen ){
fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
@@ -234921,6 +238448,8 @@ static void fts5SnippetFunction(
memset(&sFinder, 0, sizeof(Fts5SFinder));
for(i=0; i<nCol; i++){
if( iCol<0 || iCol==i ){
+ const char *pLoc = 0; /* Locale of column iCol */
+ int nLoc = 0; /* Size of pLoc in bytes */
int nDoc;
int nDocsize;
int ii;
@@ -234928,8 +238457,10 @@ static void fts5SnippetFunction(
sFinder.nFirst = 0;
rc = pApi->xColumnText(pFts, i, &sFinder.zDoc, &nDoc);
if( rc!=SQLITE_OK ) break;
- rc = pApi->xTokenize(pFts,
- sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb
+ rc = pApi->xColumnLocale(pFts, i, &pLoc, &nLoc);
+ if( rc!=SQLITE_OK ) break;
+ rc = pApi->xTokenize_v2(pFts,
+ sFinder.zDoc, nDoc, pLoc, nLoc, (void*)&sFinder, fts5SentenceFinderCb
);
if( rc!=SQLITE_OK ) break;
rc = pApi->xColumnSize(pFts, i, &nDocsize);
@@ -234987,6 +238518,9 @@ static void fts5SnippetFunction(
rc = pApi->xColumnSize(pFts, iBestCol, &nColSize);
}
if( ctx.zIn ){
+ const char *pLoc = 0; /* Locale of column iBestCol */
+ int nLoc = 0; /* Bytes in pLoc */
+
if( rc==SQLITE_OK ){
rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
}
@@ -235005,7 +238539,12 @@ static void fts5SnippetFunction(
}
if( rc==SQLITE_OK ){
- rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
+ rc = pApi->xColumnLocale(pFts, iBestCol, &pLoc, &nLoc);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pApi->xTokenize_v2(
+ pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx,fts5HighlightCb
+ );
}
if( ctx.bOpen ){
fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
@@ -235110,7 +238649,7 @@ static int fts5Bm25GetData(
** under consideration.
**
** The problem with this is that if (N < 2*nHit), the IDF is
- ** negative. Which is undesirable. So the mimimum allowable IDF is
+ ** negative. Which is undesirable. So the minimum allowable IDF is
** (1e-6) - roughly the same as a term that appears in just over
** half of set of 5,000,000 documents. */
double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
@@ -235189,6 +238728,53 @@ static void fts5Bm25Function(
}
}
+/*
+** Implementation of fts5_get_locale() function.
+*/
+static void fts5GetLocaleFunction(
+ const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
+ Fts5Context *pFts, /* First arg to pass to pApi functions */
+ sqlite3_context *pCtx, /* Context for returning result/error */
+ int nVal, /* Number of values in apVal[] array */
+ sqlite3_value **apVal /* Array of trailing arguments */
+){
+ int iCol = 0;
+ int eType = 0;
+ int rc = SQLITE_OK;
+ const char *zLocale = 0;
+ int nLocale = 0;
+
+ /* xColumnLocale() must be available */
+ assert( pApi->iVersion>=4 );
+
+ if( nVal!=1 ){
+ const char *z = "wrong number of arguments to function fts5_get_locale()";
+ sqlite3_result_error(pCtx, z, -1);
+ return;
+ }
+
+ eType = sqlite3_value_numeric_type(apVal[0]);
+ if( eType!=SQLITE_INTEGER ){
+ const char *z = "non-integer argument passed to function fts5_get_locale()";
+ sqlite3_result_error(pCtx, z, -1);
+ return;
+ }
+
+ iCol = sqlite3_value_int(apVal[0]);
+ if( iCol<0 || iCol>=pApi->xColumnCount(pFts) ){
+ sqlite3_result_error_code(pCtx, SQLITE_RANGE);
+ return;
+ }
+
+ rc = pApi->xColumnLocale(pFts, iCol, &zLocale, &nLocale);
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(pCtx, rc);
+ return;
+ }
+
+ sqlite3_result_text(pCtx, zLocale, nLocale, SQLITE_TRANSIENT);
+}
+
static int sqlite3Fts5AuxInit(fts5_api *pApi){
struct Builtin {
const char *zFunc; /* Function name (nul-terminated) */
@@ -235196,9 +238782,10 @@ static int sqlite3Fts5AuxInit(fts5_api *pApi){
fts5_extension_function xFunc;/* Callback function */
void (*xDestroy)(void*); /* Destructor function */
} aBuiltin [] = {
- { "snippet", 0, fts5SnippetFunction, 0 },
- { "highlight", 0, fts5HighlightFunction, 0 },
- { "bm25", 0, fts5Bm25Function, 0 },
+ { "snippet", 0, fts5SnippetFunction, 0 },
+ { "highlight", 0, fts5HighlightFunction, 0 },
+ { "bm25", 0, fts5Bm25Function, 0 },
+ { "fts5_get_locale", 0, fts5GetLocaleFunction, 0 },
};
int rc = SQLITE_OK; /* Return code */
int i; /* To iterate through builtin functions */
@@ -235525,7 +239112,7 @@ static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
** * The 52 upper and lower case ASCII characters, and
** * The 10 integer ASCII characters.
** * The underscore character "_" (0x5F).
-** * The unicode "subsitute" character (0x1A).
+** * The unicode "substitute" character (0x1A).
*/
static int sqlite3Fts5IsBareword(char t){
u8 aBareword[128] = {
@@ -235863,7 +239450,6 @@ static int fts5ConfigSetEnum(
** eventually free any such error message using sqlite3_free().
*/
static int fts5ConfigParseSpecial(
- Fts5Global *pGlobal,
Fts5Config *pConfig, /* Configuration object to update */
const char *zCmd, /* Special command to parse */
const char *zArg, /* Argument to parse */
@@ -235871,6 +239457,7 @@ static int fts5ConfigParseSpecial(
){
int rc = SQLITE_OK;
int nCmd = (int)strlen(zCmd);
+
if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){
const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES;
const char *p;
@@ -235927,12 +239514,11 @@ static int fts5ConfigParseSpecial(
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
const char *p = (const char*)zArg;
sqlite3_int64 nArg = strlen(zArg) + 1;
- char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
- char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
- char *pSpace = pDel;
+ char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg);
- if( azArg && pSpace ){
- if( pConfig->pTok ){
+ if( azArg ){
+ char *pSpace = (char*)&azArg[nArg];
+ if( pConfig->t.azArg ){
*pzErr = sqlite3_mprintf("multiple tokenize=... directives");
rc = SQLITE_ERROR;
}else{
@@ -235955,16 +239541,14 @@ static int fts5ConfigParseSpecial(
*pzErr = sqlite3_mprintf("parse error in tokenize directive");
rc = SQLITE_ERROR;
}else{
- rc = sqlite3Fts5GetTokenizer(pGlobal,
- (const char**)azArg, (int)nArg, pConfig,
- pzErr
- );
+ pConfig->t.azArg = (const char**)azArg;
+ pConfig->t.nArg = nArg;
+ azArg = 0;
}
}
}
-
sqlite3_free(azArg);
- sqlite3_free(pDel);
+
return rc;
}
@@ -235993,6 +239577,16 @@ static int fts5ConfigParseSpecial(
return rc;
}
+ if( sqlite3_strnicmp("contentless_unindexed", zCmd, nCmd)==0 ){
+ if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
+ *pzErr = sqlite3_mprintf("malformed contentless_delete=... directive");
+ rc = SQLITE_ERROR;
+ }else{
+ pConfig->bContentlessUnindexed = (zArg[0]=='1');
+ }
+ return rc;
+ }
+
if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){
if( pConfig->zContentRowid ){
*pzErr = sqlite3_mprintf("multiple content_rowid=... directives");
@@ -236013,6 +239607,16 @@ static int fts5ConfigParseSpecial(
return rc;
}
+ if( sqlite3_strnicmp("locale", zCmd, nCmd)==0 ){
+ if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
+ *pzErr = sqlite3_mprintf("malformed locale=... directive");
+ rc = SQLITE_ERROR;
+ }else{
+ pConfig->bLocale = (zArg[0]=='1');
+ }
+ return rc;
+ }
+
if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){
const Fts5Enum aDetail[] = {
{ "none", FTS5_DETAIL_NONE },
@@ -236042,16 +239646,6 @@ static int fts5ConfigParseSpecial(
}
/*
-** Allocate an instance of the default tokenizer ("simple") at
-** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
-** code if an error occurs.
-*/
-static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
- assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
- return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
-}
-
-/*
** Gobble up the first bareword or quoted word from the input buffer zIn.
** Return a pointer to the character immediately following the last in
** the gobbled word if successful, or a NULL pointer otherwise (failed
@@ -236110,7 +239704,8 @@ static int fts5ConfigParseColumn(
Fts5Config *p,
char *zCol,
char *zArg,
- char **pzErr
+ char **pzErr,
+ int *pbUnindexed
){
int rc = SQLITE_OK;
if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME)
@@ -236121,6 +239716,7 @@ static int fts5ConfigParseColumn(
}else if( zArg ){
if( 0==sqlite3_stricmp(zArg, "unindexed") ){
p->abUnindexed[p->nCol] = 1;
+ *pbUnindexed = 1;
}else{
*pzErr = sqlite3_mprintf("unrecognized column option: %s", zArg);
rc = SQLITE_ERROR;
@@ -236141,11 +239737,26 @@ static int fts5ConfigMakeExprlist(Fts5Config *p){
sqlite3Fts5BufferAppendPrintf(&rc, &buf, "T.%Q", p->zContentRowid);
if( p->eContent!=FTS5_CONTENT_NONE ){
+ assert( p->eContent==FTS5_CONTENT_EXTERNAL
+ || p->eContent==FTS5_CONTENT_NORMAL
+ || p->eContent==FTS5_CONTENT_UNINDEXED
+ );
for(i=0; i<p->nCol; i++){
if( p->eContent==FTS5_CONTENT_EXTERNAL ){
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]);
- }else{
+ }else if( p->eContent==FTS5_CONTENT_NORMAL || p->abUnindexed[i] ){
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i);
+ }else{
+ sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
+ }
+ }
+ }
+ if( p->eContent==FTS5_CONTENT_NORMAL && p->bLocale ){
+ for(i=0; i<p->nCol; i++){
+ if( p->abUnindexed[i]==0 ){
+ sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.l%d", i);
+ }else{
+ sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
}
}
}
@@ -236179,10 +239790,12 @@ static int sqlite3Fts5ConfigParse(
Fts5Config *pRet; /* New object to return */
int i;
sqlite3_int64 nByte;
+ int bUnindexed = 0; /* True if there are one or more UNINDEXED */
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
if( pRet==0 ) return SQLITE_NOMEM;
memset(pRet, 0, sizeof(Fts5Config));
+ pRet->pGlobal = pGlobal;
pRet->db = db;
pRet->iCookie = -1;
@@ -236231,13 +239844,13 @@ static int sqlite3Fts5ConfigParse(
rc = SQLITE_ERROR;
}else{
if( bOption ){
- rc = fts5ConfigParseSpecial(pGlobal, pRet,
+ rc = fts5ConfigParseSpecial(pRet,
ALWAYS(zOne)?zOne:"",
zTwo?zTwo:"",
pzErr
);
}else{
- rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
+ rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr, &bUnindexed);
zOne = 0;
}
}
@@ -236269,11 +239882,17 @@ static int sqlite3Fts5ConfigParse(
rc = SQLITE_ERROR;
}
- /* If a tokenizer= option was successfully parsed, the tokenizer has
- ** already been allocated. Otherwise, allocate an instance of the default
- ** tokenizer (unicode61) now. */
- if( rc==SQLITE_OK && pRet->pTok==0 ){
- rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
+ /* We only allow contentless_unindexed=1 if the table is actually a
+ ** contentless one.
+ */
+ if( rc==SQLITE_OK
+ && pRet->bContentlessUnindexed
+ && pRet->eContent!=FTS5_CONTENT_NONE
+ ){
+ *pzErr = sqlite3_mprintf(
+ "contentless_unindexed=1 requires a contentless table"
+ );
+ rc = SQLITE_ERROR;
}
/* If no zContent option was specified, fill in the default values. */
@@ -236284,6 +239903,9 @@ static int sqlite3Fts5ConfigParse(
);
if( pRet->eContent==FTS5_CONTENT_NORMAL ){
zTail = "content";
+ }else if( bUnindexed && pRet->bContentlessUnindexed ){
+ pRet->eContent = FTS5_CONTENT_UNINDEXED;
+ zTail = "content";
}else if( pRet->bColumnsize ){
zTail = "docsize";
}
@@ -236317,9 +239939,14 @@ static int sqlite3Fts5ConfigParse(
static void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
if( pConfig ){
int i;
- if( pConfig->pTok ){
- pConfig->pTokApi->xDelete(pConfig->pTok);
+ if( pConfig->t.pTok ){
+ if( pConfig->t.pApi1 ){
+ pConfig->t.pApi1->xDelete(pConfig->t.pTok);
+ }else{
+ pConfig->t.pApi2->xDelete(pConfig->t.pTok);
+ }
}
+ sqlite3_free((char*)pConfig->t.azArg);
sqlite3_free(pConfig->zDb);
sqlite3_free(pConfig->zName);
for(i=0; i<pConfig->nCol; i++){
@@ -236394,10 +240021,24 @@ static int sqlite3Fts5Tokenize(
void *pCtx, /* Context passed to xToken() */
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
){
- if( pText==0 ) return SQLITE_OK;
- return pConfig->pTokApi->xTokenize(
- pConfig->pTok, pCtx, flags, pText, nText, xToken
- );
+ int rc = SQLITE_OK;
+ if( pText ){
+ if( pConfig->t.pTok==0 ){
+ rc = sqlite3Fts5LoadTokenizer(pConfig);
+ }
+ if( rc==SQLITE_OK ){
+ if( pConfig->t.pApi1 ){
+ rc = pConfig->t.pApi1->xTokenize(
+ pConfig->t.pTok, pCtx, flags, pText, nText, xToken
+ );
+ }else{
+ rc = pConfig->t.pApi2->xTokenize(pConfig->t.pTok, pCtx, flags,
+ pText, nText, pConfig->t.pLocale, pConfig->t.nLocale, xToken
+ );
+ }
+ }
+ }
+ return rc;
}
/*
@@ -236601,6 +240242,19 @@ static int sqlite3Fts5ConfigSetValue(
}else{
pConfig->bSecureDelete = (bVal ? 1 : 0);
}
+ }
+
+ else if( 0==sqlite3_stricmp(zKey, "insttoken") ){
+ int bVal = -1;
+ if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
+ bVal = sqlite3_value_int(pVal);
+ }
+ if( bVal<0 ){
+ *pbBadkey = 1;
+ }else{
+ pConfig->bPrefixInsttoken = (bVal ? 1 : 0);
+ }
+
}else{
*pbBadkey = 1;
}
@@ -236651,13 +240305,10 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
&& iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE
){
rc = SQLITE_ERROR;
- if( pConfig->pzErrmsg ){
- assert( 0==*pConfig->pzErrmsg );
- *pConfig->pzErrmsg = sqlite3_mprintf("invalid fts5 file format "
- "(found %d, expected %d or %d) - run 'rebuild'",
- iVersion, FTS5_CURRENT_VERSION, FTS5_CURRENT_VERSION_SECUREDELETE
- );
- }
+ sqlite3Fts5ConfigErrmsg(pConfig, "invalid fts5 file format "
+ "(found %d, expected %d or %d) - run 'rebuild'",
+ iVersion, FTS5_CURRENT_VERSION, FTS5_CURRENT_VERSION_SECUREDELETE
+ );
}else{
pConfig->iVersion = iVersion;
}
@@ -236669,6 +240320,29 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
}
/*
+** Set (*pConfig->pzErrmsg) to point to an sqlite3_malloc()ed buffer
+** containing the error message created using printf() style formatting
+** string zFmt and its trailing arguments.
+*/
+static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){
+ va_list ap; /* ... printf arguments */
+ char *zMsg = 0;
+
+ va_start(ap, zFmt);
+ zMsg = sqlite3_vmprintf(zFmt, ap);
+ if( pConfig->pzErrmsg ){
+ assert( *pConfig->pzErrmsg==0 );
+ *pConfig->pzErrmsg = zMsg;
+ }else{
+ sqlite3_free(zMsg);
+ }
+
+ va_end(ap);
+}
+
+
+
+/*
** 2014 May 31
**
** The author disclaims copyright to this source code. In place of
@@ -236724,7 +240398,7 @@ struct Fts5Expr {
/*
** eType:
-** Expression node type. Always one of:
+** Expression node type. Usually one of:
**
** FTS5_AND (nChild, apChild valid)
** FTS5_OR (nChild, apChild valid)
@@ -236732,6 +240406,10 @@ struct Fts5Expr {
** FTS5_STRING (pNear valid)
** FTS5_TERM (pNear valid)
**
+** An expression node with eType==0 may also exist. It always matches zero
+** rows. This is created when a phrase containing no tokens is parsed.
+** e.g. "".
+**
** iHeight:
** Distance from this node to furthest leaf. This is always 0 for nodes
** of type FTS5_STRING and FTS5_TERM. For all other nodes it is one
@@ -236752,9 +240430,13 @@ struct Fts5ExprNode {
/* Child nodes. For a NOT node, this array always contains 2 entries. For
** AND or OR nodes, it contains 2 or more entries. */
int nChild; /* Number of child nodes */
- Fts5ExprNode *apChild[1]; /* Array of child nodes */
+ Fts5ExprNode *apChild[FLEXARRAY]; /* Array of child nodes */
};
+/* Size (in bytes) of an Fts5ExprNode object that holds up to N children */
+#define SZ_FTS5EXPRNODE(N) \
+ (offsetof(Fts5ExprNode,apChild) + (N)*sizeof(Fts5ExprNode*))
+
#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
/*
@@ -236785,9 +240467,13 @@ struct Fts5ExprPhrase {
Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
Fts5Buffer poslist; /* Current position list */
int nTerm; /* Number of entries in aTerm[] */
- Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
+ Fts5ExprTerm aTerm[FLEXARRAY]; /* Terms that make up this phrase */
};
+/* Size (in bytes) of an Fts5ExprPhrase object that holds up to N terms */
+#define SZ_FTS5EXPRPHRASE(N) \
+ (offsetof(Fts5ExprPhrase,aTerm) + (N)*sizeof(Fts5ExprTerm))
+
/*
** One or more phrases that must appear within a certain token distance of
** each other within each matching document.
@@ -236796,9 +240482,12 @@ struct Fts5ExprNearset {
int nNear; /* NEAR parameter */
Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
int nPhrase; /* Number of entries in aPhrase[] array */
- Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
+ Fts5ExprPhrase *apPhrase[FLEXARRAY]; /* Array of phrase pointers */
};
+/* Size (in bytes) of an Fts5ExprNearset object covering up to N phrases */
+#define SZ_FTS5EXPRNEARSET(N) \
+ (offsetof(Fts5ExprNearset,apPhrase)+(N)*sizeof(Fts5ExprPhrase*))
/*
** Parse context.
@@ -236952,12 +240641,13 @@ static int sqlite3Fts5ExprNew(
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
+ assert( sParse.pExpr || sParse.rc!=SQLITE_OK );
assert_expr_depth_ok(sParse.rc, sParse.pExpr);
/* If the LHS of the MATCH expression was a user column, apply the
** implicit column-filter. */
- if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
- int n = sizeof(Fts5Colset);
+ if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
+ int n = SZ_FTS5COLSET(1);
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
if( pColset ){
pColset->nCol = 1;
@@ -236973,15 +240663,7 @@ static int sqlite3Fts5ExprNew(
sParse.rc = SQLITE_NOMEM;
sqlite3Fts5ParseNodeFree(sParse.pExpr);
}else{
- if( !sParse.pExpr ){
- const int nByte = sizeof(Fts5ExprNode);
- pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte);
- if( pNew->pRoot ){
- pNew->pRoot->bEof = 1;
- }
- }else{
- pNew->pRoot = sParse.pExpr;
- }
+ pNew->pRoot = sParse.pExpr;
pNew->pIndex = 0;
pNew->pConfig = pConfig;
pNew->apExprPhrase = sParse.apPhrase;
@@ -237799,7 +241481,7 @@ static int fts5ExprNodeTest_STRING(
}
}else{
Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
- if( pIter->iRowid==iLast || pIter->bEof ) continue;
+ if( pIter->iRowid==iLast ) continue;
bMatch = 0;
if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
return rc;
@@ -238321,12 +242003,9 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset(
Fts5ExprNearset *pRet = 0;
if( pParse->rc==SQLITE_OK ){
- if( pPhrase==0 ){
- return pNear;
- }
if( pNear==0 ){
sqlite3_int64 nByte;
- nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
+ nByte = SZ_FTS5EXPRNEARSET(SZALLOC+1);
pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
@@ -238337,7 +242016,7 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset(
int nNew = pNear->nPhrase + SZALLOC;
sqlite3_int64 nByte;
- nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
+ nByte = SZ_FTS5EXPRNEARSET(nNew+1);
pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
@@ -238428,12 +242107,12 @@ static int fts5ParseTokenize(
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
- sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
+ SZ_FTS5EXPRPHRASE(nNew+1)
);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
- if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
+ if( pPhrase==0 ) memset(pNew, 0, SZ_FTS5EXPRPHRASE(1));
pCtx->pPhrase = pPhrase = pNew;
pNew->nTerm = nNew - SZALLOC;
}
@@ -238541,10 +242220,11 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm(
if( sCtx.pPhrase==0 ){
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
- sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
+ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5EXPRPHRASE(1));
}else if( sCtx.pPhrase->nTerm ){
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
}
+ assert( pParse->apPhrase!=0 );
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
}
@@ -238564,7 +242244,7 @@ static int sqlite3Fts5ExprClonePhrase(
Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
- if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
+ if( !pExpr || iPhrase<0 || iPhrase>=pExpr->nPhrase ){
rc = SQLITE_RANGE;
}else{
pOrig = pExpr->apExprPhrase[iPhrase];
@@ -238575,19 +242255,18 @@ static int sqlite3Fts5ExprClonePhrase(
sizeof(Fts5ExprPhrase*));
}
if( rc==SQLITE_OK ){
- pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
- sizeof(Fts5ExprNode));
+ pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNODE(1));
}
if( rc==SQLITE_OK ){
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
- sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
+ SZ_FTS5EXPRNEARSET(2));
}
if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
sqlite3_int64 nByte;
Fts5Colset *pColset;
- nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
+ nByte = SZ_FTS5COLSET(pColsetOrig->nCol);
pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, (size_t)nByte);
@@ -238615,7 +242294,7 @@ static int sqlite3Fts5ExprClonePhrase(
}else{
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
- sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
+ sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRPHRASE(1));
}
}
@@ -238680,7 +242359,8 @@ static void sqlite3Fts5ParseSetDistance(
);
return;
}
- nNear = nNear * 10 + (p->p[i] - '0');
+ if( nNear<214748363 ) nNear = nNear * 10 + (p->p[i] - '0');
+ /* ^^^^^^^^^^^^^^^--- Prevent integer overflow */
}
}else{
nNear = FTS5_DEFAULT_NEARDIST;
@@ -238709,7 +242389,7 @@ static Fts5Colset *fts5ParseColset(
assert( pParse->rc==SQLITE_OK );
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
- pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
+ pNew = sqlite3_realloc64(p, SZ_FTS5COLSET(nCol+1));
if( pNew==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -238744,7 +242424,7 @@ static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p
int nCol = pParse->pConfig->nCol;
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
- sizeof(Fts5Colset) + sizeof(int)*nCol
+ SZ_FTS5COLSET(nCol+1)
);
if( pRet ){
int i;
@@ -238805,7 +242485,7 @@ static Fts5Colset *sqlite3Fts5ParseColset(
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
Fts5Colset *pRet;
if( pOrig ){
- sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
+ sqlite3_int64 nByte = SZ_FTS5COLSET(pOrig->nCol);
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
if( pRet ){
memcpy(pRet, pOrig, (size_t)nByte);
@@ -238932,6 +242612,9 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
}
}
+/*
+** Add pSub as a child of p.
+*/
static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
int ii = p->nChild;
if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){
@@ -238970,7 +242653,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
assert( pNear->nPhrase==1 );
assert( pParse->bPhraseToAnd );
- nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
+ nByte = SZ_FTS5EXPRNODE(nTerm+1);
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
if( pRet ){
pRet->eType = FTS5_AND;
@@ -238980,7 +242663,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
pParse->nPhrase--;
for(ii=0; ii<nTerm; ii++){
Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
- &pParse->rc, sizeof(Fts5ExprPhrase)
+ &pParse->rc, SZ_FTS5EXPRPHRASE(1)
);
if( pPhrase ){
if( parseGrowPhraseArray(pParse) ){
@@ -239049,7 +242732,7 @@ static Fts5ExprNode *sqlite3Fts5ParseNode(
if( pRight->eType==eType ) nChild += pRight->nChild-1;
}
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
+ nByte = SZ_FTS5EXPRNODE(nChild);
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
if( pRet ){
@@ -239076,19 +242759,23 @@ static Fts5ExprNode *sqlite3Fts5ParseNode(
"fts5: %s queries are not supported (detail!=full)",
pNear->nPhrase==1 ? "phrase": "NEAR"
);
- sqlite3_free(pRet);
+ sqlite3Fts5ParseNodeFree(pRet);
pRet = 0;
+ pNear = 0;
+ assert( pLeft==0 && pRight==0 );
}
}
}else{
+ assert( pNear==0 );
fts5ExprAddChildren(pRet, pLeft);
fts5ExprAddChildren(pRet, pRight);
+ pLeft = pRight = 0;
if( pRet->iHeight>SQLITE_FTS5_MAX_EXPR_DEPTH ){
sqlite3Fts5ParseError(pParse,
"fts5 expression tree is too large (maximum depth %d)",
SQLITE_FTS5_MAX_EXPR_DEPTH
);
- sqlite3_free(pRet);
+ sqlite3Fts5ParseNodeFree(pRet);
pRet = 0;
}
}
@@ -239140,6 +242827,8 @@ static Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
);
if( pRight->eType==FTS5_EOF ){
+ assert( pParse->apPhrase!=0 );
+ assert( pParse->nPhrase>0 );
assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
sqlite3Fts5ParseNodeFree(pRight);
pRet = pLeft;
@@ -239712,7 +243401,7 @@ static int fts5ExprPopulatePoslistsCb(
int rc = sqlite3Fts5PoslistWriterAppend(
&pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
);
- if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
+ if( rc==SQLITE_OK && (pExpr->pConfig->bTokendata || pT->bPrefix) ){
int iCol = p->iOff>>32;
int iTokOff = p->iOff & 0x7FFFFFFF;
rc = sqlite3Fts5IndexIterWriteTokendata(
@@ -239772,6 +243461,7 @@ static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){
pNode->iRowid = iRowid;
pNode->bEof = 0;
switch( pNode->eType ){
+ case 0:
case FTS5_TERM:
case FTS5_STRING:
return (pNode->pNear->apPhrase[0]->poslist.n>0);
@@ -239904,21 +243594,20 @@ static int sqlite3Fts5ExprInstToken(
return SQLITE_RANGE;
}
pTerm = &pPhrase->aTerm[iToken];
- if( pTerm->bPrefix==0 ){
- if( pExpr->pConfig->bTokendata ){
- rc = sqlite3Fts5IterToken(
- pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
- );
- }else{
- *ppOut = pTerm->pTerm;
- *pnOut = pTerm->nFullTerm;
- }
+ if( pExpr->pConfig->bTokendata || pTerm->bPrefix ){
+ rc = sqlite3Fts5IterToken(
+ pTerm->pIter, pTerm->pTerm, pTerm->nQueryTerm,
+ iRowid, iCol, iOff+iToken, ppOut, pnOut
+ );
+ }else{
+ *ppOut = pTerm->pTerm;
+ *pnOut = pTerm->nFullTerm;
}
return rc;
}
/*
-** Clear the token mappings for all Fts5IndexIter objects mannaged by
+** Clear the token mappings for all Fts5IndexIter objects managed by
** the expression passed as the only argument.
*/
static void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
@@ -239953,7 +243642,7 @@ typedef struct Fts5HashEntry Fts5HashEntry;
/*
** This file contains the implementation of an in-memory hash table used
-** to accumuluate "term -> doclist" content before it is flused to a level-0
+** to accumulate "term -> doclist" content before it is flushed to a level-0
** segment.
*/
@@ -240010,7 +243699,7 @@ struct Fts5HashEntry {
};
/*
-** Eqivalent to:
+** Equivalent to:
**
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
*/
@@ -240946,9 +244635,13 @@ struct Fts5Structure {
u64 nOriginCntr; /* Origin value for next top-level segment */
int nSegment; /* Total segments in this structure */
int nLevel; /* Number of levels in this index */
- Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
+ Fts5StructureLevel aLevel[FLEXARRAY]; /* Array of nLevel level objects */
};
+/* Size (in bytes) of an Fts5Structure object holding up to N levels */
+#define SZ_FTS5STRUCTURE(N) \
+ (offsetof(Fts5Structure,aLevel) + (N)*sizeof(Fts5StructureLevel))
+
/*
** An object of type Fts5SegWriter is used to write to segments.
*/
@@ -241078,11 +244771,15 @@ struct Fts5SegIter {
** Array of tombstone pages. Reference counted.
*/
struct Fts5TombstoneArray {
- int nRef; /* Number of pointers to this object */
+ int nRef; /* Number of pointers to this object */
int nTombstone;
- Fts5Data *apTombstone[1]; /* Array of tombstone pages */
+ Fts5Data *apTombstone[FLEXARRAY]; /* Array of tombstone pages */
};
+/* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */
+#define SZ_FTS5TOMBSTONEARRAY(N) \
+ (offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*))
+
/*
** Argument is a pointer to an Fts5Data structure that contains a
** leaf page.
@@ -241151,9 +244848,12 @@ struct Fts5Iter {
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
Fts5CResult *aFirst; /* Current merge state (see above) */
- Fts5SegIter aSeg[1]; /* Array of segment iterators */
+ Fts5SegIter aSeg[FLEXARRAY]; /* Array of segment iterators */
};
+/* Size (in bytes) of an Fts5Iter object holding up to N segment iterators */
+#define SZ_FTS5ITER(N) (offsetof(Fts5Iter,aSeg)+(N)*sizeof(Fts5SegIter))
+
/*
** An instance of the following type is used to iterate through the contents
** of a doclist-index record.
@@ -241180,9 +244880,13 @@ struct Fts5DlidxLvl {
struct Fts5DlidxIter {
int nLvl;
int iSegid;
- Fts5DlidxLvl aLvl[1];
+ Fts5DlidxLvl aLvl[FLEXARRAY];
};
+/* Size (in bytes) of an Fts5DlidxIter object with up to N levels */
+#define SZ_FTS5DLIDXITER(N) \
+ (offsetof(Fts5DlidxIter,aLvl)+(N)*sizeof(Fts5DlidxLvl))
+
static void fts5PutU16(u8 *aOut, u16 iVal){
aOut[0] = (iVal>>8);
aOut[1] = (iVal&0xFF);
@@ -241302,11 +245006,13 @@ static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
/*
** Close the read-only blob handle, if it is open.
*/
-static void sqlite3Fts5IndexCloseReader(Fts5Index *p){
+static void fts5IndexCloseReader(Fts5Index *p){
if( p->pReader ){
+ int rc;
sqlite3_blob *pReader = p->pReader;
p->pReader = 0;
- sqlite3_blob_close(pReader);
+ rc = sqlite3_blob_close(pReader);
+ if( p->rc==SQLITE_OK ) p->rc = rc;
}
}
@@ -241331,7 +245037,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
assert( p->pReader==0 );
p->pReader = pBlob;
if( rc!=SQLITE_OK ){
- sqlite3Fts5IndexCloseReader(p);
+ fts5IndexCloseReader(p);
}
if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
}
@@ -241355,11 +245061,12 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
if( rc==SQLITE_OK ){
u8 *aOut = 0; /* Read blob data into this buffer */
int nByte = sqlite3_blob_bytes(p->pReader);
- sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
+ int szData = (sizeof(Fts5Data) + 7) & ~7;
+ sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING;
pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
if( pRet ){
pRet->nn = nByte;
- aOut = pRet->p = (u8*)&pRet[1];
+ aOut = pRet->p = (u8*)pRet + szData;
}else{
rc = SQLITE_NOMEM;
}
@@ -241382,6 +245089,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
}
assert( (pRet==0)==(p->rc!=SQLITE_OK) );
+ assert( pRet==0 || EIGHT_BYTE_ALIGNMENT( pRet->p ) );
return pRet;
}
@@ -241413,9 +245121,13 @@ static int fts5IndexPrepareStmt(
){
if( p->rc==SQLITE_OK ){
if( zSql ){
- p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
+ int rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
ppStmt, 0);
+ /* If this prepare() call fails with SQLITE_ERROR, then one of the
+ ** %_idx or %_data tables has been removed or modified. Call this
+ ** corruption. */
+ p->rc = (rc==SQLITE_ERROR ? SQLITE_CORRUPT : rc);
}else{
p->rc = SQLITE_NOMEM;
}
@@ -241542,7 +245254,7 @@ static int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
Fts5Structure *p = *pp;
if( *pRc==SQLITE_OK && p->nRef>1 ){
- i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
+ i64 nByte = SZ_FTS5STRUCTURE(p->nLevel);
Fts5Structure *pNew;
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
if( pNew ){
@@ -241616,10 +245328,7 @@ static int fts5StructureDecode(
){
return FTS5_CORRUPT;
}
- nByte = (
- sizeof(Fts5Structure) + /* Main structure */
- sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
- );
+ nByte = SZ_FTS5STRUCTURE(nLevel);
pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
if( pRet ){
@@ -241699,10 +245408,7 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
if( *pRc==SQLITE_OK ){
Fts5Structure *pStruct = *ppStruct;
int nLevel = pStruct->nLevel;
- sqlite3_int64 nByte = (
- sizeof(Fts5Structure) + /* Main structure */
- sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
- );
+ sqlite3_int64 nByte = SZ_FTS5STRUCTURE(nLevel+2);
pStruct = sqlite3_realloc64(pStruct, nByte);
if( pStruct ){
@@ -242241,7 +245947,7 @@ static Fts5DlidxIter *fts5DlidxIterInit(
int bDone = 0;
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
- sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
+ sqlite3_int64 nByte = SZ_FTS5DLIDXITER(i+1);
Fts5DlidxIter *pNew;
pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
@@ -242459,7 +246165,7 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
const int nTomb = pIter->pSeg->nPgTombstone;
if( nTomb>0 ){
- int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
+ int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
Fts5TombstoneArray *pNew;
pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( pNew ){
@@ -242707,7 +246413,7 @@ static void fts5SegIterNext_None(
if( iOff<pIter->iEndofDoclist ){
/* Next entry is on the current page */
- i64 iDelta;
+ u64 iDelta;
iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
pIter->iLeafOffset = iOff;
pIter->iRowid += iDelta;
@@ -243920,8 +247626,7 @@ static Fts5Iter *fts5MultiIterAlloc(
for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
pNew = fts5IdxMalloc(p,
- sizeof(Fts5Iter) + /* pNew */
- sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
+ SZ_FTS5ITER(nSlot) + /* pNew + pNew->aSeg[] */
sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
);
if( pNew ){
@@ -245411,6 +249116,11 @@ static int fts5IndexFindDeleteMerge(Fts5Index *p, Fts5Structure *pStruct){
nBest = nPercent;
}
}
+
+ /* If pLvl is already the input level to an ongoing merge, look no
+ ** further for a merge candidate. The caller should be allowed to
+ ** continue merging from pLvl first. */
+ if( pLvl->nMerge ) break;
}
}
return iRet;
@@ -245522,6 +249232,14 @@ static int fts5IndexReturn(Fts5Index *p){
return rc;
}
+/*
+** Close the read-only blob handle, if it is open.
+*/
+static void sqlite3Fts5IndexCloseReader(Fts5Index *p){
+ fts5IndexCloseReader(p);
+ fts5IndexReturn(p);
+}
+
typedef struct Fts5FlushCtx Fts5FlushCtx;
struct Fts5FlushCtx {
Fts5Index *pIdx;
@@ -245709,7 +249427,7 @@ static void fts5DoSecureDelete(
int iDelKeyOff = 0; /* Offset of deleted key, if any */
nIdx = nPg-iPgIdx;
- aIdx = sqlite3Fts5MallocZero(&p->rc, nIdx+16);
+ aIdx = sqlite3Fts5MallocZero(&p->rc, ((i64)nIdx)+16);
if( p->rc ) return;
memcpy(aIdx, &aPg[iPgIdx], nIdx);
@@ -245979,8 +249697,11 @@ static void fts5DoSecureDelete(
** This is called as part of flushing a delete to disk in 'secure-delete'
** mode. It edits the segments within the database described by argument
** pStruct to remove the entries for term zTerm, rowid iRowid.
+**
+** Return SQLITE_OK if successful, or an SQLite error code if an error
+** has occurred. Any error code is also stored in the Fts5Index handle.
*/
-static void fts5FlushSecureDelete(
+static int fts5FlushSecureDelete(
Fts5Index *p,
Fts5Structure *pStruct,
const char *zTerm,
@@ -245990,6 +249711,24 @@ static void fts5FlushSecureDelete(
const int f = FTS5INDEX_QUERY_SKIPHASH;
Fts5Iter *pIter = 0; /* Used to find term instance */
+ /* If the version number has not been set to SECUREDELETE, do so now. */
+ if( p->pConfig->iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE ){
+ Fts5Config *pConfig = p->pConfig;
+ sqlite3_stmt *pStmt = 0;
+ fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
+ "REPLACE INTO %Q.'%q_config' VALUES ('version', %d)",
+ pConfig->zDb, pConfig->zName, FTS5_CURRENT_VERSION_SECUREDELETE
+ ));
+ if( p->rc==SQLITE_OK ){
+ int rc;
+ sqlite3_step(pStmt);
+ rc = sqlite3_finalize(pStmt);
+ if( p->rc==SQLITE_OK ) p->rc = rc;
+ pConfig->iCookie++;
+ pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE;
+ }
+ }
+
fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter);
if( fts5MultiIterEof(p, pIter)==0 ){
i64 iThis = fts5MultiIterRowid(pIter);
@@ -246007,6 +249746,7 @@ static void fts5FlushSecureDelete(
}
fts5MultiIterFree(pIter);
+ return p->rc;
}
@@ -246090,8 +249830,9 @@ static void fts5FlushOneHash(Fts5Index *p){
** using fts5FlushSecureDelete(). */
if( bSecureDelete ){
if( eDetail==FTS5_DETAIL_NONE ){
- if( iOff<nDoclist && pDoclist[iOff]==0x00 ){
- fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid);
+ if( iOff<nDoclist && pDoclist[iOff]==0x00
+ && !fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid)
+ ){
iOff++;
if( iOff<nDoclist && pDoclist[iOff]==0x00 ){
iOff++;
@@ -246100,8 +249841,9 @@ static void fts5FlushOneHash(Fts5Index *p){
continue;
}
}
- }else if( (pDoclist[iOff] & 0x01) ){
- fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid);
+ }else if( (pDoclist[iOff] & 0x01)
+ && !fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid)
+ ){
if( p->rc!=SQLITE_OK || pDoclist[iOff]==0x01 ){
iOff++;
continue;
@@ -246250,7 +249992,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
Fts5Structure *pStruct
){
Fts5Structure *pNew = 0;
- sqlite3_int64 nByte = sizeof(Fts5Structure);
+ sqlite3_int64 nByte = SZ_FTS5STRUCTURE(1);
int nSeg = pStruct->nSegment;
int i;
@@ -246279,7 +250021,8 @@ static Fts5Structure *fts5IndexOptimizeStruct(
assert( pStruct->aLevel[i].nMerge<=nThis );
}
- nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
+ nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
+ assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( pNew ){
@@ -246720,6 +250463,387 @@ static void fts5MergePrefixLists(
*p1 = out;
}
+
+/*
+** Iterate through a range of entries in the FTS index, invoking the xVisit
+** callback for each of them.
+**
+** Parameter pToken points to an nToken buffer containing an FTS index term
+** (i.e. a document term with the preceding 1 byte index identifier -
+** FTS5_MAIN_PREFIX or similar). If bPrefix is true, then the call visits
+** all entries for terms that have pToken/nToken as a prefix. If bPrefix
+** is false, then only entries with pToken/nToken as the entire key are
+** visited.
+**
+** If the current table is a tokendata=1 table, then if bPrefix is true then
+** each index term is treated separately. However, if bPrefix is false, then
+** all index terms corresponding to pToken/nToken are collapsed into a single
+** term before the callback is invoked.
+**
+** The callback invoked for each entry visited is specified by paramter xVisit.
+** Each time it is invoked, it is passed a pointer to the Fts5Index object,
+** a copy of the 7th paramter to this function (pCtx) and a pointer to the
+** iterator that indicates the current entry. If the current entry is the
+** first with a new term (i.e. different from that of the previous entry,
+** including the very first term), then the final two parameters are passed
+** a pointer to the term and its size in bytes, respectively. If the current
+** entry is not the first associated with its term, these two parameters
+** are passed 0.
+**
+** If parameter pColset is not NULL, then it is used to filter entries before
+** the callback is invoked.
+*/
+static int fts5VisitEntries(
+ Fts5Index *p, /* Fts5 index object */
+ Fts5Colset *pColset, /* Columns filter to apply, or NULL */
+ u8 *pToken, /* Buffer containing token */
+ int nToken, /* Size of buffer pToken in bytes */
+ int bPrefix, /* True for a prefix scan */
+ void (*xVisit)(Fts5Index*, void *pCtx, Fts5Iter *pIter, const u8*, int),
+ void *pCtx /* Passed as second argument to xVisit() */
+){
+ const int flags = (bPrefix ? FTS5INDEX_QUERY_SCAN : 0)
+ | FTS5INDEX_QUERY_SKIPEMPTY
+ | FTS5INDEX_QUERY_NOOUTPUT;
+ Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
+ int bNewTerm = 1;
+ Fts5Structure *pStruct = fts5StructureRead(p);
+
+ fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
+ fts5IterSetOutputCb(&p->rc, p1);
+ for( /* no-op */ ;
+ fts5MultiIterEof(p, p1)==0;
+ fts5MultiIterNext2(p, p1, &bNewTerm)
+ ){
+ Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
+ int nNew = 0;
+ const u8 *pNew = 0;
+
+ p1->xSetOutputs(p1, pSeg);
+ if( p->rc ) break;
+
+ if( bNewTerm ){
+ nNew = pSeg->term.n;
+ pNew = pSeg->term.p;
+ if( nNew<nToken || memcmp(pToken, pNew, nToken) ) break;
+ }
+
+ xVisit(p, pCtx, p1, pNew, nNew);
+ }
+ fts5MultiIterFree(p1);
+
+ fts5StructureRelease(pStruct);
+ return p->rc;
+}
+
+
+/*
+** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
+** array of these for each row it visits (so all iRowid fields are the same).
+** Or, for an iterator used by an "ORDER BY rank" query, it accumulates an
+** array of these for the entire query (in which case iRowid fields may take
+** a variety of values).
+**
+** Each instance in the array indicates the iterator (and therefore term)
+** associated with position iPos of rowid iRowid. This is used by the
+** xInstToken() API.
+**
+** iRowid:
+** Rowid for the current entry.
+**
+** iPos:
+** Position of current entry within row. In the usual ((iCol<<32)+iOff)
+** format (e.g. see macros FTS5_POS2COLUMN() and FTS5_POS2OFFSET()).
+**
+** iIter:
+** If the Fts5TokenDataIter iterator that the entry is part of is
+** actually an iterator (i.e. with nIter>0, not just a container for
+** Fts5TokenDataMap structures), then this variable is an index into
+** the apIter[] array. The corresponding term is that which the iterator
+** at apIter[iIter] currently points to.
+**
+** Or, if the Fts5TokenDataIter iterator is just a container object
+** (nIter==0), then iIter is an index into the term.p[] buffer where
+** the term is stored.
+**
+** nByte:
+** In the case where iIter is an index into term.p[], this variable
+** is the size of the term in bytes. If iIter is an index into apIter[],
+** this variable is unused.
+*/
+struct Fts5TokenDataMap {
+ i64 iRowid; /* Row this token is located in */
+ i64 iPos; /* Position of token */
+ int iIter; /* Iterator token was read from */
+ int nByte; /* Length of token in bytes (or 0) */
+};
+
+/*
+** An object used to supplement Fts5Iter for tokendata=1 iterators.
+**
+** This object serves two purposes. The first is as a container for an array
+** of Fts5TokenDataMap structures, which are used to find the token required
+** when the xInstToken() API is used. This is done by the nMapAlloc, nMap and
+** aMap[] variables.
+*/
+struct Fts5TokenDataIter {
+ int nMapAlloc; /* Allocated size of aMap[] in entries */
+ int nMap; /* Number of valid entries in aMap[] */
+ Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
+
+ /* The following are used for prefix-queries only. */
+ Fts5Buffer terms;
+
+ /* The following are used for other full-token tokendata queries only. */
+ int nIter;
+ int nIterAlloc;
+ Fts5PoslistReader *aPoslistReader;
+ int *aPoslistToIter;
+ Fts5Iter *apIter[FLEXARRAY];
+};
+
+/* Size in bytes of an Fts5TokenDataIter object holding up to N iterators */
+#define SZ_FTS5TOKENDATAITER(N) \
+ (offsetof(Fts5TokenDataIter,apIter) + (N)*sizeof(Fts5Iter))
+
+/*
+** The two input arrays - a1[] and a2[] - are in sorted order. This function
+** merges the two arrays together and writes the result to output array
+** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
+**
+** Duplicate entries are copied into the output. So the size of the output
+** array is always (n1+n2) entries.
+*/
+static void fts5TokendataMerge(
+ Fts5TokenDataMap *a1, int n1, /* Input array 1 */
+ Fts5TokenDataMap *a2, int n2, /* Input array 2 */
+ Fts5TokenDataMap *aOut /* Output array */
+){
+ int i1 = 0;
+ int i2 = 0;
+
+ assert( n1>=0 && n2>=0 );
+ while( i1<n1 || i2<n2 ){
+ Fts5TokenDataMap *pOut = &aOut[i1+i2];
+ if( i2>=n2 || (i1<n1 && (
+ a1[i1].iRowid<a2[i2].iRowid
+ || (a1[i1].iRowid==a2[i2].iRowid && a1[i1].iPos<=a2[i2].iPos)
+ ))){
+ memcpy(pOut, &a1[i1], sizeof(Fts5TokenDataMap));
+ i1++;
+ }else{
+ memcpy(pOut, &a2[i2], sizeof(Fts5TokenDataMap));
+ i2++;
+ }
+ }
+}
+
+
+/*
+** Append a mapping to the token-map belonging to object pT.
+*/
+static void fts5TokendataIterAppendMap(
+ Fts5Index *p,
+ Fts5TokenDataIter *pT,
+ int iIter,
+ int nByte,
+ i64 iRowid,
+ i64 iPos
+){
+ if( p->rc==SQLITE_OK ){
+ if( pT->nMap==pT->nMapAlloc ){
+ int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
+ int nAlloc = nNew * sizeof(Fts5TokenDataMap);
+ Fts5TokenDataMap *aNew;
+
+ aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
+ if( aNew==0 ){
+ p->rc = SQLITE_NOMEM;
+ return;
+ }
+
+ pT->aMap = aNew;
+ pT->nMapAlloc = nNew;
+ }
+
+ pT->aMap[pT->nMap].iRowid = iRowid;
+ pT->aMap[pT->nMap].iPos = iPos;
+ pT->aMap[pT->nMap].iIter = iIter;
+ pT->aMap[pT->nMap].nByte = nByte;
+ pT->nMap++;
+ }
+}
+
+/*
+** Sort the contents of the pT->aMap[] array.
+**
+** The sorting algorithm requires a malloc(). If this fails, an error code
+** is left in Fts5Index.rc before returning.
+*/
+static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
+ Fts5TokenDataMap *aTmp = 0;
+ int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
+
+ aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
+ if( aTmp ){
+ Fts5TokenDataMap *a1 = pT->aMap;
+ Fts5TokenDataMap *a2 = aTmp;
+ i64 nHalf;
+
+ for(nHalf=1; nHalf<pT->nMap; nHalf=nHalf*2){
+ int i1;
+ for(i1=0; i1<pT->nMap; i1+=(nHalf*2)){
+ int n1 = MIN(nHalf, pT->nMap-i1);
+ int n2 = MIN(nHalf, pT->nMap-i1-n1);
+ fts5TokendataMerge(&a1[i1], n1, &a1[i1+n1], n2, &a2[i1]);
+ }
+ SWAPVAL(Fts5TokenDataMap*, a1, a2);
+ }
+
+ if( a1!=pT->aMap ){
+ memcpy(pT->aMap, a1, pT->nMap*sizeof(Fts5TokenDataMap));
+ }
+ sqlite3_free(aTmp);
+
+#ifdef SQLITE_DEBUG
+ {
+ int ii;
+ for(ii=1; ii<pT->nMap; ii++){
+ Fts5TokenDataMap *p1 = &pT->aMap[ii-1];
+ Fts5TokenDataMap *p2 = &pT->aMap[ii];
+ assert( p1->iRowid<p2->iRowid
+ || (p1->iRowid==p2->iRowid && p1->iPos<=p2->iPos)
+ );
+ }
+ }
+#endif
+ }
+}
+
+/*
+** Delete an Fts5TokenDataIter structure and its contents.
+*/
+static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
+ if( pSet ){
+ int ii;
+ for(ii=0; ii<pSet->nIter; ii++){
+ fts5MultiIterFree(pSet->apIter[ii]);
+ }
+ fts5BufferFree(&pSet->terms);
+ sqlite3_free(pSet->aPoslistReader);
+ sqlite3_free(pSet->aMap);
+ sqlite3_free(pSet);
+ }
+}
+
+
+/*
+** fts5VisitEntries() context object used by fts5SetupPrefixIterTokendata()
+** to pass data to prefixIterSetupTokendataCb().
+*/
+typedef struct TokendataSetupCtx TokendataSetupCtx;
+struct TokendataSetupCtx {
+ Fts5TokenDataIter *pT; /* Object being populated with mappings */
+ int iTermOff; /* Offset of current term in terms.p[] */
+ int nTermByte; /* Size of current term in bytes */
+};
+
+/*
+** fts5VisitEntries() callback used by fts5SetupPrefixIterTokendata(). This
+** callback adds an entry to the Fts5TokenDataIter.aMap[] array for each
+** position in the current position-list. It doesn't matter that some of
+** these may be out of order - they will be sorted later.
+*/
+static void prefixIterSetupTokendataCb(
+ Fts5Index *p,
+ void *pCtx,
+ Fts5Iter *p1,
+ const u8 *pNew,
+ int nNew
+){
+ TokendataSetupCtx *pSetup = (TokendataSetupCtx*)pCtx;
+ int iPosOff = 0;
+ i64 iPos = 0;
+
+ if( pNew ){
+ pSetup->nTermByte = nNew-1;
+ pSetup->iTermOff = pSetup->pT->terms.n;
+ fts5BufferAppendBlob(&p->rc, &pSetup->pT->terms, nNew-1, pNew+1);
+ }
+
+ while( 0==sqlite3Fts5PoslistNext64(
+ p1->base.pData, p1->base.nData, &iPosOff, &iPos
+ ) ){
+ fts5TokendataIterAppendMap(p,
+ pSetup->pT, pSetup->iTermOff, pSetup->nTermByte, p1->base.iRowid, iPos
+ );
+ }
+}
+
+
+/*
+** Context object passed by fts5SetupPrefixIter() to fts5VisitEntries().
+*/
+typedef struct PrefixSetupCtx PrefixSetupCtx;
+struct PrefixSetupCtx {
+ void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
+ void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
+ i64 iLastRowid;
+ int nMerge;
+ Fts5Buffer *aBuf;
+ int nBuf;
+ Fts5Buffer doclist;
+ TokendataSetupCtx *pTokendata;
+};
+
+/*
+** fts5VisitEntries() callback used by fts5SetupPrefixIter()
+*/
+static void prefixIterSetupCb(
+ Fts5Index *p,
+ void *pCtx,
+ Fts5Iter *p1,
+ const u8 *pNew,
+ int nNew
+){
+ PrefixSetupCtx *pSetup = (PrefixSetupCtx*)pCtx;
+ const int nMerge = pSetup->nMerge;
+
+ if( p1->base.nData>0 ){
+ if( p1->base.iRowid<=pSetup->iLastRowid && pSetup->doclist.n>0 ){
+ int i;
+ for(i=0; p->rc==SQLITE_OK && pSetup->doclist.n; i++){
+ int i1 = i*nMerge;
+ int iStore;
+ assert( i1+nMerge<=pSetup->nBuf );
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
+ if( pSetup->aBuf[iStore].n==0 ){
+ fts5BufferSwap(&pSetup->doclist, &pSetup->aBuf[iStore]);
+ fts5BufferZero(&pSetup->doclist);
+ break;
+ }
+ }
+ if( iStore==i1+nMerge ){
+ pSetup->xMerge(p, &pSetup->doclist, nMerge, &pSetup->aBuf[i1]);
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
+ fts5BufferZero(&pSetup->aBuf[iStore]);
+ }
+ }
+ }
+ pSetup->iLastRowid = 0;
+ }
+
+ pSetup->xAppend(
+ p, (u64)p1->base.iRowid-(u64)pSetup->iLastRowid, p1, &pSetup->doclist
+ );
+ pSetup->iLastRowid = p1->base.iRowid;
+ }
+
+ if( pSetup->pTokendata ){
+ prefixIterSetupTokendataCb(p, (void*)pSetup->pTokendata, p1, pNew, nNew);
+ }
+}
+
static void fts5SetupPrefixIter(
Fts5Index *p, /* Index to read from */
int bDesc, /* True for "ORDER BY rowid DESC" */
@@ -246730,38 +250854,41 @@ static void fts5SetupPrefixIter(
Fts5Iter **ppIter /* OUT: New iterator */
){
Fts5Structure *pStruct;
- Fts5Buffer *aBuf;
- int nBuf = 32;
- int nMerge = 1;
+ PrefixSetupCtx s;
+ TokendataSetupCtx s2;
+
+ memset(&s, 0, sizeof(s));
+ memset(&s2, 0, sizeof(s2));
+
+ s.nMerge = 1;
+ s.iLastRowid = 0;
+ s.nBuf = 32;
+ if( iIdx==0
+ && p->pConfig->eDetail==FTS5_DETAIL_FULL
+ && p->pConfig->bPrefixInsttoken
+ ){
+ s.pTokendata = &s2;
+ s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, SZ_FTS5TOKENDATAITER(1));
+ }
- void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
- void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
- xMerge = fts5MergeRowidLists;
- xAppend = fts5AppendRowid;
+ s.xMerge = fts5MergeRowidLists;
+ s.xAppend = fts5AppendRowid;
}else{
- nMerge = FTS5_MERGE_NLIST-1;
- nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
- xMerge = fts5MergePrefixLists;
- xAppend = fts5AppendPoslist;
+ s.nMerge = FTS5_MERGE_NLIST-1;
+ s.nBuf = s.nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
+ s.xMerge = fts5MergePrefixLists;
+ s.xAppend = fts5AppendPoslist;
}
- aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
+ s.aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*s.nBuf);
pStruct = fts5StructureRead(p);
- assert( p->rc!=SQLITE_OK || (aBuf && pStruct) );
+ assert( p->rc!=SQLITE_OK || (s.aBuf && pStruct) );
if( p->rc==SQLITE_OK ){
- const int flags = FTS5INDEX_QUERY_SCAN
- | FTS5INDEX_QUERY_SKIPEMPTY
- | FTS5INDEX_QUERY_NOOUTPUT;
+ void *pCtx = (void*)&s;
int i;
- i64 iLastRowid = 0;
- Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
Fts5Data *pData;
- Fts5Buffer doclist;
- int bNewTerm = 1;
-
- memset(&doclist, 0, sizeof(doclist));
/* If iIdx is non-zero, then it is the number of a prefix-index for
** prefixes 1 character longer than the prefix being queried for. That
@@ -246769,94 +250896,46 @@ static void fts5SetupPrefixIter(
** corresponding to the prefix itself. That one is extracted from the
** main term index here. */
if( iIdx!=0 ){
- int dummy = 0;
- const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
pToken[0] = FTS5_MAIN_PREFIX;
- fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
- fts5IterSetOutputCb(&p->rc, p1);
- for(;
- fts5MultiIterEof(p, p1)==0;
- fts5MultiIterNext2(p, p1, &dummy)
- ){
- Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
- p1->xSetOutputs(p1, pSeg);
- if( p1->base.nData ){
- xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
- iLastRowid = p1->base.iRowid;
- }
- }
- fts5MultiIterFree(p1);
+ fts5VisitEntries(p, pColset, pToken, nToken, 0, prefixIterSetupCb, pCtx);
}
pToken[0] = FTS5_MAIN_PREFIX + iIdx;
- fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
- fts5IterSetOutputCb(&p->rc, p1);
-
- for( /* no-op */ ;
- fts5MultiIterEof(p, p1)==0;
- fts5MultiIterNext2(p, p1, &bNewTerm)
- ){
- Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
- int nTerm = pSeg->term.n;
- const u8 *pTerm = pSeg->term.p;
- p1->xSetOutputs(p1, pSeg);
-
- assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
- if( bNewTerm ){
- if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
- }
-
- if( p1->base.nData==0 ) continue;
- if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
- for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
- int i1 = i*nMerge;
- int iStore;
- assert( i1+nMerge<=nBuf );
- for(iStore=i1; iStore<i1+nMerge; iStore++){
- if( aBuf[iStore].n==0 ){
- fts5BufferSwap(&doclist, &aBuf[iStore]);
- fts5BufferZero(&doclist);
- break;
- }
- }
- if( iStore==i1+nMerge ){
- xMerge(p, &doclist, nMerge, &aBuf[i1]);
- for(iStore=i1; iStore<i1+nMerge; iStore++){
- fts5BufferZero(&aBuf[iStore]);
- }
- }
- }
- iLastRowid = 0;
- }
+ fts5VisitEntries(p, pColset, pToken, nToken, 1, prefixIterSetupCb, pCtx);
- xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
- iLastRowid = p1->base.iRowid;
- }
-
- assert( (nBuf%nMerge)==0 );
- for(i=0; i<nBuf; i+=nMerge){
+ assert( (s.nBuf%s.nMerge)==0 );
+ for(i=0; i<s.nBuf; i+=s.nMerge){
int iFree;
if( p->rc==SQLITE_OK ){
- xMerge(p, &doclist, nMerge, &aBuf[i]);
+ s.xMerge(p, &s.doclist, s.nMerge, &s.aBuf[i]);
}
- for(iFree=i; iFree<i+nMerge; iFree++){
- fts5BufferFree(&aBuf[iFree]);
+ for(iFree=i; iFree<i+s.nMerge; iFree++){
+ fts5BufferFree(&s.aBuf[iFree]);
}
}
- fts5MultiIterFree(p1);
- pData = fts5IdxMalloc(p, sizeof(*pData)+doclist.n+FTS5_DATA_ZERO_PADDING);
+ pData = fts5IdxMalloc(p, sizeof(*pData)
+ + ((i64)s.doclist.n)+FTS5_DATA_ZERO_PADDING);
+ assert( pData!=0 || p->rc!=SQLITE_OK );
if( pData ){
pData->p = (u8*)&pData[1];
- pData->nn = pData->szLeaf = doclist.n;
- if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
+ pData->nn = pData->szLeaf = s.doclist.n;
+ if( s.doclist.n ) memcpy(pData->p, s.doclist.p, s.doclist.n);
fts5MultiIterNew2(p, pData, bDesc, ppIter);
}
- fts5BufferFree(&doclist);
+
+ assert( (*ppIter)!=0 || p->rc!=SQLITE_OK );
+ if( p->rc==SQLITE_OK && s.pTokendata ){
+ fts5TokendataIterSortMap(p, s2.pT);
+ (*ppIter)->pTokenDataIter = s2.pT;
+ s2.pT = 0;
+ }
}
+ fts5TokendataIterDelete(s2.pT);
+ fts5BufferFree(&s.doclist);
fts5StructureRelease(pStruct);
- sqlite3_free(aBuf);
+ sqlite3_free(s.aBuf);
}
@@ -246894,7 +250973,7 @@ static int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
static int sqlite3Fts5IndexSync(Fts5Index *p){
assert( p->rc==SQLITE_OK );
fts5IndexFlush(p);
- sqlite3Fts5IndexCloseReader(p);
+ fts5IndexCloseReader(p);
return fts5IndexReturn(p);
}
@@ -246905,11 +250984,10 @@ static int sqlite3Fts5IndexSync(Fts5Index *p){
** records must be invalidated.
*/
static int sqlite3Fts5IndexRollback(Fts5Index *p){
- sqlite3Fts5IndexCloseReader(p);
+ fts5IndexCloseReader(p);
fts5IndexDiscardData(p);
fts5StructureInvalidate(p);
- /* assert( p->rc==SQLITE_OK ); */
- return SQLITE_OK;
+ return fts5IndexReturn(p);
}
/*
@@ -246918,15 +250996,17 @@ static int sqlite3Fts5IndexRollback(Fts5Index *p){
** and the initial version of the "averages" record (a zero-byte blob).
*/
static int sqlite3Fts5IndexReinit(Fts5Index *p){
- Fts5Structure s;
+ Fts5Structure *pTmp;
+ u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
fts5StructureInvalidate(p);
fts5IndexDiscardData(p);
- memset(&s, 0, sizeof(Fts5Structure));
+ pTmp = (Fts5Structure*)tmpSpace;
+ memset(pTmp, 0, SZ_FTS5STRUCTURE(1));
if( p->pConfig->bContentlessDelete ){
- s.nOriginCntr = 1;
+ pTmp->nOriginCntr = 1;
}
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
- fts5StructureWrite(p, &s);
+ fts5StructureWrite(p, pTmp);
return fts5IndexReturn(p);
}
@@ -247110,37 +251190,15 @@ static void fts5SegIterSetEOF(Fts5SegIter *pSeg){
pSeg->pLeaf = 0;
}
-/*
-** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
-** array of these for each row it visits. Or, for an iterator used by an
-** "ORDER BY rank" query, it accumulates an array of these for the entire
-** query.
-**
-** Each instance in the array indicates the iterator (and therefore term)
-** associated with position iPos of rowid iRowid. This is used by the
-** xInstToken() API.
-*/
-struct Fts5TokenDataMap {
- i64 iRowid; /* Row this token is located in */
- i64 iPos; /* Position of token */
- int iIter; /* Iterator token was read from */
-};
-
-/*
-** An object used to supplement Fts5Iter for tokendata=1 iterators.
-*/
-struct Fts5TokenDataIter {
- int nIter;
- int nIterAlloc;
-
- int nMap;
- int nMapAlloc;
- Fts5TokenDataMap *aMap;
-
- Fts5PoslistReader *aPoslistReader;
- int *aPoslistToIter;
- Fts5Iter *apIter[1];
-};
+static void fts5IterClose(Fts5IndexIter *pIndexIter){
+ if( pIndexIter ){
+ Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
+ Fts5Index *pIndex = pIter->pIndex;
+ fts5TokendataIterDelete(pIter->pTokenDataIter);
+ fts5MultiIterFree(pIter);
+ fts5IndexCloseReader(pIndex);
+ }
+}
/*
** This function appends iterator pAppend to Fts5TokenDataIter pIn and
@@ -247156,7 +251214,7 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
if( p->rc==SQLITE_OK ){
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
- int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
+ int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
if( pNew==0 ){
@@ -247169,7 +251227,7 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
}
}
if( p->rc ){
- sqlite3Fts5IterClose((Fts5IndexIter*)pAppend);
+ fts5IterClose((Fts5IndexIter*)pAppend);
}else{
pRet->apIter[pRet->nIter++] = pAppend;
}
@@ -247179,54 +251237,6 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
}
/*
-** Delete an Fts5TokenDataIter structure and its contents.
-*/
-static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
- if( pSet ){
- int ii;
- for(ii=0; ii<pSet->nIter; ii++){
- fts5MultiIterFree(pSet->apIter[ii]);
- }
- sqlite3_free(pSet->aPoslistReader);
- sqlite3_free(pSet->aMap);
- sqlite3_free(pSet);
- }
-}
-
-/*
-** Append a mapping to the token-map belonging to object pT.
-*/
-static void fts5TokendataIterAppendMap(
- Fts5Index *p,
- Fts5TokenDataIter *pT,
- int iIter,
- i64 iRowid,
- i64 iPos
-){
- if( p->rc==SQLITE_OK ){
- if( pT->nMap==pT->nMapAlloc ){
- int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
- int nByte = nNew * sizeof(Fts5TokenDataMap);
- Fts5TokenDataMap *aNew;
-
- aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nByte);
- if( aNew==0 ){
- p->rc = SQLITE_NOMEM;
- return;
- }
-
- pT->aMap = aNew;
- pT->nMapAlloc = nNew;
- }
-
- pT->aMap[pT->nMap].iRowid = iRowid;
- pT->aMap[pT->nMap].iPos = iPos;
- pT->aMap[pT->nMap].iIter = iIter;
- pT->nMap++;
- }
-}
-
-/*
** The iterator passed as the only argument must be a tokendata=1 iterator
** (pIter->pTokenDataIter!=0). This function sets the iterator output
** variables (pIter->base.*) according to the contents of the current
@@ -247266,7 +251276,7 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
pIter->base.iRowid = iRowid;
if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){
- fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, iRowid, -1);
+ fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, 0, iRowid, -1);
}else
if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){
int nReader = 0;
@@ -247430,7 +251440,7 @@ static Fts5Iter *fts5SetupTokendataIter(
fts5BufferSet(&p->rc, &bSeek, nToken, pToken);
}
if( p->rc ){
- sqlite3Fts5IterClose((Fts5IndexIter*)pNew);
+ fts5IterClose((Fts5IndexIter*)pNew);
break;
}
@@ -247495,7 +251505,7 @@ static Fts5Iter *fts5SetupTokendataIter(
** not point to any terms that match the query. So delete it and break
** out of the loop - all required iterators have been collected. */
if( pSmall==0 ){
- sqlite3Fts5IterClose((Fts5IndexIter*)pNew);
+ fts5IterClose((Fts5IndexIter*)pNew);
break;
}
@@ -247519,6 +251529,7 @@ static Fts5Iter *fts5SetupTokendataIter(
pRet = fts5MultiIterAlloc(p, 0);
}
if( pRet ){
+ pRet->nSeg = 0;
pRet->pTokenDataIter = pSet;
if( pSet ){
fts5IterSetOutputsTokendata(pRet);
@@ -247534,7 +251545,6 @@ static Fts5Iter *fts5SetupTokendataIter(
return pRet;
}
-
/*
** Open a new iterator to iterate though all rowid that match the
** specified token or token prefix.
@@ -247557,8 +251567,14 @@ static int sqlite3Fts5IndexQuery(
int iIdx = 0; /* Index to search */
int iPrefixIdx = 0; /* +1 prefix index */
int bTokendata = pConfig->bTokendata;
+ assert( buf.p!=0 );
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
+ /* The NOTOKENDATA flag is set when each token in a tokendata=1 table
+ ** should be treated individually, instead of merging all those with
+ ** a common prefix into a single entry. This is used, for example, by
+ ** queries performed as part of an integrity-check, or by the fts5vocab
+ ** module. */
if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
bTokendata = 0;
}
@@ -247589,7 +251605,7 @@ static int sqlite3Fts5IndexQuery(
}
if( bTokendata && iIdx==0 ){
- buf.p[0] = '0';
+ buf.p[0] = FTS5_MAIN_PREFIX;
pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset);
}else if( iIdx<=pConfig->nPrefix ){
/* Straight index lookup */
@@ -247602,7 +251618,7 @@ static int sqlite3Fts5IndexQuery(
fts5StructureRelease(pStruct);
}
}else{
- /* Scan multiple terms in the main index */
+ /* Scan multiple terms in the main index for a prefix query. */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
if( pRet==0 ){
@@ -247618,9 +251634,9 @@ static int sqlite3Fts5IndexQuery(
}
if( p->rc ){
- sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
+ fts5IterClose((Fts5IndexIter*)pRet);
pRet = 0;
- sqlite3Fts5IndexCloseReader(p);
+ fts5IndexCloseReader(p);
}
*ppIter = (Fts5IndexIter*)pRet;
@@ -247638,7 +251654,8 @@ static int sqlite3Fts5IndexQuery(
static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
assert( pIter->pIndex->rc==SQLITE_OK );
- if( pIter->pTokenDataIter ){
+ if( pIter->nSeg==0 ){
+ assert( pIter->pTokenDataIter );
fts5TokendataIterNext(pIter, 0, 0);
}else{
fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
@@ -247675,7 +251692,8 @@ static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){
*/
static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- if( pIter->pTokenDataIter ){
+ if( pIter->nSeg==0 ){
+ assert( pIter->pTokenDataIter );
fts5TokendataIterNext(pIter, 1, iMatch);
}else{
fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
@@ -247695,13 +251713,61 @@ static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
}
/*
+** pIter is a prefix query. This function populates pIter->pTokenDataIter
+** with an Fts5TokenDataIter object containing mappings for all rows
+** matched by the query.
+*/
+static int fts5SetupPrefixIterTokendata(
+ Fts5Iter *pIter,
+ const char *pToken, /* Token prefix to search for */
+ int nToken /* Size of pToken in bytes */
+){
+ Fts5Index *p = pIter->pIndex;
+ Fts5Buffer token = {0, 0, 0};
+ TokendataSetupCtx ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
+
+ fts5BufferGrow(&p->rc, &token, nToken+1);
+ assert( token.p!=0 || p->rc!=SQLITE_OK );
+ ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
+ SZ_FTS5TOKENDATAITER(1));
+
+ if( p->rc==SQLITE_OK ){
+
+ /* Fill in the token prefix to search for */
+ token.p[0] = FTS5_MAIN_PREFIX;
+ memcpy(&token.p[1], pToken, nToken);
+ token.n = nToken+1;
+
+ fts5VisitEntries(
+ p, 0, token.p, token.n, 1, prefixIterSetupTokendataCb, (void*)&ctx
+ );
+
+ fts5TokendataIterSortMap(p, ctx.pT);
+ }
+
+ if( p->rc==SQLITE_OK ){
+ pIter->pTokenDataIter = ctx.pT;
+ }else{
+ fts5TokendataIterDelete(ctx.pT);
+ }
+ fts5BufferFree(&token);
+
+ return fts5IndexReturn(p);
+}
+
+/*
** This is used by xInstToken() to access the token at offset iOff, column
** iCol of row iRowid. The token is returned via output variables *ppOut
** and *pnOut. The iterator passed as the first argument must be a tokendata=1
** iterator (pIter->pTokenDataIter!=0).
+**
+** pToken/nToken:
*/
static int sqlite3Fts5IterToken(
Fts5IndexIter *pIndexIter,
+ const char *pToken, int nToken,
i64 iRowid,
int iCol,
int iOff,
@@ -247709,13 +251775,22 @@ static int sqlite3Fts5IterToken(
){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
- Fts5TokenDataMap *aMap = pT->aMap;
i64 iPos = (((i64)iCol)<<32) + iOff;
-
+ Fts5TokenDataMap *aMap = 0;
int i1 = 0;
- int i2 = pT->nMap;
+ int i2 = 0;
int iTest = 0;
+ assert( pT || (pToken && pIter->nSeg>0) );
+ if( pT==0 ){
+ int rc = fts5SetupPrefixIterTokendata(pIter, pToken, nToken);
+ if( rc!=SQLITE_OK ) return rc;
+ pT = pIter->pTokenDataIter;
+ }
+
+ i2 = pT->nMap;
+ aMap = pT->aMap;
+
while( i2>i1 ){
iTest = (i1 + i2) / 2;
@@ -247738,9 +251813,15 @@ static int sqlite3Fts5IterToken(
}
if( i2>i1 ){
- Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
- *ppOut = (const char*)pMap->aSeg[0].term.p+1;
- *pnOut = pMap->aSeg[0].term.n-1;
+ if( pIter->nSeg==0 ){
+ Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
+ *ppOut = (const char*)pMap->aSeg[0].term.p+1;
+ *pnOut = pMap->aSeg[0].term.n-1;
+ }else{
+ Fts5TokenDataMap *p = &aMap[iTest];
+ *ppOut = (const char*)&pT->terms.p[p->iIter];
+ *pnOut = aMap[iTest].nByte;
+ }
}
return SQLITE_OK;
@@ -247752,7 +251833,9 @@ static int sqlite3Fts5IterToken(
*/
static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- if( pIter && pIter->pTokenDataIter ){
+ if( pIter && pIter->pTokenDataIter
+ && (pIter->nSeg==0 || pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_FULL)
+ ){
pIter->pTokenDataIter->nMap = 0;
}
}
@@ -247772,17 +251855,30 @@ static int sqlite3Fts5IndexIterWriteTokendata(
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
Fts5Index *p = pIter->pIndex;
- int ii;
+ i64 iPos = (((i64)iCol)<<32) + iOff;
assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
- assert( pIter->pTokenDataIter );
-
- for(ii=0; ii<pT->nIter; ii++){
- Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
- if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
- }
- if( ii<pT->nIter ){
- fts5TokendataIterAppendMap(p, pT, ii, iRowid, (((i64)iCol)<<32) + iOff);
+ assert( pIter->pTokenDataIter || pIter->nSeg>0 );
+ if( pIter->nSeg>0 ){
+ /* This is a prefix term iterator. */
+ if( pT==0 ){
+ pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
+ SZ_FTS5TOKENDATAITER(1));
+ pIter->pTokenDataIter = pT;
+ }
+ if( pT ){
+ fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
+ fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
+ }
+ }else{
+ int ii;
+ for(ii=0; ii<pT->nIter; ii++){
+ Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
+ if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
+ }
+ if( ii<pT->nIter ){
+ fts5TokendataIterAppendMap(p, pT, ii, 0, iRowid, iPos);
+ }
}
return fts5IndexReturn(p);
}
@@ -247792,11 +251888,9 @@ static int sqlite3Fts5IndexIterWriteTokendata(
*/
static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
if( pIndexIter ){
- Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- Fts5Index *pIndex = pIter->pIndex;
- fts5TokendataIterDelete(pIter->pTokenDataIter);
- fts5MultiIterFree(pIter);
- sqlite3Fts5IndexCloseReader(pIndex);
+ Fts5Index *pIndex = ((Fts5Iter*)pIndexIter)->pIndex;
+ fts5IterClose(pIndexIter);
+ fts5IndexReturn(pIndex);
}
}
@@ -248326,7 +252420,7 @@ static int fts5QueryCksum(
rc = sqlite3Fts5IterNext(pIter);
}
}
- sqlite3Fts5IterClose(pIter);
+ fts5IterClose(pIter);
*pCksum = cksum;
return rc;
@@ -248803,7 +252897,7 @@ static void fts5DecodeRowid(
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
- int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */
+ int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid components */
fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
if( iSegid==0 ){
@@ -249049,7 +253143,7 @@ static void fts5DecodeFunction(
** buffer overreads even if the record is corrupt. */
n = sqlite3_value_bytes(apVal[1]);
aBlob = sqlite3_value_blob(apVal[1]);
- nSpace = n + FTS5_DATA_ZERO_PADDING;
+ nSpace = ((i64)n) + FTS5_DATA_ZERO_PADDING;
a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
if( a==0 ) goto decode_out;
if( n>0 ) memcpy(a, aBlob, n);
@@ -249335,7 +253429,7 @@ static int fts5structConnectMethod(
/*
** We must have a single struct=? constraint that will be passed through
-** into the xFilter method. If there is no valid stmt=? constraint,
+** into the xFilter method. If there is no valid struct=? constraint,
** then return an SQLITE_CONSTRAINT error.
*/
static int fts5structBestIndexMethod(
@@ -249677,9 +253771,19 @@ struct Fts5Global {
Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */
Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */
Fts5Cursor *pCsr; /* First in list of all open cursors */
+ u32 aLocaleHdr[4];
};
/*
+** Size of header on fts5_locale() values. And macro to access a buffer
+** containing a copy of the header from an Fts5Config pointer.
+*/
+#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
+#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
+
+#define FTS5_INSTTOKEN_SUBTYPE 73
+
+/*
** Each auxiliary function registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pAux list.
@@ -249697,11 +253801,28 @@ struct Fts5Auxiliary {
** Each tokenizer module registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pTok list.
+**
+** bV2Native:
+** True if the tokenizer was registered using xCreateTokenizer_v2(), false
+** for xCreateTokenizer(). If this variable is true, then x2 is populated
+** with the routines as supplied by the caller and x1 contains synthesized
+** wrapper routines. In this case the user-data pointer passed to
+** x1.xCreate should be a pointer to the Fts5TokenizerModule structure,
+** not a copy of pUserData.
+**
+** Of course, if bV2Native is false, then x1 contains the real routines and
+** x2 the synthesized ones. In this case a pointer to the Fts5TokenizerModule
+** object should be passed to x2.xCreate.
+**
+** The synthesized wrapper routines are necessary for xFindTokenizer(_v2)
+** calls.
*/
struct Fts5TokenizerModule {
char *zName; /* Name of tokenizer */
void *pUserData; /* User pointer passed to xCreate() */
- fts5_tokenizer x; /* Tokenizer functions */
+ int bV2Native; /* True if v2 native tokenizer */
+ fts5_tokenizer x1; /* Tokenizer functions */
+ fts5_tokenizer_v2 x2; /* V2 tokenizer functions */
void (*xDestroy)(void*); /* Destructor function */
Fts5TokenizerModule *pNext; /* Next registered tokenizer module */
};
@@ -249737,9 +253858,11 @@ struct Fts5Sorter {
i64 iRowid; /* Current rowid */
const u8 *aPoslist; /* Position lists for current row */
int nIdx; /* Number of entries in aIdx[] */
- int aIdx[1]; /* Offsets into aPoslist for current row */
+ int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */
};
+/* Size (int bytes) of an Fts5Sorter object with N indexes */
+#define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64))
/*
** Virtual-table cursor object.
@@ -249789,7 +253912,7 @@ struct Fts5Cursor {
Fts5Auxiliary *pAux; /* Currently executing extension function */
Fts5Auxdata *pAuxdata; /* First in linked list of saved aux-data */
- /* Cache used by auxiliary functions xInst() and xInstCount() */
+ /* Cache used by auxiliary API functions xInst() and xInstCount() */
Fts5PoslistReader *aInstIter; /* One for each phrase */
int nInstAlloc; /* Size of aInst[] array (entries / 3) */
int nInstCount; /* Number of phrase instances */
@@ -249900,10 +254023,16 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
#endif
/*
-** Return true if pTab is a contentless table.
+** Return true if pTab is a contentless table. If parameter bIncludeUnindexed
+** is true, this includes contentless tables that store UNINDEXED columns
+** only.
*/
-static int fts5IsContentless(Fts5FullTable *pTab){
- return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
+static int fts5IsContentless(Fts5FullTable *pTab, int bIncludeUnindexed){
+ int eContent = pTab->p.pConfig->eContent;
+ return (
+ eContent==FTS5_CONTENT_NONE
+ || (bIncludeUnindexed && eContent==FTS5_CONTENT_UNINDEXED)
+ );
}
/*
@@ -249971,8 +254100,12 @@ static int fts5InitVtab(
assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
}
if( rc==SQLITE_OK ){
+ pConfig->pzErrmsg = pzErr;
pTab->p.pConfig = pConfig;
pTab->pGlobal = pGlobal;
+ if( bCreate || sqlite3Fts5TokenizerPreload(&pConfig->t) ){
+ rc = sqlite3Fts5LoadTokenizer(pConfig);
+ }
}
/* Open the index sub-system */
@@ -249994,11 +254127,7 @@ static int fts5InitVtab(
/* Load the initial configuration */
if( rc==SQLITE_OK ){
- assert( pConfig->pzErrmsg==0 );
- pConfig->pzErrmsg = pzErr;
- rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
- sqlite3Fts5IndexRollback(pTab->p.pIndex);
- pConfig->pzErrmsg = 0;
+ rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie-1);
}
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
@@ -250008,6 +254137,7 @@ static int fts5InitVtab(
rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
}
+ if( pConfig ) pConfig->pzErrmsg = 0;
if( rc!=SQLITE_OK ){
fts5FreeVtab(pTab);
pTab = 0;
@@ -250075,10 +254205,10 @@ static int fts5UsePatternMatch(
){
assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
- if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
+ if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
return 1;
}
- if( pConfig->ePattern==FTS5_PATTERN_LIKE
+ if( pConfig->t.ePattern==FTS5_PATTERN_LIKE
&& (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
){
return 1;
@@ -250125,10 +254255,10 @@ static int fts5UsePatternMatch(
** This function ensures that there is at most one "r" or "=". And that if
** there exists an "=" then there is no "<" or ">".
**
-** Costs are assigned as follows:
+** If an unusable MATCH operator is present in the WHERE clause, then
+** SQLITE_CONSTRAINT is returned.
**
-** a) If an unusable MATCH operator is present in the WHERE clause, the
-** cost is unconditionally set to 1e50 (a really big number).
+** Costs are assigned as follows:
**
** a) If a MATCH operator is present, the cost depends on the other
** constraints also present. As follows:
@@ -250161,7 +254291,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
int bSeenEq = 0;
int bSeenGt = 0;
int bSeenLt = 0;
- int bSeenMatch = 0;
+ int nSeenMatch = 0;
int bSeenRank = 0;
@@ -250192,18 +254322,16 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
/* A MATCH operator or equivalent */
if( p->usable==0 || iCol<0 ){
/* As there exists an unusable MATCH constraint this is an
- ** unusable plan. Set a prohibitively high cost. */
- pInfo->estimatedCost = 1e50;
- assert( iIdxStr < pInfo->nConstraint*6 + 1 );
+ ** unusable plan. Return SQLITE_CONSTRAINT. */
idxStr[iIdxStr] = 0;
- return SQLITE_OK;
+ return SQLITE_CONSTRAINT;
}else{
if( iCol==nCol+1 ){
if( bSeenRank ) continue;
idxStr[iIdxStr++] = 'r';
bSeenRank = 1;
- }else if( iCol>=0 ){
- bSeenMatch = 1;
+ }else{
+ nSeenMatch++;
idxStr[iIdxStr++] = 'M';
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
idxStr += strlen(&idxStr[iIdxStr]);
@@ -250220,6 +254348,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
idxStr += strlen(&idxStr[iIdxStr]);
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
assert( idxStr[iIdxStr]=='\0' );
+ nSeenMatch++;
}else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
idxStr[iIdxStr++] = '=';
bSeenEq = 1;
@@ -250256,7 +254385,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
*/
if( pInfo->nOrderBy==1 ){
int iSort = pInfo->aOrderBy[0].iColumn;
- if( iSort==(pConfig->nCol+1) && bSeenMatch ){
+ if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){
idxFlags |= FTS5_BI_ORDER_RANK;
}else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
idxFlags |= FTS5_BI_ORDER_ROWID;
@@ -250271,14 +254400,17 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
/* Calculate the estimated cost based on the flags set in idxFlags. */
if( bSeenEq ){
- pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
- if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
+ pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
+ if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
}else if( bSeenLt && bSeenGt ){
- pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
+ pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
}else if( bSeenLt || bSeenGt ){
- pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
+ pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
}else{
- pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
+ pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
+ }
+ for(i=1; i<nSeenMatch; i++){
+ pInfo->estimatedCost *= 0.4;
}
pInfo->idxNum = idxFlags;
@@ -250554,6 +254686,7 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
}
}else{
rc = SQLITE_OK;
+ CsrFlagSet(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
}
break;
}
@@ -250583,7 +254716,7 @@ static int fts5PrepareStatement(
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &pRet, 0);
if( rc!=SQLITE_OK ){
- *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
+ sqlite3Fts5ConfigErrmsg(pConfig, "%s", sqlite3_errmsg(pConfig->db));
}
sqlite3_free(zSql);
}
@@ -250607,7 +254740,7 @@ static int fts5CursorFirstSorted(
const char *zRankArgs = pCsr->zRankArgs;
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
- nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
+ nByte = SZ_FTS5SORTER(nPhrase);
pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
if( pSorter==0 ) return SQLITE_NOMEM;
memset(pSorter, 0, (size_t)nByte);
@@ -250808,6 +254941,145 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
}
/*
+** Set the error message on the virtual table passed as the first argument.
+*/
+static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
+ va_list ap; /* ... printf arguments */
+ va_start(ap, zFormat);
+ sqlite3_free(p->p.base.zErrMsg);
+ p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+}
+
+/*
+** Arrange for subsequent calls to sqlite3Fts5Tokenize() to use the locale
+** specified by pLocale/nLocale. The buffer indicated by pLocale must remain
+** valid until after the final call to sqlite3Fts5Tokenize() that will use
+** the locale.
+*/
+static void sqlite3Fts5SetLocale(
+ Fts5Config *pConfig,
+ const char *zLocale,
+ int nLocale
+){
+ Fts5TokenizerConfig *pT = &pConfig->t;
+ pT->pLocale = zLocale;
+ pT->nLocale = nLocale;
+}
+
+/*
+** Clear any locale configured by an earlier call to sqlite3Fts5SetLocale().
+*/
+static void sqlite3Fts5ClearLocale(Fts5Config *pConfig){
+ sqlite3Fts5SetLocale(pConfig, 0, 0);
+}
+
+/*
+** Return true if the value passed as the only argument is an
+** fts5_locale() value.
+*/
+static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal){
+ int ret = 0;
+ if( sqlite3_value_type(pVal)==SQLITE_BLOB ){
+ /* Call sqlite3_value_bytes() after sqlite3_value_blob() in this case.
+ ** If the blob was created using zeroblob(), then sqlite3_value_blob()
+ ** may call malloc(). If this malloc() fails, then the values returned
+ ** by both value_blob() and value_bytes() will be 0. If value_bytes() were
+ ** called first, then the NULL pointer returned by value_blob() might
+ ** be dereferenced. */
+ const u8 *pBlob = sqlite3_value_blob(pVal);
+ int nBlob = sqlite3_value_bytes(pVal);
+ if( nBlob>FTS5_LOCALE_HDR_SIZE
+ && 0==memcmp(pBlob, FTS5_LOCALE_HDR(pConfig), FTS5_LOCALE_HDR_SIZE)
+ ){
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+/*
+** Value pVal is guaranteed to be an fts5_locale() value, according to
+** sqlite3Fts5IsLocaleValue(). This function extracts the text and locale
+** from the value and returns them separately.
+**
+** If successful, SQLITE_OK is returned and (*ppText) and (*ppLoc) set
+** to point to buffers containing the text and locale, as utf-8,
+** respectively. In this case output parameters (*pnText) and (*pnLoc) are
+** set to the sizes in bytes of these two buffers.
+**
+** Or, if an error occurs, then an SQLite error code is returned. The final
+** value of the four output parameters is undefined in this case.
+*/
+static int sqlite3Fts5DecodeLocaleValue(
+ sqlite3_value *pVal,
+ const char **ppText,
+ int *pnText,
+ const char **ppLoc,
+ int *pnLoc
+){
+ const char *p = sqlite3_value_blob(pVal);
+ int n = sqlite3_value_bytes(pVal);
+ int nLoc = 0;
+
+ assert( sqlite3_value_type(pVal)==SQLITE_BLOB );
+ assert( n>FTS5_LOCALE_HDR_SIZE );
+
+ for(nLoc=FTS5_LOCALE_HDR_SIZE; p[nLoc]; nLoc++){
+ if( nLoc==(n-1) ){
+ return SQLITE_MISMATCH;
+ }
+ }
+ *ppLoc = &p[FTS5_LOCALE_HDR_SIZE];
+ *pnLoc = nLoc - FTS5_LOCALE_HDR_SIZE;
+
+ *ppText = &p[nLoc+1];
+ *pnText = n - nLoc - 1;
+ return SQLITE_OK;
+}
+
+/*
+** Argument pVal is the text of a full-text search expression. It may or
+** may not have been wrapped by fts5_locale(). This function extracts
+** the text of the expression, and sets output variable (*pzText) to
+** point to a nul-terminated buffer containing the expression.
+**
+** If pVal was an fts5_locale() value, then sqlite3Fts5SetLocale() is called
+** to set the tokenizer to use the specified locale.
+**
+** If output variable (*pbFreeAndReset) is set to true, then the caller
+** is required to (a) call sqlite3Fts5ClearLocale() to reset the tokenizer
+** locale, and (b) call sqlite3_free() to free (*pzText).
+*/
+static int fts5ExtractExprText(
+ Fts5Config *pConfig, /* Fts5 configuration */
+ sqlite3_value *pVal, /* Value to extract expression text from */
+ char **pzText, /* OUT: nul-terminated buffer of text */
+ int *pbFreeAndReset /* OUT: Free (*pzText) and clear locale */
+){
+ int rc = SQLITE_OK;
+
+ if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+ const char *pText = 0;
+ int nText = 0;
+ const char *pLoc = 0;
+ int nLoc = 0;
+ rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+ *pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, pText);
+ if( rc==SQLITE_OK ){
+ sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+ }
+ *pbFreeAndReset = 1;
+ }else{
+ *pzText = (char*)sqlite3_value_text(pVal);
+ *pbFreeAndReset = 0;
+ }
+
+ return rc;
+}
+
+
+/*
** This is the xFilter interface for the virtual table. See
** the virtual table xFilter method documentation for additional
** information.
@@ -250837,17 +255109,12 @@ static int fts5FilterMethod(
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
int iCol; /* Column on LHS of MATCH operator */
char **pzErrmsg = pConfig->pzErrmsg;
+ int bPrefixInsttoken = pConfig->bPrefixInsttoken;
int i;
int iIdxStr = 0;
Fts5Expr *pExpr = 0;
- if( pConfig->bLock ){
- pTab->p.base.zErrMsg = sqlite3_mprintf(
- "recursively defined fts5 content table"
- );
- return SQLITE_ERROR;
- }
-
+ assert( pConfig->bLock==0 );
if( pCsr->ePlan ){
fts5FreeCursorComponents(pCsr);
memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
@@ -250871,8 +255138,17 @@ static int fts5FilterMethod(
pRank = apVal[i];
break;
case 'M': {
- const char *zText = (const char*)sqlite3_value_text(apVal[i]);
+ char *zText = 0;
+ int bFreeAndReset = 0;
+ int bInternal = 0;
+
+ rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
+ if( rc!=SQLITE_OK ) goto filter_out;
if( zText==0 ) zText = "";
+ if( sqlite3_value_subtype(apVal[i])==FTS5_INSTTOKEN_SUBTYPE ){
+ pConfig->bPrefixInsttoken = 1;
+ }
+
iCol = 0;
do{
iCol = iCol*10 + (idxStr[iIdxStr]-'0');
@@ -250884,7 +255160,7 @@ static int fts5FilterMethod(
** indicates that the MATCH expression is not a full text query,
** but a request for an internal parameter. */
rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
- goto filter_out;
+ bInternal = 1;
}else{
char **pzErr = &pTab->p.base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
@@ -250892,9 +255168,15 @@ static int fts5FilterMethod(
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
pExpr = 0;
}
- if( rc!=SQLITE_OK ) goto filter_out;
}
+ if( bFreeAndReset ){
+ sqlite3_free(zText);
+ sqlite3Fts5ClearLocale(pConfig);
+ }
+
+ if( bInternal || rc!=SQLITE_OK ) goto filter_out;
+
break;
}
case 'L':
@@ -250982,9 +255264,7 @@ static int fts5FilterMethod(
}
}
}else if( pConfig->zContent==0 ){
- *pConfig->pzErrmsg = sqlite3_mprintf(
- "%s: table does not support scanning", pConfig->zName
- );
+ fts5SetVtabError(pTab,"%s: table does not support scanning",pConfig->zName);
rc = SQLITE_ERROR;
}else{
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
@@ -251008,6 +255288,7 @@ static int fts5FilterMethod(
filter_out:
sqlite3Fts5ExprFree(pExpr);
pConfig->pzErrmsg = pzErrmsg;
+ pConfig->bPrefixInsttoken = bPrefixInsttoken;
return rc;
}
@@ -251027,9 +255308,13 @@ static i64 fts5CursorRowid(Fts5Cursor *pCsr){
assert( pCsr->ePlan==FTS5_PLAN_MATCH
|| pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
|| pCsr->ePlan==FTS5_PLAN_SOURCE
+ || pCsr->ePlan==FTS5_PLAN_SCAN
+ || pCsr->ePlan==FTS5_PLAN_ROWID
);
if( pCsr->pSorter ){
return pCsr->pSorter->iRowid;
+ }else if( pCsr->ePlan>=FTS5_PLAN_SCAN ){
+ return sqlite3_column_int64(pCsr->pStmt, 0);
}else{
return sqlite3Fts5ExprRowid(pCsr->pExpr);
}
@@ -251046,25 +255331,16 @@ static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
int ePlan = pCsr->ePlan;
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
- switch( ePlan ){
- case FTS5_PLAN_SPECIAL:
- *pRowid = 0;
- break;
-
- case FTS5_PLAN_SOURCE:
- case FTS5_PLAN_MATCH:
- case FTS5_PLAN_SORTED_MATCH:
- *pRowid = fts5CursorRowid(pCsr);
- break;
-
- default:
- *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
- break;
+ if( ePlan==FTS5_PLAN_SPECIAL ){
+ *pRowid = 0;
+ }else{
+ *pRowid = fts5CursorRowid(pCsr);
}
return SQLITE_OK;
}
+
/*
** If the cursor requires seeking (bSeekRequired flag is set), seek it.
** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise.
@@ -251101,8 +255377,13 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK ){
rc = FTS5_CORRUPT;
+ fts5SetVtabError((Fts5FullTable*)pTab,
+ "fts5: missing row %lld from content table %s",
+ fts5CursorRowid(pCsr),
+ pTab->pConfig->zContent
+ );
}else if( pTab->pConfig->pzErrmsg ){
- *pTab->pConfig->pzErrmsg = sqlite3_mprintf(
+ fts5SetVtabError((Fts5FullTable*)pTab,
"%s", sqlite3_errmsg(pTab->pConfig->db)
);
}
@@ -251111,14 +255392,6 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
return rc;
}
-static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
- va_list ap; /* ... printf arguments */
- va_start(ap, zFormat);
- assert( p->p.base.zErrMsg==0 );
- p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
-}
-
/*
** This function is called to handle an FTS INSERT command. In other words,
** an INSERT statement of the form:
@@ -251156,7 +255429,7 @@ static int fts5SpecialInsert(
}
bLoadConfig = 1;
}else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
- if( pConfig->eContent==FTS5_CONTENT_NONE ){
+ if( fts5IsContentless(pTab, 1) ){
fts5SetVtabError(pTab,
"'rebuild' may not be used with a contentless fts5 table"
);
@@ -251212,7 +255485,7 @@ static int fts5SpecialDelete(
int eType1 = sqlite3_value_type(apVal[1]);
if( eType1==SQLITE_INTEGER ){
sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]);
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2], 0);
}
return rc;
}
@@ -251225,7 +255498,7 @@ static void fts5StorageInsert(
){
int rc = *pRc;
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
+ rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, 0, apVal, piRowid);
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
@@ -251234,6 +255507,67 @@ static void fts5StorageInsert(
}
/*
+**
+** This function is called when the user attempts an UPDATE on a contentless
+** table. Parameter bRowidModified is true if the UPDATE statement modifies
+** the rowid value. Parameter apVal[] contains the new values for each user
+** defined column of the fts5 table. pConfig is the configuration object of the
+** table being updated (guaranteed to be contentless). The contentless_delete=1
+** and contentless_unindexed=1 options may or may not be set.
+**
+** This function returns SQLITE_OK if the UPDATE can go ahead, or an SQLite
+** error code if it cannot. In this case an error message is also loaded into
+** pConfig. Output parameter (*pbContent) is set to true if the caller should
+** update the %_content table only - not the FTS index or any other shadow
+** table. This occurs when an UPDATE modifies only UNINDEXED columns of the
+** table.
+**
+** An UPDATE may proceed if:
+**
+** * The only columns modified are UNINDEXED columns, or
+**
+** * The contentless_delete=1 option was specified and all of the indexed
+** columns (not a subset) have been modified.
+*/
+static int fts5ContentlessUpdate(
+ Fts5Config *pConfig,
+ sqlite3_value **apVal,
+ int bRowidModified,
+ int *pbContent
+){
+ int ii;
+ int bSeenIndex = 0; /* Have seen modified indexed column */
+ int bSeenIndexNC = 0; /* Have seen unmodified indexed column */
+ int rc = SQLITE_OK;
+
+ for(ii=0; ii<pConfig->nCol; ii++){
+ if( pConfig->abUnindexed[ii]==0 ){
+ if( sqlite3_value_nochange(apVal[ii]) ){
+ bSeenIndexNC++;
+ }else{
+ bSeenIndex++;
+ }
+ }
+ }
+
+ if( bSeenIndex==0 && bRowidModified==0 ){
+ *pbContent = 1;
+ }else{
+ if( bSeenIndexNC || pConfig->bContentlessDelete==0 ){
+ rc = SQLITE_ERROR;
+ sqlite3Fts5ConfigErrmsg(pConfig,
+ (pConfig->bContentlessDelete ?
+ "%s a subset of columns on fts5 contentless-delete table: %s" :
+ "%s contentless fts5 table: %s")
+ , "cannot UPDATE", pConfig->zName
+ );
+ }
+ }
+
+ return rc;
+}
+
+/*
** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
** inserted, updated or deleted.
@@ -251257,7 +255591,6 @@ static int fts5UpdateMethod(
Fts5Config *pConfig = pTab->p.pConfig;
int eType0; /* value_type() of apVal[0] */
int rc = SQLITE_OK; /* Return code */
- int bUpdateOrDelete = 0;
/* A transaction must be open when this is called. */
assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
@@ -251269,7 +255602,7 @@ static int fts5UpdateMethod(
);
assert( pTab->p.pConfig->pzErrmsg==0 );
if( pConfig->pgsz==0 ){
- rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
+ rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie);
if( rc!=SQLITE_OK ) return rc;
}
@@ -251294,7 +255627,6 @@ static int fts5UpdateMethod(
rc = SQLITE_ERROR;
}else{
rc = fts5SpecialDelete(pTab, apVal);
- bUpdateOrDelete = 1;
}
}else{
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
@@ -251319,88 +255651,104 @@ static int fts5UpdateMethod(
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
assert( nArg!=1 || eType0==SQLITE_INTEGER );
- /* Filter out attempts to run UPDATE or DELETE on contentless tables.
- ** This is not suported. Except - they are both supported if the CREATE
- ** VIRTUAL TABLE statement contained "contentless_delete=1". */
- if( eType0==SQLITE_INTEGER
- && pConfig->eContent==FTS5_CONTENT_NONE
- && pConfig->bContentlessDelete==0
- ){
- pTab->p.base.zErrMsg = sqlite3_mprintf(
- "cannot %s contentless fts5 table: %s",
- (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
- );
- rc = SQLITE_ERROR;
- }
-
/* DELETE */
- else if( nArg==1 ){
- i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
- bUpdateOrDelete = 1;
+ if( nArg==1 ){
+ /* It is only possible to DELETE from a contentless table if the
+ ** contentless_delete=1 flag is set. */
+ if( fts5IsContentless(pTab, 1) && pConfig->bContentlessDelete==0 ){
+ fts5SetVtabError(pTab,
+ "cannot DELETE from contentless fts5 table: %s", pConfig->zName
+ );
+ rc = SQLITE_ERROR;
+ }else{
+ i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
+ }
}
/* INSERT or UPDATE */
else{
int eType1 = sqlite3_value_numeric_type(apVal[1]);
- if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
- rc = SQLITE_MISMATCH;
+ /* It is an error to write an fts5_locale() value to a table without
+ ** the locale=1 option. */
+ if( pConfig->bLocale==0 ){
+ int ii;
+ for(ii=0; ii<pConfig->nCol; ii++){
+ sqlite3_value *pVal = apVal[ii+2];
+ if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+ fts5SetVtabError(pTab, "fts5_locale() requires locale=1");
+ rc = SQLITE_MISMATCH;
+ goto update_out;
+ }
+ }
}
- else if( eType0!=SQLITE_INTEGER ){
+ if( eType0!=SQLITE_INTEGER ){
/* An INSERT statement. If the conflict-mode is REPLACE, first remove
** the current entry (if any). */
if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
- bUpdateOrDelete = 1;
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0);
}
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
/* UPDATE */
else{
+ Fts5Storage *pStorage = pTab->pStorage;
i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
- if( eType1==SQLITE_INTEGER && iOld!=iNew ){
+ int bContent = 0; /* Content only update */
+
+ /* If this is a contentless table (including contentless_unindexed=1
+ ** tables), check if the UPDATE may proceed. */
+ if( fts5IsContentless(pTab, 1) ){
+ rc = fts5ContentlessUpdate(pConfig, &apVal[2], iOld!=iNew, &bContent);
+ if( rc!=SQLITE_OK ) goto update_out;
+ }
+
+ if( eType1!=SQLITE_INTEGER ){
+ rc = SQLITE_MISMATCH;
+ }else if( iOld!=iNew ){
+ assert( bContent==0 );
if( eConflict==SQLITE_REPLACE ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+ rc = sqlite3Fts5StorageDelete(pStorage, iNew, 0, 0);
}
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}else{
- rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
+ rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageContentInsert(pStorage, 0, apVal, pRowid);
+ }
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 0);
}
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
+ rc = sqlite3Fts5StorageIndexInsert(pStorage, apVal, *pRowid);
}
}
+ }else if( bContent ){
+ /* This occurs when an UPDATE on a contentless table affects *only*
+ ** UNINDEXED columns. This is a no-op for contentless_unindexed=0
+ ** tables, or a write to the %_content table only for =1 tables. */
+ assert( fts5IsContentless(pTab, 1) );
+ rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageContentInsert(pStorage, 1, apVal, pRowid);
+ }
}else{
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
- bUpdateOrDelete = 1;
+ sqlite3Fts5StorageReleaseDeleteRow(pStorage);
}
}
}
- if( rc==SQLITE_OK
- && bUpdateOrDelete
- && pConfig->bSecureDelete
- && pConfig->iVersion==FTS5_CURRENT_VERSION
- ){
- rc = sqlite3Fts5StorageConfigValue(
- pTab->pStorage, "version", 0, FTS5_CURRENT_VERSION_SECUREDELETE
- );
- if( rc==SQLITE_OK ){
- pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE;
- }
- }
-
+ update_out:
pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -251422,9 +255770,11 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method.
*/
static int fts5BeginMethod(sqlite3_vtab *pVtab){
- fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
- fts5NewTransaction((Fts5FullTable*)pVtab);
- return SQLITE_OK;
+ int rc = fts5NewTransaction((Fts5FullTable*)pVtab);
+ if( rc==SQLITE_OK ){
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
+ }
+ return rc;
}
/*
@@ -251447,6 +255797,7 @@ static int fts5RollbackMethod(sqlite3_vtab *pVtab){
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
+ pTab->p.pConfig->pgsz = 0;
return rc;
}
@@ -251478,17 +255829,40 @@ static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
}
-static int fts5ApiTokenize(
+/*
+** Implementation of xTokenize_v2() API.
+*/
+static int fts5ApiTokenize_v2(
Fts5Context *pCtx,
const char *pText, int nText,
+ const char *pLoc, int nLoc,
void *pUserData,
int (*xToken)(void*, int, const char*, int, int, int)
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- return sqlite3Fts5Tokenize(
- pTab->pConfig, FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
+ int rc = SQLITE_OK;
+
+ sqlite3Fts5SetLocale(pTab->pConfig, pLoc, nLoc);
+ rc = sqlite3Fts5Tokenize(pTab->pConfig,
+ FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
);
+ sqlite3Fts5SetLocale(pTab->pConfig, 0, 0);
+
+ return rc;
+}
+
+/*
+** Implementation of xTokenize() API. This is just xTokenize_v2() with NULL/0
+** passed as the locale.
+*/
+static int fts5ApiTokenize(
+ Fts5Context *pCtx,
+ const char *pText, int nText,
+ void *pUserData,
+ int (*xToken)(void*, int, const char*, int, int, int)
+){
+ return fts5ApiTokenize_v2(pCtx, pText, nText, 0, 0, pUserData, xToken);
}
static int fts5ApiPhraseCount(Fts5Context *pCtx){
@@ -251501,6 +255875,49 @@ static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
}
+/*
+** Argument pStmt is an SQL statement of the type used by Fts5Cursor. This
+** function extracts the text value of column iCol of the current row.
+** Additionally, if there is an associated locale, it invokes
+** sqlite3Fts5SetLocale() to configure the tokenizer. In all cases the caller
+** should invoke sqlite3Fts5ClearLocale() to clear the locale at some point
+** after this function returns.
+**
+** If successful, (*ppText) is set to point to a buffer containing the text
+** value as utf-8 and SQLITE_OK returned. (*pnText) is set to the size of that
+** buffer in bytes. It is not guaranteed to be nul-terminated. If an error
+** occurs, an SQLite error code is returned. The final values of the two
+** output parameters are undefined in this case.
+*/
+static int fts5TextFromStmt(
+ Fts5Config *pConfig,
+ sqlite3_stmt *pStmt,
+ int iCol,
+ const char **ppText,
+ int *pnText
+){
+ sqlite3_value *pVal = sqlite3_column_value(pStmt, iCol+1);
+ const char *pLoc = 0;
+ int nLoc = 0;
+ int rc = SQLITE_OK;
+
+ if( pConfig->bLocale
+ && pConfig->eContent==FTS5_CONTENT_EXTERNAL
+ && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+ ){
+ rc = sqlite3Fts5DecodeLocaleValue(pVal, ppText, pnText, &pLoc, &nLoc);
+ }else{
+ *ppText = (const char*)sqlite3_value_text(pVal);
+ *pnText = sqlite3_value_bytes(pVal);
+ if( pConfig->bLocale && pConfig->eContent==FTS5_CONTENT_NORMAL ){
+ pLoc = (const char*)sqlite3_column_text(pStmt, iCol+1+pConfig->nCol);
+ nLoc = sqlite3_column_bytes(pStmt, iCol+1+pConfig->nCol);
+ }
+ }
+ sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+ return rc;
+}
+
static int fts5ApiColumnText(
Fts5Context *pCtx,
int iCol,
@@ -251510,28 +255927,35 @@ static int fts5ApiColumnText(
int rc = SQLITE_OK;
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+
+ assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
if( iCol<0 || iCol>=pTab->pConfig->nCol ){
rc = SQLITE_RANGE;
- }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
- || pCsr->ePlan==FTS5_PLAN_SPECIAL
- ){
+ }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab), 0) ){
*pz = 0;
*pn = 0;
}else{
rc = fts5SeekCursor(pCsr, 0);
if( rc==SQLITE_OK ){
- *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
- *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
+ rc = fts5TextFromStmt(pTab->pConfig, pCsr->pStmt, iCol, pz, pn);
+ sqlite3Fts5ClearLocale(pTab->pConfig);
}
}
return rc;
}
+/*
+** This is called by various API functions - xInst, xPhraseFirst,
+** xPhraseFirstColumn etc. - to obtain the position list for phrase iPhrase
+** of the current row. This function works for both detail=full tables (in
+** which case the position-list was read from the fts index) or for other
+** detail= modes if the row content is available.
+*/
static int fts5CsrPoslist(
- Fts5Cursor *pCsr,
- int iPhrase,
- const u8 **pa,
- int *pn
+ Fts5Cursor *pCsr, /* Fts5 cursor object */
+ int iPhrase, /* Phrase to find position list for */
+ const u8 **pa, /* OUT: Pointer to position list buffer */
+ int *pn /* OUT: Size of (*pa) in bytes */
){
Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
int rc = SQLITE_OK;
@@ -251539,20 +255963,32 @@ static int fts5CsrPoslist(
if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
rc = SQLITE_RANGE;
+ }else if( pConfig->eDetail!=FTS5_DETAIL_FULL
+ && fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
+ ){
+ *pa = 0;
+ *pn = 0;
+ return SQLITE_OK;
}else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
Fts5PoslistPopulator *aPopulator;
int i;
+
aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
if( aPopulator==0 ) rc = SQLITE_NOMEM;
+ if( rc==SQLITE_OK ){
+ rc = fts5SeekCursor(pCsr, 0);
+ }
for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
- int n; const char *z;
- rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
+ const char *z = 0;
+ int n = 0;
+ rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprPopulatePoslists(
pConfig, pCsr->pExpr, aPopulator, i, z, n
);
}
+ sqlite3Fts5ClearLocale(pConfig);
}
sqlite3_free(aPopulator);
@@ -251577,7 +256013,6 @@ static int fts5CsrPoslist(
*pn = 0;
}
-
return rc;
}
@@ -251646,7 +256081,8 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
aInst[0] = iBest;
aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
- if( aInst[1]<0 || aInst[1]>=nCol ){
+ assert( aInst[1]>=0 );
+ if( aInst[1]>=nCol ){
rc = FTS5_CORRUPT;
break;
}
@@ -251724,7 +256160,7 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
if( pConfig->bColumnsize ){
i64 iRowid = fts5CursorRowid(pCsr);
rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
- }else if( pConfig->zContent==0 ){
+ }else if( !pConfig->zContent || pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
int i;
for(i=0; i<pConfig->nCol; i++){
if( pConfig->abUnindexed[i]==0 ){
@@ -251733,17 +256169,19 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
}
}else{
int i;
+ rc = fts5SeekCursor(pCsr, 0);
for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
if( pConfig->abUnindexed[i]==0 ){
- const char *z; int n;
- void *p = (void*)(&pCsr->aColumnSize[i]);
+ const char *z = 0;
+ int n = 0;
pCsr->aColumnSize[i] = 0;
- rc = fts5ApiColumnText(pCtx, i, &z, &n);
+ rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5Tokenize(
- pConfig, FTS5_TOKENIZE_AUX, z, n, p, fts5ColumnSizeCb
+ rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_AUX,
+ z, n, (void*)&pCsr->aColumnSize[i], fts5ColumnSizeCb
);
}
+ sqlite3Fts5ClearLocale(pConfig);
}
}
}
@@ -251823,11 +256261,10 @@ static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){
}
static void fts5ApiPhraseNext(
- Fts5Context *pUnused,
+ Fts5Context *pCtx,
Fts5PhraseIter *pIter,
int *piCol, int *piOff
){
- UNUSED_PARAM(pUnused);
if( pIter->a>=pIter->b ){
*piCol = -1;
*piOff = -1;
@@ -251835,8 +256272,12 @@ static void fts5ApiPhraseNext(
int iVal;
pIter->a += fts5GetVarint32(pIter->a, iVal);
if( iVal==1 ){
+ /* Avoid returning a (*piCol) value that is too large for the table,
+ ** even if the position-list is corrupt. The caller might not be
+ ** expecting it. */
+ int nCol = ((Fts5Table*)(((Fts5Cursor*)pCtx)->base.pVtab))->pConfig->nCol;
pIter->a += fts5GetVarint32(pIter->a, iVal);
- *piCol = iVal;
+ *piCol = (iVal>=nCol ? nCol-1 : iVal);
*piOff = 0;
pIter->a += fts5GetVarint32(pIter->a, iVal);
}
@@ -251986,8 +256427,48 @@ static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
);
+/*
+** The xColumnLocale() API.
+*/
+static int fts5ApiColumnLocale(
+ Fts5Context *pCtx,
+ int iCol,
+ const char **pzLocale,
+ int *pnLocale
+){
+ int rc = SQLITE_OK;
+ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
+ Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
+
+ *pzLocale = 0;
+ *pnLocale = 0;
+
+ assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
+ if( iCol<0 || iCol>=pConfig->nCol ){
+ rc = SQLITE_RANGE;
+ }else if(
+ pConfig->abUnindexed[iCol]==0
+ && 0==fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
+ && pConfig->bLocale
+ ){
+ rc = fts5SeekCursor(pCsr, 0);
+ if( rc==SQLITE_OK ){
+ const char *zDummy = 0;
+ int nDummy = 0;
+ rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &zDummy, &nDummy);
+ if( rc==SQLITE_OK ){
+ *pzLocale = pConfig->t.pLocale;
+ *pnLocale = pConfig->t.nLocale;
+ }
+ sqlite3Fts5ClearLocale(pConfig);
+ }
+ }
+
+ return rc;
+}
+
static const Fts5ExtensionApi sFts5Api = {
- 3, /* iVersion */
+ 4, /* iVersion */
fts5ApiUserData,
fts5ApiColumnCount,
fts5ApiRowCount,
@@ -252008,7 +256489,9 @@ static const Fts5ExtensionApi sFts5Api = {
fts5ApiPhraseFirstColumn,
fts5ApiPhraseNextColumn,
fts5ApiQueryToken,
- fts5ApiInstToken
+ fts5ApiInstToken,
+ fts5ApiColumnLocale,
+ fts5ApiTokenize_v2
};
/*
@@ -252059,6 +256542,7 @@ static void fts5ApiInvoke(
sqlite3_value **argv
){
assert( pCsr->pAux==0 );
+ assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
pCsr->pAux = pAux;
pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
pCsr->pAux = 0;
@@ -252072,6 +256556,21 @@ static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){
return pCsr;
}
+/*
+** Parameter zFmt is a printf() style formatting string. This function
+** formats it using the trailing arguments and returns the result as
+** an error message to the context passed as the first argument.
+*/
+static void fts5ResultError(sqlite3_context *pCtx, const char *zFmt, ...){
+ char *zErr = 0;
+ va_list ap;
+ va_start(ap, zFmt);
+ zErr = sqlite3_vmprintf(zFmt, ap);
+ sqlite3_result_error(pCtx, zErr, -1);
+ sqlite3_free(zErr);
+ va_end(ap);
+}
+
static void fts5ApiCallback(
sqlite3_context *context,
int argc,
@@ -252087,12 +256586,13 @@ static void fts5ApiCallback(
iCsrId = sqlite3_value_int64(argv[0]);
pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
- if( pCsr==0 || pCsr->ePlan==0 ){
- char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
+ if( pCsr==0 || (pCsr->ePlan==0 || pCsr->ePlan==FTS5_PLAN_SPECIAL) ){
+ fts5ResultError(context, "no such cursor: %lld", iCsrId);
}else{
+ sqlite3_vtab *pTab = pCsr->base.pVtab;
fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
+ sqlite3_free(pTab->zErrMsg);
+ pTab->zErrMsg = 0;
}
}
@@ -252210,8 +256710,8 @@ static int fts5ColumnMethod(
** auxiliary function. */
sqlite3_result_int64(pCtx, pCsr->iCsrId);
}else if( iCol==pConfig->nCol+1 ){
-
/* The value of the "rank" column. */
+
if( pCsr->ePlan==FTS5_PLAN_SOURCE ){
fts5PoslistBlob(pCtx, pCsr);
}else if(
@@ -252222,20 +256722,32 @@ static int fts5ColumnMethod(
fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
}
}
- }else if( !fts5IsContentless(pTab) ){
- pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
- rc = fts5SeekCursor(pCsr, 1);
- if( rc==SQLITE_OK ){
- sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
+ }else{
+ if( !sqlite3_vtab_nochange(pCtx) && pConfig->eContent!=FTS5_CONTENT_NONE ){
+ pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
+ rc = fts5SeekCursor(pCsr, 1);
+ if( rc==SQLITE_OK ){
+ sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
+ if( pConfig->bLocale
+ && pConfig->eContent==FTS5_CONTENT_EXTERNAL
+ && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+ ){
+ const char *z = 0;
+ int n = 0;
+ rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &z, &n);
+ if( rc==SQLITE_OK ){
+ sqlite3_result_text(pCtx, z, n, SQLITE_TRANSIENT);
+ }
+ sqlite3Fts5ClearLocale(pConfig);
+ }else{
+ sqlite3_result_value(pCtx, pVal);
+ }
+ }
+
+ pConfig->pzErrmsg = 0;
}
- pConfig->pzErrmsg = 0;
- }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){
- char *zErr = sqlite3_mprintf("cannot UPDATE a subset of "
- "columns on fts5 contentless-delete table: %s", pConfig->zName
- );
- sqlite3_result_error(pCtx, zErr, -1);
- sqlite3_free(zErr);
}
+
return rc;
}
@@ -252375,47 +256887,210 @@ static int fts5CreateAux(
}
/*
-** Register a new tokenizer. This is the implementation of the
-** fts5_api.xCreateTokenizer() method.
+** This function is used by xCreateTokenizer_v2() and xCreateTokenizer().
+** It allocates and partially populates a new Fts5TokenizerModule object.
+** The new object is already linked into the Fts5Global context before
+** returning.
+**
+** If successful, SQLITE_OK is returned and a pointer to the new
+** Fts5TokenizerModule object returned via output parameter (*ppNew). All
+** that is required is for the caller to fill in the methods in
+** Fts5TokenizerModule.x1 and x2, and to set Fts5TokenizerModule.bV2Native
+** as appropriate.
+**
+** If an error occurs, an SQLite error code is returned and the final value
+** of (*ppNew) undefined.
*/
-static int fts5CreateTokenizer(
- fts5_api *pApi, /* Global context (one per db handle) */
+static int fts5NewTokenizerModule(
+ Fts5Global *pGlobal, /* Global context (one per db handle) */
const char *zName, /* Name of new function */
void *pUserData, /* User data for aux. function */
- fts5_tokenizer *pTokenizer, /* Tokenizer implementation */
- void(*xDestroy)(void*) /* Destructor for pUserData */
+ void(*xDestroy)(void*), /* Destructor for pUserData */
+ Fts5TokenizerModule **ppNew
){
- Fts5Global *pGlobal = (Fts5Global*)pApi;
- Fts5TokenizerModule *pNew;
- sqlite3_int64 nName; /* Size of zName and its \0 terminator */
- sqlite3_int64 nByte; /* Bytes of space to allocate */
int rc = SQLITE_OK;
+ Fts5TokenizerModule *pNew;
+ sqlite3_int64 nName; /* Size of zName and its \0 terminator */
+ sqlite3_int64 nByte; /* Bytes of space to allocate */
nName = strlen(zName) + 1;
nByte = sizeof(Fts5TokenizerModule) + nName;
- pNew = (Fts5TokenizerModule*)sqlite3_malloc64(nByte);
+ *ppNew = pNew = (Fts5TokenizerModule*)sqlite3Fts5MallocZero(&rc, nByte);
if( pNew ){
- memset(pNew, 0, (size_t)nByte);
pNew->zName = (char*)&pNew[1];
memcpy(pNew->zName, zName, nName);
pNew->pUserData = pUserData;
- pNew->x = *pTokenizer;
pNew->xDestroy = xDestroy;
pNew->pNext = pGlobal->pTok;
pGlobal->pTok = pNew;
if( pNew->pNext==0 ){
pGlobal->pDfltTok = pNew;
}
+ }
+
+ return rc;
+}
+
+/*
+** An instance of this type is used as the Fts5Tokenizer object for
+** wrapper tokenizers - those that provide access to a v1 tokenizer via
+** the fts5_tokenizer_v2 API, and those that provide access to a v2 tokenizer
+** via the fts5_tokenizer API.
+*/
+typedef struct Fts5VtoVTokenizer Fts5VtoVTokenizer;
+struct Fts5VtoVTokenizer {
+ int bV2Native; /* True if v2 native tokenizer */
+ fts5_tokenizer x1; /* Tokenizer functions */
+ fts5_tokenizer_v2 x2; /* V2 tokenizer functions */
+ Fts5Tokenizer *pReal;
+};
+
+/*
+** Create a wrapper tokenizer. The context argument pCtx points to the
+** Fts5TokenizerModule object.
+*/
+static int fts5VtoVCreate(
+ void *pCtx,
+ const char **azArg,
+ int nArg,
+ Fts5Tokenizer **ppOut
+){
+ Fts5TokenizerModule *pMod = (Fts5TokenizerModule*)pCtx;
+ Fts5VtoVTokenizer *pNew = 0;
+ int rc = SQLITE_OK;
+
+ pNew = (Fts5VtoVTokenizer*)sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
+ if( rc==SQLITE_OK ){
+ pNew->x1 = pMod->x1;
+ pNew->x2 = pMod->x2;
+ pNew->bV2Native = pMod->bV2Native;
+ if( pMod->bV2Native ){
+ rc = pMod->x2.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal);
+ }else{
+ rc = pMod->x1.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pNew);
+ pNew = 0;
+ }
+ }
+
+ *ppOut = (Fts5Tokenizer*)pNew;
+ return rc;
+}
+
+/*
+** Delete an Fts5VtoVTokenizer wrapper tokenizer.
+*/
+static void fts5VtoVDelete(Fts5Tokenizer *pTok){
+ Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
+ if( p ){
+ if( p->bV2Native ){
+ p->x2.xDelete(p->pReal);
+ }else{
+ p->x1.xDelete(p->pReal);
+ }
+ sqlite3_free(p);
+ }
+}
+
+
+/*
+** xTokenizer method for a wrapper tokenizer that offers the v1 interface
+** (no support for locales).
+*/
+static int fts5V1toV2Tokenize(
+ Fts5Tokenizer *pTok,
+ void *pCtx, int flags,
+ const char *pText, int nText,
+ int (*xToken)(void*, int, const char*, int, int, int)
+){
+ Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
+ assert( p->bV2Native );
+ return p->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
+}
+
+/*
+** xTokenizer method for a wrapper tokenizer that offers the v2 interface
+** (with locale support).
+*/
+static int fts5V2toV1Tokenize(
+ Fts5Tokenizer *pTok,
+ void *pCtx, int flags,
+ const char *pText, int nText,
+ const char *pLocale, int nLocale,
+ int (*xToken)(void*, int, const char*, int, int, int)
+){
+ Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
+ assert( p->bV2Native==0 );
+ UNUSED_PARAM2(pLocale,nLocale);
+ return p->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
+}
+
+/*
+** Register a new tokenizer. This is the implementation of the
+** fts5_api.xCreateTokenizer_v2() method.
+*/
+static int fts5CreateTokenizer_v2(
+ fts5_api *pApi, /* Global context (one per db handle) */
+ const char *zName, /* Name of new function */
+ void *pUserData, /* User data for aux. function */
+ fts5_tokenizer_v2 *pTokenizer, /* Tokenizer implementation */
+ void(*xDestroy)(void*) /* Destructor for pUserData */
+){
+ Fts5Global *pGlobal = (Fts5Global*)pApi;
+ int rc = SQLITE_OK;
+
+ if( pTokenizer->iVersion>2 ){
+ rc = SQLITE_ERROR;
}else{
- rc = SQLITE_NOMEM;
+ Fts5TokenizerModule *pNew = 0;
+ rc = fts5NewTokenizerModule(pGlobal, zName, pUserData, xDestroy, &pNew);
+ if( pNew ){
+ pNew->x2 = *pTokenizer;
+ pNew->bV2Native = 1;
+ pNew->x1.xCreate = fts5VtoVCreate;
+ pNew->x1.xTokenize = fts5V1toV2Tokenize;
+ pNew->x1.xDelete = fts5VtoVDelete;
+ }
}
return rc;
}
+/*
+** The fts5_api.xCreateTokenizer() method.
+*/
+static int fts5CreateTokenizer(
+ fts5_api *pApi, /* Global context (one per db handle) */
+ const char *zName, /* Name of new function */
+ void *pUserData, /* User data for aux. function */
+ fts5_tokenizer *pTokenizer, /* Tokenizer implementation */
+ void(*xDestroy)(void*) /* Destructor for pUserData */
+){
+ Fts5TokenizerModule *pNew = 0;
+ int rc = SQLITE_OK;
+
+ rc = fts5NewTokenizerModule(
+ (Fts5Global*)pApi, zName, pUserData, xDestroy, &pNew
+ );
+ if( pNew ){
+ pNew->x1 = *pTokenizer;
+ pNew->x2.xCreate = fts5VtoVCreate;
+ pNew->x2.xTokenize = fts5V2toV1Tokenize;
+ pNew->x2.xDelete = fts5VtoVDelete;
+ }
+ return rc;
+}
+
+/*
+** Search the global context passed as the first argument for a tokenizer
+** module named zName. If found, return a pointer to the Fts5TokenizerModule
+** object. Otherwise, return NULL.
+*/
static Fts5TokenizerModule *fts5LocateTokenizer(
- Fts5Global *pGlobal,
- const char *zName
+ Fts5Global *pGlobal, /* Global (one per db handle) object */
+ const char *zName /* Name of tokenizer module to find */
){
Fts5TokenizerModule *pMod = 0;
@@ -252432,6 +257107,36 @@ static Fts5TokenizerModule *fts5LocateTokenizer(
/*
** Find a tokenizer. This is the implementation of the
+** fts5_api.xFindTokenizer_v2() method.
+*/
+static int fts5FindTokenizer_v2(
+ fts5_api *pApi, /* Global context (one per db handle) */
+ const char *zName, /* Name of tokenizer */
+ void **ppUserData,
+ fts5_tokenizer_v2 **ppTokenizer /* Populate this object */
+){
+ int rc = SQLITE_OK;
+ Fts5TokenizerModule *pMod;
+
+ pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName);
+ if( pMod ){
+ if( pMod->bV2Native ){
+ *ppUserData = pMod->pUserData;
+ }else{
+ *ppUserData = (void*)pMod;
+ }
+ *ppTokenizer = &pMod->x2;
+ }else{
+ *ppTokenizer = 0;
+ *ppUserData = 0;
+ rc = SQLITE_ERROR;
+ }
+
+ return rc;
+}
+
+/*
+** Find a tokenizer. This is the implementation of the
** fts5_api.xFindTokenizer() method.
*/
static int fts5FindTokenizer(
@@ -252445,55 +257150,75 @@ static int fts5FindTokenizer(
pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName);
if( pMod ){
- *pTokenizer = pMod->x;
- *ppUserData = pMod->pUserData;
+ if( pMod->bV2Native==0 ){
+ *ppUserData = pMod->pUserData;
+ }else{
+ *ppUserData = (void*)pMod;
+ }
+ *pTokenizer = pMod->x1;
}else{
- memset(pTokenizer, 0, sizeof(fts5_tokenizer));
+ memset(pTokenizer, 0, sizeof(*pTokenizer));
+ *ppUserData = 0;
rc = SQLITE_ERROR;
}
return rc;
}
-static int sqlite3Fts5GetTokenizer(
- Fts5Global *pGlobal,
- const char **azArg,
- int nArg,
- Fts5Config *pConfig,
- char **pzErr
-){
- Fts5TokenizerModule *pMod;
+/*
+** Attempt to instantiate the tokenizer.
+*/
+static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig){
+ const char **azArg = pConfig->t.azArg;
+ const int nArg = pConfig->t.nArg;
+ Fts5TokenizerModule *pMod = 0;
int rc = SQLITE_OK;
- pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
+ pMod = fts5LocateTokenizer(pConfig->pGlobal, nArg==0 ? 0 : azArg[0]);
if( pMod==0 ){
assert( nArg>0 );
rc = SQLITE_ERROR;
- if( pzErr ) *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
+ sqlite3Fts5ConfigErrmsg(pConfig, "no such tokenizer: %s", azArg[0]);
}else{
- rc = pMod->x.xCreate(
- pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**) = 0;
+ if( pMod->bV2Native ){
+ xCreate = pMod->x2.xCreate;
+ pConfig->t.pApi2 = &pMod->x2;
+ }else{
+ pConfig->t.pApi1 = &pMod->x1;
+ xCreate = pMod->x1.xCreate;
+ }
+
+ rc = xCreate(pMod->pUserData,
+ (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->t.pTok
);
- pConfig->pTokApi = &pMod->x;
+
if( rc!=SQLITE_OK ){
- if( pzErr && rc!=SQLITE_NOMEM ){
- *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+ if( rc!=SQLITE_NOMEM ){
+ sqlite3Fts5ConfigErrmsg(pConfig, "error in tokenizer constructor");
}
- }else{
- pConfig->ePattern = sqlite3Fts5TokenizerPattern(
- pMod->x.xCreate, pConfig->pTok
+ }else if( pMod->bV2Native==0 ){
+ pConfig->t.ePattern = sqlite3Fts5TokenizerPattern(
+ pMod->x1.xCreate, pConfig->t.pTok
);
}
}
if( rc!=SQLITE_OK ){
- pConfig->pTokApi = 0;
- pConfig->pTok = 0;
+ pConfig->t.pApi1 = 0;
+ pConfig->t.pApi2 = 0;
+ pConfig->t.pTok = 0;
}
return rc;
}
+
+/*
+** xDestroy callback passed to sqlite3_create_module(). This is invoked
+** when the db handle is being closed. Free memory associated with
+** tokenizers and aux functions registered with this db handle.
+*/
static void fts5ModuleDestroy(void *pCtx){
Fts5TokenizerModule *pTok, *pNextTok;
Fts5Auxiliary *pAux, *pNextAux;
@@ -252514,6 +257239,10 @@ static void fts5ModuleDestroy(void *pCtx){
sqlite3_free(pGlobal);
}
+/*
+** Implementation of the fts5() function used by clients to obtain the
+** API pointer.
+*/
static void fts5Fts5Func(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
@@ -252537,7 +257266,82 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2025-06-28 14:00:48 2af157d77fb1304a74176eaee7fbc7c7e932d946bf25325e9c26c91db19e3079", -1, SQLITE_TRANSIENT);
+}
+
+/*
+** Implementation of fts5_locale(LOCALE, TEXT) function.
+**
+** If parameter LOCALE is NULL, or a zero-length string, then a copy of
+** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as
+** text, and the value returned is a blob consisting of:
+**
+** * The 4 bytes 0x00, 0xE0, 0xB2, 0xEb (FTS5_LOCALE_HEADER).
+** * The LOCALE, as utf-8 text, followed by
+** * 0x00, followed by
+** * The TEXT, as utf-8 text.
+**
+** There is no final nul-terminator following the TEXT value.
+*/
+static void fts5LocaleFunc(
+ sqlite3_context *pCtx, /* Function call context */
+ int nArg, /* Number of args */
+ sqlite3_value **apArg /* Function arguments */
+){
+ const char *zLocale = 0;
+ int nLocale = 0;
+ const char *zText = 0;
+ int nText = 0;
+
+ assert( nArg==2 );
+ UNUSED_PARAM(nArg);
+
+ zLocale = (const char*)sqlite3_value_text(apArg[0]);
+ nLocale = sqlite3_value_bytes(apArg[0]);
+
+ zText = (const char*)sqlite3_value_text(apArg[1]);
+ nText = sqlite3_value_bytes(apArg[1]);
+
+ if( zLocale==0 || zLocale[0]=='\0' ){
+ sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT);
+ }else{
+ Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx);
+ u8 *pBlob = 0;
+ u8 *pCsr = 0;
+ int nBlob = 0;
+
+ nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText;
+ pBlob = (u8*)sqlite3_malloc(nBlob);
+ if( pBlob==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ return;
+ }
+
+ pCsr = pBlob;
+ memcpy(pCsr, (const u8*)p->aLocaleHdr, FTS5_LOCALE_HDR_SIZE);
+ pCsr += FTS5_LOCALE_HDR_SIZE;
+ memcpy(pCsr, zLocale, nLocale);
+ pCsr += nLocale;
+ (*pCsr++) = 0x00;
+ if( zText ) memcpy(pCsr, zText, nText);
+ assert( &pCsr[nText]==&pBlob[nBlob] );
+
+ sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
+ }
+}
+
+/*
+** Implementation of fts5_insttoken() function.
+*/
+static void fts5InsttokenFunc(
+ sqlite3_context *pCtx, /* Function call context */
+ int nArg, /* Number of args */
+ sqlite3_value **apArg /* Function arguments */
+){
+ assert( nArg==1 );
+ (void)nArg;
+ sqlite3_result_value(pCtx, apArg[0]);
+ sqlite3_result_subtype(pCtx, FTS5_INSTTOKEN_SUBTYPE);
}
/*
@@ -252632,10 +257436,22 @@ static int fts5Init(sqlite3 *db){
void *p = (void*)pGlobal;
memset(pGlobal, 0, sizeof(Fts5Global));
pGlobal->db = db;
- pGlobal->api.iVersion = 2;
+ pGlobal->api.iVersion = 3;
pGlobal->api.xCreateFunction = fts5CreateAux;
pGlobal->api.xCreateTokenizer = fts5CreateTokenizer;
pGlobal->api.xFindTokenizer = fts5FindTokenizer;
+ pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2;
+ pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2;
+
+ /* Initialize pGlobal->aLocaleHdr[] to a 128-bit pseudo-random vector.
+ ** The constants below were generated randomly. */
+ sqlite3_randomness(sizeof(pGlobal->aLocaleHdr), pGlobal->aLocaleHdr);
+ pGlobal->aLocaleHdr[0] ^= 0xF924976D;
+ pGlobal->aLocaleHdr[1] ^= 0x16596E13;
+ pGlobal->aLocaleHdr[2] ^= 0x7C80BEAA;
+ pGlobal->aLocaleHdr[3] ^= 0x9B03A67F;
+ assert( sizeof(pGlobal->aLocaleHdr)==16 );
+
rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
@@ -252654,6 +257470,20 @@ static int fts5Init(sqlite3 *db){
p, fts5SourceIdFunc, 0, 0
);
}
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_function(
+ db, "fts5_locale", 2,
+ SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE|SQLITE_SUBTYPE,
+ p, fts5LocaleFunc, 0, 0
+ );
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_function(
+ db, "fts5_insttoken", 1,
+ SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
+ p, fts5InsttokenFunc, 0, 0
+ );
+ }
}
/* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
@@ -252661,8 +257491,8 @@ static int fts5Init(sqlite3 *db){
** its entry point to enable the matchinfo() demo. */
#ifdef SQLITE_FTS5_ENABLE_TEST_MI
if( rc==SQLITE_OK ){
- extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
- rc = sqlite3Fts5TestRegisterMatchinfo(db);
+ extern int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api*);
+ rc = sqlite3Fts5TestRegisterMatchinfoAPI(&pGlobal->api);
}
#endif
@@ -252728,13 +257558,40 @@ SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3 *db){
/* #include "fts5Int.h" */
+/*
+** pSavedRow:
+** SQL statement FTS5_STMT_LOOKUP2 is a copy of FTS5_STMT_LOOKUP, it
+** does a by-rowid lookup to retrieve a single row from the %_content
+** table or equivalent external-content table/view.
+**
+** However, FTS5_STMT_LOOKUP2 is only used when retrieving the original
+** values for a row being UPDATEd. In that case, the SQL statement is
+** not reset and pSavedRow is set to point at it. This is so that the
+** insert operation that follows the delete may access the original
+** row values for any new values for which sqlite3_value_nochange() returns
+** true. i.e. if the user executes:
+**
+** CREATE VIRTUAL TABLE ft USING fts5(a, b, c, locale=1);
+** ...
+** UPDATE fts SET a=?, b=? WHERE rowid=?;
+**
+** then the value passed to the xUpdate() method of this table as the
+** new.c value is an sqlite3_value_nochange() value. So in this case it
+** must be read from the saved row stored in Fts5Storage.pSavedRow.
+**
+** This is necessary - using sqlite3_value_nochange() instead of just having
+** SQLite pass the original value back via xUpdate() - so as not to discard
+** any locale information associated with such values.
+**
+*/
struct Fts5Storage {
Fts5Config *pConfig;
Fts5Index *pIndex;
int bTotalsValid; /* True if nTotalRow/aTotalSize[] are valid */
i64 nTotalRow; /* Total number of rows in FTS table */
i64 *aTotalSize; /* Total sizes of each column */
- sqlite3_stmt *aStmt[11];
+ sqlite3_stmt *pSavedRow;
+ sqlite3_stmt *aStmt[12];
};
@@ -252748,14 +257605,15 @@ struct Fts5Storage {
# error "FTS5_STMT_LOOKUP mismatch"
#endif
-#define FTS5_STMT_INSERT_CONTENT 3
-#define FTS5_STMT_REPLACE_CONTENT 4
-#define FTS5_STMT_DELETE_CONTENT 5
-#define FTS5_STMT_REPLACE_DOCSIZE 6
-#define FTS5_STMT_DELETE_DOCSIZE 7
-#define FTS5_STMT_LOOKUP_DOCSIZE 8
-#define FTS5_STMT_REPLACE_CONFIG 9
-#define FTS5_STMT_SCAN 10
+#define FTS5_STMT_LOOKUP2 3
+#define FTS5_STMT_INSERT_CONTENT 4
+#define FTS5_STMT_REPLACE_CONTENT 5
+#define FTS5_STMT_DELETE_CONTENT 6
+#define FTS5_STMT_REPLACE_DOCSIZE 7
+#define FTS5_STMT_DELETE_DOCSIZE 8
+#define FTS5_STMT_LOOKUP_DOCSIZE 9
+#define FTS5_STMT_REPLACE_CONFIG 10
+#define FTS5_STMT_SCAN 11
/*
** Prepare the two insert statements - Fts5Storage.pInsertContent and
@@ -252785,6 +257643,7 @@ static int fts5StorageGetStmt(
"SELECT %s FROM %s T WHERE T.%Q >= ? AND T.%Q <= ? ORDER BY T.%Q ASC",
"SELECT %s FROM %s T WHERE T.%Q <= ? AND T.%Q >= ? ORDER BY T.%Q DESC",
"SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP */
+ "SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP2 */
"INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */
"REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */
@@ -252800,6 +257659,8 @@ static int fts5StorageGetStmt(
Fts5Config *pC = p->pConfig;
char *zSql = 0;
+ assert( ArraySize(azStmt)==ArraySize(p->aStmt) );
+
switch( eStmt ){
case FTS5_STMT_SCAN:
zSql = sqlite3_mprintf(azStmt[eStmt],
@@ -252816,6 +257677,7 @@ static int fts5StorageGetStmt(
break;
case FTS5_STMT_LOOKUP:
+ case FTS5_STMT_LOOKUP2:
zSql = sqlite3_mprintf(azStmt[eStmt],
pC->zContentExprlist, pC->zContent, pC->zContentRowid
);
@@ -252823,20 +257685,35 @@ static int fts5StorageGetStmt(
case FTS5_STMT_INSERT_CONTENT:
case FTS5_STMT_REPLACE_CONTENT: {
- int nCol = pC->nCol + 1;
- char *zBind;
+ char *zBind = 0;
int i;
- zBind = sqlite3_malloc64(1 + nCol*2);
- if( zBind ){
- for(i=0; i<nCol; i++){
- zBind[i*2] = '?';
- zBind[i*2 + 1] = ',';
+ assert( pC->eContent==FTS5_CONTENT_NORMAL
+ || pC->eContent==FTS5_CONTENT_UNINDEXED
+ );
+
+ /* Add bindings for the "c*" columns - those that store the actual
+ ** table content. If eContent==NORMAL, then there is one binding
+ ** for each column. Or, if eContent==UNINDEXED, then there are only
+ ** bindings for the UNINDEXED columns. */
+ for(i=0; rc==SQLITE_OK && i<(pC->nCol+1); i++){
+ if( !i || pC->eContent==FTS5_CONTENT_NORMAL || pC->abUnindexed[i-1] ){
+ zBind = sqlite3Fts5Mprintf(&rc, "%z%s?%d", zBind, zBind?",":"",i+1);
+ }
+ }
+
+ /* Add bindings for any "l*" columns. Only non-UNINDEXED columns
+ ** require these. */
+ if( pC->bLocale && pC->eContent==FTS5_CONTENT_NORMAL ){
+ for(i=0; rc==SQLITE_OK && i<pC->nCol; i++){
+ if( pC->abUnindexed[i]==0 ){
+ zBind = sqlite3Fts5Mprintf(&rc, "%z,?%d", zBind, pC->nCol+i+2);
+ }
}
- zBind[i*2-1] = '\0';
- zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
- sqlite3_free(zBind);
}
+
+ zSql = sqlite3Fts5Mprintf(&rc, azStmt[eStmt], pC->zDb, pC->zName,zBind);
+ sqlite3_free(zBind);
break;
}
@@ -252862,7 +257739,7 @@ static int fts5StorageGetStmt(
rc = SQLITE_NOMEM;
}else{
int f = SQLITE_PREPARE_PERSISTENT;
- if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
+ if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB;
p->pConfig->bLock++;
rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
p->pConfig->bLock--;
@@ -252870,6 +257747,11 @@ static int fts5StorageGetStmt(
if( rc!=SQLITE_OK && pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
}
+ if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmt<FTS5_STMT_SCAN ){
+ /* One of the internal tables - not the %_content table - is missing.
+ ** This counts as a corrupted table. */
+ rc = SQLITE_CORRUPT;
+ }
}
}
@@ -253022,9 +257904,11 @@ static int sqlite3Fts5StorageOpen(
p->pIndex = pIndex;
if( bCreate ){
- if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL
+ || pConfig->eContent==FTS5_CONTENT_UNINDEXED
+ ){
int nDefn = 32 + pConfig->nCol*10;
- char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
+ char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
if( zDefn==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -253033,8 +257917,20 @@ static int sqlite3Fts5StorageOpen(
sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
iOff = (int)strlen(zDefn);
for(i=0; i<pConfig->nCol; i++){
- sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
- iOff += (int)strlen(&zDefn[iOff]);
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL
+ || pConfig->abUnindexed[i]
+ ){
+ sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
+ iOff += (int)strlen(&zDefn[iOff]);
+ }
+ }
+ if( pConfig->bLocale ){
+ for(i=0; i<pConfig->nCol; i++){
+ if( pConfig->abUnindexed[i]==0 ){
+ sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
+ iOff += (int)strlen(&zDefn[iOff]);
+ }
+ }
}
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
}
@@ -253112,14 +258008,48 @@ static int fts5StorageInsertCallback(
}
/*
+** This function is used as part of an UPDATE statement that modifies the
+** rowid of a row. In that case, this function is called first to set
+** Fts5Storage.pSavedRow to point to a statement that may be used to
+** access the original values of the row being deleted - iDel.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+** It is not considered an error if row iDel does not exist. In this case
+** pSavedRow is not set and SQLITE_OK returned.
+*/
+static int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel){
+ int rc = SQLITE_OK;
+ sqlite3_stmt *pSeek = 0;
+
+ assert( p->pSavedRow==0 );
+ rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+1, &pSeek, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pSeek, 1, iDel);
+ if( sqlite3_step(pSeek)!=SQLITE_ROW ){
+ rc = sqlite3_reset(pSeek);
+ }else{
+ p->pSavedRow = pSeek;
+ }
+ }
+
+ return rc;
+}
+
+/*
** If a row with rowid iDel is present in the %_content table, add the
** delete-markers to the FTS index necessary to delete it. Do not actually
** remove the %_content row at this time though.
+**
+** If parameter bSaveRow is true, then Fts5Storage.pSavedRow is left
+** pointing to a statement (FTS5_STMT_LOOKUP2) that may be used to access
+** the original values of the row being deleted. This is used by UPDATE
+** statements.
*/
static int fts5StorageDeleteFromIndex(
Fts5Storage *p,
i64 iDel,
- sqlite3_value **apVal
+ sqlite3_value **apVal,
+ int bSaveRow /* True to set pSavedRow */
){
Fts5Config *pConfig = p->pConfig;
sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */
@@ -253128,12 +258058,21 @@ static int fts5StorageDeleteFromIndex(
int iCol;
Fts5InsertCtx ctx;
+ assert( bSaveRow==0 || apVal==0 );
+ assert( bSaveRow==0 || bSaveRow==1 );
+ assert( FTS5_STMT_LOOKUP2==FTS5_STMT_LOOKUP+1 );
+
if( apVal==0 ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0);
- if( rc!=SQLITE_OK ) return rc;
- sqlite3_bind_int64(pSeek, 1, iDel);
- if( sqlite3_step(pSeek)!=SQLITE_ROW ){
- return sqlite3_reset(pSeek);
+ if( p->pSavedRow && bSaveRow ){
+ pSeek = p->pSavedRow;
+ p->pSavedRow = 0;
+ }else{
+ rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+bSaveRow, &pSeek, 0);
+ if( rc!=SQLITE_OK ) return rc;
+ sqlite3_bind_int64(pSeek, 1, iDel);
+ if( sqlite3_step(pSeek)!=SQLITE_ROW ){
+ return sqlite3_reset(pSeek);
+ }
}
}
@@ -253141,27 +258080,56 @@ static int fts5StorageDeleteFromIndex(
ctx.iCol = -1;
for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
if( pConfig->abUnindexed[iCol-1]==0 ){
- const char *zText;
- int nText;
+ sqlite3_value *pVal = 0;
+ sqlite3_value *pFree = 0;
+ const char *pText = 0;
+ int nText = 0;
+ const char *pLoc = 0;
+ int nLoc = 0;
+
assert( pSeek==0 || apVal==0 );
assert( pSeek!=0 || apVal!=0 );
if( pSeek ){
- zText = (const char*)sqlite3_column_text(pSeek, iCol);
- nText = sqlite3_column_bytes(pSeek, iCol);
- }else if( ALWAYS(apVal) ){
- zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
- nText = sqlite3_value_bytes(apVal[iCol-1]);
+ pVal = sqlite3_column_value(pSeek, iCol);
}else{
- continue;
+ pVal = apVal[iCol-1];
}
- ctx.szCol = 0;
- rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
- zText, nText, (void*)&ctx, fts5StorageInsertCallback
- );
- p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
- if( p->aTotalSize[iCol-1]<0 ){
- rc = FTS5_CORRUPT;
+
+ if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+ rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+ }else{
+ if( sqlite3_value_type(pVal)!=SQLITE_TEXT ){
+ /* Make a copy of the value to work with. This is because the call
+ ** to sqlite3_value_text() below forces the type of the value to
+ ** SQLITE_TEXT, and we may need to use it again later. */
+ pFree = pVal = sqlite3_value_dup(pVal);
+ if( pVal==0 ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+ if( rc==SQLITE_OK ){
+ pText = (const char*)sqlite3_value_text(pVal);
+ nText = sqlite3_value_bytes(pVal);
+ if( pConfig->bLocale && pSeek ){
+ pLoc = (const char*)sqlite3_column_text(pSeek, iCol+pConfig->nCol);
+ nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
+ }
+ }
}
+
+ if( rc==SQLITE_OK ){
+ sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+ ctx.szCol = 0;
+ rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
+ pText, nText, (void*)&ctx, fts5StorageInsertCallback
+ );
+ p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
+ if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
+ rc = FTS5_CORRUPT;
+ }
+ sqlite3Fts5ClearLocale(pConfig);
+ }
+ sqlite3_value_free(pFree);
}
}
if( rc==SQLITE_OK && p->nTotalRow<1 ){
@@ -253170,12 +258138,30 @@ static int fts5StorageDeleteFromIndex(
p->nTotalRow--;
}
- rc2 = sqlite3_reset(pSeek);
- if( rc==SQLITE_OK ) rc = rc2;
+ if( rc==SQLITE_OK && bSaveRow ){
+ assert( p->pSavedRow==0 );
+ p->pSavedRow = pSeek;
+ }else{
+ rc2 = sqlite3_reset(pSeek);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
return rc;
}
/*
+** Reset any saved statement pSavedRow. Zero pSavedRow as well. This
+** should be called by the xUpdate() method of the fts5 table before
+** returning from any operation that may have set Fts5Storage.pSavedRow.
+*/
+static void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage *pStorage){
+ assert( pStorage->pSavedRow==0
+ || pStorage->pSavedRow==pStorage->aStmt[FTS5_STMT_LOOKUP2]
+ );
+ sqlite3_reset(pStorage->pSavedRow);
+ pStorage->pSavedRow = 0;
+}
+
+/*
** This function is called to process a DELETE on a contentless_delete=1
** table. It adds the tombstone required to delete the entry with rowid
** iDel. If successful, SQLITE_OK is returned. Or, if an error occurs,
@@ -253187,7 +258173,9 @@ static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){
int rc = SQLITE_OK;
assert( p->pConfig->bContentlessDelete );
- assert( p->pConfig->eContent==FTS5_CONTENT_NONE );
+ assert( p->pConfig->eContent==FTS5_CONTENT_NONE
+ || p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
+ );
/* Look up the origin of the document in the %_docsize table. Store
** this in stack variable iOrigin. */
@@ -253231,12 +258219,12 @@ static int fts5StorageInsertDocsize(
rc = sqlite3Fts5IndexGetOrigin(p->pIndex, &iOrigin);
sqlite3_bind_int64(pReplace, 3, iOrigin);
}
- if( rc==SQLITE_OK ){
- sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
- sqlite3_step(pReplace);
- rc = sqlite3_reset(pReplace);
- sqlite3_bind_null(pReplace, 2);
- }
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
+ sqlite3_step(pReplace);
+ rc = sqlite3_reset(pReplace);
+ sqlite3_bind_null(pReplace, 2);
}
}
return rc;
@@ -253290,7 +258278,12 @@ static int fts5StorageSaveTotals(Fts5Storage *p){
/*
** Remove a row from the FTS table.
*/
-static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
+static int sqlite3Fts5StorageDelete(
+ Fts5Storage *p, /* Storage object */
+ i64 iDel, /* Rowid to delete from table */
+ sqlite3_value **apVal, /* Optional - values to remove from index */
+ int bSaveRow /* If true, set pSavedRow for deleted row */
+){
Fts5Config *pConfig = p->pConfig;
int rc;
sqlite3_stmt *pDel = 0;
@@ -253306,8 +258299,14 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **ap
if( rc==SQLITE_OK ){
if( p->pConfig->bContentlessDelete ){
rc = fts5StorageContentlessDelete(p, iDel);
+ if( rc==SQLITE_OK
+ && bSaveRow
+ && p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
+ ){
+ rc = sqlite3Fts5StorageFindDeleteRow(p, iDel);
+ }
}else{
- rc = fts5StorageDeleteFromIndex(p, iDel, apVal);
+ rc = fts5StorageDeleteFromIndex(p, iDel, apVal, bSaveRow);
}
}
@@ -253322,7 +258321,9 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **ap
}
/* Delete the %_content record */
- if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL
+ || pConfig->eContent==FTS5_CONTENT_UNINDEXED
+ ){
if( rc==SQLITE_OK ){
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
}
@@ -253354,8 +258355,13 @@ static int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
);
if( rc==SQLITE_OK && pConfig->bColumnsize ){
rc = fts5ExecPrintf(pConfig->db, 0,
- "DELETE FROM %Q.'%q_docsize';",
- pConfig->zDb, pConfig->zName
+ "DELETE FROM %Q.'%q_docsize';", pConfig->zDb, pConfig->zName
+ );
+ }
+
+ if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
+ rc = fts5ExecPrintf(pConfig->db, 0,
+ "DELETE FROM %Q.'%q_content';", pConfig->zDb, pConfig->zName
);
}
@@ -253396,14 +258402,36 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p){
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
ctx.szCol = 0;
if( pConfig->abUnindexed[ctx.iCol]==0 ){
- const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
- int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- zText, nText,
- (void*)&ctx,
- fts5StorageInsertCallback
- );
+ int nText = 0; /* Size of pText in bytes */
+ const char *pText = 0; /* Pointer to buffer containing text value */
+ int nLoc = 0; /* Size of pLoc in bytes */
+ const char *pLoc = 0; /* Pointer to buffer containing text value */
+
+ sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);
+ if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
+ && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+ ){
+ rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+ }else{
+ pText = (const char*)sqlite3_value_text(pVal);
+ nText = sqlite3_value_bytes(pVal);
+ if( pConfig->bLocale ){
+ int iCol = ctx.iCol + 1 + pConfig->nCol;
+ pLoc = (const char*)sqlite3_column_text(pScan, iCol);
+ nLoc = sqlite3_column_bytes(pScan, iCol);
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+ rc = sqlite3Fts5Tokenize(pConfig,
+ FTS5_TOKENIZE_DOCUMENT,
+ pText, nText,
+ (void*)&ctx,
+ fts5StorageInsertCallback
+ );
+ sqlite3Fts5ClearLocale(pConfig);
+ }
}
sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
@@ -253469,6 +258497,7 @@ static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
*/
static int sqlite3Fts5StorageContentInsert(
Fts5Storage *p,
+ int bReplace, /* True to use REPLACE instead of INSERT */
sqlite3_value **apVal,
i64 *piRowid
){
@@ -253476,7 +258505,9 @@ static int sqlite3Fts5StorageContentInsert(
int rc = SQLITE_OK;
/* Insert the new row into the %_content table. */
- if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
+ if( pConfig->eContent!=FTS5_CONTENT_NORMAL
+ && pConfig->eContent!=FTS5_CONTENT_UNINDEXED
+ ){
if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
*piRowid = sqlite3_value_int64(apVal[1]);
}else{
@@ -253485,9 +258516,52 @@ static int sqlite3Fts5StorageContentInsert(
}else{
sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
int i; /* Counter variable */
- rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
- for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
- rc = sqlite3_bind_value(pInsert, i, apVal[i]);
+
+ assert( FTS5_STMT_INSERT_CONTENT+1==FTS5_STMT_REPLACE_CONTENT );
+ assert( bReplace==0 || bReplace==1 );
+ rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT+bReplace, &pInsert, 0);
+ if( pInsert ) sqlite3_clear_bindings(pInsert);
+
+ /* Bind the rowid value */
+ sqlite3_bind_value(pInsert, 1, apVal[1]);
+
+ /* Loop through values for user-defined columns. i=2 is the leftmost
+ ** user-defined column. As is column 1 of pSavedRow. */
+ for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
+ int bUnindexed = pConfig->abUnindexed[i-2];
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL || bUnindexed ){
+ sqlite3_value *pVal = apVal[i];
+
+ if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
+ /* This is an UPDATE statement, and user-defined column (i-2) was not
+ ** modified. Retrieve the value from Fts5Storage.pSavedRow. */
+ pVal = sqlite3_column_value(p->pSavedRow, i-1);
+ if( pConfig->bLocale && bUnindexed==0 ){
+ sqlite3_bind_value(pInsert, pConfig->nCol + i,
+ sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1)
+ );
+ }
+ }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+ const char *pText = 0;
+ const char *pLoc = 0;
+ int nText = 0;
+ int nLoc = 0;
+ assert( pConfig->bLocale );
+
+ rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
+ if( bUnindexed==0 ){
+ int iLoc = pConfig->nCol + i;
+ sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
+ }
+ }
+
+ continue;
+ }
+
+ rc = sqlite3_bind_value(pInsert, i, pVal);
+ }
}
if( rc==SQLITE_OK ){
sqlite3_step(pInsert);
@@ -253522,14 +258596,38 @@ static int sqlite3Fts5StorageIndexInsert(
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
ctx.szCol = 0;
if( pConfig->abUnindexed[ctx.iCol]==0 ){
- const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
- int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- zText, nText,
- (void*)&ctx,
- fts5StorageInsertCallback
- );
+ int nText = 0; /* Size of pText in bytes */
+ const char *pText = 0; /* Pointer to buffer containing text value */
+ int nLoc = 0; /* Size of pText in bytes */
+ const char *pLoc = 0; /* Pointer to buffer containing text value */
+
+ sqlite3_value *pVal = apVal[ctx.iCol+2];
+ if( p->pSavedRow && sqlite3_value_nochange(pVal) ){
+ pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1);
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
+ int iCol = ctx.iCol + 1 + pConfig->nCol;
+ pLoc = (const char*)sqlite3_column_text(p->pSavedRow, iCol);
+ nLoc = sqlite3_column_bytes(p->pSavedRow, iCol);
+ }
+ }else{
+ pVal = apVal[ctx.iCol+2];
+ }
+
+ if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
+ rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
+ }else{
+ pText = (const char*)sqlite3_value_text(pVal);
+ nText = sqlite3_value_bytes(pVal);
+ }
+
+ if( rc==SQLITE_OK ){
+ sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+ rc = sqlite3Fts5Tokenize(pConfig,
+ FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx,
+ fts5StorageInsertCallback
+ );
+ sqlite3Fts5ClearLocale(pConfig);
+ }
}
sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
@@ -253693,29 +258791,61 @@ static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
}
for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( pConfig->abUnindexed[i] ) continue;
- ctx.iCol = i;
- ctx.szCol = 0;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- if( rc==SQLITE_OK ){
- const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
- int nText = sqlite3_column_bytes(pScan, i+1);
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- zText, nText,
- (void*)&ctx,
- fts5StorageIntegrityCallback
- );
- }
- if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
- rc = FTS5_CORRUPT;
- }
- aTotalSize[i] += ctx.szCol;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
+ if( pConfig->abUnindexed[i]==0 ){
+ const char *pText = 0;
+ int nText = 0;
+ const char *pLoc = 0;
+ int nLoc = 0;
+ sqlite3_value *pVal = sqlite3_column_value(pScan, i+1);
+
+ if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
+ && sqlite3Fts5IsLocaleValue(pConfig, pVal)
+ ){
+ rc = sqlite3Fts5DecodeLocaleValue(
+ pVal, &pText, &nText, &pLoc, &nLoc
+ );
+ }else{
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
+ int iCol = i + 1 + pConfig->nCol;
+ pLoc = (const char*)sqlite3_column_text(pScan, iCol);
+ nLoc = sqlite3_column_bytes(pScan, iCol);
+ }
+ pText = (const char*)sqlite3_value_text(pVal);
+ nText = sqlite3_value_bytes(pVal);
+ }
+
+ ctx.iCol = i;
+ ctx.szCol = 0;
+
+ if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
+ }
+
+ if( rc==SQLITE_OK ){
+ sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
+ rc = sqlite3Fts5Tokenize(pConfig,
+ FTS5_TOKENIZE_DOCUMENT,
+ pText, nText,
+ (void*)&ctx,
+ fts5StorageIntegrityCallback
+ );
+ sqlite3Fts5ClearLocale(pConfig);
+ }
+
+ /* If this is not a columnsize=0 database, check that the number
+ ** of tokens in the value matches the aColSize[] value read from
+ ** the %_docsize table. */
+ if( rc==SQLITE_OK
+ && pConfig->bColumnsize
+ && ctx.szCol!=aColSize[i]
+ ){
+ rc = FTS5_CORRUPT;
+ }
+ aTotalSize[i] += ctx.szCol;
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ sqlite3Fts5TermsetFree(ctx.pTermset);
+ ctx.pTermset = 0;
+ }
}
}
sqlite3Fts5TermsetFree(ctx.pTermset);
@@ -254022,7 +259152,7 @@ static int fts5AsciiCreate(
int i;
memset(p, 0, sizeof(AsciiTokenizer));
memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar));
- for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
fts5AsciiAddExceptions(p, zArg, 1);
@@ -254033,7 +259163,6 @@ static int fts5AsciiCreate(
rc = SQLITE_ERROR;
}
}
- if( rc==SQLITE_OK && i<nArg ) rc = SQLITE_ERROR;
if( rc!=SQLITE_OK ){
fts5AsciiDelete((Fts5Tokenizer*)p);
p = 0;
@@ -254142,7 +259271,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ while( zIn<zTerm && (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
@@ -254325,7 +259454,7 @@ static int fts5UnicodeCreate(
}
/* Search for a "categories" argument */
- for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
if( 0==sqlite3_stricmp(azArg[i], "categories") ){
zCat = azArg[i+1];
}
@@ -254334,7 +259463,7 @@ static int fts5UnicodeCreate(
rc = unicodeSetCategories(p, zCat);
}
- for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
@@ -254359,8 +259488,6 @@ static int fts5UnicodeCreate(
rc = SQLITE_ERROR;
}
}
- if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;
-
}else{
rc = SQLITE_NOMEM;
}
@@ -254499,7 +259626,7 @@ static int fts5UnicodeTokenize(
typedef struct PorterTokenizer PorterTokenizer;
struct PorterTokenizer {
- fts5_tokenizer tokenizer; /* Parent tokenizer module */
+ fts5_tokenizer_v2 tokenizer_v2; /* Parent tokenizer module */
Fts5Tokenizer *pTokenizer; /* Parent tokenizer instance */
char aBuf[FTS5_PORTER_MAX_TOKEN + 64];
};
@@ -254511,7 +259638,7 @@ static void fts5PorterDelete(Fts5Tokenizer *pTok){
if( pTok ){
PorterTokenizer *p = (PorterTokenizer*)pTok;
if( p->pTokenizer ){
- p->tokenizer.xDelete(p->pTokenizer);
+ p->tokenizer_v2.xDelete(p->pTokenizer);
}
sqlite3_free(p);
}
@@ -254530,6 +259657,7 @@ static int fts5PorterCreate(
PorterTokenizer *pRet;
void *pUserdata = 0;
const char *zBase = "unicode61";
+ fts5_tokenizer_v2 *pV2 = 0;
if( nArg>0 ){
zBase = azArg[0];
@@ -254538,14 +259666,15 @@ static int fts5PorterCreate(
pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer));
if( pRet ){
memset(pRet, 0, sizeof(PorterTokenizer));
- rc = pApi->xFindTokenizer(pApi, zBase, &pUserdata, &pRet->tokenizer);
+ rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2);
}else{
rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
int nArg2 = (nArg>0 ? nArg-1 : 0);
- const char **azArg2 = (nArg2 ? &azArg[1] : 0);
- rc = pRet->tokenizer.xCreate(pUserdata, azArg2, nArg2, &pRet->pTokenizer);
+ const char **az2 = (nArg2 ? &azArg[1] : 0);
+ memcpy(&pRet->tokenizer_v2, pV2, sizeof(fts5_tokenizer_v2));
+ rc = pRet->tokenizer_v2.xCreate(pUserdata, az2, nArg2, &pRet->pTokenizer);
}
if( rc!=SQLITE_OK ){
@@ -255196,6 +260325,7 @@ static int fts5PorterTokenize(
void *pCtx,
int flags,
const char *pText, int nText,
+ const char *pLoc, int nLoc,
int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd)
){
PorterTokenizer *p = (PorterTokenizer*)pTokenizer;
@@ -255203,8 +260333,8 @@ static int fts5PorterTokenize(
sCtx.xToken = xToken;
sCtx.pCtx = pCtx;
sCtx.aBuf = p->aBuf;
- return p->tokenizer.xTokenize(
- p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
+ return p->tokenizer_v2.xTokenize(
+ p->pTokenizer, (void*)&sCtx, flags, pText, nText, pLoc, nLoc, fts5PorterCb
);
}
@@ -255234,41 +260364,46 @@ static int fts5TriCreate(
Fts5Tokenizer **ppOut
){
int rc = SQLITE_OK;
- TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
+ TrigramTokenizer *pNew = 0;
UNUSED_PARAM(pUnused);
- if( pNew==0 ){
- rc = SQLITE_NOMEM;
+ if( nArg%2 ){
+ rc = SQLITE_ERROR;
}else{
int i;
- pNew->bFold = 1;
- pNew->iFoldParam = 0;
- for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
- const char *zArg = azArg[i+1];
- if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
- if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
- rc = SQLITE_ERROR;
+ pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pNew->bFold = 1;
+ pNew->iFoldParam = 0;
+
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
+ const char *zArg = azArg[i+1];
+ if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
+ if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
+ rc = SQLITE_ERROR;
+ }else{
+ pNew->bFold = (zArg[0]=='0');
+ }
+ }else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
+ if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
+ rc = SQLITE_ERROR;
+ }else{
+ pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
+ }
}else{
- pNew->bFold = (zArg[0]=='0');
- }
- }else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
- if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
rc = SQLITE_ERROR;
- }else{
- pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
}
- }else{
- rc = SQLITE_ERROR;
}
- }
- if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;
- if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
- rc = SQLITE_ERROR;
- }
+ if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
+ rc = SQLITE_ERROR;
+ }
- if( rc!=SQLITE_OK ){
- fts5TriDelete((Fts5Tokenizer*)pNew);
- pNew = 0;
+ if( rc!=SQLITE_OK ){
+ fts5TriDelete((Fts5Tokenizer*)pNew);
+ pNew = 0;
+ }
}
}
*ppOut = (Fts5Tokenizer*)pNew;
@@ -255291,8 +260426,8 @@ static int fts5TriTokenize(
char *zOut = aBuf;
int ii;
const unsigned char *zIn = (const unsigned char*)pText;
- const unsigned char *zEof = &zIn[nText];
- u32 iCode;
+ const unsigned char *zEof = (zIn ? &zIn[nText] : 0);
+ u32 iCode = 0;
int aStart[3]; /* Input offset of each character in aBuf[] */
UNUSED_PARAM(unusedFlags);
@@ -255301,8 +260436,8 @@ static int fts5TriTokenize(
for(ii=0; ii<3; ii++){
do {
aStart[ii] = zIn - (const unsigned char*)pText;
+ if( zIn>=zEof ) return SQLITE_OK;
READ_UTF8(zIn, zEof, iCode);
- if( iCode==0 ) return SQLITE_OK;
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
}while( iCode==0 );
WRITE_UTF8(zOut, iCode);
@@ -255323,8 +260458,11 @@ static int fts5TriTokenize(
/* Read characters from the input up until the first non-diacritic */
do {
iNext = zIn - (const unsigned char*)pText;
+ if( zIn>=zEof ){
+ iCode = 0;
+ break;
+ }
READ_UTF8(zIn, zEof, iCode);
- if( iCode==0 ) break;
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
}while( iCode==0 );
@@ -255374,6 +260512,16 @@ static int sqlite3Fts5TokenizerPattern(
}
/*
+** Return true if the tokenizer described by p->azArg[] is the trigram
+** tokenizer. This tokenizer needs to be loaded before xBestIndex is
+** called for the first time in order to correctly handle LIKE/GLOB.
+*/
+static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){
+ return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram"));
+}
+
+
+/*
** Register all built-in tokenizers with FTS5.
*/
static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -255383,7 +260531,6 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
} aBuiltin[] = {
{ "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
{ "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
- { "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
{ "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
};
@@ -255398,7 +260545,20 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
0
);
}
-
+ if( rc==SQLITE_OK ){
+ fts5_tokenizer_v2 sPorter = {
+ 2,
+ fts5PorterCreate,
+ fts5PorterDelete,
+ fts5PorterTokenize
+ };
+ rc = pApi->xCreateTokenizer_v2(pApi,
+ "porter",
+ (void*)pApi,
+ &sPorter,
+ 0
+ );
+ }
return rc;
}
@@ -255768,6 +260928,9 @@ static int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
default: return 1; }
break;
+
+ default:
+ return 1;
}
return 0;
}
@@ -256180,7 +261343,6 @@ static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
aAscii[0] = 0; /* 0x00 is never a token character */
}
-
/*
** 2015 May 30
**
@@ -256592,6 +261754,7 @@ struct Fts5VocabCursor {
int nLeTerm; /* Size of zLeTerm in bytes */
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
+ int colUsed; /* Copy of sqlite3_index_info.colUsed */
/* These are used by 'col' tables only */
int iCol;
@@ -256618,9 +261781,11 @@ struct Fts5VocabCursor {
/*
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
*/
-#define FTS5_VOCAB_TERM_EQ 0x01
-#define FTS5_VOCAB_TERM_GE 0x02
-#define FTS5_VOCAB_TERM_LE 0x04
+#define FTS5_VOCAB_TERM_EQ 0x0100
+#define FTS5_VOCAB_TERM_GE 0x0200
+#define FTS5_VOCAB_TERM_LE 0x0400
+
+#define FTS5_VOCAB_COLUSED_MASK 0xFF
/*
@@ -256718,12 +261883,12 @@ static int fts5VocabInitVtab(
*pzErr = sqlite3_mprintf("wrong number of vtable arguments");
rc = SQLITE_ERROR;
}else{
- int nByte; /* Bytes of space to allocate */
+ i64 nByte; /* Bytes of space to allocate */
const char *zDb = bDb ? argv[3] : argv[1];
const char *zTab = bDb ? argv[4] : argv[3];
const char *zType = bDb ? argv[5] : argv[4];
- int nDb = (int)strlen(zDb)+1;
- int nTab = (int)strlen(zTab)+1;
+ i64 nDb = strlen(zDb)+1;
+ i64 nTab = strlen(zTab)+1;
int eType = 0;
rc = fts5VocabTableType(zType, pzErr, &eType);
@@ -256797,11 +261962,13 @@ static int fts5VocabBestIndexMethod(
int iTermEq = -1;
int iTermGe = -1;
int iTermLe = -1;
- int idxNum = 0;
+ int idxNum = (int)pInfo->colUsed;
int nArg = 0;
UNUSED_PARAM(pUnused);
+ assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
+
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
if( p->usable==0 ) continue;
@@ -256893,7 +262060,7 @@ static int fts5VocabOpenMethod(
if( rc==SQLITE_OK ){
pVTab->zErrMsg = sqlite3_mprintf(
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
- );
+ );
rc = SQLITE_ERROR;
}
}else{
@@ -257053,9 +262220,19 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
switch( pTab->eType ){
case FTS5_VOCAB_ROW:
- if( eDetail==FTS5_DETAIL_FULL ){
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
- pCsr->aCnt[0]++;
+ /* Do not bother counting the number of instances if the "cnt"
+ ** column is not being read (according to colUsed). */
+ if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
+ while( iPos<nPos ){
+ u32 ii;
+ fts5FastGetVarint32(pPos, iPos, ii);
+ if( ii==1 ){
+ /* New column in the position list */
+ fts5FastGetVarint32(pPos, iPos, ii);
+ }else{
+ /* An instance - increment pCsr->aCnt[] */
+ pCsr->aCnt[0]++;
+ }
}
}
pCsr->aDoc[0]++;
@@ -257153,6 +262330,7 @@ static int fts5VocabFilterMethod(
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
+ pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);
if( pEq ){
zTerm = (const char *)sqlite3_value_text(pEq);
@@ -257320,7 +262498,7 @@ static int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
}
-
+/* Here ends the fts5.c composite file. */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
/************** End of fts5.c ************************************************/
@@ -257676,4 +262854,5 @@ SQLITE_API int sqlite3_stmt_init(
/************** End of stmt.c ************************************************/
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
+#endif /* SQLITE_AMALGAMATION */
/************************** End of sqlite3.c ******************************/