summaryrefslogtreecommitdiff
path: root/ext/sqlite3
diff options
context:
space:
mode:
authorScott MacVicar <scottmac@php.net>2009-05-07 11:27:45 +0000
committerScott MacVicar <scottmac@php.net>2009-05-07 11:27:45 +0000
commite718846c5bce9d9be555a838909fb8db7be3ca39 (patch)
tree9ce2bb2254661cf5f4a8adbddb1120ac447bc321 /ext/sqlite3
parentcba448a9d358451338d57c5e45f7c7e06f3143d2 (diff)
downloadphp-git-e718846c5bce9d9be555a838909fb8db7be3ca39.tar.gz
MFH Update bundled libsqlite to 3.6.14
Diffstat (limited to 'ext/sqlite3')
-rw-r--r--ext/sqlite3/libsqlite/sqlite3.c4128
-rw-r--r--ext/sqlite3/libsqlite/sqlite3.h240
2 files changed, 2534 insertions, 1834 deletions
diff --git a/ext/sqlite3/libsqlite/sqlite3.c b/ext/sqlite3/libsqlite/sqlite3.c
index ea10f8d0de..da0d008d22 100644
--- a/ext/sqlite3/libsqlite/sqlite3.c
+++ b/ext/sqlite3/libsqlite/sqlite3.c
@@ -4,7 +4,7 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.13. By combining all the individual C code files into this
+** version 3.6.14. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a one translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -15,13 +15,13 @@
** programs, you need this file and the "sqlite3.h" header file that defines
** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy in the first
-** 5503 lines past this header comment.) Additional code files may be
+** 5533 lines past this header comment.) Additional code files may be
** needed if you want a wrapper to interface SQLite with your choice of
** programming language. The code for the "sqlite3" command-line shell
** is also in a separate file. This file contains only code for the core
** SQLite library.
**
-** This amalgamation was generated on 2009-04-13 09:10:17 UTC.
+** This amalgamation was generated on 2009-05-07 01:56:00 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ -369,10 +369,10 @@
#endif
/*
-** If SQLITE_MALLOC_SOFT_LIMIT is defined, then try to keep the
+** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
** sizes of memory allocations below this value where possible.
*/
-#if defined(SQLITE_POW2_MEMORY_SIZE) && !defined(SQLITE_MALLOC_SOFT_LIMIT)
+#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
# define SQLITE_MALLOC_SOFT_LIMIT 1024
#endif
@@ -444,6 +444,20 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
#endif
/*
+** Sometimes we need a small amount of code such as a variable initialization
+** to setup for a later assert() statement. We do not want this code to
+** appear when assert() is disabled. The following macro is therefore
+** used to contain that setup code. The "VVA" acronym stands for
+** "Verification, Validation, and Accreditation". In other words, the
+** code within VVA_ONLY() will only run during verification processes.
+*/
+#ifndef NDEBUG
+# define VVA_ONLY(X) X
+#else
+# define VVA_ONLY(X)
+#endif
+
+/*
** The ALWAYS and NEVER macros surround boolean expressions which
** are intended to always be true or false, respectively. Such
** expressions could be omitted from the code completely. But they
@@ -484,20 +498,6 @@ SQLITE_PRIVATE int sqlite3Assert(void);
# define unlikely(X) !!(X)
#endif
-/*
-** Sometimes we need a small amount of code such as a variable initialization
-** to setup for a later assert() statement. We do not want this code to
-** appear when assert() is disabled. The following macro is therefore
-** used to contain that setup code. The "VVA" acronym stands for
-** "Verification, Validation, and Accreditation". In other words, the
-** code within VVA_ONLY() will only run during verification processes.
-*/
-#ifndef NDEBUG
-# define VVA_ONLY(X) X
-#else
-# define VVA_ONLY(X)
-#endif
-
/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
/************** Begin file sqlite3.h *****************************************/
/*
@@ -601,8 +601,8 @@ extern "C" {
**
** Requirements: [H10011] [H10014]
*/
-#define SQLITE_VERSION "3.6.13"
-#define SQLITE_VERSION_NUMBER 3006013
+#define SQLITE_VERSION "3.6.14"
+#define SQLITE_VERSION_NUMBER 3006014
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -1293,6 +1293,11 @@ struct sqlite3_vfs {
** of sqlite3_initialize() does any initialization. All other calls
** are harmless no-ops.
**
+** A call to sqlite3_shutdown() is an "effective" call if it is the first
+** call to sqlite3_shutdown() since the last sqlite3_initialize(). Only
+** an effective call to sqlite3_shutdown() does any deinitialization.
+** All other calls to sqlite3_shutdown() are harmless no-ops.
+**
** Among other things, sqlite3_initialize() shall invoke
** sqlite3_os_init(). Similarly, sqlite3_shutdown()
** shall invoke sqlite3_os_end().
@@ -1720,14 +1725,18 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** triggers are not counted. Use the [sqlite3_total_changes()] function
** to find the total number of changes including changes caused by triggers.
**
+** Changes to a view that are simulated by an [INSTEAD OF trigger]
+** are not counted. Only real table changes are counted.
+**
** A "row change" is a change to a single row of a single table
** caused by an INSERT, DELETE, or UPDATE statement. Rows that
-** are changed as side effects of REPLACE constraint resolution,
-** rollback, ABORT processing, DROP TABLE, or by any other
+** are changed as side effects of [REPLACE] constraint resolution,
+** rollback, ABORT processing, [DROP TABLE], or by any other
** mechanisms do not count as direct row changes.
**
** A "trigger context" is a scope of execution that begins and
-** ends with the script of a trigger. Most SQL statements are
+** ends with the script of a [CREATE TRIGGER | trigger].
+** Most SQL statements are
** evaluated outside of any trigger. This is the "top level"
** trigger context. If a trigger fires from the top level, a
** new trigger context is entered for the duration of that one
@@ -1749,16 +1758,8 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** However, the number returned does not include changes
** caused by subtriggers since those have their own context.
**
-** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. Doing so is much faster than going
-** through and deleting individual elements from the table. Because of this
-** optimization, the deletions in "DELETE FROM table" are not row changes and
-** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
-** functions, regardless of the number of elements that were originally
-** in the table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead. Or recompile using the
-** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the
-** optimization on all queries.
+** See also the [sqlite3_total_changes()] interface and the
+** [count_changes pragma].
**
** Requirements:
** [H12241] [H12243]
@@ -1772,27 +1773,21 @@ SQLITE_API int sqlite3_changes(sqlite3*);
/*
** CAPI3REF: Total Number Of Rows Modified {H12260} <S10600>
**
-** This function returns the number of row changes caused by INSERT,
-** UPDATE or DELETE statements since the [database connection] was opened.
-** The count includes all changes from all trigger contexts. However,
-** the count does not include changes used to implement REPLACE constraints,
-** do rollbacks or ABORT processing, or DROP table processing.
+** This function returns the number of row changes caused by [INSERT],
+** [UPDATE] or [DELETE] statements since the [database connection] was opened.
+** The count includes all changes from all
+** [CREATE TRIGGER | trigger] contexts. However,
+** the count does not include changes used to implement [REPLACE] constraints,
+** do rollbacks or ABORT processing, or [DROP TABLE] processing. The
+** count does not rows of views that fire an [INSTEAD OF trigger], though if
+** the INSTEAD OF trigger makes changes of its own, those changes are
+** counted.
** The changes are counted as soon as the statement that makes them is
** completed (when the statement handle is passed to [sqlite3_reset()] or
** [sqlite3_finalize()]).
**
-** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. (This is much faster than going
-** through and deleting individual elements from the table.) Because of this
-** optimization, the deletions in "DELETE FROM table" are not row changes and
-** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
-** functions, regardless of the number of elements that were originally
-** in the table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead. Or recompile using the
-** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the
-** optimization on all queries.
-**
-** See also the [sqlite3_changes()] interface.
+** See also the [sqlite3_changes()] interface and the
+** [count_changes pragma].
**
** Requirements:
** [H12261] [H12263]
@@ -1826,8 +1821,16 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
** that is inside an explicit transaction, then the entire transaction
** will be rolled back automatically.
**
-** A call to sqlite3_interrupt() has no effect on SQL statements
-** that are started after sqlite3_interrupt() returns.
+** The sqlite3_interrupt(D) call is in effect until all currently running
+** SQL statements on [database connection] D complete. Any new SQL statements
+** that are started after the sqlite3_interrupt() call and before the
+** running statements reaches zero are interrupted as if they had been
+** running prior to the sqlite3_interrupt() call. New SQL statements
+** that are started after the running statement count reaches zero are
+** not effected by the sqlite3_interrupt().
+** A call to sqlite3_interrupt(D) that occurs when there are no running
+** SQL statements is a no-op and has no effect on SQL statements
+** that are started after the sqlite3_interrupt() call returns.
**
** Requirements:
** [H12271] [H12272]
@@ -1840,20 +1843,30 @@ SQLITE_API void sqlite3_interrupt(sqlite3*);
/*
** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} <S70200>
**
-** These routines are useful for command-line input to determine if the
-** currently entered text seems to form complete a SQL statement or
+** These routines are useful during command-line input to determine if the
+** currently entered text seems to form a complete SQL statement or
** if additional input is needed before sending the text into
-** SQLite for parsing. These routines return true if the input string
+** SQLite for parsing. These routines return 1 if the input string
** appears to be a complete SQL statement. A statement is judged to be
-** complete if it ends with a semicolon token and is not a fragment of a
-** CREATE TRIGGER statement. Semicolons that are embedded within
+** complete if it ends with a semicolon token and is not a prefix of a
+** well-formed CREATE TRIGGER statement. Semicolons that are embedded within
** string literals or quoted identifier names or comments are not
** independent tokens (they are part of the token in which they are
-** embedded) and thus do not count as a statement terminator.
+** embedded) and thus do not count as a statement terminator. Whitespace
+** and comments that follow the final semicolon are ignored.
+**
+** These routines return 0 if the statement is incomplete. If a
+** memory allocation fails, then SQLITE_NOMEM is returned.
**
** These routines do not parse the SQL statements thus
** will not detect syntactically incorrect SQL.
**
+** If SQLite has not been initialized using [sqlite3_initialize()] prior
+** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
+** automatically by sqlite3_complete16(). If that initialization fails,
+** then the return value from sqlite3_complete16() will be non-zero
+** regardless of whether or not the input SQL is complete.
+**
** Requirements: [H10511] [H10512]
**
** The input to [sqlite3_complete()] must be a zero-terminated
@@ -2281,13 +2294,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** requested is ok. When the callback returns [SQLITE_DENY], the
** [sqlite3_prepare_v2()] or equivalent call that triggered the
** authorizer will fail with an error message explaining that
-** access is denied. If the authorizer code is [SQLITE_READ]
-** and the callback returns [SQLITE_IGNORE] then the
-** [prepared statement] statement is constructed to substitute
-** a NULL value in place of the table column that would have
-** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
-** return can be used to deny an untrusted user access to individual
-** columns of a table.
+** access is denied.
**
** The first parameter to the authorizer callback is a copy of the third
** parameter to the sqlite3_set_authorizer() interface. The second parameter
@@ -2296,6 +2303,17 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** to the callback are zero-terminated strings that contain additional
** details about the action to be authorized.
**
+** If the action code is [SQLITE_READ]
+** and the callback returns [SQLITE_IGNORE] then the
+** [prepared statement] statement is constructed to substitute
+** a NULL value in place of the table column that would have
+** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
+** return can be used to deny an untrusted user access to individual
+** columns of a table.
+** If the action code is [SQLITE_DELETE] and the callback returns
+** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
+** [truncate optimization] is disabled and all rows are deleted individually.
+**
** An authorizer is used when [sqlite3_prepare | preparing]
** SQL statements from an untrusted source, to ensure that the SQL statements
** do not try to access data they are not allowed to see, or that they do not
@@ -2329,7 +2347,9 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
**
** Note that the authorizer callback is invoked only during
** [sqlite3_prepare()] or its variants. Authorization is not
-** performed during statement evaluation in [sqlite3_step()].
+** performed during statement evaluation in [sqlite3_step()], unless
+** as stated in the previous paragraph, sqlite3_step() invokes
+** sqlite3_prepare_v2() to reprepare a statement after a schema change.
**
** Requirements:
** [H12501] [H12502] [H12503] [H12504] [H12505] [H12506] [H12507] [H12510]
@@ -3985,12 +4005,14 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
** the name is passed as the second function argument.
**
** The third argument may be one of the constants [SQLITE_UTF8],
-** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied
+** [SQLITE_UTF16LE], or [SQLITE_UTF16BE], indicating that the user-supplied
** routine expects to be passed pointers to strings encoded using UTF-8,
** UTF-16 little-endian, or UTF-16 big-endian, respectively. The
-** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that
+** third argument might also be [SQLITE_UTF16] to indicate that the routine
+** expects pointers to be UTF-16 strings in the native byte order, or the
+** argument can be [SQLITE_UTF16_ALIGNED] if the
** the routine expects pointers to 16-bit word aligned strings
-** of UTF-16 in the native byte order of the host computer.
+** of UTF-16 in the native byte order.
**
** A pointer to the user supplied routine must be passed as the fifth
** argument. If it is NULL, this is the same as deleting the collation
@@ -4015,6 +4037,8 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
** collation creation functions or when the [database connection] is closed
** using [sqlite3_close()].
**
+** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
+**
** Requirements:
** [H16603] [H16604] [H16606] [H16609] [H16612] [H16615] [H16618] [H16621]
** [H16624] [H16627] [H16630]
@@ -4568,15 +4592,20 @@ typedef struct sqlite3_module sqlite3_module;
/*
** CAPI3REF: Virtual Table Object {H18000} <S20400>
-** KEYWORDS: sqlite3_module
+** KEYWORDS: sqlite3_module {virtual table module}
** EXPERIMENTAL
**
-** A module is a class of virtual tables. Each module is defined
-** by an instance of the following structure. This structure consists
-** mostly of methods for the module.
+** This structure, sometimes called a a "virtual table module",
+** defines the implementation of a [virtual tables].
+** This structure consists mostly of methods for the module.
**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
+** A virtual table module is created by filling in a persistent
+** instance of this structure and passing a pointer to that instance
+** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
+** The registration remains valid until it is replaced by a different
+** module or until the [database connection] closes. The content
+** of this structure must not change while it is registered with
+** any database connection.
*/
struct sqlite3_module {
int iVersion;
@@ -4614,8 +4643,8 @@ struct sqlite3_module {
** EXPERIMENTAL
**
** The sqlite3_index_info structure and its substructures is used to
-** pass information into and receive the reply from the xBestIndex
-** method of an sqlite3_module. The fields under **Inputs** are the
+** pass information into and receive the reply from the [xBestIndex]
+** method of a [virtual table module]. The fields under **Inputs** are the
** inputs to xBestIndex and are read-only. xBestIndex inserts its
** results into the **Outputs** fields.
**
@@ -4638,17 +4667,19 @@ struct sqlite3_module {
** Information about the ORDER BY clause is stored in aOrderBy[].
** Each term of aOrderBy records a column of the ORDER BY clause.
**
-** The xBestIndex method must fill aConstraintUsage[] with information
+** The [xBestIndex] method must fill aConstraintUsage[] with information
** about what parameters to pass to xFilter. If argvIndex>0 then
** the right-hand side of the corresponding aConstraint[] is evaluated
** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit
** is true, then the constraint is assumed to be fully handled by the
** virtual table and is not checked again by SQLite.
**
-** The idxNum and idxPtr values are recorded and passed into xFilter.
-** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true.
+** The idxNum and idxPtr values are recorded and passed into the
+** [xFilter] method.
+** [sqlite3_free()] is used to free idxPtr if and only iff
+** needToFreeIdxPtr is true.
**
-** The orderByConsumed means that output from xFilter will occur in
+** The orderByConsumed means that output from [xFilter]/[xNext] will occur in
** the correct order to satisfy the ORDER BY clause so that no separate
** sorting step is required.
**
@@ -4656,9 +4687,6 @@ struct sqlite3_module {
** particular lookup. A full scan of a table with N entries should have
** a cost of N. A binary search of a table of N entries should have a
** cost of approximately log(N).
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
*/
struct sqlite3_index_info {
/* Inputs */
@@ -4696,34 +4724,44 @@ struct sqlite3_index_info {
** CAPI3REF: Register A Virtual Table Implementation {H18200} <S20400>
** EXPERIMENTAL
**
-** This routine is used to register a new module name with a
-** [database connection]. Module names must be registered before
-** creating new virtual tables on the module, or before using
-** preexisting virtual tables of the module.
+** This routine is used to register a new [virtual table module] name.
+** Module names must be registered before
+** creating a new [virtual table] using the module, or before using a
+** preexisting [virtual table] for the module.
+**
+** The module name is registered on the [database connection] specified
+** by the first parameter. The name of the module is given by the
+** second parameter. The third parameter is a pointer to
+** 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.
**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
+** This interface has exactly the same effect as calling
+** [sqlite3_create_module_v2()] with a NULL client data destructor.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
- const sqlite3_module *, /* Methods for the module */
- void * /* Client data for xCreate/xConnect */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData /* Client data for xCreate/xConnect */
);
/*
** CAPI3REF: Register A Virtual Table Implementation {H18210} <S20400>
** EXPERIMENTAL
**
-** This routine is identical to the [sqlite3_create_module()] method above,
-** except that it allows a destructor function to be specified. It is
-** even more experimental than the rest of the virtual tables API.
+** This routine is identical to the [sqlite3_create_module()] method,
+** except that it has an extra parameter to specify
+** a destructor function for the client data pointer. SQLite will
+** invoke the destructor function (if it is not NULL) when SQLite
+** no longer needs the pClientData pointer.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
- const sqlite3_module *, /* Methods for the module */
- void *, /* Client data for xCreate/xConnect */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData, /* Client data for xCreate/xConnect */
void(*xDestroy)(void*) /* Module destructor function */
);
@@ -4732,8 +4770,9 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
** KEYWORDS: sqlite3_vtab
** EXPERIMENTAL
**
-** Every module implementation uses a subclass of the following structure
-** to describe a particular instance of the module. Each subclass will
+** Every [virtual table module] implementation uses a subclass
+** of the following structure to describe a particular instance
+** of the [virtual table]. Each subclass will
** be tailored to the specific needs of the module implementation.
** The purpose of this superclass is to define certain fields that are
** common to all module implementations.
@@ -4743,13 +4782,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
** take care that any prior string is freed by a call to [sqlite3_free()]
** prior to assigning a new string to zErrMsg. After the error message
** is delivered up to the client application, the string will be automatically
-** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note
-** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field
-** since virtual tables are commonly implemented in loadable extensions which
-** do not have access to sqlite3MPrintf() or sqlite3Free().
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
+** freed by sqlite3_free() and the zErrMsg field will be zeroed.
*/
struct sqlite3_vtab {
const sqlite3_module *pModule; /* The module for this virtual table */
@@ -4760,20 +4793,21 @@ struct sqlite3_vtab {
/*
** CAPI3REF: Virtual Table Cursor Object {H18020} <S20400>
-** KEYWORDS: sqlite3_vtab_cursor
+** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
** EXPERIMENTAL
**
-** Every module implementation uses a subclass of the following structure
-** to describe cursors that point into the virtual table and are used
+** Every [virtual table module] implementation uses a subclass of the
+** following structure to describe cursors that point into the
+** [virtual table] and are used
** to loop through the virtual table. Cursors are created using the
-** xOpen method of the module. Each module implementation will define
+** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed
+** by the [sqlite3_module.xClose | xClose] method. Cussors are used
+** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
+** of the module. Each module implementation will define
** the content of a cursor structure to suit its own needs.
**
** This superclass exists in order to define fields of the cursor that
** are common to all implementations.
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
*/
struct sqlite3_vtab_cursor {
sqlite3_vtab *pVtab; /* Virtual table of this cursor */
@@ -4784,21 +4818,20 @@ struct sqlite3_vtab_cursor {
** CAPI3REF: Declare The Schema Of A Virtual Table {H18280} <S20400>
** EXPERIMENTAL
**
-** The xCreate and xConnect methods of a module use the following API
+** The [xCreate] and [xConnect] methods of a
+** [virtual table module] call this interface
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
/*
** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
** EXPERIMENTAL
**
** Virtual tables can provide alternative implementations of functions
-** using the xFindFunction method. But global versions of those functions
+** using the [xFindFunction] method of the [virtual table module].
+** But global versions of those functions
** must exist in order to be overloaded.
**
** This API makes sure a global version of a function with a particular
@@ -4807,10 +4840,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zC
** of the new function always causes an exception to be thrown. So
** the new function is not good for anything by itself. Its only
** purpose is to be a placeholder function that can be overloaded
-** by virtual tables.
-**
-** This API should be considered part of the virtual table interface,
-** which is experimental and subject to change.
+** by a [virtual table].
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
@@ -6035,13 +6065,25 @@ typedef struct HashElem HashElem;
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly. Change this structure only by using the routines below.
-** However, many of the "procedures" and "functions" for modifying and
+** However, some of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
+**
+** All elements of the hash table are on a single doubly-linked list.
+** Hash.first points to the head of this list.
+**
+** There are Hash.htsize buckets. Each bucket points to a spot in
+** the global doubly-linked list. The contents of the bucket are the
+** element pointed to plus the next _ht.count-1 elements in the list.
+**
+** Hash.htsize and Hash.ht may be zero. In that case lookup is done
+** by a linear search of the global list. For small tables, the
+** Hash.ht table is never allocated because if there are few elements
+** in the table, it is faster to do a linear search than to manage
+** the hash table.
*/
struct Hash {
- unsigned int copyKey: 1; /* True if copy of key made on insert */
- unsigned int htsize : 31; /* Number of buckets in the hash table */
+ unsigned int htsize; /* Number of buckets in the hash table */
unsigned int count; /* Number of entries in this table */
HashElem *first; /* The first element of the array */
struct _ht { /* the hash table */
@@ -6057,18 +6099,17 @@ struct Hash {
** be opaque because it is used by macros.
*/
struct HashElem {
- HashElem *next, *prev; /* Next and previous elements in the table */
- void *data; /* Data associated with this element */
- void *pKey; int nKey; /* Key associated with this element */
+ HashElem *next, *prev; /* Next and previous elements in the table */
+ void *data; /* Data associated with this element */
+ const char *pKey; int nKey; /* Key associated with this element */
};
/*
** Access routines. To delete, insert a NULL pointer.
*/
-SQLITE_PRIVATE void sqlite3HashInit(Hash*, int copyKey);
-SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData);
-SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const void *pKey, int nKey);
-SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey);
+SQLITE_PRIVATE void sqlite3HashInit(Hash*);
+SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData);
+SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey);
SQLITE_PRIVATE void sqlite3HashClear(Hash*);
/*
@@ -6086,13 +6127,13 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define sqliteHashFirst(H) ((H)->first)
#define sqliteHashNext(E) ((E)->next)
#define sqliteHashData(E) ((E)->data)
-#define sqliteHashKey(E) ((E)->pKey)
-#define sqliteHashKeysize(E) ((E)->nKey)
+/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */
+/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */
/*
** Number of entries in a hash table
*/
-#define sqliteHashCount(H) ((H)->count)
+/* #define sqliteHashCount(H) ((H)->count) // NOT USED */
#endif /* _SQLITE_HASH_H_ */
@@ -6729,7 +6770,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
const void *pData, int nData,
- int nZero, int bias);
+ int nZero, int bias, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes);
@@ -6975,106 +7016,106 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_If 11
#define OP_ToInt 144 /* same as TK_TO_INT */
#define OP_String8 94 /* same as TK_STRING */
-#define OP_VRowid 12
-#define OP_CollSeq 13
-#define OP_OpenRead 14
-#define OP_Expire 15
-#define OP_AutoCommit 16
+#define OP_CollSeq 12
+#define OP_OpenRead 13
+#define OP_Expire 14
+#define OP_AutoCommit 15
#define OP_Gt 75 /* same as TK_GT */
-#define OP_Pagecount 17
-#define OP_IntegrityCk 18
-#define OP_Sort 20
-#define OP_Copy 21
-#define OP_Trace 22
-#define OP_Function 23
-#define OP_IfNeg 24
+#define OP_Pagecount 16
+#define OP_IntegrityCk 17
+#define OP_Sort 18
+#define OP_Copy 20
+#define OP_Trace 21
+#define OP_Function 22
+#define OP_IfNeg 23
#define OP_And 67 /* same as TK_AND */
#define OP_Subtract 85 /* same as TK_MINUS */
-#define OP_Noop 25
-#define OP_Return 26
+#define OP_Noop 24
+#define OP_Return 25
#define OP_Remainder 88 /* same as TK_REM */
-#define OP_NewRowid 27
+#define OP_NewRowid 26
#define OP_Multiply 86 /* same as TK_STAR */
-#define OP_Variable 28
-#define OP_String 29
-#define OP_RealAffinity 30
-#define OP_VRename 31
-#define OP_ParseSchema 32
-#define OP_VOpen 33
-#define OP_Close 34
-#define OP_CreateIndex 35
-#define OP_IsUnique 36
-#define OP_NotFound 37
-#define OP_Int64 38
-#define OP_MustBeInt 39
-#define OP_Halt 40
-#define OP_Rowid 41
-#define OP_IdxLT 42
-#define OP_AddImm 43
-#define OP_Statement 44
-#define OP_RowData 45
-#define OP_MemMax 46
+#define OP_Variable 27
+#define OP_String 28
+#define OP_RealAffinity 29
+#define OP_VRename 30
+#define OP_ParseSchema 31
+#define OP_VOpen 32
+#define OP_Close 33
+#define OP_CreateIndex 34
+#define OP_IsUnique 35
+#define OP_NotFound 36
+#define OP_Int64 37
+#define OP_MustBeInt 38
+#define OP_Halt 39
+#define OP_Rowid 40
+#define OP_IdxLT 41
+#define OP_AddImm 42
+#define OP_Statement 43
+#define OP_RowData 44
+#define OP_MemMax 45
#define OP_Or 66 /* same as TK_OR */
-#define OP_NotExists 47
-#define OP_Gosub 48
+#define OP_NotExists 46
+#define OP_Gosub 47
#define OP_Divide 87 /* same as TK_SLASH */
-#define OP_Integer 49
+#define OP_Integer 48
#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/
-#define OP_Prev 50
-#define OP_RowSetRead 51
+#define OP_Prev 49
+#define OP_RowSetRead 50
#define OP_Concat 89 /* same as TK_CONCAT */
-#define OP_RowSetAdd 52
+#define OP_RowSetAdd 51
#define OP_BitAnd 80 /* same as TK_BITAND */
-#define OP_VColumn 53
-#define OP_CreateTable 54
-#define OP_Last 55
-#define OP_SeekLe 56
+#define OP_VColumn 52
+#define OP_CreateTable 53
+#define OP_Last 54
+#define OP_SeekLe 55
#define OP_IsNull 71 /* same as TK_ISNULL */
-#define OP_IncrVacuum 57
-#define OP_IdxRowid 58
+#define OP_IncrVacuum 56
+#define OP_IdxRowid 57
#define OP_ShiftRight 83 /* same as TK_RSHIFT */
-#define OP_ResetCount 59
-#define OP_ContextPush 60
-#define OP_Yield 61
-#define OP_DropTrigger 62
-#define OP_DropIndex 63
-#define OP_IdxGE 64
-#define OP_IdxDelete 65
-#define OP_Vacuum 68
-#define OP_IfNot 69
-#define OP_DropTable 70
-#define OP_SeekLt 79
-#define OP_MakeRecord 90
+#define OP_ResetCount 58
+#define OP_ContextPush 59
+#define OP_Yield 60
+#define OP_DropTrigger 61
+#define OP_DropIndex 62
+#define OP_IdxGE 63
+#define OP_IdxDelete 64
+#define OP_Vacuum 65
+#define OP_IfNot 68
+#define OP_DropTable 69
+#define OP_SeekLt 70
+#define OP_MakeRecord 79
#define OP_ToBlob 142 /* same as TK_TO_BLOB */
-#define OP_ResultRow 91
-#define OP_Delete 92
-#define OP_AggFinal 95
-#define OP_Compare 96
+#define OP_ResultRow 90
+#define OP_Delete 91
+#define OP_AggFinal 92
+#define OP_Compare 95
#define OP_ShiftLeft 82 /* same as TK_LSHIFT */
-#define OP_Goto 97
-#define OP_TableLock 98
-#define OP_Clear 99
+#define OP_Goto 96
+#define OP_TableLock 97
+#define OP_Clear 98
#define OP_Le 76 /* same as TK_LE */
-#define OP_VerifyCookie 100
-#define OP_AggStep 101
+#define OP_VerifyCookie 99
+#define OP_AggStep 100
#define OP_ToText 141 /* same as TK_TO_TEXT */
#define OP_Not 19 /* same as TK_NOT */
#define OP_ToReal 145 /* same as TK_TO_REAL */
-#define OP_SetNumColumns 102
-#define OP_Transaction 103
-#define OP_VFilter 104
+#define OP_SetNumColumns 101
+#define OP_Transaction 102
+#define OP_VFilter 103
#define OP_Ne 73 /* same as TK_NE */
-#define OP_VDestroy 105
-#define OP_ContextPop 106
+#define OP_VDestroy 104
+#define OP_ContextPop 105
#define OP_BitOr 81 /* same as TK_BITOR */
-#define OP_Next 107
-#define OP_Count 108
-#define OP_IdxInsert 109
+#define OP_Next 106
+#define OP_Count 107
+#define OP_IdxInsert 108
#define OP_Lt 77 /* same as TK_LT */
-#define OP_SeekGe 110
-#define OP_Insert 111
-#define OP_Destroy 112
-#define OP_ReadCookie 113
+#define OP_SeekGe 109
+#define OP_Insert 110
+#define OP_Destroy 111
+#define OP_ReadCookie 112
+#define OP_RowSetTest 113
#define OP_LoadAnalysis 114
#define OP_Explain 115
#define OP_HaltIfNull 116
@@ -7119,20 +7160,20 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x08, 0x02, 0x00,\
-/* 8 */ 0x00, 0x04, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00,\
-/* 16 */ 0x00, 0x02, 0x00, 0x04, 0x01, 0x04, 0x00, 0x00,\
-/* 24 */ 0x05, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x00,\
-/* 32 */ 0x00, 0x00, 0x00, 0x02, 0x11, 0x11, 0x02, 0x05,\
-/* 40 */ 0x00, 0x02, 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11,\
-/* 48 */ 0x01, 0x02, 0x01, 0x21, 0x08, 0x00, 0x02, 0x01,\
-/* 56 */ 0x11, 0x01, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00,\
-/* 64 */ 0x11, 0x00, 0x2c, 0x2c, 0x00, 0x05, 0x00, 0x05,\
-/* 72 */ 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x11,\
+/* 8 */ 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,\
+/* 16 */ 0x02, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x05,\
+/* 24 */ 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x00, 0x00,\
+/* 32 */ 0x00, 0x00, 0x02, 0x11, 0x11, 0x02, 0x05, 0x00,\
+/* 40 */ 0x02, 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11, 0x01,\
+/* 48 */ 0x02, 0x01, 0x21, 0x08, 0x00, 0x02, 0x01, 0x11,\
+/* 56 */ 0x01, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x11,\
+/* 64 */ 0x00, 0x00, 0x2c, 0x2c, 0x05, 0x00, 0x11, 0x05,\
+/* 72 */ 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00,\
/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\
/* 88 */ 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00,\
-/* 96 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 104 */ 0x01, 0x00, 0x00, 0x01, 0x02, 0x08, 0x11, 0x00,\
-/* 112 */ 0x02, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02,\
+/* 96 */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\
+/* 104 */ 0x00, 0x00, 0x01, 0x02, 0x08, 0x11, 0x00, 0x02,\
+/* 112 */ 0x02, 0x15, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02,\
/* 120 */ 0x00, 0x02, 0x01, 0x11, 0x00, 0x00, 0x05, 0x00,\
/* 128 */ 0x11, 0x05, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,\
/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
@@ -7324,7 +7365,7 @@ SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
/* Functions used to manage pager transactions and savepoints. */
SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*, int*);
-SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag);
+SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int);
SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
@@ -7919,7 +7960,6 @@ struct Schema {
Hash tblHash; /* All tables indexed by name */
Hash idxHash; /* All (named) indices indexed by name */
Hash trigHash; /* All triggers indexed by name */
- Hash aFKey; /* Foreign keys indexed by to-table */
Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
u8 file_format; /* Schema format version for this file */
u8 enc; /* Text encoding used by this database */
@@ -8475,28 +8515,21 @@ struct Table {
**
** Each REFERENCES clause generates an instance of the following structure
** which is attached to the from-table. The to-table need not exist when
-** the from-table is created. The existence of the to-table is not checked
-** until an attempt is made to insert data into the from-table.
-**
-** The sqlite.aFKey hash table stores pointers to this structure
-** given the name of a to-table. For each to-table, all foreign keys
-** associated with that table are on a linked list using the FKey.pNextTo
-** field.
+** the from-table is created. The existence of the to-table is not checked.
*/
struct FKey {
Table *pFrom; /* The table that contains the REFERENCES clause */
FKey *pNextFrom; /* Next foreign key in pFrom */
char *zTo; /* Name of table that the key points to */
- FKey *pNextTo; /* Next foreign key that points to zTo */
int nCol; /* Number of columns in this key */
- 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 0 use PRIMARY KEY */
- } *aCol; /* One entry for each of nCol column s */
u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
u8 updateConf; /* How to resolve conflicts that occur on UPDATE */
u8 deleteConf; /* How to resolve conflicts that occur on DELETE */
u8 insertConf; /* How to resolve conflicts that occur on INSERT */
+ 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 0 use PRIMARY KEY */
+ } aCol[1]; /* One entry for each of nCol column s */
};
/*
@@ -8570,6 +8603,7 @@ struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
u16 nField; /* Number of entries in apMem[] */
u16 flags; /* Boolean settings. UNPACKED_... below */
+ i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */
Mem *aMem; /* Values */
};
@@ -8581,6 +8615,7 @@ struct UnpackedRecord {
#define UNPACKED_IGNORE_ROWID 0x0004 /* Ignore trailing rowid on key1 */
#define UNPACKED_INCRKEY 0x0008 /* Make this key an epsilon larger */
#define UNPACKED_PREFIX_MATCH 0x0010 /* A prefix match is considered OK */
+#define UNPACKED_PREFIX_SEARCH 0x0020 /* A prefix match is considered OK */
/*
** Each SQL index is represented in memory by an
@@ -8634,8 +8669,9 @@ struct Index {
*/
struct Token {
const unsigned char *z; /* Text of the token. Not NULL-terminated! */
- unsigned dyn : 1; /* True for malloced memory, false for static */
- unsigned n : 31; /* Number of characters in this token */
+ unsigned dyn : 1; /* True for malloced memory, false for static */
+ unsigned quoted : 1; /* True if token still has its quotes */
+ unsigned n : 30; /* Number of characters in this token */
};
/*
@@ -8797,7 +8833,7 @@ struct Expr {
#define EP_Error 0x0008 /* Expression contains one or more errors */
#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
-#define EP_Dequoted 0x0040 /* True if the string has been dequoted */
+#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */
@@ -9022,15 +9058,17 @@ struct WhereLevel {
};
/*
-** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin().
+** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
+** and the WhereInfo.wctrlFlags member.
*/
#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
-#define WHERE_FILL_ROWSET 0x0008 /* Save results in a RowSet object */
-#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */
-#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
+#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
+#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */
+#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
+#define WHERE_FORCE_TABLE 0x0040 /* Do not use an index-only search */
/*
** The WHERE clause processing routine has two halves. The
@@ -9043,7 +9081,6 @@ struct WhereInfo {
Parse *pParse; /* Parsing and code generating context */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
- int regRowSet; /* Store rowids in this rowset if >=0 */
SrcList *pTabList; /* List of tables in the join */
int iTop; /* The very beginning of the WHERE loop */
int iContinue; /* Jump here to continue with next record */
@@ -9172,6 +9209,13 @@ struct SelectDest {
};
/*
+** Size of the column cache
+*/
+#ifndef SQLITE_N_COLCACHE
+# define SQLITE_N_COLCACHE 10
+#endif
+
+/*
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
@@ -9207,15 +9251,19 @@ struct Parse {
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
int ckBase; /* Base register of data during check constraints */
- int disableColCache; /* True to disable adding to column cache */
- int nColCache; /* Number of entries in the column cache */
- int iColCache; /* Next entry of the cache to replace */
+ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
+ int iCacheCnt; /* Counter used to generate aColCache[].lru values */
+ u8 nColCache; /* Number of entries in the column cache */
+ u8 iColCache; /* Next entry of the cache to replace */
struct yColCache {
int iTable; /* Table cursor number */
int iColumn; /* Table column number */
- char affChange; /* True if this register has had an affinity change */
- int iReg; /* Register holding value of this column */
- } aColCache[10]; /* One for each valid column cache entry */
+ u8 affChange; /* True if this register has had an affinity change */
+ u8 tempReg; /* iReg is a temp register that needs to be freed */
+ int iLevel; /* Nesting level */
+ int iReg; /* Reg with value of this column. 0 means none. */
+ int lru; /* Least recently used entry has the smallest value */
+ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
u32 writeMask; /* Start a write transaction on these databases */
u32 cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
@@ -9273,12 +9321,13 @@ struct AuthContext {
};
/*
-** Bitfield flags for P2 value in OP_Insert and OP_Delete
+** Bitfield flags for P5 value in OP_Insert and OP_Delete
*/
-#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */
-#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */
-#define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */
-#define OPFLAG_APPEND 8 /* This is likely to be an append */
+#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */
+#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */
+#define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */
+#define OPFLAG_APPEND 8 /* This is likely to be an append */
+#define OPFLAG_USESEEKRESULT 16 /* Try to avoid a seek in BtreeInsert() */
/*
* Each trigger present in the database schema is stored as an instance of
@@ -9569,7 +9618,6 @@ SQLITE_PRIVATE int sqlite3Corrupt(void);
SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *);
SQLITE_PRIVATE int sqlite3StrNICmp(const char *, const char *, int);
SQLITE_PRIVATE int sqlite3IsNumber(const char*, int*, u8);
-SQLITE_PRIVATE int sqlite3Strlen(sqlite3*, const char*);
SQLITE_PRIVATE int sqlite3Strlen30(const char*);
SQLITE_PRIVATE int sqlite3MallocInit(void);
@@ -9628,8 +9676,7 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...);
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ErrorClear(Parse*);
-SQLITE_PRIVATE void sqlite3Dequote(char*);
-SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
+SQLITE_PRIVATE int sqlite3Dequote(char*);
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
SQLITE_PRIVATE void sqlite3FinishCoding(Parse*);
@@ -9677,6 +9724,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*);
SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
+SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, u8 iBatch, i64);
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);
SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
@@ -9718,14 +9766,17 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, E
#endif
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8, int);
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
-SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse*, int);
+SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
+SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
+SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int);
+SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
-SQLITE_PRIVATE void sqlite3ExprWritableRegister(Parse*,int);
SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse*,int,int);
SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
@@ -9767,8 +9818,8 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
- int*,int,int,int,int);
-SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
+ int*,int,int,int,int,int*);
+SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int,int,int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
@@ -10029,6 +10080,8 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
+SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
+
/*
@@ -10776,6 +10829,7 @@ static int parseDateOrTime(
const char *zDate,
DateTime *p
){
+ int isRealNum; /* Return from sqlite3IsNumber(). Not used */
if( parseYyyyMmDd(zDate,p)==0 ){
return 0;
}else if( parseHhMmSs(zDate, p)==0 ){
@@ -10783,7 +10837,7 @@ static int parseDateOrTime(
}else if( sqlite3StrICmp(zDate,"now")==0){
setDateTimeToCurrent(context, p);
return 0;
- }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
+ }else if( sqlite3IsNumber(zDate, &isRealNum, SQLITE_UTF8) ){
double r;
getValue(zDate, &r);
p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
@@ -10981,7 +11035,7 @@ static int parseModifier(const char *zMod, DateTime *p){
** seconds since 1970. Convert to a real julian day number.
*/
if( strcmp(z, "unixepoch")==0 && p->validJD ){
- p->iJD = p->iJD/86400 + 21086676*(i64)10000000;
+ p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
clearYMD_HMS_TZ(p);
rc = 0;
}
@@ -15604,7 +15658,7 @@ SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
if( z==0 ){
return 0;
}
- n = (db ? sqlite3Strlen(db, z) : sqlite3Strlen30(z))+1;
+ n = sqlite3Strlen30(z) + 1;
assert( (n&0x7fffffff)==n );
zNew = sqlite3DbMallocRaw(db, (int)n);
if( zNew ){
@@ -16064,9 +16118,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
case etRADIX:
if( infop->flags & FLAG_SIGNED ){
i64 v;
- if( flag_longlong ) v = va_arg(ap,i64);
- else if( flag_long ) v = va_arg(ap,long int);
- else v = va_arg(ap,int);
+ if( flag_longlong ){
+ v = va_arg(ap,i64);
+ }else if( flag_long ){
+ v = va_arg(ap,long int);
+ }else{
+ v = va_arg(ap,int);
+ }
if( v<0 ){
longvalue = -v;
prefix = '-';
@@ -16077,9 +16135,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
else prefix = 0;
}
}else{
- if( flag_longlong ) longvalue = va_arg(ap,u64);
- else if( flag_long ) longvalue = va_arg(ap,unsigned long int);
- else longvalue = va_arg(ap,unsigned int);
+ if( flag_longlong ){
+ longvalue = va_arg(ap,u64);
+ }else if( flag_long ){
+ longvalue = va_arg(ap,unsigned long int);
+ }else{
+ longvalue = va_arg(ap,unsigned int);
+ }
prefix = 0;
}
if( longvalue==0 ) flag_alternateform = 0;
@@ -16891,6 +16953,10 @@ struct VdbeCursor {
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
+ /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
+ ** OP_IsUnique opcode on this cursor. */
+ int seekResult;
+
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheValid is true.
** aRow might point to (ephemeral) data for the current row, or it might
@@ -17736,6 +17802,9 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
**
** $Id$
*/
+#ifdef SQLITE_HAVE_ISNAN
+# include <math.h>
+#endif
/*
** Routine needed to support the testcase() macro.
@@ -17770,9 +17839,20 @@ SQLITE_PRIVATE int sqlite3Assert(void){
/*
** Return true if the floating point value is Not a Number (NaN).
+**
+** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
+** Otherwise, we have our own implementation that works on most systems.
*/
SQLITE_PRIVATE int sqlite3IsNaN(double x){
- /* This NaN test sometimes fails if compiled on GCC with -ffast-math.
+ int rc; /* The value return */
+#if !defined(SQLITE_HAVE_ISNAN)
+ /*
+ ** Systems that support the isnan() library function should probably
+ ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
+ ** found that many systems do not have a working isnan() function so
+ ** this implementation is provided as an alternative.
+ **
+ ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
** On the other hand, the use of -ffast-math comes with the following
** warning:
**
@@ -17794,12 +17874,21 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
#endif
volatile double y = x;
volatile double z = y;
- return y!=z;
+ rc = (y!=z);
+#else /* if defined(SQLITE_HAVE_ISNAN) */
+ rc = isnan(x);
+#endif /* SQLITE_HAVE_ISNAN */
+ testcase( rc );
+ return rc;
}
/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
+**
+** The value returned will never be negative. Nor will it ever be greater
+** than the actual length of the string. For very long strings (greater
+** than 1GiB) the value returned might be less than the true string length.
*/
SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
const char *z2 = z;
@@ -17808,24 +17897,6 @@ SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
}
/*
-** Return the length of a string, except do not allow the string length
-** to exceed the SQLITE_LIMIT_LENGTH setting.
-*/
-SQLITE_PRIVATE int sqlite3Strlen(sqlite3 *db, const char *z){
- const char *z2 = z;
- int len;
- int x;
- while( *z2 ){ z2++; }
- x = (int)(z2 - z);
- len = 0x7fffffff & x;
- if( len!=x || len > db->aLimit[SQLITE_LIMIT_LENGTH] ){
- return db->aLimit[SQLITE_LIMIT_LENGTH];
- }else{
- return len;
- }
-}
-
-/*
** Set the most recent error code and error string for the sqlite
** handle "db". The error code is set to "err_code".
**
@@ -17883,6 +17954,7 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
va_list ap;
sqlite3 *db = pParse->db;
pParse->nErr++;
+ testcase( pParse->zErrMsg!=0 );
sqlite3DbFree(db, pParse->zErrMsg);
va_start(ap, zFormat);
pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap);
@@ -17907,35 +17979,43 @@ SQLITE_PRIVATE void sqlite3ErrorClear(Parse *pParse){
** input does not begin with a quote character, then this routine
** is a no-op.
**
+** The input string must be zero-terminated. A new zero-terminator
+** is added to the dequoted string.
+**
+** The return value is -1 if no dequoting occurs or the length of the
+** dequoted string, exclusive of the zero terminator, if dequoting does
+** occur.
+**
** 2002-Feb-14: This routine is extended to remove MS-Access style
** brackets from around identifers. For example: "[a-b-c]" becomes
** "a-b-c".
*/
-SQLITE_PRIVATE void sqlite3Dequote(char *z){
+SQLITE_PRIVATE int sqlite3Dequote(char *z){
char quote;
int i, j;
- if( z==0 ) return;
+ if( z==0 ) return -1;
quote = z[0];
switch( quote ){
case '\'': break;
case '"': break;
case '`': break; /* For MySQL compatibility */
case '[': quote = ']'; break; /* For MS SqlServer compatibility */
- default: return;
+ default: return -1;
}
- for(i=1, j=0; z[i]; i++){
+ for(i=1, j=0; ALWAYS(z[i]); i++){
if( z[i]==quote ){
if( z[i+1]==quote ){
z[j++] = quote;
i++;
}else{
- z[j++] = 0;
break;
}
}else{
z[j++] = z[i];
}
}
+ z[j] = 0;
+ return j;
}
/* Convenient short-hand */
@@ -17961,10 +18041,15 @@ SQLITE_PRIVATE int sqlite3StrNICmp(const char *zLeft, const char *zRight, int N)
}
/*
-** Return TRUE if z is a pure numeric string. Return FALSE if the
-** string contains any character which is not part of a number. If
-** the string is numeric and contains the '.' character, set *realnum
-** to TRUE (otherwise FALSE).
+** Return TRUE if z is a pure numeric string. Return FALSE and leave
+** *realnum unchanged if the string contains any character which is not
+** part of a number.
+**
+** If the string is pure numeric, set *realnum to TRUE if the string
+** contains the '.' character or an "E+000" style exponentiation suffix.
+** Otherwise set *realnum to FALSE. Note that just becaue *realnum is
+** false does not mean that the number can be successfully converted into
+** an integer - it might be too big.
**
** An empty string is considered non-numeric.
*/
@@ -17976,20 +18061,20 @@ SQLITE_PRIVATE int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
return 0;
}
z += incr;
- if( realnum ) *realnum = 0;
+ *realnum = 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
if( *z=='.' ){
z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
- if( realnum ) *realnum = 1;
+ *realnum = 1;
}
if( *z=='e' || *z=='E' ){
z += incr;
if( *z=='+' || *z=='-' ) z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
- if( realnum ) *realnum = 1;
+ *realnum = 1;
}
return *z==0;
}
@@ -18148,25 +18233,25 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum){
}
/*
-** The string zNum represents an integer. There might be some other
+** The string zNum represents an unsigned integer. There might be some other
** information following the integer too, but that part is ignored.
** If the integer that the prefix of zNum represents will fit in a
** 64-bit signed integer, return TRUE. Otherwise return FALSE.
**
-** This routine returns FALSE for the string -9223372036854775808 even that
-** that number will, in theory fit in a 64-bit integer. Positive
-** 9223373036854775808 will not fit in 64 bits. So it seems safer to return
-** false.
+** If the negFlag parameter is true, that means that zNum really represents
+** a negative number. (The leading "-" is omitted from zNum.) This
+** parameter is needed to determine a boundary case. A string
+** of "9223373036854775808" returns false if negFlag is false or true
+** if negFlag is true.
+**
+** Leading zeros are ignored.
*/
SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
int i, c;
int neg = 0;
- if( *zNum=='-' ){
- neg = 1;
- zNum++;
- }else if( *zNum=='+' ){
- zNum++;
- }
+
+ assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */
+
if( negFlag ) neg = 1-neg;
while( *zNum=='0' ){
zNum++; /* Skip leading zeros. Ticket #2454 */
@@ -18471,33 +18556,40 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
u32 a,b;
+ /* The 1-byte case. Overwhelmingly the most common. Handled inline
+ ** by the getVarin32() macro */
a = *p;
/* a: p0 (unmasked) */
#ifndef getVarint32
if (!(a&0x80))
{
+ /* Values between 0 and 127 */
*v = a;
return 1;
}
#endif
+ /* The 2-byte case */
p++;
b = *p;
/* b: p1 (unmasked) */
if (!(b&0x80))
{
+ /* Values between 128 and 16383 */
a &= 0x7f;
a = a<<7;
*v = a | b;
return 2;
}
+ /* The 3-byte case */
p++;
a = a<<14;
a |= *p;
/* a: p0<<14 | p2 (unmasked) */
if (!(a&0x80))
{
+ /* Values between 16384 and 2097151 */
a &= (0x7f<<14)|(0x7f);
b &= 0x7f;
b = b<<7;
@@ -18505,12 +18597,39 @@ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
return 3;
}
+ /* A 32-bit varint is used to store size information in btrees.
+ ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
+ ** A 3-byte varint is sufficient, for example, to record the size
+ ** of a 1048569-byte BLOB or string.
+ **
+ ** We only unroll the first 1-, 2-, and 3- byte cases. The very
+ ** rare larger cases can be handled by the slower 64-bit varint
+ ** routine.
+ */
+#if 1
+ {
+ u64 v64;
+ u8 n;
+
+ p -= 2;
+ n = sqlite3GetVarint(p, &v64);
+ assert( n>3 && n<=9 );
+ *v = (u32)v64;
+ return n;
+ }
+
+#else
+ /* For following code (kept for historical record only) shows an
+ ** unrolling for the 3- and 4-byte varint cases. This code is
+ ** slightly faster, but it is also larger and much harder to test.
+ */
p++;
b = b<<14;
b |= *p;
/* b: p1<<14 | p3 (unmasked) */
if (!(b&0x80))
{
+ /* Values between 2097152 and 268435455 */
b &= (0x7f<<14)|(0x7f);
a &= (0x7f<<14)|(0x7f);
a = a<<7;
@@ -18524,6 +18643,7 @@ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
if (!(a&0x80))
{
+ /* Walues between 268435456 and 34359738367 */
a &= (0x1f<<28)|(0x7f<<14)|(0x7f);
b &= (0x1f<<28)|(0x7f<<14)|(0x7f);
b = b<<7;
@@ -18545,6 +18665,7 @@ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
*v = (u32)v64;
return n;
}
+#endif
}
/*
@@ -18556,7 +18677,7 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
do{
i++;
v >>= 7;
- }while( v!=0 && i<9 );
+ }while( v!=0 && ALWAYS(i<9) );
return i;
}
@@ -18694,13 +18815,18 @@ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
u32 magic;
if( db==0 ) return 0;
magic = db->magic;
- if( magic!=SQLITE_MAGIC_OPEN &&
- magic!=SQLITE_MAGIC_BUSY ) return 0;
- return 1;
+ if( magic!=SQLITE_MAGIC_OPEN
+#ifdef SQLITE_DEBUG
+ && magic!=SQLITE_MAGIC_BUSY
+#endif
+ ){
+ return 0;
+ }else{
+ return 1;
+ }
}
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
u32 magic;
- if( db==0 ) return 0;
magic = db->magic;
if( magic!=SQLITE_MAGIC_SICK &&
magic!=SQLITE_MAGIC_OPEN &&
@@ -18731,12 +18857,9 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
-** "copyKey" is true if the hash table should make its own private
-** copy of keys and false if it should just use the supplied pointer.
*/
-SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew, int copyKey){
+SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
assert( pNew!=0 );
- pNew->copyKey = copyKey!=0;
pNew->first = 0;
pNew->count = 0;
pNew->htsize = 0;
@@ -18758,9 +18881,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
pH->htsize = 0;
while( elem ){
HashElem *next_elem = elem->next;
- if( pH->copyKey ){
- sqlite3_free(elem->pKey);
- }
sqlite3_free(elem);
elem = next_elem;
}
@@ -18768,25 +18888,21 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
}
/*
-** Hash and comparison functions when the mode is SQLITE_HASH_STRING
+** The hashing function.
*/
-static int strHash(const void *pKey, int nKey){
- const char *z = (const char *)pKey;
+static unsigned int strHash(const char *z, int nKey){
int h = 0;
- if( nKey<=0 ) nKey = sqlite3Strlen30(z);
+ assert( nKey>=0 );
while( nKey > 0 ){
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
nKey--;
}
- return h & 0x7fffffff;
-}
-static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
+ return h;
}
-/* Link an element into the hash table
+/* Link pNew element into the hash table pH. If pEntry!=0 then also
+** insert pNew into the pEntry hash bucket.
*/
static void insertElement(
Hash *pH, /* The complete hash table */
@@ -18794,7 +18910,13 @@ static void insertElement(
HashElem *pNew /* The element to be inserted */
){
HashElem *pHead; /* First element already in pEntry */
- pHead = pEntry->chain;
+ if( pEntry ){
+ pHead = pEntry->count ? pEntry->chain : 0;
+ pEntry->count++;
+ pEntry->chain = pNew;
+ }else{
+ pHead = 0;
+ }
if( pHead ){
pNew->next = pHead;
pNew->prev = pHead->prev;
@@ -18807,44 +18929,45 @@ static void insertElement(
pNew->prev = 0;
pH->first = pNew;
}
- pEntry->count++;
- pEntry->chain = pNew;
}
/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
-** to resize if sqlite3_malloc() fails.
+**
+** The hash table might fail to resize if sqlite3_malloc() fails or
+** if the new size is the same as the prior size.
+** Return TRUE if the resize occurs and false if not.
*/
-static void rehash(Hash *pH, int new_size){
+static int rehash(Hash *pH, unsigned int new_size){
struct _ht *new_ht; /* The new hash table */
HashElem *elem, *next_elem; /* For looping over existing elements */
-#ifdef SQLITE_MALLOC_SOFT_LIMIT
+#if SQLITE_MALLOC_SOFT_LIMIT>0
if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
}
- if( new_size==pH->htsize ) return;
+ if( new_size==pH->htsize ) return 0;
#endif
- /* There is a call to sqlite3_malloc() inside rehash(). If there is
- ** already an allocation at pH->ht, then if this malloc() fails it
- ** is benign (since failing to resize a hash table is a performance
- ** hit only, not a fatal error).
+ /* The inability to allocates space for a larger hash table is
+ ** a performance hit but it is not a fatal error. So mark the
+ ** allocation as a benign.
*/
- if( pH->htsize>0 ) sqlite3BeginBenignMalloc();
- new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) );
- if( pH->htsize>0 ) sqlite3EndBenignMalloc();
+ sqlite3BeginBenignMalloc();
+ new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
+ sqlite3EndBenignMalloc();
- if( new_ht==0 ) return;
+ if( new_ht==0 ) return 0;
sqlite3_free(pH->ht);
pH->ht = new_ht;
- pH->htsize = 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){
- int h = strHash(elem->pKey, elem->nKey) & (new_size-1);
+ unsigned int h = strHash(elem->pKey, elem->nKey) % new_size;
next_elem = elem->next;
insertElement(pH, &new_ht[h], elem);
}
+ return 1;
}
/* This function (for internal use only) locates an element in an
@@ -18853,9 +18976,9 @@ static void rehash(Hash *pH, int new_size){
*/
static HashElem *findElementGivenHash(
const Hash *pH, /* The pH to be searched */
- const void *pKey, /* The key we are searching for */
- int nKey,
- int h /* The hash for this key. */
+ const char *pKey, /* The key we are searching for */
+ int nKey, /* Bytes in key (not counting zero terminator) */
+ unsigned int h /* The hash for this key. */
){
HashElem *elem; /* Used to loop thru the element list */
int count; /* Number of elements left to test */
@@ -18864,12 +18987,15 @@ static HashElem *findElementGivenHash(
struct _ht *pEntry = &pH->ht[h];
elem = pEntry->chain;
count = pEntry->count;
- while( count-- && elem ){
- if( strCompare(elem->pKey,elem->nKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
+ }else{
+ elem = pH->first;
+ count = pH->count;
+ }
+ while( count-- && ALWAYS(elem) ){
+ if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
+ return elem;
}
+ elem = elem->next;
}
return 0;
}
@@ -18880,7 +19006,7 @@ static HashElem *findElementGivenHash(
static void removeElementGivenHash(
Hash *pH, /* The pH containing "elem" */
HashElem* elem, /* The element to be removed from the pH */
- int h /* Hash value for the element */
+ unsigned int h /* Hash value for the element */
){
struct _ht *pEntry;
if( elem->prev ){
@@ -18891,16 +19017,13 @@ static void removeElementGivenHash(
if( elem->next ){
elem->next->prev = elem->prev;
}
- pEntry = &pH->ht[h];
- if( pEntry->chain==elem ){
- pEntry->chain = elem->next;
- }
- pEntry->count--;
- if( pEntry->count<=0 ){
- pEntry->chain = 0;
- }
- if( pH->copyKey ){
- sqlite3_free(elem->pKey);
+ if( pH->ht ){
+ pEntry = &pH->ht[h];
+ if( pEntry->chain==elem ){
+ pEntry->chain = elem->next;
+ }
+ pEntry->count--;
+ assert( pEntry->count>=0 );
}
sqlite3_free( elem );
pH->count--;
@@ -18912,27 +19035,22 @@ static void removeElementGivenHash(
}
/* Attempt to locate an element of the hash table pH with a key
-** that matches pKey,nKey. Return a pointer to the corresponding
-** HashElem structure for this element if it is found, or NULL
-** otherwise.
-*/
-SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){
- int h; /* A hash on key */
- HashElem *elem; /* The element that matches key */
-
- if( pH==0 || pH->ht==0 ) return 0;
- h = strHash(pKey,nKey);
- elem = findElementGivenHash(pH,pKey,nKey, h % pH->htsize);
- return elem;
-}
-
-/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
-SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
+SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
HashElem *elem; /* The element that matches key */
- elem = sqlite3HashFindElem(pH, pKey, nKey);
+ unsigned int h; /* A hash on key */
+
+ assert( pH!=0 );
+ assert( pKey!=0 );
+ assert( nKey>=0 );
+ if( pH->ht ){
+ h = strHash(pKey, nKey) % pH->htsize;
+ }else{
+ h = 0;
+ }
+ elem = findElementGivenHash(pH, pKey, nKey, h);
return elem ? elem->data : 0;
}
@@ -18940,8 +19058,7 @@ SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey)
** and the data is "data".
**
** If no element exists with a matching key, then a new
-** element is created. A copy of the key is made if the copyKey
-** flag is set. NULL is returned.
+** element is created and NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
@@ -18951,64 +19068,48 @@ SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey)
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
-SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
- int hraw; /* Raw hash value of the key */
- int h; /* the hash of the key modulo hash table size */
+SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
+ unsigned int h; /* the hash of the key modulo hash table size */
HashElem *elem; /* Used to loop thru the element list */
HashElem *new_elem; /* New element added to the pH */
assert( pH!=0 );
- hraw = strHash(pKey, nKey);
+ assert( pKey!=0 );
+ assert( nKey>=0 );
if( pH->htsize ){
- h = hraw % pH->htsize;
- elem = findElementGivenHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- if( !pH->copyKey ){
- elem->pKey = (void *)pKey;
- }
- assert(nKey==elem->nKey);
- }
- return old_data;
+ h = strHash(pKey, nKey) % pH->htsize;
+ }else{
+ h = 0;
+ }
+ elem = findElementGivenHash(pH,pKey,nKey,h);
+ if( elem ){
+ void *old_data = elem->data;
+ if( data==0 ){
+ removeElementGivenHash(pH,elem,h);
+ }else{
+ elem->data = data;
+ elem->pKey = pKey;
+ assert(nKey==elem->nKey);
}
+ return old_data;
}
if( data==0 ) return 0;
new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
- if( pH->copyKey && pKey!=0 ){
- new_elem->pKey = sqlite3Malloc( nKey );
- if( new_elem->pKey==0 ){
- sqlite3_free(new_elem);
- return data;
- }
- memcpy((void*)new_elem->pKey, pKey, nKey);
- }else{
- new_elem->pKey = (void*)pKey;
- }
+ new_elem->pKey = pKey;
new_elem->nKey = nKey;
+ new_elem->data = data;
pH->count++;
- if( pH->htsize==0 ){
- rehash(pH, 128/sizeof(pH->ht[0]));
- if( pH->htsize==0 ){
- pH->count = 0;
- if( pH->copyKey ){
- sqlite3_free(new_elem->pKey);
- }
- sqlite3_free(new_elem);
- return data;
+ if( pH->count>=10 && pH->count > 2*pH->htsize ){
+ if( rehash(pH, pH->count*2) && pH->htsize ){
+ h = strHash(pKey, nKey) % pH->htsize;
}
}
- if( pH->count > pH->htsize ){
- rehash(pH,pH->htsize*2);
+ if( pH->ht ){
+ insertElement(pH, &pH->ht[h], new_elem);
+ }else{
+ insertElement(pH, 0, new_elem);
}
- assert( pH->htsize>0 );
- h = hraw % pH->htsize;
- insertElement(pH, &pH->ht[h], new_elem);
- new_elem->data = data;
return 0;
}
@@ -19030,65 +19131,65 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 9 */ "SCopy",
/* 10 */ "OpenWrite",
/* 11 */ "If",
- /* 12 */ "VRowid",
- /* 13 */ "CollSeq",
- /* 14 */ "OpenRead",
- /* 15 */ "Expire",
- /* 16 */ "AutoCommit",
- /* 17 */ "Pagecount",
- /* 18 */ "IntegrityCk",
+ /* 12 */ "CollSeq",
+ /* 13 */ "OpenRead",
+ /* 14 */ "Expire",
+ /* 15 */ "AutoCommit",
+ /* 16 */ "Pagecount",
+ /* 17 */ "IntegrityCk",
+ /* 18 */ "Sort",
/* 19 */ "Not",
- /* 20 */ "Sort",
- /* 21 */ "Copy",
- /* 22 */ "Trace",
- /* 23 */ "Function",
- /* 24 */ "IfNeg",
- /* 25 */ "Noop",
- /* 26 */ "Return",
- /* 27 */ "NewRowid",
- /* 28 */ "Variable",
- /* 29 */ "String",
- /* 30 */ "RealAffinity",
- /* 31 */ "VRename",
- /* 32 */ "ParseSchema",
- /* 33 */ "VOpen",
- /* 34 */ "Close",
- /* 35 */ "CreateIndex",
- /* 36 */ "IsUnique",
- /* 37 */ "NotFound",
- /* 38 */ "Int64",
- /* 39 */ "MustBeInt",
- /* 40 */ "Halt",
- /* 41 */ "Rowid",
- /* 42 */ "IdxLT",
- /* 43 */ "AddImm",
- /* 44 */ "Statement",
- /* 45 */ "RowData",
- /* 46 */ "MemMax",
- /* 47 */ "NotExists",
- /* 48 */ "Gosub",
- /* 49 */ "Integer",
- /* 50 */ "Prev",
- /* 51 */ "RowSetRead",
- /* 52 */ "RowSetAdd",
- /* 53 */ "VColumn",
- /* 54 */ "CreateTable",
- /* 55 */ "Last",
- /* 56 */ "SeekLe",
- /* 57 */ "IncrVacuum",
- /* 58 */ "IdxRowid",
- /* 59 */ "ResetCount",
- /* 60 */ "ContextPush",
- /* 61 */ "Yield",
- /* 62 */ "DropTrigger",
- /* 63 */ "DropIndex",
- /* 64 */ "IdxGE",
- /* 65 */ "IdxDelete",
+ /* 20 */ "Copy",
+ /* 21 */ "Trace",
+ /* 22 */ "Function",
+ /* 23 */ "IfNeg",
+ /* 24 */ "Noop",
+ /* 25 */ "Return",
+ /* 26 */ "NewRowid",
+ /* 27 */ "Variable",
+ /* 28 */ "String",
+ /* 29 */ "RealAffinity",
+ /* 30 */ "VRename",
+ /* 31 */ "ParseSchema",
+ /* 32 */ "VOpen",
+ /* 33 */ "Close",
+ /* 34 */ "CreateIndex",
+ /* 35 */ "IsUnique",
+ /* 36 */ "NotFound",
+ /* 37 */ "Int64",
+ /* 38 */ "MustBeInt",
+ /* 39 */ "Halt",
+ /* 40 */ "Rowid",
+ /* 41 */ "IdxLT",
+ /* 42 */ "AddImm",
+ /* 43 */ "Statement",
+ /* 44 */ "RowData",
+ /* 45 */ "MemMax",
+ /* 46 */ "NotExists",
+ /* 47 */ "Gosub",
+ /* 48 */ "Integer",
+ /* 49 */ "Prev",
+ /* 50 */ "RowSetRead",
+ /* 51 */ "RowSetAdd",
+ /* 52 */ "VColumn",
+ /* 53 */ "CreateTable",
+ /* 54 */ "Last",
+ /* 55 */ "SeekLe",
+ /* 56 */ "IncrVacuum",
+ /* 57 */ "IdxRowid",
+ /* 58 */ "ResetCount",
+ /* 59 */ "ContextPush",
+ /* 60 */ "Yield",
+ /* 61 */ "DropTrigger",
+ /* 62 */ "DropIndex",
+ /* 63 */ "IdxGE",
+ /* 64 */ "IdxDelete",
+ /* 65 */ "Vacuum",
/* 66 */ "Or",
/* 67 */ "And",
- /* 68 */ "Vacuum",
- /* 69 */ "IfNot",
- /* 70 */ "DropTable",
+ /* 68 */ "IfNot",
+ /* 69 */ "DropTable",
+ /* 70 */ "SeekLt",
/* 71 */ "IsNull",
/* 72 */ "NotNull",
/* 73 */ "Ne",
@@ -19097,7 +19198,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 76 */ "Le",
/* 77 */ "Lt",
/* 78 */ "Ge",
- /* 79 */ "SeekLt",
+ /* 79 */ "MakeRecord",
/* 80 */ "BitAnd",
/* 81 */ "BitOr",
/* 82 */ "ShiftLeft",
@@ -19108,30 +19209,30 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 87 */ "Divide",
/* 88 */ "Remainder",
/* 89 */ "Concat",
- /* 90 */ "MakeRecord",
- /* 91 */ "ResultRow",
- /* 92 */ "Delete",
+ /* 90 */ "ResultRow",
+ /* 91 */ "Delete",
+ /* 92 */ "AggFinal",
/* 93 */ "BitNot",
/* 94 */ "String8",
- /* 95 */ "AggFinal",
- /* 96 */ "Compare",
- /* 97 */ "Goto",
- /* 98 */ "TableLock",
- /* 99 */ "Clear",
- /* 100 */ "VerifyCookie",
- /* 101 */ "AggStep",
- /* 102 */ "SetNumColumns",
- /* 103 */ "Transaction",
- /* 104 */ "VFilter",
- /* 105 */ "VDestroy",
- /* 106 */ "ContextPop",
- /* 107 */ "Next",
- /* 108 */ "Count",
- /* 109 */ "IdxInsert",
- /* 110 */ "SeekGe",
- /* 111 */ "Insert",
- /* 112 */ "Destroy",
- /* 113 */ "ReadCookie",
+ /* 95 */ "Compare",
+ /* 96 */ "Goto",
+ /* 97 */ "TableLock",
+ /* 98 */ "Clear",
+ /* 99 */ "VerifyCookie",
+ /* 100 */ "AggStep",
+ /* 101 */ "SetNumColumns",
+ /* 102 */ "Transaction",
+ /* 103 */ "VFilter",
+ /* 104 */ "VDestroy",
+ /* 105 */ "ContextPop",
+ /* 106 */ "Next",
+ /* 107 */ "Count",
+ /* 108 */ "IdxInsert",
+ /* 109 */ "SeekGe",
+ /* 110 */ "Insert",
+ /* 111 */ "Destroy",
+ /* 112 */ "ReadCookie",
+ /* 113 */ "RowSetTest",
/* 114 */ "LoadAnalysis",
/* 115 */ "Explain",
/* 116 */ "HaltIfNull",
@@ -27424,16 +27525,23 @@ static int winOpen(
}else{
dwDesiredAccess = GENERIC_READ;
}
- if( flags & SQLITE_OPEN_CREATE ){
+ /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
+ ** created. SQLite doesn't use it to indicate "exclusive access"
+ ** as it is usually understood.
+ */
+ assert(!(flags & SQLITE_OPEN_EXCLUSIVE) || (flags & SQLITE_OPEN_CREATE));
+ if( flags & SQLITE_OPEN_EXCLUSIVE ){
+ /* Creates a new file, only if it does not already exist. */
+ /* If the file exists, it fails. */
+ dwCreationDisposition = CREATE_NEW;
+ }else if( flags & SQLITE_OPEN_CREATE ){
+ /* Open existing file, or create if it doesn't exist */
dwCreationDisposition = OPEN_ALWAYS;
}else{
+ /* Opens a file, only if it exists. */
dwCreationDisposition = OPEN_EXISTING;
}
- if( flags & SQLITE_OPEN_MAIN_DB ){
- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
- }else{
- dwShareMode = 0;
- }
+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
if( flags & SQLITE_OPEN_DELETEONCLOSE ){
#if SQLITE_OS_WINCE
dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
@@ -27712,13 +27820,11 @@ static int getSectorSize(
void *zConverted = convertUtf8Filename(zFullpath);
if( zConverted ){
if( isNT() ){
- int i;
/* trim path to just drive reference */
WCHAR *p = zConverted;
- for(i=0;i<MAX_PATH;i++){
- if( p[i] == '\\' ){
- i++;
- p[i] = '\0';
+ for(;*p;p++){
+ if( *p == '\\' ){
+ *p = '\0';
break;
}
}
@@ -27729,13 +27835,11 @@ static int getSectorSize(
&dwDummy);
#if SQLITE_OS_WINCE==0
}else{
- int i;
/* trim path to just drive reference */
CHAR *p = (CHAR *)zConverted;
- for(i=0;i<MAX_PATH;i++){
- if( p[i] == '\\' ){
- i++;
- p[i] = '\0';
+ for(;*p;p++){
+ if( *p == '\\' ){
+ *p = '\0';
break;
}
}
@@ -29499,7 +29603,7 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
/* Step 4. Try to recycle a page buffer if appropriate. */
if( pCache->bPurgeable && pcache1.pLruTail && (
- pCache->nPage>=pCache->nMax-1 || pcache1.nCurrentPage>=pcache1.nMaxPage
+ (pCache->nPage+1>=pCache->nMax) || pcache1.nCurrentPage>=pcache1.nMaxPage
)){
pPage = pcache1.pLruTail;
pcache1RemoveFromHash(pPage);
@@ -29737,46 +29841,88 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
**
*************************************************************************
**
-** This module implements an object we call a "Row Set".
+** This module implements an object we call a "RowSet".
+**
+** The RowSet object is a collection of rowids. Rowids
+** are inserted into the RowSet in an arbitrary order. Inserts
+** can be intermixed with tests to see if a given rowid has been
+** previously inserted into the RowSet.
+**
+** After all inserts are finished, it is possible to extract the
+** elements of the RowSet in sorted order. Once this extraction
+** process has started, no new elements may be inserted.
+**
+** Hence, the primitive operations for a RowSet are:
+**
+** CREATE
+** INSERT
+** TEST
+** SMALLEST
+** DESTROY
+**
+** The CREATE and DESTROY primitives are the constructor and destructor,
+** obviously. The INSERT primitive adds a new element to the RowSet.
+** TEST checks to see if an element is already in the RowSet. SMALLEST
+** extracts the least value from the RowSet.
+**
+** The INSERT primitive might allocate additional memory. Memory is
+** allocated in chunks so most INSERTs do no allocation. There is an
+** upper bound on the size of allocated memory. No memory is freed
+** until DESTROY.
+**
+** The TEST primitive includes a "batch" number. The TEST primitive
+** will only see elements that were inserted before the last change
+** in the batch number. In other words, if an INSERT occurs between
+** two TESTs where the TESTs have the same batch nubmer, then the
+** value added by the INSERT will not be visible to the second TEST.
+** The initial batch number is zero, so if the very first TEST contains
+** a non-zero batch number, it will see all prior INSERTs.
**
-** The RowSet object is a bag of rowids. Rowids
-** are inserted into the bag in an arbitrary order. Then they are
-** pulled from the bag in sorted order. Rowids only appear in the
-** bag once. If the same rowid is inserted multiple times, the
-** second and subsequent inserts make no difference on the output.
+** No INSERTs may occurs after a SMALLEST. An assertion will fail if
+** that is attempted.
**
-** This implementation accumulates rowids in a linked list. For
-** output, it first sorts the linked list (removing duplicates during
-** the sort) then returns elements one by one by walking the list.
+** The cost of an INSERT is roughly constant. (Sometime new memory
+** has to be allocated on an INSERT.) The cost of a TEST with a new
+** batch number is O(NlogN) where N is the number of elements in the RowSet.
+** The cost of a TEST using the same batch number is O(logN). The cost
+** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
+** primitives are constant time. The cost of DESTROY is O(N).
**
-** Big chunks of rowid/next-ptr pairs are allocated at a time, to
-** reduce the malloc overhead.
+** There is an added cost of O(N) when switching between TEST and
+** SMALLEST primitives.
**
** $Id$
*/
+
+/*
+** Target size for allocation chunks.
+*/
+#define ROWSET_ALLOCATION_SIZE 1024
+
/*
** The number of rowset entries per allocation chunk.
*/
-#define ROWSET_ENTRY_PER_CHUNK 63
+#define ROWSET_ENTRY_PER_CHUNK \
+ ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
/*
-** Each entry in a RowSet is an instance of the following
-** structure:
+** Each entry in a RowSet is an instance of the following object.
*/
struct RowSetEntry {
i64 v; /* ROWID value for this entry */
- struct RowSetEntry *pNext; /* Next entry on a list of all entries */
+ struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */
+ struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */
};
/*
-** Index entries are allocated in large chunks (instances of the
+** RowSetEntry objects are allocated in large chunks (instances of the
** following structure) to reduce memory allocation overhead. The
** chunks are kept on a linked list so that they can be deallocated
** when the RowSet is destroyed.
*/
struct RowSetChunk {
- struct RowSetChunk *pNext; /* Next chunk on list of them all */
+ struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */
struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
};
@@ -29788,11 +29934,13 @@ struct RowSetChunk {
struct RowSet {
struct RowSetChunk *pChunk; /* List of all chunk allocations */
sqlite3 *db; /* The database connection */
- struct RowSetEntry *pEntry; /* List of entries in the rowset */
+ struct RowSetEntry *pEntry; /* List of entries using pRight */
struct RowSetEntry *pLast; /* Last entry on the pEntry list */
struct RowSetEntry *pFresh; /* Source of new entry objects */
+ struct RowSetEntry *pTree; /* Binary tree of entries */
u16 nFresh; /* Number of objects on pFresh */
- u8 isSorted; /* True if content is sorted */
+ u8 isSorted; /* True if pEntry is sorted */
+ u8 iBatch; /* Current insert batch */
};
/*
@@ -29815,25 +29963,30 @@ SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int
p->db = db;
p->pEntry = 0;
p->pLast = 0;
+ p->pTree = 0;
p->pFresh = (struct RowSetEntry*)&p[1];
p->nFresh = (u16)((N - sizeof(*p))/sizeof(struct RowSetEntry));
p->isSorted = 1;
+ p->iBatch = 0;
return p;
}
/*
-** Deallocate all chunks from a RowSet.
+** Deallocate all chunks from a RowSet. This frees all memory that
+** the RowSet has allocated over its lifetime. This routine is
+** the destructor for the RowSet.
*/
SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
struct RowSetChunk *pChunk, *pNextChunk;
for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
- pNextChunk = pChunk->pNext;
+ pNextChunk = pChunk->pNextChunk;
sqlite3DbFree(p->db, pChunk);
}
p->pChunk = 0;
p->nFresh = 0;
p->pEntry = 0;
p->pLast = 0;
+ p->pTree = 0;
p->isSorted = 1;
}
@@ -29844,8 +29997,8 @@ SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
** memory allocation fails.
*/
SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
- struct RowSetEntry *pEntry;
- struct RowSetEntry *pLast;
+ struct RowSetEntry *pEntry; /* The new entry */
+ struct RowSetEntry *pLast; /* The last prior entry */
assert( p!=0 );
if( p->nFresh==0 ){
struct RowSetChunk *pNew;
@@ -29853,7 +30006,7 @@ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
if( pNew==0 ){
return;
}
- pNew->pNext = p->pChunk;
+ pNew->pNextChunk = p->pChunk;
p->pChunk = pNew;
p->pFresh = pNew->aEntry;
p->nFresh = ROWSET_ENTRY_PER_CHUNK;
@@ -29861,26 +30014,27 @@ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
pEntry = p->pFresh++;
p->nFresh--;
pEntry->v = rowid;
- pEntry->pNext = 0;
+ pEntry->pRight = 0;
pLast = p->pLast;
if( pLast ){
if( p->isSorted && rowid<=pLast->v ){
p->isSorted = 0;
}
- pLast->pNext = pEntry;
+ pLast->pRight = pEntry;
}else{
- assert( p->pEntry==0 );
+ assert( p->pEntry==0 ); /* Fires if INSERT after SMALLEST */
p->pEntry = pEntry;
}
p->pLast = pEntry;
}
/*
-** Merge two lists of RowSet entries. Remove duplicates.
+** Merge two lists of RowSetEntry objects. Remove duplicates.
**
-** The input lists are assumed to be in sorted order.
+** The input lists are connected via pRight pointers and are
+** assumed to each already be in sorted order.
*/
-static struct RowSetEntry *boolidxMerge(
+static struct RowSetEntry *rowSetMerge(
struct RowSetEntry *pA, /* First sorted list to be merged */
struct RowSetEntry *pB /* Second sorted list to be merged */
){
@@ -29889,34 +30043,34 @@ static struct RowSetEntry *boolidxMerge(
pTail = &head;
while( pA && pB ){
- assert( pA->pNext==0 || pA->v<=pA->pNext->v );
- assert( pB->pNext==0 || pB->v<=pB->pNext->v );
+ assert( pA->pRight==0 || pA->v<=pA->pRight->v );
+ assert( pB->pRight==0 || pB->v<=pB->pRight->v );
if( pA->v<pB->v ){
- pTail->pNext = pA;
- pA = pA->pNext;
- pTail = pTail->pNext;
+ pTail->pRight = pA;
+ pA = pA->pRight;
+ pTail = pTail->pRight;
}else if( pB->v<pA->v ){
- pTail->pNext = pB;
- pB = pB->pNext;
- pTail = pTail->pNext;
+ pTail->pRight = pB;
+ pB = pB->pRight;
+ pTail = pTail->pRight;
}else{
- pA = pA->pNext;
+ pA = pA->pRight;
}
}
if( pA ){
- assert( pA->pNext==0 || pA->v<=pA->pNext->v );
- pTail->pNext = pA;
+ assert( pA->pRight==0 || pA->v<=pA->pRight->v );
+ pTail->pRight = pA;
}else{
- assert( pB==0 || pB->pNext==0 || pB->v<=pB->pNext->v );
- pTail->pNext = pB;
+ assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v );
+ pTail->pRight = pB;
}
- return head.pNext;
+ return head.pRight;
}
/*
-** Sort all elements of the RowSet into ascending order.
+** Sort all elements on the pEntry list of the RowSet into ascending order.
*/
-static void sqlite3RowSetSort(RowSet *p){
+static void rowSetSort(RowSet *p){
unsigned int i;
struct RowSetEntry *pEntry;
struct RowSetEntry *aBucket[40];
@@ -29925,35 +30079,143 @@ static void sqlite3RowSetSort(RowSet *p){
memset(aBucket, 0, sizeof(aBucket));
while( p->pEntry ){
pEntry = p->pEntry;
- p->pEntry = pEntry->pNext;
- pEntry->pNext = 0;
+ p->pEntry = pEntry->pRight;
+ pEntry->pRight = 0;
for(i=0; aBucket[i]; i++){
- pEntry = boolidxMerge(aBucket[i],pEntry);
+ pEntry = rowSetMerge(aBucket[i], pEntry);
aBucket[i] = 0;
}
aBucket[i] = pEntry;
}
pEntry = 0;
for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
- pEntry = boolidxMerge(pEntry,aBucket[i]);
+ pEntry = rowSetMerge(pEntry, aBucket[i]);
}
p->pEntry = pEntry;
p->pLast = 0;
p->isSorted = 1;
}
+
+/*
+** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
+** Convert this tree into a linked list connected by the pRight pointers
+** and return pointers to the first and last elements of the new list.
+*/
+static void rowSetTreeToList(
+ struct RowSetEntry *pIn, /* Root of the input tree */
+ struct RowSetEntry **ppFirst, /* Write head of the output list here */
+ struct RowSetEntry **ppLast /* Write tail of the output list here */
+){
+ assert( pIn!=0 );
+ if( pIn->pLeft ){
+ struct RowSetEntry *p;
+ rowSetTreeToList(pIn->pLeft, ppFirst, &p);
+ p->pRight = pIn;
+ }else{
+ *ppFirst = pIn;
+ }
+ if( pIn->pRight ){
+ rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
+ }else{
+ *ppLast = pIn;
+ }
+ assert( (*ppLast)->pRight==0 );
+}
+
+
+/*
+** Convert a sorted list of elements (connected by pRight) into a binary
+** tree with depth of iDepth. A depth of 1 means the tree contains a single
+** node taken from the head of *ppList. A depth of 2 means a tree with
+** three nodes. And so forth.
+**
+** Use as many entries from the input list as required and update the
+** *ppList to point to the unused elements of the list. If the input
+** list contains too few elements, then construct an incomplete tree
+** and leave *ppList set to NULL.
+**
+** Return a pointer to the root of the constructed binary tree.
+*/
+static struct RowSetEntry *rowSetNDeepTree(
+ struct RowSetEntry **ppList,
+ int iDepth
+){
+ struct RowSetEntry *p; /* Root of the new tree */
+ struct RowSetEntry *pLeft; /* Left subtree */
+ if( *ppList==0 ){
+ return 0;
+ }
+ if( iDepth==1 ){
+ p = *ppList;
+ *ppList = p->pRight;
+ p->pLeft = p->pRight = 0;
+ return p;
+ }
+ pLeft = rowSetNDeepTree(ppList, iDepth-1);
+ p = *ppList;
+ if( p==0 ){
+ return pLeft;
+ }
+ p->pLeft = pLeft;
+ *ppList = p->pRight;
+ p->pRight = rowSetNDeepTree(ppList, iDepth-1);
+ return p;
+}
+
/*
-** Extract the next (smallest) element from the RowSet.
+** Convert a sorted list of elements into a binary tree. Make the tree
+** as deep as it needs to be in order to contain the entire list.
+*/
+static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
+ int iDepth; /* Depth of the tree so far */
+ struct RowSetEntry *p; /* Current tree root */
+ struct RowSetEntry *pLeft; /* Left subtree */
+
+ assert( pList!=0 );
+ p = pList;
+ pList = p->pRight;
+ p->pLeft = p->pRight = 0;
+ for(iDepth=1; pList; iDepth++){
+ pLeft = p;
+ p = pList;
+ pList = p->pRight;
+ p->pLeft = pLeft;
+ p->pRight = rowSetNDeepTree(&pList, iDepth);
+ }
+ return p;
+}
+
+/*
+** Convert the list in p->pEntry into a sorted list if it is not
+** sorted already. If there is a binary tree on p->pTree, then
+** convert it into a list too and merge it into the p->pEntry list.
+*/
+static void rowSetToList(RowSet *p){
+ if( !p->isSorted ){
+ rowSetSort(p);
+ }
+ if( p->pTree ){
+ struct RowSetEntry *pHead, *pTail;
+ rowSetTreeToList(p->pTree, &pHead, &pTail);
+ p->pTree = 0;
+ p->pEntry = rowSetMerge(p->pEntry, pHead);
+ }
+}
+
+/*
+** Extract the smallest element from the RowSet.
** Write the element into *pRowid. Return 1 on success. Return
** 0 if the RowSet is already empty.
+**
+** After this routine has been called, the sqlite3RowSetInsert()
+** routine may not be called again.
*/
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
- if( !p->isSorted ){
- sqlite3RowSetSort(p);
- }
+ rowSetToList(p);
if( p->pEntry ){
*pRowid = p->pEntry->v;
- p->pEntry = p->pEntry->pNext;
+ p->pEntry = p->pEntry->pRight;
if( p->pEntry==0 ){
sqlite3RowSetClear(p);
}
@@ -29963,6 +30225,34 @@ SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
}
}
+/*
+** Check to see if element iRowid was inserted into the the rowset as
+** part of any insert batch prior to iBatch. Return 1 or 0.
+*/
+SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
+ struct RowSetEntry *p;
+ if( iBatch!=pRowSet->iBatch ){
+ if( pRowSet->pEntry ){
+ rowSetToList(pRowSet);
+ pRowSet->pTree = rowSetListToTree(pRowSet->pEntry);
+ pRowSet->pEntry = 0;
+ pRowSet->pLast = 0;
+ }
+ pRowSet->iBatch = iBatch;
+ }
+ p = pRowSet->pTree;
+ while( p ){
+ if( p->v<iRowid ){
+ p = p->pRight;
+ }else if( p->v>iRowid ){
+ p = p->pLeft;
+ }else{
+ return 1;
+ }
+ }
+ return 0;
+}
+
/************** End of rowset.c **********************************************/
/************** Begin file pager.c *******************************************/
/*
@@ -30195,6 +30485,12 @@ struct PagerSavepoint {
** TODO: It might be easier to set this variable in writeJournalHdr()
** and writeMasterJournal() only. Change its meaning to "unsynced data
** has been written to the journal".
+**
+** subjInMemory
+**
+** This is a boolean variable. If true, then any required sub-journal
+** is opened as an in-memory journal file. If false, then in-memory
+** sub-journals are only used for in-memory pager files.
*/
struct Pager {
sqlite3_vfs *pVfs; /* OS functions to use for IO */
@@ -30228,6 +30524,7 @@ struct Pager {
u8 setMaster; /* True if a m-j name has been written to jrnl */
u8 doNotSync; /* Boolean. While true, do not spill the cache */
u8 dbSizeValid; /* Set when dbSize is correct */
+ u8 subjInMemory; /* True to use in-memory sub-journals */
Pgno dbSize; /* Number of pages in the database */
Pgno dbOrigSize; /* dbSize before the current transaction */
Pgno dbFileSize; /* Number of pages in the database file */
@@ -31007,6 +31304,7 @@ static void pager_reset(Pager *pPager){
if( SQLITE_OK==pPager->errCode ){
sqlite3BackupRestart(pPager->pBackup);
sqlite3PcacheClear(pPager->pPCache);
+ pPager->dbSizeValid = 0;
}
}
@@ -31020,7 +31318,7 @@ static void releaseAllSavepoints(Pager *pPager){
for(ii=0; ii<pPager->nSavepoint; ii++){
sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
}
- if( !pPager->exclusiveMode ){
+ if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){
sqlite3OsClose(pPager->sjfd);
}
sqlite3_free(pPager->aSavepoint);
@@ -31256,7 +31554,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
}
}else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
- rc = sqlite3OsTruncate(pPager->jfd, 0);
+ if( pPager->journalOff==0 ){
+ rc = SQLITE_OK;
+ }else{
+ rc = sqlite3OsTruncate(pPager->jfd, 0);
+ }
pPager->journalOff = 0;
pPager->journalStarted = 0;
}else if( pPager->exclusiveMode
@@ -33145,7 +33447,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
nPathname + 1 + /* zFilename */
nPathname + 8 + 1 /* zJournal */
);
- assert( EIGHT_BYTE_ALIGNMENT(journalFileSize) );
+ assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
if( !pPtr ){
sqlite3_free(zPathname);
return SQLITE_NOMEM;
@@ -33630,9 +33932,15 @@ static int pagerSharedLock(Pager *pPager){
/*
** If the reference count has reached zero, rollback any active
** transaction and unlock the pager.
+**
+** Except, in locking_mode=EXCLUSIVE when there is nothing to in
+** the rollback journal, the unlock is not performed and there is
+** nothing to rollback, so this routine is a no-op.
*/
static void pagerUnlockIfUnused(Pager *pPager){
- if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){
+ if( (sqlite3PcacheRefCount(pPager->pPCache)==0)
+ && (!pPager->exclusiveMode || pPager->journalOff>0)
+ ){
pagerUnlockAndRollback(pPager);
}
}
@@ -33860,7 +34168,7 @@ SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
static int openSubJournal(Pager *pPager){
int rc = SQLITE_OK;
if( isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ){
- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
+ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
sqlite3MemJournalOpen(pPager->sjfd);
}else{
rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL);
@@ -33979,10 +34287,19 @@ static int pager_open_journal(Pager *pPager){
**
** If the journal file is opened (or if it is already open), then a
** journal-header is written to the start of it.
+**
+** If the subjInMemory argument is non-zero, then any sub-journal opened
+** within this transaction will be opened as an in-memory file. This
+** has no effect if the sub-journal is already opened (as it may be when
+** running in exclusive mode) or if the transaction does not require a
+** sub-journal. If the subjInMemory argument is zero, then any required
+** sub-journal is implemented in-memory if pPager is an in-memory database,
+** or using a temporary file otherwise.
*/
-SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag){
+SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
int rc = SQLITE_OK;
assert( pPager->state!=PAGER_UNLOCK );
+ pPager->subjInMemory = (u8)subjInMemory;
if( pPager->state==PAGER_SHARED ){
assert( pPager->pInJournal==0 );
assert( !MEMDB && !pPager->tempFile );
@@ -34067,7 +34384,7 @@ static int pager_write(PgHdr *pPg){
** create it if it does not.
*/
assert( pPager->state!=PAGER_UNLOCK );
- rc = sqlite3PagerBegin(pPager, 0);
+ rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -35150,11 +35467,14 @@ SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
** PAGER_JOURNALMODE_OFF
** PAGER_JOURNALMODE_MEMORY
**
-** If the parameter is not _QUERY, then the journal-mode is set to the
-** value specified. Except, an in-memory database can only have its
-** journal mode set to _OFF or _MEMORY. Attempts to change the journal
-** mode of an in-memory database to something other than _OFF or _MEMORY
-** are silently ignored.
+** If the parameter is not _QUERY, then the journal_mode is set to the
+** value specified if the change is allowed. The change is disallowed
+** for the following reasons:
+**
+** * An in-memory database can only have its journal_mode set to _OFF
+** or _MEMORY.
+**
+** * The journal mode may not be changed while a transaction is active.
**
** The returned indicate the current (possibly updated) journal-mode.
*/
@@ -35166,8 +35486,15 @@ SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *pPager, int eMode){
|| eMode==PAGER_JOURNALMODE_OFF
|| eMode==PAGER_JOURNALMODE_MEMORY );
assert( PAGER_JOURNALMODE_QUERY<0 );
- if( eMode>=0 && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY
- || eMode==PAGER_JOURNALMODE_OFF) ){
+ if( eMode>=0
+ && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY
+ || eMode==PAGER_JOURNALMODE_OFF)
+ && !pPager->dbModified
+ && (!isOpen(pPager->jfd) || 0==pPager->journalOff)
+ ){
+ if( isOpen(pPager->jfd) ){
+ sqlite3OsClose(pPager->jfd);
+ }
pPager->journalMode = (u8)eMode;
}
return (int)pPager->journalMode;
@@ -36964,18 +37291,59 @@ SQLITE_PRIVATE void sqlite3BtreeParseCell(
** data header and the local payload, but not any overflow page or
** the space used by the cell pointer.
*/
+static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
+ u8 *pIter = &pCell[pPage->childPtrSize];
+ u32 nSize;
+
+#ifdef SQLITE_DEBUG
+ /* The value returned by this function should always be the same as
+ ** the (CellInfo.nSize) value found by doing a full parse of the
+ ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
+ ** this function verifies that this invariant is not violated. */
+ CellInfo debuginfo;
+ sqlite3BtreeParseCellPtr(pPage, pCell, &debuginfo);
+#endif
+
+ if( pPage->intKey ){
+ u8 *pEnd;
+ if( pPage->hasData ){
+ pIter += getVarint32(pIter, nSize);
+ }else{
+ nSize = 0;
+ }
+
+ /* pIter now points at the 64-bit integer key value, a variable length
+ ** integer. The following block moves pIter to point at the first byte
+ ** past the end of the key value. */
+ pEnd = &pIter[9];
+ while( (*pIter++)&0x80 && pIter<pEnd );
+ }else{
+ pIter += getVarint32(pIter, nSize);
+ }
+
+ if( nSize>pPage->maxLocal ){
+ int minLocal = pPage->minLocal;
+ nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
+ if( nSize>pPage->maxLocal ){
+ nSize = minLocal;
+ }
+ nSize += 4;
+ }
+ nSize += (pIter - pCell);
+
+ /* The minimum size of any cell is 4 bytes. */
+ if( nSize<4 ){
+ nSize = 4;
+ }
+
+ assert( nSize==debuginfo.nSize );
+ return (u16)nSize;
+}
#ifndef NDEBUG
static u16 cellSize(MemPage *pPage, int iCell){
- CellInfo info;
- sqlite3BtreeParseCell(pPage, iCell, &info);
- return info.nSize;
+ return cellSizePtr(pPage, findCell(pPage, iCell));
}
#endif
-static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
- CellInfo info;
- sqlite3BtreeParseCellPtr(pPage, pCell, &info);
- return info.nSize;
-}
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
@@ -37122,13 +37490,13 @@ static int allocateSpace(MemPage *pPage, int nByte){
if( size>=nByte ){
int x = size - nByte;
if( x<4 ){
- /* Remove the slot from the free-list. Update the number of
- ** fragmented bytes within the page. */
+ /* Remove the slot from the free-list. Update the number of
+ ** fragmented bytes within the page. */
memcpy(&data[addr], &data[pc], 2);
data[hdr+7] = (u8)(nFrag + x);
}else{
- /* The slot remains on the free-list. Reduce its size to account
- ** for the portion used by the new allocation. */
+ /* The slot remains on the free-list. Reduce its size to account
+ ** for the portion used by the new allocation. */
put2byte(&data[pc+2], x);
}
return pc + x;
@@ -37562,6 +37930,12 @@ static int btreeInvokeBusyHandler(void *pArg){
** database file will be deleted when sqlite3BtreeClose() is called.
** If zFilename is ":memory:" then an in-memory database is created
** that is automatically destroyed when it is closed.
+**
+** If the database is already opened in the same database connection
+** and we are in shared cache mode, then the open will fail with an
+** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
+** objects in the same database connection since doing so will lead
+** to problems with locking.
*/
SQLITE_PRIVATE int sqlite3BtreeOpen(
const char *zFilename, /* Name of the file containing the BTree database */
@@ -37627,6 +38001,17 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
assert( pBt->nRef>0 );
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
+ int iDb;
+ for(iDb=db->nDb-1; iDb>=0; iDb--){
+ Btree *pExisting = db->aDb[iDb].pBt;
+ if( pExisting && pExisting->pBt==pBt ){
+ sqlite3_mutex_leave(mutexShared);
+ sqlite3_mutex_leave(mutexOpen);
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return SQLITE_CONSTRAINT;
+ }
+ }
p->pBt = pBt;
pBt->nRef++;
break;
@@ -37684,7 +38069,6 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
pBt->pageSize = 0;
- sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the magic name ":memory:" will create an in-memory database, then
** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
@@ -37706,9 +38090,10 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);
#endif
}
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
+ if( rc ) goto btree_open_out;
pBt->usableSize = pBt->pageSize - nReserve;
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
- sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
/* Add the new BtShared object to the linked list sharable BtShareds.
@@ -38152,7 +38537,8 @@ static int lockBtree(BtShared *pBt){
pBt->usableSize = (u16)usableSize;
pBt->pageSize = (u16)pageSize;
freeTempSpace(pBt);
- sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
+ if( rc ) goto page1_init_failed;
return SQLITE_OK;
}
if( usableSize<500 ){
@@ -38231,14 +38617,6 @@ static void unlockBtreeIfUnused(BtShared *pBt){
if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
if( sqlite3PagerRefcount(pBt->pPager)>=1 ){
assert( pBt->pPage1->aData );
-#if 0
- if( pBt->pPage1->aData==0 ){
- MemPage *pPage = pBt->pPage1;
- pPage->aData = sqlite3PagerGetData(pPage->pDbPage);
- pPage->pBt = pBt;
- pPage->pgno = 1;
- }
-#endif
releasePage(pBt->pPage1);
}
pBt->pPage1 = 0;
@@ -38381,7 +38759,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
if( pBt->readOnly ){
rc = SQLITE_READONLY;
}else{
- rc = sqlite3PagerBegin(pBt->pPager, wrflag>1);
+ rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}
@@ -38831,7 +39209,7 @@ static int autoVacuumCommit(BtShared *pBt){
** database are written into the database file and flushed to oxide.
** At the end of this call, the rollback journal still exists on the
** disk and we are still holding all locks, so the transaction has not
-** committed. See sqlite3BtreeCommit() for the second phase of the
+** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the
** commit process.
**
** This call is a no-op if no write-transaction is currently active on pBt.
@@ -38871,12 +39249,13 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
** Commit the transaction currently in progress.
**
** This routine implements the second phase of a 2-phase commit. The
-** sqlite3BtreeSync() routine does the first phase and should be invoked
-** prior to calling this routine. The sqlite3BtreeSync() routine did
-** all the work of writing information out to disk and flushing the
+** sqlite3BtreeCommitPhaseOne() routine does the first phase and should
+** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne()
+** routine did all the work of writing information out to disk and flushing the
** contents so that they are written onto the disk platter. All this
-** routine has to do is delete or truncate the rollback journal
-** (which causes the transaction to commit) and drop locks.
+** routine has to do is delete or truncate or zero the header in the
+** the rollback journal (which causes the transaction to commit) and
+** drop locks.
**
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
@@ -38915,7 +39294,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p){
}
}
- /* Set the handles current transaction state to TRANS_NONE and unlock
+ /* Set the current transaction state to TRANS_NONE and unlock
** the pager if this call closed the only read or write transaction.
*/
btreeClearHasContent(pBt);
@@ -40071,6 +40450,22 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+ /* If the cursor already points to the last entry, this is a no-op. */
+ if( CURSOR_VALID==pCur->eState && pCur->atLast ){
+#ifdef SQLITE_DEBUG
+ /* This block serves to assert() that the cursor really does point
+ ** to the last entry in the b-tree. */
+ int ii;
+ for(ii=0; ii<pCur->iPage; ii++){
+ assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
+ }
+ assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 );
+ assert( pCur->apPage[pCur->iPage]->leaf );
+#endif
+ return SQLITE_OK;
+ }
+
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
if( CURSOR_INVALID==pCur->eState ){
@@ -40080,7 +40475,6 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( pCur->eState==CURSOR_VALID );
*pRes = 0;
rc = moveToRightmost(pCur);
- getCellInfo(pCur);
pCur->atLast = rc==SQLITE_OK ?1:0;
}
}
@@ -40171,14 +40565,13 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
pCur->aiIdx[pCur->iPage] = (u16)((upr+lwr)/2);
}
for(;;){
- void *pCellKey;
- i64 nCellKey;
- int idx = pCur->aiIdx[pCur->iPage];
+ int idx = pCur->aiIdx[pCur->iPage]; /* Index of current cell in pPage */
+ u8 *pCell; /* Pointer to current cell in pPage */
+
pCur->info.nSize = 0;
- pCur->validNKey = 1;
+ pCell = findCell(pPage, idx) + pPage->childPtrSize;
if( pPage->intKey ){
- u8 *pCell;
- pCell = findCell(pPage, idx) + pPage->childPtrSize;
+ i64 nCellKey;
if( pPage->hasData ){
u32 dummy;
pCell += getVarint32(pCell, dummy);
@@ -40192,26 +40585,50 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
assert( nCellKey>intKey );
c = +1;
}
+ pCur->validNKey = 1;
+ pCur->info.nKey = nCellKey;
}else{
- int available;
- pCellKey = (void *)fetchPayload(pCur, &available, 0);
- nCellKey = pCur->info.nKey;
- if( available>=nCellKey ){
- c = sqlite3VdbeRecordCompare((int)nCellKey, pCellKey, pIdxKey);
+ /* The maximum supported page-size is 32768 bytes. This means that
+ ** the maximum number of record bytes stored on an index B-Tree
+ ** page is at most 8198 bytes, which may be stored as a 2-byte
+ ** varint. This information is used to attempt to avoid parsing
+ ** the entire cell by checking for the cases where the record is
+ ** stored entirely within the b-tree page by inspecting the first
+ ** 2 bytes of the cell.
+ */
+ int nCell = pCell[0];
+ if( !(nCell & 0x80) && nCell<=pPage->maxLocal ){
+ /* This branch runs if the record-size field of the cell is a
+ ** single byte varint and the record fits entirely on the main
+ ** b-tree page. */
+ c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
+ }else if( !(pCell[1] & 0x80)
+ && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
+ ){
+ /* The record-size field is a 2 byte varint and the record
+ ** fits entirely on the main b-tree page. */
+ c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
- pCellKey = sqlite3Malloc( (int)nCellKey );
+ /* The record flows over onto one or more overflow pages. In
+ ** this case the whole cell needs to be parsed, a buffer allocated
+ ** and accessPayload() used to retrieve the record into the
+ ** buffer before VdbeRecordCompare() can be called. */
+ void *pCellKey;
+ u8 * const pCellBody = pCell - pPage->childPtrSize;
+ sqlite3BtreeParseCellPtr(pPage, pCellBody, &pCur->info);
+ nCell = (int)pCur->info.nKey;
+ pCellKey = sqlite3Malloc( nCell );
if( pCellKey==0 ){
rc = SQLITE_NOMEM;
goto moveto_finish;
}
- rc = sqlite3BtreeKey(pCur, 0, (int)nCellKey, (void*)pCellKey);
- c = sqlite3VdbeRecordCompare((int)nCellKey, pCellKey, pIdxKey);
+ rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0, 0);
+ c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
if( rc ) goto moveto_finish;
}
}
if( c==0 ){
- pCur->info.nKey = nCellKey;
if( pPage->intKey && !pPage->leaf ){
lwr = idx;
upr = lwr - 1;
@@ -40228,7 +40645,6 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
upr = idx-1;
}
if( lwr>upr ){
- pCur->info.nKey = nCellKey;
break;
}
pCur->aiIdx[pCur->iPage] = (u16)((lwr+upr)/2);
@@ -41189,7 +41605,7 @@ static int insertCell(
CellInfo info;
sqlite3BtreeParseCellPtr(pPage, pCell, &info);
assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload );
- if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
+ if( info.iOverflow ){
Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno);
if( rc!=SQLITE_OK ) return rc;
@@ -41212,39 +41628,32 @@ static void assemblePage(
u16 *aSize /* Sizes of the cells */
){
int i; /* Loop counter */
- int totalSize; /* Total size of all cells */
- int hdr; /* Index of page header */
- int cellptr; /* Address of next cell pointer */
+ u8 *pCellptr; /* Address of next cell pointer */
int cellbody; /* Address of next cell body */
- u8 *data; /* Data for the page */
+ u8 * const data = pPage->aData; /* Pointer to data for pPage */
+ const int hdr = pPage->hdrOffset; /* Offset of header on pPage */
+ const int nUsable = pPage->pBt->usableSize; /* Usable size of page */
assert( pPage->nOverflow==0 );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( nCell>=0 && nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 );
- totalSize = 0;
- for(i=0; i<nCell; i++){
- totalSize += aSize[i];
- }
- assert( totalSize+2*nCell<=pPage->nFree );
- assert( pPage->nCell==0 );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- cellptr = pPage->cellOffset;
- data = pPage->aData;
- hdr = pPage->hdrOffset;
- put2byte(&data[hdr+3], nCell);
- if( nCell ){
- cellbody = allocateSpace(pPage, totalSize);
- assert( cellbody>0 );
- assert( pPage->nFree >= 2*nCell );
- pPage->nFree -= 2*nCell;
- for(i=0; i<nCell; i++){
- put2byte(&data[cellptr], cellbody);
- memcpy(&data[cellbody], apCell[i], aSize[i]);
- cellptr += 2;
- cellbody += aSize[i];
- }
- assert( cellbody==pPage->pBt->usableSize );
+
+ /* Check that the page has just been zeroed by zeroPage() */
+ assert( pPage->nCell==0 );
+ assert( get2byte(&data[hdr+5])==nUsable );
+
+ pCellptr = &data[pPage->cellOffset + nCell*2];
+ cellbody = nUsable;
+ for(i=nCell-1; i>=0; i--){
+ pCellptr -= 2;
+ cellbody -= aSize[i];
+ put2byte(pCellptr, cellbody);
+ memcpy(&data[cellbody], apCell[i], aSize[i]);
}
+ put2byte(&data[hdr+3], nCell);
+ put2byte(&data[hdr+5], cellbody);
+ pPage->nFree -= (nCell*2 + nUsable - cellbody);
pPage->nCell = (u16)nCell;
}
@@ -42276,16 +42685,28 @@ static int checkForReadConflicts(
**
** For an INTKEY table, only the nKey value of the key is used. pKey is
** ignored. For a ZERODATA table, the pData and nData are both ignored.
+**
+** If the seekResult parameter is non-zero, then a successful call to
+** sqlite3BtreeMoveto() to seek cursor pCur to (pKey, nKey) has already
+** been performed. seekResult is the search result returned (a negative
+** number if pCur points at an entry that is smaller than (pKey, nKey), or
+** a positive value if pCur points at an etry that is larger than
+** (pKey, nKey)).
+**
+** If the seekResult parameter is 0, then cursor pCur may point to any
+** entry or to no entry at all. In this case this function has to seek
+** the cursor before the new key can be inserted.
*/
SQLITE_PRIVATE int sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const void *pKey, i64 nKey, /* The key of the new record */
const void *pData, int nData, /* The data of the new record */
int nZero, /* Number of extra 0 bytes to append to data */
- int appendBias /* True if this is likely an append */
+ int appendBias, /* True if this is likely an append */
+ int seekResult /* Result of prior sqlite3BtreeMoveto() call */
){
int rc;
- int loc;
+ int loc = seekResult;
int szNew;
int idx;
MemPage *pPage;
@@ -42308,12 +42729,21 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
return pCur->skip;
}
- /* Save the positions of any other cursors open on this table */
- sqlite3BtreeClearCursor(pCur);
- if(
- SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
+ /* Save the positions of any other cursors open on this table.
+ **
+ ** In some cases, the call to sqlite3BtreeMoveto() below is a no-op. For
+ ** example, when inserting data into a table with auto-generated integer
+ ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
+ ** integer key to use. It then calls this function to actually insert the
+ ** data into the intkey B-Tree. In this case sqlite3BtreeMoveto() recognizes
+ ** that the cursor is already where it needs to be and returns without
+ ** doing any work. To avoid thwarting these optimizations, it is important
+ ** not to clear the cursor here.
+ */
+ if(
+ SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || (!loc &&
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
- ){
+ )){
return rc;
}
@@ -42359,17 +42789,42 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
assert( pPage->leaf );
}
rc = insertCell(pPage, idx, newCell, szNew, 0, 0);
- if( rc==SQLITE_OK ){
+ assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
+
+ /* If no error has occured, call balance() to deal with any overflow and
+ ** move the cursor to point at the root of the table (since balance may
+ ** have rearranged the table in such a way as to invalidate BtCursor.apPage[]
+ ** or BtCursor.aiIdx[]).
+ **
+ ** Except, if all of the following are true, do nothing:
+ **
+ ** * Inserting the new cell did not cause overflow,
+ **
+ ** * Before inserting the new cell the cursor was pointing at the
+ ** largest key in an intkey B-Tree, and
+ **
+ ** * The key value associated with the new cell is now the largest
+ ** in the B-Tree.
+ **
+ ** In this case the cursor can be safely left pointing at the (new)
+ ** largest key value in the B-Tree. Doing so speeds up inserting a set
+ ** of entries with increasing integer key values via a single cursor
+ ** (comes up with "INSERT INTO ... SELECT ..." statements), as
+ ** the next insert operation is not required to seek the cursor.
+ */
+ if( rc==SQLITE_OK
+ && (pPage->nOverflow || !pCur->atLast || loc>=0 || !pCur->apPage[0]->intKey)
+ ){
rc = balance(pCur, 1);
+ if( rc==SQLITE_OK ){
+ moveToRoot(pCur);
+ }
}
-
+
/* Must make sure nOverflow is reset to zero even if the balance()
** fails. Internal data structure corruption will result otherwise. */
pCur->apPage[pCur->iPage]->nOverflow = 0;
- if( rc==SQLITE_OK ){
- moveToRoot(pCur);
- }
end_insert:
return rc;
}
@@ -43201,7 +43656,7 @@ static void checkPtrmap(
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ) pCheck->mallocFailed = 1;
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild);
return;
}
@@ -43328,7 +43783,7 @@ static int checkTreePage(
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
if( (rc = sqlite3BtreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
- if( rc==SQLITE_NOMEM ) pCheck->mallocFailed = 1;
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
checkAppendMsg(pCheck, zContext,
"unable to get the page. error code=%d", rc);
return 0;
@@ -44653,16 +45108,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
*/
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
- if( p->flags&MEM_Agg ){
- sqlite3VdbeMemFinalize(p, p->u.pDef);
- assert( (p->flags & MEM_Agg)==0 );
- sqlite3VdbeMemRelease(p);
- }else if( p->flags&MEM_Dyn && p->xDel ){
- assert( (p->flags&MEM_RowSet)==0 );
- p->xDel((void *)p->z);
- p->xDel = 0;
- }else if( p->flags&MEM_RowSet ){
- sqlite3RowSetClear(p->u.pRowSet);
+ if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet) ){
+ if( p->flags&MEM_Agg ){
+ sqlite3VdbeMemFinalize(p, p->u.pDef);
+ assert( (p->flags & MEM_Agg)==0 );
+ sqlite3VdbeMemRelease(p);
+ }else if( p->flags&MEM_Dyn && p->xDel ){
+ assert( (p->flags&MEM_RowSet)==0 );
+ p->xDel((void *)p->z);
+ p->xDel = 0;
+ }else if( p->flags&MEM_RowSet ){
+ sqlite3RowSetClear(p->u.pRowSet);
+ }
}
}
@@ -45358,12 +45815,14 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n);
pVal = sqlite3ValueNew(db);
if( !zVal || !pVal ) goto no_mem;
- sqlite3Dequote(zVal);
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
- sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc);
+ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
}else{
- sqlite3ValueApplyAffinity(pVal, affinity, enc);
+ sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
+ }
+ if( enc!=SQLITE_UTF8 ){
+ sqlite3VdbeChangeEncoding(pVal, enc);
}
}else if( op==TK_UMINUS ) {
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
@@ -46169,9 +46628,9 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
*/
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
int mask;
- assert( i>=0 && i<p->db->nDb );
+ assert( i>=0 && i<p->db->nDb && i<sizeof(u32)*8 );
assert( i<(int)sizeof(p->btreeMask)*8 );
- mask = 1<<i;
+ mask = ((u32)1)<<i;
if( (p->btreeMask & mask)==0 ){
p->btreeMask |= mask;
sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt);
@@ -47379,7 +47838,7 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
int i;
for(i=0; i<pVdbeFunc->nAux; i++){
struct AuxData *pAux = &pVdbeFunc->apAux[i];
- if( (i>31 || !(mask&(1<<i))) && pAux->pAux ){
+ if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
if( pAux->xDelete ){
pAux->xDelete(pAux->pAux);
}
@@ -47441,8 +47900,8 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
p->lastRowid = keyToInt(p->movetoTarget);
- p->rowidIsValid = res==0 ?1:0;
- if( res<0 ){
+ p->rowidIsValid = ALWAYS(res==0) ?1:0;
+ if( NEVER(res<0) ){
rc = sqlite3BtreeNext(p->pCursor, &res);
if( rc ) return rc;
}
@@ -47905,6 +48364,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
mem1.flags = 0;
+ mem1.u.i = 0; /* not needed, here to silence compiler warning */
mem1.zMalloc = 0;
idx1 = getVarint32(aKey1, szHdr1);
@@ -47935,6 +48395,18 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
}
if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1);
+ /* If the PREFIX_SEARCH flag is set and all fields except the final
+ ** rowid field were equal, then clear the PREFIX_SEARCH flag and set
+ ** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1).
+ ** This is used by the OP_IsUnique opcode.
+ */
+ if( (pPKey2->flags & UNPACKED_PREFIX_SEARCH) && i==(pPKey2->nField-1) ){
+ assert( idx1==szHdr1 && rc );
+ assert( mem1.flags & MEM_Int );
+ pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH;
+ pPKey2->rowid = mem1.u.i;
+ }
+
if( rc==0 ){
/* rc==0 here means that one of the keys ran out of fields and
** all the fields up to that point were equal. If the UNPACKED_INCRKEY
@@ -48520,6 +48992,10 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
}
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode;
+ if( pCtx->s.flags & MEM_Null ){
+ sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
+ SQLITE_UTF8, SQLITE_STATIC);
+ }
}
/* Force an SQLITE_TOOBIG error. */
@@ -49272,15 +49748,32 @@ SQLITE_API int sqlite3_bind_text16(
#endif /* SQLITE_OMIT_UTF16 */
SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int rc;
- Vdbe *p = (Vdbe *)pStmt;
- rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
- if( rc==SQLITE_OK ){
- rc = sqlite3VdbeChangeEncoding(&p->aVar[i-1], ENC(p->db));
+ switch( pValue->type ){
+ case SQLITE_INTEGER: {
+ rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
+ break;
+ }
+ case SQLITE_FLOAT: {
+ rc = sqlite3_bind_double(pStmt, i, pValue->r);
+ break;
+ }
+ case SQLITE_BLOB: {
+ if( pValue->flags & MEM_Zero ){
+ rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
+ }else{
+ rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
+ }
+ break;
+ }
+ case SQLITE_TEXT: {
+ rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT,
+ pValue->enc);
+ break;
+ }
+ default: {
+ rc = sqlite3_bind_null(pStmt, i);
+ break;
}
- sqlite3_mutex_leave(p->db->mutex);
- rc = sqlite3ApiExit(p->db, rc);
}
return rc;
}
@@ -49876,6 +50369,8 @@ static void memTracePrint(FILE *out, Mem *p){
fprintf(out, " i:%lld", p->u.i);
}else if( p->flags & MEM_Real ){
fprintf(out, " r:%g", p->r);
+ }else if( p->flags & MEM_RowSet ){
+ fprintf(out, " (rowset)");
}else{
char zBuf[200];
sqlite3VdbeMemPrettyPrint(p, zBuf);
@@ -52001,7 +52496,7 @@ case OP_Savepoint: {
db->isTransactionSavepoint = 1;
}else{
db->nSavepoint++;
- }
+ }
/* Link the new savepoint into the database handle's list. */
pNew->pNext = db->pSavepoint;
@@ -52875,103 +53370,82 @@ case OP_Found: { /* jump, in3 */
/* Opcode: IsUnique P1 P2 P3 P4 *
**
-** The P3 register contains an integer record number. Call this
-** record number R. The P4 register contains an index key created
-** using MakeRecord. Call it K.
-**
-** P1 is an index. So it has no data and its key consists of a
-** record generated by OP_MakeRecord where the last field is the
+** Cursor P1 is open on an index. So it has no data and its key consists
+** of a record generated by OP_MakeRecord where the last field is the
** rowid of the entry that the index refers to.
-**
-** This instruction asks if there is an entry in P1 where the
-** fields matches K but the rowid is different from R.
-** If there is no such entry, then there is an immediate
-** jump to P2. If any entry does exist where the index string
-** matches K but the record number is not R, then the record
-** number for that entry is written into P3 and control
-** falls through to the next instruction.
+**
+** The P3 register contains an integer record number. Call this record
+** number R. Register P4 is the first in a set of N contiguous registers
+** that make up an unpacked index key that can be used with cursor P1.
+** The value of N can be inferred from the cursor. N includes the rowid
+** value appended to the end of the index record. This rowid value may
+** or may not be the same as R.
+**
+** If any of the N registers beginning with register P4 contains a NULL
+** value, jump immediately to P2.
+**
+** Otherwise, this instruction checks if cursor P1 contains an entry
+** where the first (N-1) fields match but the rowid value at the end
+** of the index entry is not R. If there is no such entry, control jumps
+** to instruction P2. Otherwise, the rowid of the conflicting index
+** entry is copied to register P3 and control falls through to the next
+** instruction.
**
** See also: NotFound, NotExists, Found
*/
case OP_IsUnique: { /* jump, in3 */
- int i = pOp->p1;
+ u16 ii;
VdbeCursor *pCx;
BtCursor *pCrsr;
- Mem *pK;
- i64 R;
+ u16 nField;
+ Mem *aMem = &p->aMem[pOp->p4.i];
- /* Pop the value R off the top of the stack
- */
+ /* Assert that the values of parameters P1 and P4 are in range. */
assert( pOp->p4type==P4_INT32 );
assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
- pK = &p->aMem[pOp->p4.i];
- sqlite3VdbeMemIntegerify(pIn3);
- R = pIn3->u.i;
- assert( i>=0 && i<p->nCursor );
- pCx = p->apCsr[i];
- assert( pCx!=0 );
- pCrsr = pCx->pCursor;
- if( pCrsr!=0 ){
- int res;
- i64 v; /* The record number that matches K */
- UnpackedRecord *pIdxKey; /* Unpacked version of P4 */
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- /* Make sure K is a string and make zKey point to K
- */
- assert( pK->flags & MEM_Blob );
- pIdxKey = sqlite3VdbeRecordUnpack(pCx->pKeyInfo, pK->n, pK->z,
- aTempRec, sizeof(aTempRec));
- if( pIdxKey==0 ){
- goto no_mem;
- }
- pIdxKey->flags |= UNPACKED_IGNORE_ROWID;
+ /* Find the index cursor. */
+ pCx = p->apCsr[pOp->p1];
+ assert( pCx->deferredMoveto==0 );
+ pCx->seekResult = 0;
+ pCx->cacheStatus = CACHE_STALE;
+ pCrsr = pCx->pCursor;
- /* Search for an entry in P1 where all but the last rowid match K
- ** If there is no such entry, jump immediately to P2.
- */
- assert( pCx->deferredMoveto==0 );
- pCx->cacheStatus = CACHE_STALE;
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, pIdxKey, 0, 0, &res);
- if( rc!=SQLITE_OK ){
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
- goto abort_due_to_error;
- }
- if( res<0 ){
- rc = sqlite3BtreeNext(pCrsr, &res);
- if( res ){
- pc = pOp->p2 - 1;
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
- break;
- }
- }
- rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res);
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- if( res>0 ){
+ /* If any of the values are NULL, take the jump. */
+ nField = pCx->pKeyInfo->nField;
+ for(ii=0; ii<nField; ii++){
+ if( aMem[ii].flags & MEM_Null ){
pc = pOp->p2 - 1;
+ pCrsr = 0;
break;
}
+ }
+ assert( (aMem[nField].flags & MEM_Null)==0 );
- /* At this point, pCrsr is pointing to an entry in P1 where all but
- ** the final entry (the rowid) matches K. Check to see if the
- ** final rowid column is different from R. If it equals R then jump
- ** immediately to P2.
- */
- rc = sqlite3VdbeIdxRowid(pCrsr, &v);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- if( v==R ){
+ if( pCrsr!=0 ){
+ UnpackedRecord r; /* B-Tree index search key */
+ i64 R; /* Rowid stored in register P3 */
+
+ /* Populate the index search key. */
+ r.pKeyInfo = pCx->pKeyInfo;
+ r.nField = nField + 1;
+ r.flags = UNPACKED_PREFIX_SEARCH;
+ r.aMem = aMem;
+
+ /* Extract the value of R from register P3. */
+ sqlite3VdbeMemIntegerify(pIn3);
+ R = pIn3->u.i;
+
+ /* Search the B-Tree index. If no conflicting record is found, jump
+ ** to P2. Otherwise, copy the rowid of the conflicting record to
+ ** register P3 and fall through to the next instruction. */
+ rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &pCx->seekResult);
+ if( (r.flags & UNPACKED_PREFIX_SEARCH) || r.rowid==R ){
pc = pOp->p2 - 1;
- break;
+ }else{
+ pIn3->u.i = r.rowid;
}
-
- /* The final varint of the key is different from R. Store it back
- ** into register R3. (The record number of an entry that violates
- ** a UNIQUE constraint.)
- */
- pIn3->u.i = v;
- assert( pIn3->flags&MEM_Int );
}
break;
}
@@ -53002,15 +53476,17 @@ case OP_NotExists: { /* jump, in3 */
assert( pIn3->flags & MEM_Int );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pIn3->u.i);
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res);
+ rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
pC->lastRowid = pIn3->u.i;
pC->rowidIsValid = res==0 ?1:0;
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
+ pC->deferredMoveto = 0;
if( res!=0 ){
pc = pOp->p2 - 1;
assert( pC->rowidIsValid==0 );
}
+ pC->seekResult = res;
}else if( !pC->pseudoTable ){
/* This happens when an attempt to open a read cursor on the
** sqlite_master table returns SQLITE_EMPTY.
@@ -53018,6 +53494,7 @@ case OP_NotExists: { /* jump, in3 */
assert( pC->isTable );
pc = pOp->p2 - 1;
assert( pC->rowidIsValid==0 );
+ pC->seekResult = 0;
}
break;
}
@@ -53260,6 +53737,7 @@ case OP_Insert: {
pC->nullRow = 0;
}else{
int nZero;
+ int seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
if( pData->flags & MEM_Zero ){
nZero = pData->u.nZero;
}else{
@@ -53268,7 +53746,8 @@ case OP_Insert: {
sqlite3BtreeSetCachedRowid(pC->pCursor, 0);
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
pData->z, pData->n, nZero,
- pOp->p5 & OPFLAG_APPEND);
+ pOp->p5 & OPFLAG_APPEND, seekResult
+ );
}
pC->rowidIsValid = 0;
@@ -53432,6 +53911,10 @@ case OP_RowData: {
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
+**
+** P1 can be either an ordinary table or a virtual table. There used to
+** be a separate OP_VRowid opcode for use with virtual tables, but this
+** one opcode now works for both table types.
*/
case OP_Rowid: { /* out2-prerelease */
int i = pOp->p1;
@@ -53441,19 +53924,37 @@ case OP_Rowid: { /* out2-prerelease */
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC!=0 );
- rc = sqlite3VdbeCursorMoveto(pC);
- if( rc ) goto abort_due_to_error;
- if( pC->rowidIsValid ){
- v = pC->lastRowid;
+ if( pC->nullRow ){
+ /* Do nothing so that reg[P2] remains NULL */
+ break;
+ }else if( pC->deferredMoveto ){
+ v = pC->movetoTarget;
}else if( pC->pseudoTable ){
v = keyToInt(pC->iKey);
- }else if( pC->nullRow ){
- /* Leave the rowid set to a NULL */
- break;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ }else if( pC->pVtabCursor ){
+ sqlite3_vtab *pVtab;
+ const sqlite3_module *pModule;
+ pVtab = pC->pVtabCursor->pVtab;
+ pModule = pVtab->pModule;
+ assert( pModule->xRowid );
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xRowid(pC->pVtabCursor, &v);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
- assert( pC->pCursor!=0 );
- sqlite3BtreeKeySize(pC->pCursor, &v);
- v = keyToInt(v);
+ rc = sqlite3VdbeCursorMoveto(pC);
+ if( rc ) goto abort_due_to_error;
+ if( pC->rowidIsValid ){
+ v = pC->lastRowid;
+ }else{
+ assert( pC->pCursor!=0 );
+ sqlite3BtreeKeySize(pC->pCursor, &v);
+ v = keyToInt(v);
+ }
}
pOut->u.i = v;
MemSetTypeFlag(pOut, MEM_Int);
@@ -53617,7 +54118,7 @@ case OP_Next: { /* jump */
break;
}
-/* Opcode: IdxInsert P1 P2 P3 * *
+/* Opcode: IdxInsert P1 P2 P3 * P5
**
** Register P2 holds a SQL index key made using the
** MakeRecord instructions. This opcode writes that key
@@ -53642,7 +54143,9 @@ case OP_IdxInsert: { /* in2 */
if( rc==SQLITE_OK ){
int nKey = pIn2->n;
const char *zKey = pIn2->z;
- rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3);
+ rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3,
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
+ );
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
}
@@ -54140,6 +54643,59 @@ case OP_RowSetRead: { /* jump, out3 */
break;
}
+/* Opcode: RowSetTest P1 P2 P3 P4
+**
+** Register P3 is assumed to hold a 64-bit integer value. If register P1
+** contains a RowSet object and that RowSet object contains
+** the value held in P3, jump to register P2. Otherwise, insert the
+** integer in P3 into the RowSet and continue on to the
+** next opcode.
+**
+** The RowSet object is optimized for the case where successive sets
+** of integers, where each set contains no duplicates. Each set
+** of values is identified by a unique P4 value. The first set
+** must have P4==0, the final set P4=-1. P4 must be either -1 or
+** non-negative. For non-negative values of P4 only the lower 4
+** bits are significant.
+**
+** This allows optimizations: (a) when P4==0 there is no need to test
+** the rowset object for P3, as it is guaranteed not to contain it,
+** (b) when P4==-1 there is no need to insert the value, as it will
+** never be tested for, and (c) when a value that is part of set X is
+** inserted, there is no need to search to see if the same value was
+** previously inserted as part of set X (only if it was previously
+** inserted as part of some other set).
+*/
+case OP_RowSetTest: { /* jump, in1, in3 */
+ int iSet = pOp->p4.i;
+ assert( pIn3->flags&MEM_Int );
+
+ /* If there is anything other than a rowset object in memory cell P1,
+ ** delete it now and initialize P1 with an empty rowset
+ */
+ if( (pIn1->flags & MEM_RowSet)==0 ){
+ sqlite3VdbeMemSetRowSet(pIn1);
+ if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
+ }
+
+ assert( pOp->p4type==P4_INT32 );
+ assert( iSet==-1 || iSet>=0 );
+ if( iSet ){
+ int exists;
+ exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+ (u8)(iSet>=0 ? iSet & 0xf : 0xff),
+ pIn3->u.i);
+ if( exists ){
+ pc = pOp->p2 - 1;
+ break;
+ }
+ }
+ if( iSet>=0 ){
+ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
+ }
+ break;
+}
+
#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * *
@@ -54574,37 +55130,6 @@ case OP_VFilter: { /* jump */
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VRowid P1 P2 * * *
-**
-** Store into register P2 the rowid of
-** the virtual-table that the P1 cursor is pointing to.
-*/
-case OP_VRowid: { /* out2-prerelease */
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
- sqlite_int64 iRow;
- VdbeCursor *pCur = p->apCsr[pOp->p1];
-
- assert( pCur->pVtabCursor );
- if( pCur->nullRow ){
- break;
- }
- pVtab = pCur->pVtabCursor->pVtab;
- pModule = pVtab->pModule;
- assert( pModule->xRowid );
- if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = pVtab->zErrMsg;
- pVtab->zErrMsg = 0;
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
- MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = iRow;
- break;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
@@ -55685,7 +56210,7 @@ static int memjrnlWrite(
/* An in-memory journal file should only ever be appended to. Random
** access writes are not required by sqlite.
*/
- assert(iOfst==p->endpoint.iOffset);
+ assert( iOfst==p->endpoint.iOffset );
UNUSED_PARAMETER(iOfst);
while( nWrite>0 ){
@@ -56202,7 +56727,11 @@ static int lookupName(
if( iCol>=0 ){
testcase( iCol==31 );
testcase( iCol==32 );
- *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
+ if( iCol>=32 ){
+ *piColMask = 0xffffffff;
+ }else{
+ *piColMask |= ((u32)1)<<iCol;
+ }
}
break;
}
@@ -56273,7 +56802,7 @@ static int lookupName(
** Because no reference was made to outer contexts, the pNC->nRef
** fields are not changed in any context.
*/
- if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
+ if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
sqlite3DbFree(db, zCol);
pExpr->op = TK_STRING;
pExpr->pTab = 0;
@@ -57535,21 +58064,18 @@ SQLITE_PRIVATE Expr *sqlite3Expr(
int c;
assert( pToken->dyn==0 );
pNew->span = *pToken;
-
- /* The pToken->z value is read-only. But the new expression
- ** node created here might be passed to sqlite3DequoteExpr() which
- ** will attempt to modify pNew->token.z. Hence, if the token
- ** is quoted, make a copy now so that DequoteExpr() will change
- ** the copy rather than the original text.
- */
if( pToken->n>=2
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
sqlite3TokenCopy(db, &pNew->token, pToken);
+ if( pNew->token.z ){
+ pNew->token.n = sqlite3Dequote((char*)pNew->token.z);
+ assert( pNew->token.n==(unsigned)sqlite3Strlen30((char*)pNew->token.z) );
+ }
+ if( c=='"' ) pNew->flags |= EP_DblQuoted;
}else{
pNew->token = *pToken;
- pNew->flags |= EP_Dequoted;
- VVA_ONLY( pNew->vvaFlags |= EVVA_ReadOnlyToken; )
}
+ pNew->token.quoted = 0;
}else if( pLeft ){
if( pRight ){
if( pRight->span.dyn==0 && pLeft->span.dyn==0 ){
@@ -57787,18 +58313,6 @@ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
}
/*
-** The Expr.token field might be a string literal that is quoted.
-** If so, remove the quotation marks.
-*/
-SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
- if( !ExprHasAnyProperty(p, EP_Dequoted) ){
- ExprSetProperty(p, EP_Dequoted);
- assert( (p->vvaFlags & EVVA_ReadOnlyToken)==0 );
- sqlite3Dequote((char*)p->token.z);
- }
-}
-
-/*
** Return the number of bytes allocated for the expression structure
** passed as the first argument. This is always one of EXPR_FULLSIZE,
** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
@@ -58591,7 +59105,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
int testAddr = 0; /* One-time test address */
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
-
+ sqlite3ExprCachePush(pParse);
/* This code must be run in its entirety every time it is encountered
** if any of the following is true:
@@ -58698,11 +59212,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
}
/* Evaluate the expression and insert it into the temp table */
- pParse->disableColCache++;
r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
- assert( pParse->disableColCache>0 );
- pParse->disableColCache--;
-
if( isRowid ){
sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
@@ -58727,7 +59237,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
** value of this select in a memory cell and record the number
** of the memory cell in iColumn.
*/
- static const Token one = { (u8*)"1", 0, 1 };
+ static const Token one = { (u8*)"1", 0, 0, 1 };
Select *pSel;
SelectDest dest;
@@ -58756,6 +59266,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
if( testAddr ){
sqlite3VdbeJumpHere(v, testAddr-1);
}
+ sqlite3ExprCachePop(pParse, 1);
return;
}
@@ -58833,6 +59344,120 @@ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
}
}
+/*
+** Clear a cache entry.
+*/
+static void cacheEntryClear(Parse *pParse, struct yColCache *p){
+ if( p->tempReg ){
+ if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
+ pParse->aTempReg[pParse->nTempReg++] = p->iReg;
+ }
+ p->tempReg = 0;
+ }
+}
+
+
+/*
+** Record in the column cache that a particular column from a
+** particular table is stored in a particular register.
+*/
+SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
+ int i;
+ int minLru;
+ int idxLru;
+ struct yColCache *p;
+
+ /* First replace any existing entry */
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
+ cacheEntryClear(pParse, p);
+ p->iLevel = pParse->iCacheLevel;
+ p->iReg = iReg;
+ p->affChange = 0;
+ p->lru = pParse->iCacheCnt++;
+ return;
+ }
+ }
+ if( iReg<=0 ) return;
+
+ /* Find an empty slot and replace it */
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg==0 ){
+ p->iLevel = pParse->iCacheLevel;
+ p->iTable = iTab;
+ p->iColumn = iCol;
+ p->iReg = iReg;
+ p->affChange = 0;
+ p->tempReg = 0;
+ p->lru = pParse->iCacheCnt++;
+ return;
+ }
+ }
+
+ /* Replace the last recently used */
+ minLru = 0x7fffffff;
+ idxLru = -1;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->lru<minLru ){
+ idxLru = i;
+ minLru = p->lru;
+ }
+ }
+ if( idxLru>=0 ){
+ p = &pParse->aColCache[idxLru];
+ p->iLevel = pParse->iCacheLevel;
+ p->iTable = iTab;
+ p->iColumn = iCol;
+ p->iReg = iReg;
+ p->affChange = 0;
+ p->tempReg = 0;
+ p->lru = pParse->iCacheCnt++;
+ return;
+ }
+}
+
+/*
+** Indicate that a register is being overwritten. Purge the register
+** from the column cache.
+*/
+SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg){
+ int i;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg==iReg ){
+ cacheEntryClear(pParse, p);
+ p->iReg = 0;
+ }
+ }
+}
+
+/*
+** Remember the current column cache context. Any new entries added
+** added to the column cache after this call are removed when the
+** corresponding pop occurs.
+*/
+SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){
+ pParse->iCacheLevel++;
+}
+
+/*
+** Remove from the column cache any entries that were added since the
+** the previous N Push operations. In other words, restore the cache
+** to the state it was in N Pushes ago.
+*/
+SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse, int N){
+ int i;
+ struct yColCache *p;
+ assert( N>0 );
+ assert( pParse->iCacheLevel>=N );
+ pParse->iCacheLevel -= N;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg && p->iLevel>pParse->iCacheLevel ){
+ cacheEntryClear(pParse, p);
+ p->iReg = 0;
+ }
+ }
+}
/*
** Generate code that will extract the iColumn-th column from
@@ -58861,20 +59486,21 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
int i;
struct yColCache *p;
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- if( p->iTable==iTable && p->iColumn==iColumn
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn
&& (!p->affChange || allowAffChng) ){
#if 0
sqlite3VdbeAddOp0(v, OP_Noop);
VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg));
#endif
+ p->lru = pParse->iCacheCnt++;
+ p->tempReg = 0; /* This pins the register, but also leaks it */
return p->iReg;
}
}
assert( v!=0 );
if( iColumn<0 ){
- int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
- sqlite3VdbeAddOp2(v, op, iTable, iReg);
+ sqlite3VdbeAddOp2(v, OP_Rowid, iTable, iReg);
}else if( pTab==0 ){
sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg);
}else{
@@ -58887,37 +59513,21 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
}
#endif
}
- if( pParse->disableColCache==0 ){
- i = pParse->iColCache;
- p = &pParse->aColCache[i];
- p->iTable = iTable;
- p->iColumn = iColumn;
- p->iReg = iReg;
- p->affChange = 0;
- i++;
- if( i>=ArraySize(pParse->aColCache) ) i = 0;
- if( i>pParse->nColCache ) pParse->nColCache = i;
- pParse->iColCache = i;
- }
+ sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
return iReg;
}
/*
-** Clear all column cache entries associated with the vdbe
-** cursor with cursor number iTable.
+** Clear all column cache entries.
*/
-SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){
- if( iTable<0 ){
- pParse->nColCache = 0;
- pParse->iColCache = 0;
- }else{
- int i;
- for(i=0; i<pParse->nColCache; i++){
- if( pParse->aColCache[i].iTable==iTable ){
- testcase( i==pParse->nColCache-1 );
- pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
- pParse->iColCache = pParse->nColCache;
- }
+SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
+ int i;
+ struct yColCache *p;
+
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg ){
+ cacheEntryClear(pParse, p);
+ p->iReg = 0;
}
}
}
@@ -58929,10 +59539,11 @@ SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){
SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
int iEnd = iStart + iCount - 1;
int i;
- for(i=0; i<pParse->nColCache; i++){
- int r = pParse->aColCache[i].iReg;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ int r = p->iReg;
if( r>=iStart && r<=iEnd ){
- pParse->aColCache[i].affChange = 1;
+ p->affChange = 1;
}
}
}
@@ -58943,12 +59554,13 @@ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, in
*/
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
int i;
+ struct yColCache *p;
if( iFrom==iTo ) return;
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
- for(i=0; i<pParse->nColCache; i++){
- int x = pParse->aColCache[i].iReg;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ int x = p->iReg;
if( x>=iFrom && x<iFrom+nReg ){
- pParse->aColCache[i].iReg += iTo-iFrom;
+ p->iReg += iTo-iFrom;
}
}
}
@@ -58971,33 +59583,15 @@ SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int n
*/
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
int i;
- for(i=0; i<pParse->nColCache; i++){
- int r = pParse->aColCache[i].iReg;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ int r = p->iReg;
if( r>=iFrom && r<=iTo ) return 1;
}
return 0;
}
/*
-** There is a value in register iReg.
-**
-** We are going to modify the value, so we need to make sure it
-** is not a cached register. If iReg is a cached register,
-** then clear the corresponding cache line.
-*/
-SQLITE_PRIVATE void sqlite3ExprWritableRegister(Parse *pParse, int iReg){
- int i;
- if( usedAsColumnCache(pParse, iReg, iReg) ){
- for(i=0; i<pParse->nColCache; i++){
- if( pParse->aColCache[i].iReg==iReg ){
- pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
- pParse->iColCache = pParse->nColCache;
- }
- }
- }
-}
-
-/*
** If the last instruction coded is an ephemeral copy of any of
** the registers in the nReg registers beginning with iReg, then
** convert the last instruction from OP_SCopy to OP_Copy.
@@ -59034,6 +59628,7 @@ SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){
** alias has not yet been computed.
*/
static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){
+#if 0
sqlite3 *db = pParse->db;
int iReg;
if( pParse->nAliasAlloc<pParse->nAlias ){
@@ -59048,7 +59643,7 @@ static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){
assert( iAlias>0 && iAlias<=pParse->nAlias );
iReg = pParse->aAlias[iAlias-1];
if( iReg==0 ){
- if( pParse->disableColCache ){
+ if( pParse->iCacheLevel>0 ){
iReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
}else{
iReg = ++pParse->nMem;
@@ -59057,6 +59652,10 @@ static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){
}
}
return iReg;
+#else
+ UNUSED_PARAMETER(iAlias);
+ return sqlite3ExprCodeTarget(pParse, pExpr, target);
+#endif
}
/*
@@ -59126,8 +59725,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
case TK_STRING: {
- sqlite3DequoteExpr(pExpr);
- sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0,
+ sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0,
(char*)pExpr->token.z, pExpr->token.n);
break;
}
@@ -59436,9 +60034,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
/* Code the <expr> from "<expr> IN (...)". The temporary table
** pExpr->iTable contains the values that make up the (...) set.
*/
- pParse->disableColCache++;
+ sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pExpr->pLeft, target);
- pParse->disableColCache--;
j2 = sqlite3VdbeAddOp1(v, OP_IsNull, target);
if( eType==IN_INDEX_ROWID ){
j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, target);
@@ -59499,6 +60096,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
sqlite3VdbeJumpHere(v, j2);
sqlite3VdbeJumpHere(v, j5);
+ sqlite3ExprCachePop(pParse, 1);
VdbeComment((v, "end IN expr r%d", target));
break;
}
@@ -59575,6 +60173,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
Expr cacheX; /* Cached expression X */
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
+ VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
assert((pExpr->x.pList->nExpr % 2) == 0);
@@ -59593,8 +60192,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
opCompare.pLeft = &cacheX;
pTest = &opCompare;
}
- pParse->disableColCache++;
for(i=0; i<nExpr; i=i+2){
+ sqlite3ExprCachePush(pParse);
if( pX ){
assert( pTest!=0 );
opCompare.pRight = aListelem[i].pExpr;
@@ -59608,16 +60207,19 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
+ sqlite3ExprCachePop(pParse, 1);
sqlite3VdbeResolveLabel(v, nextCase);
}
if( pExpr->pRight ){
+ sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pExpr->pRight, target);
+ sqlite3ExprCachePop(pParse, 1);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
+ assert( db->mallocFailed || pParse->nErr>0
+ || pParse->iCacheLevel==iCacheLevel );
sqlite3VdbeResolveLabel(v, endLabel);
- assert( pParse->disableColCache>0 );
- pParse->disableColCache--;
break;
}
#ifndef SQLITE_OMIT_TRIGGER
@@ -59631,7 +60233,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
assert( pExpr->affinity==OE_Rollback ||
pExpr->affinity == OE_Abort ||
pExpr->affinity == OE_Fail );
- sqlite3DequoteExpr(pExpr);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0,
(char*)pExpr->token.z, pExpr->token.n);
} else {
@@ -59892,23 +60493,17 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
case TK_AND: {
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
- testcase( pParse->disableColCache==0 );
+ sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
- pParse->disableColCache++;
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- assert( pParse->disableColCache>0 );
- pParse->disableColCache--;
sqlite3VdbeResolveLabel(v, d2);
+ sqlite3ExprCachePop(pParse, 1);
break;
}
case TK_OR: {
testcase( jumpIfNull==0 );
- testcase( pParse->disableColCache==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- pParse->disableColCache++;
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- assert( pParse->disableColCache>0 );
- pParse->disableColCache--;
break;
}
case TK_NOT: {
@@ -60052,24 +60647,18 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
switch( pExpr->op ){
case TK_AND: {
testcase( jumpIfNull==0 );
- testcase( pParse->disableColCache==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
- pParse->disableColCache++;
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- assert( pParse->disableColCache>0 );
- pParse->disableColCache--;
break;
}
case TK_OR: {
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
- testcase( pParse->disableColCache==0 );
+ sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
- pParse->disableColCache++;
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- assert( pParse->disableColCache>0 );
- pParse->disableColCache--;
sqlite3VdbeResolveLabel(v, d2);
+ sqlite3ExprCachePop(pParse, 1);
break;
}
case TK_NOT: {
@@ -60405,7 +60994,7 @@ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList)
}
/*
-** Allocate or deallocate temporary use registers during code generation.
+** Allocate a single new register for use to hold some intermediate result.
*/
SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
if( pParse->nTempReg==0 ){
@@ -60413,9 +61002,25 @@ SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
}
return pParse->aTempReg[--pParse->nTempReg];
}
+
+/*
+** Deallocate a register, making available for reuse for some other
+** purpose.
+**
+** If a register is currently being used by the column cache, then
+** the dallocation is deferred until the column cache line that uses
+** the register becomes stale.
+*/
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- sqlite3ExprWritableRegister(pParse, iReg);
+ int i;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg==iReg ){
+ p->tempReg = 1;
+ return;
+ }
+ }
pParse->aTempReg[pParse->nTempReg++] = iReg;
}
}
@@ -60671,7 +61276,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
#endif
v = sqlite3GetVdbe(pParse);
- if( !v ) return;
+ if( NEVER(v==0) ) return;
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
assert( iDb>=0 );
@@ -60725,7 +61330,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
#endif
int isVirtualRename = 0; /* True if this is a v-table with an xRename() */
- if( db->mallocFailed ) goto exit_rename_table;
+ if( NEVER(db->mallocFailed) ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
@@ -60958,7 +61563,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
- while( (zEnd>zCol && *zEnd==';') || sqlite3Isspace(*zEnd) ){
+ while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
sqlite3NestedParse(pParse,
@@ -61177,7 +61782,7 @@ static void analyzeOneTable(
int iDb; /* Index of database containing pTab */
v = sqlite3GetVdbe(pParse);
- if( v==0 || pTab==0 || pTab->pIndex==0 ){
+ if( v==0 || NEVER(pTab==0) || pTab->pIndex==0 ){
/* Do no analysis for tables that have no indices */
return;
}
@@ -61377,13 +61982,14 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
return;
}
+ assert( pName2!=0 || pName1==0 );
if( pName1==0 ){
/* Form 1: Analyze everything */
for(i=0; i<db->nDb; i++){
if( i==1 ) continue; /* Do not analyze the TEMP database */
analyzeDatabase(pParse, i);
}
- }else if( pName2==0 || pName2->n==0 ){
+ }else if( pName2->n==0 ){
/* Form 2: Analyze the database or table named */
iDb = sqlite3FindDb(db, pName1);
if( iDb>=0 ){
@@ -61584,7 +62190,6 @@ static void attachFunc(
const char *zFile;
Db *aNew;
char *zErrDyn = 0;
- char zErr[128];
UNUSED_PARAMETER(NotUsed);
@@ -61600,22 +62205,20 @@ static void attachFunc(
** * Specified database name already being used.
*/
if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
- sqlite3_snprintf(
- sizeof(zErr), zErr, "too many attached databases - max %d",
+ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
db->aLimit[SQLITE_LIMIT_ATTACHED]
);
goto attach_error;
}
if( !db->autoCommit ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "cannot ATTACH database within transaction");
+ zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
goto attach_error;
}
for(i=0; i<db->nDb; i++){
char *z = db->aDb[i].zName;
- if( z && zName && sqlite3StrICmp(z, zName)==0 ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "database %s is already in use", zName);
+ assert( z && zName );
+ if( sqlite3StrICmp(z, zName)==0 ){
+ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
goto attach_error;
}
}
@@ -61632,7 +62235,7 @@ static void attachFunc(
if( aNew==0 ) return;
}
db->aDb = aNew;
- aNew = &db->aDb[db->nDb++];
+ aNew = &db->aDb[db->nDb];
memset(aNew, 0, sizeof(*aNew));
/* Open the database file. If the btree is successfully opened, use
@@ -61642,15 +62245,19 @@ static void attachFunc(
rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE,
db->openFlags | SQLITE_OPEN_MAIN_DB,
&aNew->pBt);
- if( rc==SQLITE_OK ){
+ db->nDb++;
+ if( rc==SQLITE_CONSTRAINT ){
+ rc = SQLITE_ERROR;
+ zErrDyn = sqlite3MPrintf(db, "database is already attached");
+ }else if( rc==SQLITE_OK ){
Pager *pPager;
aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
- sqlite3_snprintf(sizeof(zErr), zErr,
+ zErrDyn = sqlite3MPrintf(db,
"attached databases must use the same text encoding as main database");
- goto attach_error;
+ rc = SQLITE_ERROR;
}
pPager = sqlite3BtreePager(aNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
@@ -61713,9 +62320,10 @@ static void attachFunc(
db->nDb = iDb;
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
db->mallocFailed = 1;
- sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
- }else{
- sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
+ sqlite3DbFree(db, zErrDyn);
+ zErrDyn = sqlite3MPrintf(db, "out of memory");
+ }else if( zErrDyn==0 ){
+ zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
}
goto attach_error;
}
@@ -61727,9 +62335,6 @@ attach_error:
if( zErrDyn ){
sqlite3_result_error(context, zErrDyn, -1);
sqlite3DbFree(db, zErrDyn);
- }else{
- zErr[sizeof(zErr)-1] = 0;
- sqlite3_result_error(context, zErr, -1);
}
if( rc ) sqlite3_result_error_code(context, rc);
}
@@ -61921,7 +62526,7 @@ SQLITE_PRIVATE int sqlite3FixInit(
){
sqlite3 *db;
- if( iDb<0 || iDb==1 ) return 0;
+ if( NEVER(iDb<0) || iDb==1 ) return 0;
db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
@@ -61953,7 +62558,7 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
const char *zDb;
struct SrcList_item *pItem;
- if( pList==0 ) return 0;
+ if( NEVER(pList==0) ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase==0 ){
@@ -62137,10 +62742,8 @@ SQLITE_API int sqlite3_set_authorizer(
** Write an error message into pParse->zErrMsg that explains that the
** user-supplied authorization function returned an illegal value.
*/
-static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
- sqlite3ErrorMsg(pParse, "illegal return value (%d) from the "
- "authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
- "or SQLITE_DENY", rc);
+static void sqliteAuthBadReturnCode(Parse *pParse){
+ sqlite3ErrorMsg(pParse, "authorizer malfunction");
pParse->rc = SQLITE_ERROR;
}
@@ -62169,26 +62772,30 @@ SQLITE_PRIVATE void sqlite3AuthRead(
int iDb; /* The index of the database the expression refers to */
if( db->xAuth==0 ) return;
- if( pExpr->op!=TK_COLUMN ) return;
+ assert( pExpr->op==TK_COLUMN );
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
/* An attempt to read a column out of a subquery or other
** temporary table. */
return;
}
- for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
- if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
- }
- if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){
+ if( pTabList ){
+ for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
+ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
+ }
+ assert( iSrc<pTabList->nSrc );
pTab = pTabList->a[iSrc].pTab;
- }else if( (pStack = pParse->trigStack)!=0 ){
- /* This must be an attempt to read the NEW or OLD pseudo-tables
- ** of a trigger.
- */
- assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
- pTab = pStack->pTab;
+ }else{
+ pStack = pParse->trigStack;
+ if( ALWAYS(pStack) ){
+ /* This must be an attempt to read the NEW or OLD pseudo-tables
+ ** of a trigger.
+ */
+ assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
+ pTab = pStack->pTab;
+ }
}
- if( pTab==0 ) return;
+ if( NEVER(pTab==0) ) return;
if( pExpr->iColumn>=0 ){
assert( pExpr->iColumn<pTab->nCol );
zCol = pTab->aCol[pExpr->iColumn].zName;
@@ -62213,7 +62820,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
}
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK ){
- sqliteAuthBadReturnCode(pParse, rc);
+ sqliteAuthBadReturnCode(pParse);
}
}
@@ -62249,7 +62856,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
rc = SQLITE_DENY;
- sqliteAuthBadReturnCode(pParse, rc);
+ sqliteAuthBadReturnCode(pParse);
}
return rc;
}
@@ -62264,11 +62871,10 @@ SQLITE_PRIVATE void sqlite3AuthContextPush(
AuthContext *pContext,
const char *zContext
){
+ assert( pParse );
pContext->pParse = pParse;
- if( pParse ){
- pContext->zAuthContext = pParse->zAuthContext;
- pParse->zAuthContext = zContext;
- }
+ pContext->zAuthContext = pParse->zAuthContext;
+ pParse->zAuthContext = zContext;
}
/*
@@ -62445,7 +63051,9 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
if( (mask & pParse->cookieMask)==0 ) continue;
sqlite3VdbeUsesBtree(v, iDb);
sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
- sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);
+ if( db->init.busy==0 ){
+ sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);
+ }
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
{
@@ -62475,7 +63083,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqlite3VdbeTrace(v, trace);
#endif
- assert( pParse->disableColCache==0 ); /* Disables and re-enables match */
+ assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
pParse->nTab, pParse->explain);
pParse->rc = SQLITE_DONE;
@@ -62546,7 +63154,7 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
int i;
int nName;
assert( zName!=0 );
- nName = sqlite3Strlen(db, zName) + 1;
+ nName = sqlite3Strlen30(zName);
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
@@ -62608,7 +63216,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
Index *p = 0;
int i;
- int nName = sqlite3Strlen(db, zName)+1;
+ int nName = sqlite3Strlen30(zName);
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
Schema *pSchema = db->aDb[j].pSchema;
@@ -62644,7 +63252,7 @@ static void sqlite3DeleteIndex(Index *p){
const char *zName = p->zName;
pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName,
- sqlite3Strlen30(zName)+1, 0);
+ sqlite3Strlen30(zName), 0);
assert( pOld==0 || pOld==p );
freeIndex(p);
}
@@ -62660,8 +63268,8 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char
int len;
Hash *pHash = &db->aDb[iDb].pSchema->idxHash;
- len = sqlite3Strlen(db, zIdxName);
- pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0);
+ len = sqlite3Strlen30(zIdxName);
+ pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0);
if( pIndex ){
if( pIndex->pTable->pIndex==pIndex ){
pIndex->pTable->pIndex = pIndex->pNext;
@@ -62774,8 +63382,7 @@ static void sqliteResetColumnNames(Table *pTable){
** Table. No changes are made to disk by this routine.
**
** This routine just deletes the data structure. It does not unlink
-** the table data structure from the hash table. Nor does it remove
-** foreign keys from the sqlite.aFKey hash table. But it does destroy
+** the table data structure from the hash table. But it does destroy
** memory structures of the indices and foreign keys associated with
** the table.
*/
@@ -62803,13 +63410,9 @@ SQLITE_PRIVATE void sqlite3DeleteTable(Table *pTable){
}
#ifndef SQLITE_OMIT_FOREIGN_KEY
- /* Delete all foreign keys associated with this table. The keys
- ** should have already been unlinked from the pSchema->aFKey hash table
- */
+ /* Delete all foreign keys associated with this table. */
for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
pNextFKey = pFKey->pNextFrom;
- assert( sqlite3HashFind(&pTable->pSchema->aFKey,
- pFKey->zTo, sqlite3Strlen30(pFKey->zTo)+1)!=pFKey );
sqlite3DbFree(db, pFKey);
}
#endif
@@ -62833,7 +63436,6 @@ SQLITE_PRIVATE void sqlite3DeleteTable(Table *pTable){
*/
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
Table *p;
- FKey *pF1, *pF2;
Db *pDb;
assert( db!=0 );
@@ -62841,33 +63443,20 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char
assert( zTabName && zTabName[0] );
pDb = &db->aDb[iDb];
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
- sqlite3Strlen30(zTabName)+1,0);
- if( p ){
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
- int nTo = sqlite3Strlen30(pF1->zTo) + 1;
- pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo);
- if( pF2==pF1 ){
- sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo);
- }else{
- while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
- if( pF2 ){
- pF2->pNextTo = pF1->pNextTo;
- }
- }
- }
-#endif
- sqlite3DeleteTable(p);
- }
+ sqlite3Strlen30(zTabName),0);
+ sqlite3DeleteTable(p);
db->flags |= SQLITE_InternChanges;
}
/*
** Given a token, return a string that consists of the text of that
-** token with any quotations removed. Space to hold the returned string
+** token. Space to hold the returned string
** is obtained from sqliteMalloc() and must be freed by the calling
** function.
**
+** Any quotation marks (ex: "name", 'name', [name], or `name`) that
+** surround the body of the token are removed.
+**
** Tokens are often just pointers into the original SQL text and so
** are not \000 terminated and are not persistent. The returned string
** is \000 terminated and is persistent.
@@ -62876,7 +63465,7 @@ SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
char *zName;
if( pName ){
zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
- sqlite3Dequote(zName);
+ if( pName->quoted ) sqlite3Dequote(zName);
}else{
zName = 0;
}
@@ -63565,7 +64154,7 @@ SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, i
pColl = sqlite3GetCollSeq(db, pColl, zName, nName);
if( !pColl ){
if( nName<0 ){
- nName = sqlite3Strlen(db, zName);
+ nName = sqlite3Strlen30(zName);
}
sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName);
pColl = 0;
@@ -63970,26 +64559,14 @@ SQLITE_PRIVATE void sqlite3EndTable(
*/
if( db->init.busy && pParse->nErr==0 ){
Table *pOld;
- FKey *pFKey;
Schema *pSchema = p->pSchema;
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName,
- sqlite3Strlen30(p->zName)+1,p);
+ sqlite3Strlen30(p->zName),p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
db->mallocFailed = 1;
return;
}
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
- void *data;
- int nTo = sqlite3Strlen30(pFKey->zTo) + 1;
- pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo);
- data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);
- if( data==(void *)pFKey ){
- db->mallocFailed = 1;
- }
- }
-#endif
pParse->pNewTable = 0;
db->nTable++;
db->flags |= SQLITE_InternChanges;
@@ -64496,9 +65073,7 @@ exit_drop_table:
** in the ON DELETE, ON UPDATE and ON INSERT clauses.
**
** An FKey structure is created and added to the table currently
-** under construction in the pParse->pNewTable field. The new FKey
-** is not linked into db->aFKey at this point - that does not happen
-** until sqlite3EndTable().
+** under construction in the pParse->pNewTable field.
**
** The foreign key is set for IMMEDIATE processing. A subsequent call
** to sqlite3DeferForeignKey() might change this to DEFERRED.
@@ -64539,7 +65114,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
}else{
nCol = pFromCol->nExpr;
}
- nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
+ nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
if( pToCol ){
for(i=0; i<pToCol->nExpr; i++){
nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
@@ -64551,14 +65126,12 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
}
pFKey->pFrom = p;
pFKey->pNextFrom = p->pFKey;
- z = (char*)&pFKey[1];
- pFKey->aCol = (struct sColMap*)z;
- z += sizeof(struct sColMap)*nCol;
+ z = (char*)&pFKey->aCol[nCol];
pFKey->zTo = z;
memcpy(z, pTo->z, pTo->n);
z[pTo->n] = 0;
+ sqlite3Dequote(z);
z += pTo->n+1;
- pFKey->pNextTo = 0;
pFKey->nCol = nCol;
if( pFromCol==0 ){
pFKey->aCol[0].iFrom = p->nCol-1;
@@ -64675,19 +65248,25 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
regRecord = sqlite3GetTempReg(pParse);
regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
if( pIndex->onError!=OE_None ){
- int j1, j2;
- int regRowid;
-
- regRowid = regIdxKey + pIndex->nColumn;
- j1 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdxKey, 0, pIndex->nColumn);
- j2 = sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx,
- 0, regRowid, SQLITE_INT_TO_PTR(regRecord), P4_INT32);
+ const int regRowid = regIdxKey + pIndex->nColumn;
+ const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
+ void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
+
+ /* The registers accessed by the OP_IsUnique opcode were allocated
+ ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
+ ** call above. Just before that function was freed they were released
+ ** (made available to the compiler for reuse) using
+ ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
+ ** opcode use the values stored within seems dangerous. However, since
+ ** we can be sure that no other temp registers have been allocated
+ ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
+ */
+ sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, 0,
"indexed columns are not unique", P4_STATIC);
- sqlite3VdbeJumpHere(v, j1);
- sqlite3VdbeJumpHere(v, j2);
}
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
sqlite3VdbeJumpHere(v, addr1);
@@ -64870,6 +65449,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
if( pList==0 ){
nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName;
nullId.n = sqlite3Strlen30((char*)nullId.z);
+ nullId.quoted = 0;
pList = sqlite3ExprListAppend(pParse, 0, 0, &nullId);
if( pList==0 ) goto exit_create_index;
pList->a[0].sortOrder = (u8)sortOrder;
@@ -65026,7 +65606,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
if( db->init.busy ){
Index *p;
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
- pIndex->zName, sqlite3Strlen30(pIndex->zName)+1,
+ pIndex->zName, sqlite3Strlen30(pIndex->zName),
pIndex);
if( p ){
assert( p==pIndex ); /* Malloc must have failed */
@@ -65994,7 +66574,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
*/
static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
assert( !db->xCollNeeded || !db->xCollNeeded16 );
- if( nName<0 ) nName = sqlite3Strlen(db, zName);
+ if( nName<0 ) nName = sqlite3Strlen30(zName);
if( db->xCollNeeded ){
char *zExternal = sqlite3DbStrNDup(db, zName, nName);
if( !zExternal ) return;
@@ -66127,7 +66707,7 @@ static CollSeq *findCollSeqEntry(
int create
){
CollSeq *pColl;
- if( nName<0 ) nName = sqlite3Strlen(db, zName);
+ if( nName<0 ) nName = sqlite3Strlen30(zName);
pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
if( 0==pColl && create ){
@@ -66382,14 +66962,13 @@ SQLITE_PRIVATE void sqlite3SchemaFree(void *p){
temp1 = pSchema->tblHash;
temp2 = pSchema->trigHash;
- sqlite3HashInit(&pSchema->trigHash, 0);
- sqlite3HashClear(&pSchema->aFKey);
+ sqlite3HashInit(&pSchema->trigHash);
sqlite3HashClear(&pSchema->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
}
sqlite3HashClear(&temp2);
- sqlite3HashInit(&pSchema->tblHash, 0);
+ sqlite3HashInit(&pSchema->tblHash);
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
Table *pTab = sqliteHashData(pElem);
assert( pTab->dbMem==0 );
@@ -66414,10 +66993,9 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
if( !p ){
db->mallocFailed = 1;
}else if ( 0==p->file_format ){
- sqlite3HashInit(&p->tblHash, 0);
- sqlite3HashInit(&p->idxHash, 0);
- sqlite3HashInit(&p->trigHash, 0);
- sqlite3HashInit(&p->aFKey, 1);
+ sqlite3HashInit(&p->tblHash);
+ sqlite3HashInit(&p->idxHash);
+ sqlite3HashInit(&p->trigHash);
p->enc = SQLITE_UTF8;
}
return p;
@@ -66488,26 +67066,6 @@ SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
return 0;
}
-/*
-** Generate code that will open a table for reading.
-*/
-SQLITE_PRIVATE void sqlite3OpenTable(
- Parse *p, /* Generate code into this VDBE */
- int iCur, /* The cursor number of the table */
- int iDb, /* The database index in sqlite3.aDb[] */
- Table *pTab, /* The table to be opened */
- int opcode /* OP_OpenRead or OP_OpenWrite */
-){
- Vdbe *v;
- if( IsVirtual(pTab) ) return;
- v = sqlite3GetVdbe(p);
- assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
- sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
- sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
- sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
- VdbeComment((v, "%s", pTab->zName));
-}
-
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
/*
@@ -66533,6 +67091,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
pWhere = sqlite3ExprDup(db, pWhere, 0);
viewName.z = (u8*)pView->zName;
viewName.n = (unsigned int)sqlite3Strlen30((const char*)viewName.z);
+ viewName.quoted = 0;
pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
}
@@ -66803,10 +67362,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
*/
if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) ){
assert( !isView );
- sqlite3VdbeAddOp3(v, OP_Clear, pTab->tnum, iDb, memCnt);
- if( !pParse->nested ){
- sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
- }
+ sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
+ pTab->zName, P4_STATIC);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
@@ -66819,13 +67376,15 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
{
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
+ int regRowid; /* Actual register containing rowids */
/* Collect rowids of every row to be deleted.
*/
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
- WHERE_FILL_ROWSET, iRowSet);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
if( pWInfo==0 ) goto delete_from_cleanup;
+ regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
}
@@ -68235,12 +68794,14 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
p->n++;
}
+#ifndef SQLITE_OMIT_DEPRECATED
/* The sqlite3_aggregate_count() function is deprecated. But just to make
** sure it still operates correctly, verify that its count agrees with our
** internal count when using count(*) and when the total count can be
** expressed as a 32-bit integer. */
assert( argc==1 || p==0 || p->n>0x7fffffff
|| p->n==sqlite3_aggregate_count(context) );
+#endif
}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
@@ -68314,9 +68875,15 @@ static void groupConcatStep(
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
+ int n;
pAccum->useMalloc = 1;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
- if( pAccum->nChar ){
+#ifdef SQLITE_OMIT_DEPRECATED
+ n = context->pMem->n;
+#else
+ n = sqlite3_aggregate_count(context);
+#endif
+ if( n>1 ){
if( argc==2 ){
zSep = (char*)sqlite3_value_text(argv[1]);
nSep = sqlite3_value_bytes(argv[1]);
@@ -68545,6 +69112,26 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
*/
/*
+** Generate code that will open a table for reading.
+*/
+SQLITE_PRIVATE void sqlite3OpenTable(
+ Parse *p, /* Generate code into this VDBE */
+ int iCur, /* The cursor number of the table */
+ int iDb, /* The database index in sqlite3.aDb[] */
+ Table *pTab, /* The table to be opened */
+ int opcode /* OP_OpenRead or OP_OpenWrite */
+){
+ Vdbe *v;
+ if( IsVirtual(pTab) ) return;
+ v = sqlite3GetVdbe(p);
+ assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
+ sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
+ sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
+ sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
+ VdbeComment((v, "%s", pTab->zName));
+}
+
+/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
@@ -68943,7 +69530,7 @@ SQLITE_PRIVATE void sqlite3Insert(
*/
assert( pTabList->nSrc==1 );
zTab = pTabList->a[0].zName;
- if( zTab==0 ) goto insert_cleanup;
+ if( NEVER(zTab==0) ) goto insert_cleanup;
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ){
goto insert_cleanup;
@@ -69065,7 +69652,8 @@ SQLITE_PRIVATE void sqlite3Insert(
/* Resolve the expressions in the SELECT statement and execute it. */
rc = sqlite3Select(pParse, pSelect, &dest);
- if( rc || pParse->nErr || db->mallocFailed ){
+ assert( pParse->nErr==0 || rc );
+ if( rc || NEVER(pParse->nErr) || db->mallocFailed ){
goto insert_cleanup;
}
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
@@ -69151,7 +69739,7 @@ SQLITE_PRIVATE void sqlite3Insert(
if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
- pTabList, 0, pTab->nCol, nColumn);
+ pTabList, 0, pTab->nCol-nHidden, nColumn);
goto insert_cleanup;
}
if( pColumn!=0 && nColumn!=pColumn->nId ){
@@ -69289,12 +69877,14 @@ SQLITE_PRIVATE void sqlite3Insert(
regTrigRowid = sqlite3GetTempReg(pParse);
if( keyColumn<0 ){
sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid);
- }else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regTrigRowid);
}else{
int j1;
- assert( pSelect==0 ); /* Otherwise useTempTable is true */
- sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regTrigRowid);
+ if( useTempTable ){
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regTrigRowid);
+ }else{
+ assert( pSelect==0 ); /* Otherwise useTempTable is true */
+ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regTrigRowid);
+ }
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regTrigRowid);
sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid);
sqlite3VdbeJumpHere(v, j1);
@@ -69368,7 +69958,7 @@ SQLITE_PRIVATE void sqlite3Insert(
VdbeOp *pOp;
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
- if( pOp && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
+ if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
appendFlag = 1;
pOp->opcode = OP_NewRowid;
pOp->p1 = baseCur;
@@ -69448,27 +70038,14 @@ SQLITE_PRIVATE void sqlite3Insert(
}else
#endif
{
- sqlite3GenerateConstraintChecks(
- pParse,
- pTab,
- baseCur,
- regIns,
- aRegIdx,
- keyColumn>=0,
- 0,
- onError,
- endOfLoop
+ int isReplace; /* Set to true if constraints may cause a replace */
+ sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx,
+ keyColumn>=0, 0, onError, endOfLoop, &isReplace
);
sqlite3CompleteInsertion(
- pParse,
- pTab,
- baseCur,
- regIns,
- aRegIdx,
- 0,
- (tmask&TRIGGER_AFTER) ? newIdx : -1,
- appendFlag
- );
+ pParse, pTab, baseCur, regIns, aRegIdx, 0,
+ (tmask&TRIGGER_AFTER) ? newIdx : -1, appendFlag, isReplace==0
+ );
}
}
@@ -69618,18 +70195,19 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int rowidChng, /* True if the rowid might collide with existing entry */
int isUpdate, /* True for UPDATE, False for INSERT */
int overrideError, /* Override onError to this if not OE_Default */
- int ignoreDest /* Jump to this label on an OE_Ignore resolution */
+ int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
+ int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */
){
- int i;
- Vdbe *v;
- int nCol;
- int onError;
+ int i; /* loop counter */
+ Vdbe *v; /* VDBE under constrution */
+ int nCol; /* Number of columns */
+ int onError; /* Conflict resolution strategy */
int j1; /* Addresss of jump instruction */
int j2 = 0, j3; /* Addresses of jump instructions */
int regData; /* Register containing first data column */
- int iCur;
- Index *pIdx;
- int seenReplace = 0;
+ int iCur; /* Table cursor number */
+ Index *pIdx; /* Pointer to one of the indices */
+ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int hasTwoRowids = (isUpdate && rowidChng);
v = sqlite3GetVdbe(pParse);
@@ -69673,7 +70251,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
break;
}
- case OE_Replace: {
+ default: {
+ assert( onError==OE_Replace );
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i);
sqlite3VdbeJumpHere(v, j1);
@@ -69770,11 +70349,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
sqlite3IndexAffinityStr(v, pIdx);
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
- sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
- if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */
+ if( onError==OE_None ){
+ sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+ continue; /* pIdx is not a UNIQUE index */
+ }
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( onError==OE_Default ){
@@ -69787,12 +70368,12 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Check to see if the new index entry will be unique */
- j2 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdx, 0, pIdx->nColumn);
regR = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid-hasTwoRowids, regR);
j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
- regR, SQLITE_INT_TO_PTR(aRegIdx[iCur]),
+ regR, SQLITE_INT_TO_PTR(regIdx),
P4_INT32);
+ sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
/* Generate code that executes if the new index entry is not unique */
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
@@ -69801,30 +70382,25 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
- int j, n1, n2;
- char zErrMsg[200];
- sqlite3_snprintf(ArraySize(zErrMsg), zErrMsg,
- pIdx->nColumn>1 ? "columns " : "column ");
- n1 = sqlite3Strlen30(zErrMsg);
- for(j=0; j<pIdx->nColumn && n1<ArraySize(zErrMsg)-30; j++){
+ int j;
+ StrAccum errMsg;
+ const char *zSep;
+ char *zErr;
+
+ sqlite3StrAccumInit(&errMsg, 0, 0, 200);
+ errMsg.db = pParse->db;
+ zSep = pIdx->nColumn>1 ? "columns " : "column ";
+ for(j=0; j<pIdx->nColumn; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
- n2 = sqlite3Strlen30(zCol);
- if( j>0 ){
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], ", ");
- n1 += 2;
- }
- if( n1+n2>ArraySize(zErrMsg)-30 ){
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "...");
- n1 += 3;
- break;
- }else{
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol);
- n1 += n2;
- }
+ sqlite3StrAccumAppend(&errMsg, zSep, -1);
+ zSep = ", ";
+ sqlite3StrAccumAppend(&errMsg, zCol, -1);
}
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1],
- pIdx->nColumn>1 ? " are not unique" : " is not unique");
- sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErrMsg,0);
+ sqlite3StrAccumAppend(&errMsg,
+ pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
+ zErr = sqlite3StrAccumFinish(&errMsg);
+ sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErr, 0);
+ sqlite3DbFree(errMsg.db, zErr);
break;
}
case OE_Ignore: {
@@ -69832,16 +70408,20 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
break;
}
- case OE_Replace: {
+ default: {
+ assert( onError==OE_Replace );
sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0);
seenReplace = 1;
break;
}
}
- sqlite3VdbeJumpHere(v, j2);
sqlite3VdbeJumpHere(v, j3);
sqlite3ReleaseTempReg(pParse, regR);
}
+
+ if( pbMayReplace ){
+ *pbMayReplace = seenReplace;
+ }
}
/*
@@ -69861,7 +70441,8 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
int *aRegIdx, /* Register used by each index. 0 for unused indices */
int isUpdate, /* True for UPDATE, False for INSERT */
int newIdx, /* Index of NEW table for triggers. -1 if none */
- int appendBias /* True if this is likely to be an append */
+ int appendBias, /* True if this is likely to be an append */
+ int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
int i;
Vdbe *v;
@@ -69878,6 +70459,9 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
for(i=nIdx-1; i>=0; i--){
if( aRegIdx[i]==0 ) continue;
sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
+ if( useSeekResult ){
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ }
}
regData = regRowid + 1;
regRec = sqlite3GetTempReg(pParse);
@@ -69898,6 +70482,9 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
if( appendBias ){
pik_flags |= OPFLAG_APPEND;
}
+ if( useSeekResult ){
+ pik_flags |= OPFLAG_USESEEKRESULT;
+ }
sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid);
if( !pParse->nested ){
sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
@@ -69935,7 +70522,7 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
(char*)pKey, P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
}
- if( pParse->nTab<=baseCur+i ){
+ if( pParse->nTab<baseCur+i ){
pParse->nTab = baseCur+i;
}
return i-1;
@@ -69995,7 +70582,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
return 0; /* Different sort orders */
}
- if( pSrc->azColl[i]!=pDest->azColl[i] ){
+ if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){
return 0; /* Different collating sequences */
}
}
@@ -70226,7 +70813,7 @@ static int xferOptimization(
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
autoIncEnd(pParse, iDbDest, pDest, regAutoinc);
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
- for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
+ for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
}
assert( pSrcIdx );
@@ -70306,13 +70893,12 @@ SQLITE_API int sqlite3_exec(
void *pArg, /* First argument to xCallback() */
char **pzErrMsg /* Write error messages here */
){
- int rc = SQLITE_OK;
- const char *zLeftover;
- sqlite3_stmt *pStmt = 0;
- char **azCols = 0;
-
- int nRetry = 0;
- int nCallback;
+ int rc = SQLITE_OK; /* Return code */
+ const char *zLeftover; /* Tail of unprocessed SQL */
+ sqlite3_stmt *pStmt = 0; /* The current SQL statement */
+ char **azCols = 0; /* Names of result columns */
+ int nRetry = 0; /* Number of retry attempts */
+ int callbackIsInit; /* True if callback data is initialized */
if( zSql==0 ) zSql = "";
@@ -70334,7 +70920,7 @@ SQLITE_API int sqlite3_exec(
continue;
}
- nCallback = 0;
+ callbackIsInit = 0;
nCol = sqlite3_column_count(pStmt);
while( 1 ){
@@ -70343,13 +70929,12 @@ SQLITE_API int sqlite3_exec(
/* Invoke the callback function if required */
if( xCallback && (SQLITE_ROW==rc ||
- (SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){
- if( 0==nCallback ){
+ (SQLITE_DONE==rc && !callbackIsInit
+ && db->flags&SQLITE_NullCallback)) ){
+ if( !callbackIsInit ){
+ azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
if( azCols==0 ){
- azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
- if( azCols==0 ){
- goto exec_out;
- }
+ goto exec_out;
}
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
@@ -70357,7 +70942,7 @@ SQLITE_API int sqlite3_exec(
** strings so there is no way for sqlite3_column_name() to fail. */
assert( azCols[i]!=0 );
}
- nCallback++;
+ callbackIsInit = 1;
}
if( rc==SQLITE_ROW ){
azVals = &azCols[nCol];
@@ -70399,7 +70984,7 @@ exec_out:
sqlite3DbFree(db, azCols);
rc = sqlite3ApiExit(db, rc);
- if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
+ if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
*pzErrMsg = sqlite3Malloc(nErrMsg);
if( *pzErrMsg ){
@@ -72963,6 +73548,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
*/
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int rc;
+ int i;
BtCursor *curMain;
int size;
Table *pTab;
@@ -73052,7 +73638,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
sqlite3BtreeEnter(pDb->pBt);
rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain);
- if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
+ if( rc==SQLITE_EMPTY ) rc = SQLITE_OK;
+ if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
goto initone_error_out;
}
@@ -73074,17 +73661,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
** the possible values of meta[4].
*/
- if( rc==SQLITE_OK ){
- int i;
- for(i=0; i<ArraySize(meta); i++){
- rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
- if( rc ){
- sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
- goto initone_error_out;
- }
+ for(i=0; i<ArraySize(meta); i++){
+ rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
+ if( rc ){
+ sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
+ goto initone_error_out;
}
- }else{
- memset(meta, 0, sizeof(meta));
}
pDb->pSchema->schema_cookie = meta[0];
@@ -73865,42 +74447,7 @@ static void setToken(Token *p, const char *z){
p->z = (u8*)z;
p->n = z ? sqlite3Strlen30(z) : 0;
p->dyn = 0;
-}
-
-/*
-** Set the token to the double-quoted and escaped version of the string pointed
-** to by z. For example;
-**
-** {a"bc} -> {"a""bc"}
-*/
-static void setQuotedToken(Parse *pParse, Token *p, const char *z){
-
- /* Check if the string appears to be quoted using "..." or `...`
- ** or [...] or '...' or if the string contains any " characters.
- ** If it does, then record a version of the string with the special
- ** characters escaped.
- */
- const char *z2 = z;
- if( *z2!='[' && *z2!='`' && *z2!='\'' ){
- while( *z2 ){
- if( *z2=='"' ) break;
- z2++;
- }
- }
-
- if( *z2 ){
- /* String contains " characters - copy and quote the string. */
- p->z = (u8 *)sqlite3MPrintf(pParse->db, "\"%w\"", z);
- if( p->z ){
- p->n = sqlite3Strlen30((char *)p->z);
- p->dyn = 1;
- }
- }else{
- /* String contains no " characters - copy the pointer. */
- p->z = (u8*)z;
- p->n = (int)(z2 - z);
- p->dyn = 0;
- }
+ p->quoted = 0;
}
/*
@@ -74093,6 +74640,7 @@ static void pushOntoSorter(
int nExpr = pOrderBy->nExpr;
int regBase = sqlite3GetTempRange(pParse, nExpr+2);
int regRecord = sqlite3GetTempReg(pParse);
+ sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
@@ -74245,6 +74793,7 @@ static void selectInnerLoop(
/* If the destination is an EXISTS(...) expression, the actual
** values returned by the SELECT are not required.
*/
+ sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
}
nColumn = nResultCol;
@@ -74862,7 +75411,6 @@ static int selectColumnsFromExprList(
sqlite3DbFree(db, zName);
break;
}
- sqlite3Dequote(zName);
/* Make sure the column name is unique. If the name is not unique,
** append a integer to the name so that it becomes unique.
@@ -75018,6 +75566,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
** The current implementation interprets "LIMIT 0" to mean
** no rows.
*/
+ sqlite3ExprCacheClear(pParse);
if( p->pLimit ){
p->iLimit = iLimit = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
@@ -75066,7 +75615,8 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
}else{
pRet = 0;
}
- if( pRet==0 ){
+ assert( iCol>=0 );
+ if( pRet==0 && iCol<p->pEList->nExpr ){
pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
}
return pRet;
@@ -75773,7 +76323,7 @@ static int multiSelectOrderBy(
}
/* Compute the comparison permutation and keyinfo that is used with
- ** the permutation in order to comparisons to determine if the next
+ ** the permutation used to determine if the next
** row of results comes from selectA or selectB. Also add explicit
** collations to the ORDER BY clause terms so that when the subqueries
** to the right and the left are evaluated, they use the correct
@@ -76896,12 +77446,12 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
if( pRight==0 ) break;
- setQuotedToken(pParse, &pRight->token, zName);
+ setToken(&pRight->token, zName);
if( longNames || pTabList->nSrc>1 ){
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
if( pExpr==0 ) break;
- setQuotedToken(pParse, &pLeft->token, zTabName);
+ setToken(&pLeft->token, zTabName);
setToken(&pExpr->span,
sqlite3MPrintf(db, "%s.%s", zTabName, zName));
pExpr->span.dyn = 1;
@@ -77127,6 +77677,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
struct AggInfo_col *pC;
pAggInfo->directMode = 1;
+ sqlite3ExprCacheClear(pParse);
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
int nArg;
int addrNext = 0;
@@ -77166,12 +77717,14 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
+ sqlite3ExprCacheClear(pParse);
}
}
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
}
pAggInfo->directMode = 0;
+ sqlite3ExprCacheClear(pParse);
}
/*
@@ -77436,7 +77989,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* This case is for non-aggregate queries
** Begin the database scan
*/
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
if( pWInfo==0 ) goto select_end;
/* If sorting index that was created by a prior OP_OpenEphemeral
@@ -77558,7 +78111,7 @@ SQLITE_PRIVATE int sqlite3Select(
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
if( pWInfo==0 ) goto select_end;
if( pGroupBy==0 ){
/* The optimizer is able to deliver rows in group by order so
@@ -77589,6 +78142,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
}
regBase = sqlite3GetTempRange(pParse, nCol);
+ sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
j = nGroupBy+1;
@@ -77615,6 +78169,7 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort"));
sAggInfo.useSortingIdx = 1;
+ sqlite3ExprCacheClear(pParse);
}
/* Evaluate the current GROUP BY terms and store in b0, b1, b2...
@@ -77623,6 +78178,7 @@ SQLITE_PRIVATE int sqlite3Select(
** from the previous row currently stored in a0, a1, a2...
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
+ sqlite3ExprCacheClear(pParse);
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j);
@@ -77813,7 +78369,7 @@ SQLITE_PRIVATE int sqlite3Select(
** of output.
*/
resetAccumulator(pParse, &sAggInfo);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDel);
goto select_end;
@@ -78455,7 +79011,7 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
db->mallocFailed = 1;
}else if( pLink->pSchema==pLink->pTabSchema ){
Table *pTab;
- int n = sqlite3Strlen30(pLink->table) + 1;
+ int n = sqlite3Strlen30(pLink->table);
pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n);
assert( pTab!=0 );
pLink->pNext = pTab->pTrigger;
@@ -78682,7 +79238,7 @@ drop_trigger_cleanup:
** is set on.
*/
static Table *tableOfTrigger(Trigger *pTrigger){
- int n = sqlite3Strlen30(pTrigger->table) + 1;
+ int n = sqlite3Strlen30(pTrigger->table);
return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
}
@@ -78833,6 +79389,7 @@ static SrcList *targetSrcList(
assert( iDb<pParse->db->nDb );
sDb.z = (u8*)pParse->db->aDb[iDb].zName;
sDb.n = sqlite3Strlen30((char*)sDb.z);
+ sDb.quoted = 0;
pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target);
} else {
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
@@ -78859,7 +79416,7 @@ static int codeTriggerProgram(
sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0);
VdbeComment((v, "begin trigger %s", pStepList->pTrig->name));
while( pTriggerStep ){
- sqlite3ExprClearColumnCache(pParse, -1);
+ sqlite3ExprCacheClear(pParse);
orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
@@ -79100,7 +79657,8 @@ static void updateVirtualTable(
** sqlite3_value objects.
*/
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
- if( pTab && !pTab->pSelect ){
+ assert( pTab!=0 );
+ if( !pTab->pSelect ){
sqlite3_value *pValue;
u8 enc = ENC(sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i];
@@ -79390,14 +79948,13 @@ SQLITE_PRIVATE void sqlite3Update(
/* Begin the database scan
*/
sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
- WHERE_ONEPASS_DESIRED, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
if( pWInfo==0 ) goto update_cleanup;
okOnePass = pWInfo->okOnePass;
/* Remember the rowid of every item to be updated.
*/
- sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid);
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
if( !okOnePass ){
regRowSet = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
@@ -79414,7 +79971,7 @@ SQLITE_PRIVATE void sqlite3Update(
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
}
- if( !isView && !IsVirtual(pTab) ){
+ if( !isView ){
/*
** Open every index that needs updating. Note that if any
** index could potentially invoke a REPLACE conflict resolution
@@ -79493,7 +80050,7 @@ SQLITE_PRIVATE void sqlite3Update(
continue;
}
j = aXRef[i];
- if( new_col_mask&((u32)1<<i) || new_col_mask==0xffffffff ){
+ if( (i<32 && (new_col_mask&((u32)1<<i))!=0) || new_col_mask==0xffffffff ){
if( j<0 ){
sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regCols+i);
sqlite3ColumnDefault(v, pTab, i);
@@ -79519,7 +80076,7 @@ SQLITE_PRIVATE void sqlite3Update(
sqlite3VdbeJumpHere(v, iEndBeforeTrigger);
}
- if( !isView && !IsVirtual(pTab) ){
+ if( !isView ){
/* Loop over every record that needs updating. We have to load
** the old data for each record to be updated because some columns
** might not change and we will need to copy the old value.
@@ -79557,7 +80114,7 @@ SQLITE_PRIVATE void sqlite3Update(
*/
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid,
aRegIdx, chngRowid, 1,
- onError, addr);
+ onError, addr, 0);
/* Delete the old indices for the current record.
*/
@@ -79574,7 +80131,7 @@ SQLITE_PRIVATE void sqlite3Update(
/* Create the new index entries and the new record.
*/
sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid,
- aRegIdx, 1, -1, 0);
+ aRegIdx, 1, -1, 0, 0);
}
/* Increment the row counter
@@ -79756,13 +80313,15 @@ static void updateVirtualTable(
*/
static int execSql(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt;
+ VVA_ONLY( int rc; )
if( !zSql ){
return SQLITE_NOMEM;
}
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
return sqlite3_errcode(db);
}
- while( SQLITE_ROW==sqlite3_step(pStmt) ){}
+ VVA_ONLY( rc = ) sqlite3_step(pStmt);
+ assert( rc!=SQLITE_ROW );
return sqlite3_finalize(pStmt);
}
@@ -79873,7 +80432,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
|| (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
- || db->mallocFailed
+ || NEVER(db->mallocFailed)
){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
@@ -79961,7 +80520,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** opened for writing. This way, the SQL transaction used to create the
** temporary database never needs to be committed.
*/
- if( rc==SQLITE_OK ){
+ {
u32 meta;
int i;
@@ -79983,10 +80542,12 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
/* Copy Btree meta values */
for(i=0; i<ArraySize(aCopy); i+=2){
+ /* GetMeta() and UpdateMeta() cannot fail in this context because
+ ** we already have page 1 loaded into cache and marked dirty. */
rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum;
rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum;
}
rc = sqlite3BtreeCopyFile(pMain, pTemp);
@@ -79998,9 +80559,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
#endif
}
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
- }
+ assert( rc==SQLITE_OK );
+ rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
end_of_vacuum:
/* Restore the original value of db->flags */
@@ -80340,7 +80900,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
Table *pOld;
Schema *pSchema = pTab->pSchema;
const char *zName = pTab->zName;
- int nName = sqlite3Strlen30(zName) + 1;
+ int nName = sqlite3Strlen30(zName);
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
if( pOld ){
db->mallocFailed = 1;
@@ -80929,10 +81489,8 @@ typedef struct WhereCost WhereCost;
/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause. Each WHERE
-** clause subexpression is separated from the others by AND operators.
-** (Note: the same data structure is also reused to hold a group of terms
-** separated by OR operators. But at the top-level, everything is AND
-** separated.)
+** clause subexpression is separated from the others by AND operators,
+** usually, or sometimes subexpressions separated by OR.
**
** All WhereTerms are collected into a single WhereClause structure.
** The following identity holds:
@@ -81114,11 +81672,12 @@ struct WhereCost {
*/
#define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */
#define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */
-#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) */
+#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
-#define WHERE_INDEXED 0x00070000 /* Anything that uses an index */
-#define WHERE_IN_ABLE 0x00071000 /* Able to support an IN operator */
+#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
+#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
+#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
#define WHERE_IDX_ONLY 0x00800000 /* Use index only - omit table */
@@ -81261,7 +81820,7 @@ static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
}
/*
-** Initialize an expression mask set
+** Initialize an expression mask set (a WhereMaskSet object)
*/
#define initMaskSet(P) memset(P, 0, sizeof(*P))
@@ -81271,6 +81830,7 @@ static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
*/
static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){
int i;
+ assert( pMaskSet->n<=sizeof(Bitmask)*8 );
for(i=0; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
return ((Bitmask)1)<<i;
@@ -81512,6 +82072,7 @@ static int isLikeOrGlob(
Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
ExprList *pList; /* List of operands to the LIKE operator */
int c; /* One character in z[] */
+ int n; /* Length of string z[] */
int cnt; /* Number of non-wildcard prefix characters */
char wc[3]; /* Wildcard characters */
CollSeq *pColl; /* Collating sequence for LHS */
@@ -81542,11 +82103,13 @@ static int isLikeOrGlob(
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
return 0;
}
- sqlite3DequoteExpr(pRight);
- z = (char *)pRight->token.z;
+ z = (const char*)pRight->token.z;
cnt = 0;
if( z ){
- while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; }
+ n = pRight->token.n;
+ while( cnt<n && (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
+ cnt++;
+ }
}
if( cnt==0 || 255==(u8)z[cnt-1] ){
return 0;
@@ -82047,7 +82610,6 @@ static void exprAnalyze(
if( pStr1 ){
sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
pStr1->token.n = nPattern;
- pStr1->flags = EP_Dequoted;
}
pStr2 = sqlite3ExprDup(db, pStr1, 0);
if( !db->mallocFailed ){
@@ -82361,8 +82923,247 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
#define TRACE_IDX_OUTPUTS(A)
#endif
+/*
+** Required because bestIndex() is called by bestOrClauseIndex()
+*/
+static void bestIndex(
+ Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*);
+
+/*
+** This routine attempts to find an scanning strategy that can be used
+** to optimize an 'OR' expression that is part of a WHERE clause.
+**
+** The table associated with FROM clause term pSrc may be either a
+** regular B-Tree table or a virtual table.
+*/
+static void bestOrClauseIndex(
+ Parse *pParse, /* The parsing context */
+ WhereClause *pWC, /* The WHERE clause */
+ struct SrcList_item *pSrc, /* The FROM clause term to search */
+ Bitmask notReady, /* Mask of cursors that are not available */
+ ExprList *pOrderBy, /* The ORDER BY clause */
+ WhereCost *pCost /* Lowest cost query plan */
+){
+#ifndef SQLITE_OMIT_OR_OPTIMIZATION
+ const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
+ const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */
+ WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
+
+ /* Search the WHERE clause terms for a usable WO_OR term. */
+ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
+ if( pTerm->eOperator==WO_OR
+ && ((pTerm->prereqAll & ~maskSrc) & notReady)==0
+ && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
+ ){
+ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
+ WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
+ WhereTerm *pOrTerm;
+ int flags = WHERE_MULTI_OR;
+ double rTotal = 0;
+ double nRow = 0;
+
+ for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
+ WhereCost sTermCost;
+ WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
+ (pOrTerm - pOrWC->a), (pTerm - pWC->a)
+ ));
+ if( pOrTerm->eOperator==WO_AND ){
+ WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
+ bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost);
+ }else if( pOrTerm->leftCursor==iCur ){
+ WhereClause tempWC;
+ tempWC.pParse = pWC->pParse;
+ tempWC.pMaskSet = pWC->pMaskSet;
+ tempWC.op = TK_AND;
+ tempWC.a = pOrTerm;
+ tempWC.nTerm = 1;
+ bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost);
+ }else{
+ continue;
+ }
+ rTotal += sTermCost.rCost;
+ nRow += sTermCost.nRow;
+ if( rTotal>=pCost->rCost ) break;
+ }
+
+ /* If there is an ORDER BY clause, increase the scan cost to account
+ ** for the cost of the sort. */
+ if( pOrderBy!=0 ){
+ rTotal += nRow*estLog(nRow);
+ WHERETRACE(("... sorting increases OR cost to %.9g\n", rTotal));
+ }
+
+ /* If the cost of scanning using this OR term for optimization is
+ ** less than the current cost stored in pCost, replace the contents
+ ** of pCost. */
+ WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
+ if( rTotal<pCost->rCost ){
+ pCost->rCost = rTotal;
+ pCost->nRow = nRow;
+ pCost->plan.wsFlags = flags;
+ pCost->plan.u.pTerm = pTerm;
+ }
+ }
+ }
+#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+}
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
+** 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 sqlite3_free().
+*/
+static sqlite3_index_info *allocateIndexInfo(
+ Parse *pParse,
+ WhereClause *pWC,
+ struct SrcList_item *pSrc,
+ ExprList *pOrderBy
+){
+ int i, j;
+ int nTerm;
+ struct sqlite3_index_constraint *pIdxCons;
+ struct sqlite3_index_orderby *pIdxOrderBy;
+ struct sqlite3_index_constraint_usage *pUsage;
+ WhereTerm *pTerm;
+ int nOrderBy;
+ sqlite3_index_info *pIdxInfo;
+
+ WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));
+
+ /* Count the number of possible WHERE clause constraints referring
+ ** to this virtual table */
+ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ testcase( pTerm->eOperator==WO_IN );
+ testcase( pTerm->eOperator==WO_ISNULL );
+ if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+ nTerm++;
+ }
+
+ /* If the ORDER BY clause contains only columns in the current
+ ** virtual table then allocate space for the aOrderBy part of
+ ** the sqlite3_index_info structure.
+ */
+ nOrderBy = 0;
+ if( pOrderBy ){
+ for(i=0; i<pOrderBy->nExpr; i++){
+ Expr *pExpr = pOrderBy->a[i].pExpr;
+ if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
+ }
+ if( i==pOrderBy->nExpr ){
+ nOrderBy = pOrderBy->nExpr;
+ }
+ }
+
+ /* Allocate the sqlite3_index_info structure
+ */
+ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
+ + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
+ + sizeof(*pIdxOrderBy)*nOrderBy );
+ if( pIdxInfo==0 ){
+ sqlite3ErrorMsg(pParse, "out of memory");
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ return 0;
+ }
+
+ /* Initialize the structure. The sqlite3_index_info structure contains
+ ** many fields that are declared "const" to prevent xBestIndex from
+ ** changing them. We have to do some funky casting in order to
+ ** initialize those fields.
+ */
+ pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1];
+ pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
+ pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
+ *(int*)&pIdxInfo->nConstraint = nTerm;
+ *(int*)&pIdxInfo->nOrderBy = nOrderBy;
+ *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
+ *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
+ *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
+ pUsage;
+
+ for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ testcase( pTerm->eOperator==WO_IN );
+ testcase( pTerm->eOperator==WO_ISNULL );
+ if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+ pIdxCons[j].iColumn = pTerm->u.leftColumn;
+ pIdxCons[j].iTermOffset = i;
+ pIdxCons[j].op = (u8)pTerm->eOperator;
+ /* 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( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+ j++;
+ }
+ for(i=0; i<nOrderBy; i++){
+ Expr *pExpr = pOrderBy->a[i].pExpr;
+ pIdxOrderBy[i].iColumn = pExpr->iColumn;
+ pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
+ }
+
+ return pIdxInfo;
+}
+
+/*
+** The table object reference passed as the second argument to this function
+** must represent a virtual table. This function invokes the xBestIndex()
+** method of the virtual table with the sqlite3_index_info pointer passed
+** as the argument.
+**
+** If an error occurs, pParse is populated with an error message and a
+** non-zero value is returned. Otherwise, 0 is returned and the output
+** part of the sqlite3_index_info structure is left populated.
+**
+** Whether or not an error is returned, it is the responsibility of the
+** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
+** that this is required.
+*/
+static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
+ sqlite3_vtab *pVtab = pTab->pVtab;
+ int i;
+ int rc;
+
+ (void)sqlite3SafetyOff(pParse->db);
+ WHERETRACE(("xBestIndex for %s\n", pTab->zName));
+ TRACE_IDX_INPUTS(p);
+ rc = pVtab->pModule->xBestIndex(pVtab, p);
+ TRACE_IDX_OUTPUTS(p);
+ (void)sqlite3SafetyOn(pParse->db);
+
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ){
+ pParse->db->mallocFailed = 1;
+ }else if( !pVtab->zErrMsg ){
+ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
+ }else{
+ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
+ }
+ }
+ sqlite3DbFree(pParse->db, pVtab->zErrMsg);
+ pVtab->zErrMsg = 0;
+
+ for(i=0; i<p->nConstraint; i++){
+ if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
+ sqlite3ErrorMsg(pParse,
+ "table %s: xBestIndex returned an invalid plan", pTab->zName);
+ }
+ }
+
+ return pParse->nErr;
+}
+
+
+/*
** Compute the best index for a virtual table.
**
** The best index is computed by the xBestIndex method of the virtual
@@ -82378,114 +83179,39 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
** routine takes care of freeing the sqlite3_index_info structure after
** everybody has finished with it.
*/
-static double bestVirtualIndex(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to search */
- Bitmask notReady, /* Mask of cursors that are not available */
- ExprList *pOrderBy, /* The order by clause */
- int orderByUsable, /* True if we can potential sort */
- sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
+static void bestVirtualIndex(
+ Parse *pParse, /* The parsing context */
+ WhereClause *pWC, /* The WHERE clause */
+ struct SrcList_item *pSrc, /* The FROM clause term to search */
+ Bitmask notReady, /* Mask of cursors that are not available */
+ ExprList *pOrderBy, /* The order by clause */
+ WhereCost *pCost, /* Lowest cost query plan */
+ sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
){
Table *pTab = pSrc->pTab;
- sqlite3_vtab *pVtab = pTab->pVtab;
sqlite3_index_info *pIdxInfo;
struct sqlite3_index_constraint *pIdxCons;
- struct sqlite3_index_orderby *pIdxOrderBy;
struct sqlite3_index_constraint_usage *pUsage;
WhereTerm *pTerm;
int i, j;
int nOrderBy;
- int rc;
+
+ /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
+ ** malloc in allocateIndexInfo() fails and this function returns leaving
+ ** wsFlags in an uninitialized state, the caller may behave unpredictably.
+ */
+ memset(pCost, 0, sizeof(*pCost));
+ pCost->plan.wsFlags = WHERE_VIRTUALTABLE;
/* If the sqlite3_index_info structure has not been previously
- ** allocated and initialized for this virtual table, then allocate
- ** and initialize it now
+ ** allocated and initialized, then allocate and initialize it now.
*/
pIdxInfo = *ppIdxInfo;
if( pIdxInfo==0 ){
- int nTerm;
- WHERETRACE(("Recomputing index info for %s...\n", pTab->zName));
-
- /* Count the number of possible WHERE clause constraints referring
- ** to this virtual table */
- for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
- testcase( pTerm->eOperator==WO_IN );
- testcase( pTerm->eOperator==WO_ISNULL );
- if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
- nTerm++;
- }
-
- /* If the ORDER BY clause contains only columns in the current
- ** virtual table then allocate space for the aOrderBy part of
- ** the sqlite3_index_info structure.
- */
- nOrderBy = 0;
- if( pOrderBy ){
- for(i=0; i<pOrderBy->nExpr; i++){
- Expr *pExpr = pOrderBy->a[i].pExpr;
- if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
- }
- if( i==pOrderBy->nExpr ){
- nOrderBy = pOrderBy->nExpr;
- }
- }
-
- /* Allocate the sqlite3_index_info structure
- */
- pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
- + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
- + sizeof(*pIdxOrderBy)*nOrderBy );
- if( pIdxInfo==0 ){
- sqlite3ErrorMsg(pParse, "out of memory");
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- return (double)0;
- }
- *ppIdxInfo = pIdxInfo;
-
- /* Initialize the structure. The sqlite3_index_info structure contains
- ** many fields that are declared "const" to prevent xBestIndex from
- ** changing them. We have to do some funky casting in order to
- ** initialize those fields.
- */
- pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1];
- pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
- pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
- *(int*)&pIdxInfo->nConstraint = nTerm;
- *(int*)&pIdxInfo->nOrderBy = nOrderBy;
- *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
- *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
- *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
- pUsage;
-
- for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
- testcase( pTerm->eOperator==WO_IN );
- testcase( pTerm->eOperator==WO_ISNULL );
- if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
- pIdxCons[j].iColumn = pTerm->u.leftColumn;
- pIdxCons[j].iTermOffset = i;
- pIdxCons[j].op = (u8)pTerm->eOperator;
- /* 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( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
- j++;
- }
- for(i=0; i<nOrderBy; i++){
- Expr *pExpr = pOrderBy->a[i].pExpr;
- pIdxOrderBy[i].iColumn = pExpr->iColumn;
- pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
- }
+ *ppIdxInfo = pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pOrderBy);
+ }
+ if( pIdxInfo==0 ){
+ return;
}
/* At this point, the sqlite3_index_info structure that pIdxInfo points
@@ -82500,14 +83226,7 @@ static double bestVirtualIndex(
** sqlite3ViewGetColumnNames() would have picked up the error.
*/
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
- assert( pVtab );
-#if 0
- if( pTab->pVtab==0 ){
- sqlite3ErrorMsg(pParse, "undefined module %s for table %s",
- pTab->azModuleArg[0], pTab->zName);
- return 0.0;
- }
-#endif
+ assert( pTab->pVtab );
/* Set the aConstraint[].usable fields and initialize all
** output variables to zero.
@@ -82547,40 +83266,37 @@ static double bestVirtualIndex(
/* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
nOrderBy = pIdxInfo->nOrderBy;
- if( pIdxInfo->nOrderBy && !orderByUsable ){
- *(int*)&pIdxInfo->nOrderBy = 0;
+ if( !pOrderBy ){
+ pIdxInfo->nOrderBy = 0;
}
- (void)sqlite3SafetyOff(pParse->db);
- WHERETRACE(("xBestIndex for %s\n", pTab->zName));
- TRACE_IDX_INPUTS(pIdxInfo);
- rc = pVtab->pModule->xBestIndex(pVtab, pIdxInfo);
- TRACE_IDX_OUTPUTS(pIdxInfo);
- (void)sqlite3SafetyOn(pParse->db);
-
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ){
- pParse->db->mallocFailed = 1;
- }else if( !pVtab->zErrMsg ){
- sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
- }else{
- sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
- }
+ if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
+ return;
}
- sqlite3DbFree(pParse->db, pVtab->zErrMsg);
- pVtab->zErrMsg = 0;
- for(i=0; i<pIdxInfo->nConstraint; i++){
- if( !pIdxInfo->aConstraint[i].usable && pUsage[i].argvIndex>0 ){
- sqlite3ErrorMsg(pParse,
- "table %s: xBestIndex returned an invalid plan", pTab->zName);
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- return (double)0;
- }
+ /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
+ ** inital value of lowestCost in this loop. If it is, then the
+ ** (cost<lowestCost) test below will never be true.
+ **
+ ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
+ ** is defined.
+ */
+ if( (SQLITE_BIG_DBL/((double)2))<pIdxInfo->estimatedCost ){
+ pCost->rCost = (SQLITE_BIG_DBL/((double)2));
+ }else{
+ pCost->rCost = pIdxInfo->estimatedCost;
}
+ pCost->plan.u.pVtabIdx = pIdxInfo;
+ if( pIdxInfo && pIdxInfo->orderByConsumed ){
+ pCost->plan.wsFlags |= WHERE_ORDERBY;
+ }
+ pCost->plan.nEq = 0;
+ pIdxInfo->nOrderBy = nOrderBy;
- *(int*)&pIdxInfo->nOrderBy = nOrderBy;
- return pIdxInfo->estimatedCost;
+ /* Try to find a more efficient access pattern by using multiple indexes
+ ** to optimize an OR expression within the WHERE clause.
+ */
+ bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -82612,7 +83328,7 @@ static double bestVirtualIndex(
** selected plan may still take advantage of the tables built-in rowid
** index.
*/
-static void bestIndex(
+static void bestBtreeIndex(
Parse *pParse, /* The parsing context */
WhereClause *pWC, /* The WHERE clause */
struct SrcList_item *pSrc, /* The FROM clause term to search */
@@ -82630,7 +83346,6 @@ static void bestIndex(
double cost; /* Cost of using pProbe */
double nRow; /* Estimated number of rows in result set */
int i; /* Loop counter */
- Bitmask maskSrc; /* Bitmask for the pSrc table */
WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName,notReady));
pProbe = pSrc->pTab->pIndex;
@@ -82746,61 +83461,7 @@ static void bestIndex(
}
}
-#ifndef SQLITE_OMIT_OR_OPTIMIZATION
- /* Search for an OR-clause that can be used to look up the table.
- */
- maskSrc = getMask(pWC->pMaskSet, iCur);
- for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- WhereClause tempWC;
- tempWC = *pWC;
- if( pTerm->eOperator==WO_OR
- && ((pTerm->prereqAll & ~maskSrc) & notReady)==0
- && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 ){
- WhereClause *pOrWC = &pTerm->u.pOrInfo->wc;
- WhereTerm *pOrTerm;
- int j;
- int sortable = 0;
- double rTotal = 0;
- nRow = 0;
- for(j=0, pOrTerm=pOrWC->a; j<pOrWC->nTerm; j++, pOrTerm++){
- WhereCost sTermCost;
- WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", j,i));
- if( pOrTerm->eOperator==WO_AND ){
- WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
- bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost);
- }else if( pOrTerm->leftCursor==iCur ){
- tempWC.a = pOrTerm;
- tempWC.nTerm = 1;
- bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost);
- }else{
- continue;
- }
- rTotal += sTermCost.rCost;
- nRow += sTermCost.nRow;
- if( rTotal>=pCost->rCost ) break;
- }
- if( pOrderBy!=0 ){
- if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) && !rev ){
- sortable = 1;
- }else{
- rTotal += nRow*estLog(nRow);
- WHERETRACE(("... sorting increases OR cost to %.9g\n", rTotal));
- }
- }
- WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n",
- rTotal, nRow));
- if( rTotal<pCost->rCost ){
- pCost->rCost = rTotal;
- pCost->nRow = nRow;
- pCost->plan.wsFlags = WHERE_MULTI_OR;
- pCost->plan.u.pTerm = pTerm;
- if( sortable ){
- pCost->plan.wsFlags = WHERE_ORDERBY|WHERE_MULTI_OR;
- }
- }
- }
- }
-#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+ bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
/* If the pSrc table is the right table of a LEFT JOIN then we may not
** use an index to satisfy IS NULL constraints on that table. This is
@@ -82825,9 +83486,10 @@ static void bestIndex(
WHERETRACE(("... index %s:\n", pProbe->zName));
/* Count the number of columns in the index that are satisfied
- ** by x=EXPR constraints or x IN (...) constraints. For a term
- ** of the form x=EXPR we only have to do a single binary search.
- ** But for x IN (...) we have to do a number of binary searched
+ ** by x=EXPR or x IS NULL constraints or x IN (...) constraints.
+ ** For a term of the form x=EXPR or x IS NULL we only have to do
+ ** a single binary search. But for x IN (...) we have to do a
+ ** number of binary searched
** equal to the number of entries on the RHS of the IN operator.
** The inMultipler variable with try to estimate the number of
** binary searches needed.
@@ -82847,6 +83509,8 @@ static void bestIndex(
}else if( pExpr->x.pList ){
inMultiplier *= pExpr->x.pList->nExpr + 1;
}
+ }else if( pTerm->eOperator & WO_ISNULL ){
+ wsFlags |= WHERE_COLUMN_NULL;
}
}
nRow = pProbe->aiRowEst[i] * inMultiplier;
@@ -82859,9 +83523,12 @@ static void bestIndex(
}
cost = nRow + inMultiplier*estLog(pProbe->aiRowEst[0]);
nEq = i;
- if( pProbe->onError!=OE_None && (wsFlags & WHERE_COLUMN_IN)==0
- && nEq==pProbe->nColumn ){
- wsFlags |= WHERE_UNIQUE;
+ if( pProbe->onError!=OE_None && nEq==pProbe->nColumn ){
+ testcase( wsFlags & WHERE_COLUMN_IN );
+ testcase( wsFlags & WHERE_COLUMN_NULL );
+ if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
+ wsFlags |= WHERE_UNIQUE;
+ }
}
WHERETRACE(("...... nEq=%d inMult=%.9g nRow=%.9g cost=%.9g\n",
nEq, inMultiplier, nRow, cost));
@@ -82892,8 +83559,9 @@ static void bestIndex(
/* Add the additional cost of sorting if that is a factor.
*/
if( pOrderBy ){
- if( (wsFlags & WHERE_COLUMN_IN)==0 &&
- isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){
+ if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0
+ && isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev)
+ ){
if( wsFlags==0 ){
wsFlags = WHERE_COLUMN_RANGE;
}
@@ -82954,6 +83622,31 @@ static void bestIndex(
pCost->rCost, pCost->plan.wsFlags, pCost->plan.nEq));
}
+/*
+** Find the query plan for accessing table pSrc->pTab. Write the
+** best query plan and its cost into the WhereCost object supplied
+** as the last parameter. This function may calculate the cost of
+** both real and virtual table scans.
+*/
+static void bestIndex(
+ Parse *pParse, /* The parsing context */
+ WhereClause *pWC, /* The WHERE clause */
+ struct SrcList_item *pSrc, /* The FROM clause term to search */
+ Bitmask notReady, /* Mask of cursors that are not available */
+ ExprList *pOrderBy, /* The ORDER BY clause */
+ WhereCost *pCost /* Lowest cost query plan */
+){
+ if( IsVirtual(pSrc->pTab) ){
+ sqlite3_index_info *p = 0;
+ bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, &p);
+ if( p->needToFreeIdxStr ){
+ sqlite3_free(p->idxStr);
+ }
+ sqlite3DbFree(pParse->db, p);
+ }else{
+ bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
+ }
+}
/*
** Disable a term in the WHERE clause. Except, do not disable the term
@@ -83151,32 +83844,13 @@ static int codeAllEqualityTerms(
}
/*
-** Return TRUE if the WhereClause pWC contains no terms that
-** are not virtual and which have not been coded.
-**
-** To put it another way, return TRUE if no additional WHERE clauses
-** tests are required in order to establish that the current row
-** should go to output and return FALSE if there are some terms of
-** the WHERE clause that need to be validated before outputing the row.
-*/
-static int whereRowReadyForOutput(WhereClause *pWC){
- WhereTerm *pTerm;
- int j;
-
- for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
- if( (pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED))==0 ) return 0;
- }
- return 1;
-}
-
-/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
static Bitmask codeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
- u8 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
+ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
Bitmask notReady /* Which tables are currently available */
){
int j, k; /* Loop counters */
@@ -83192,9 +83866,8 @@ static Bitmask codeOneLoopStart(
struct SrcList_item *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrCont; /* Jump here to continue with next cycle */
- int regRowSet; /* Write rowids to this RowSet if non-negative */
- int codeRowSetEarly; /* True if index fully constrains the search */
-
+ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
+ int iReleaseReg = 0; /* Temp register to free before returning */
pParse = pWInfo->pParse;
v = pParse->pVdbe;
@@ -83203,9 +83876,8 @@ static Bitmask codeOneLoopStart(
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
- omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0;
- regRowSet = pWInfo->regRowSet;
- codeRowSetEarly = 0;
+ omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
+ && (wctrlFlags & WHERE_FORCE_TABLE)==0;
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
@@ -83244,20 +83916,16 @@ static Bitmask codeOneLoopStart(
pVtabIdx->aConstraint;
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
- pParse->disableColCache++;
for(j=1; j<=nConstraint; j++){
for(k=0; k<nConstraint; k++){
if( aUsage[k].argvIndex==j ){
int iTerm = aConstraint[k].iTermOffset;
- assert( pParse->disableColCache );
sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
break;
}
}
if( k==nConstraint ) break;
}
- assert( pParse->disableColCache );
- pParse->disableColCache--;
sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
@@ -83272,11 +83940,6 @@ static Bitmask codeOneLoopStart(
pLevel->op = OP_VNext;
pLevel->p1 = iCur;
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
- codeRowSetEarly = regRowSet>=0 ? whereRowReadyForOutput(pWC) : 0;
- if( codeRowSetEarly ){
- sqlite3VdbeAddOp2(v, OP_VRowid, iCur, iReg);
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, iReg);
- }
sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -83287,22 +83950,17 @@ static Bitmask codeOneLoopStart(
** we reference multiple rows using a "rowid IN (...)"
** construct.
*/
- int r1;
- int rtmp = sqlite3GetTempReg(pParse);
+ iReleaseReg = sqlite3GetTempReg(pParse);
pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
assert( pTerm->leftCursor==iCur );
assert( omitTable==0 );
- r1 = codeEqualityTerm(pParse, pTerm, pLevel, rtmp);
+ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
addrNxt = pLevel->addrNxt;
- sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, addrNxt);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, r1);
- codeRowSetEarly = (pWC->nTerm==1 && regRowSet>=0) ?1:0;
- if( codeRowSetEarly ){
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1);
- }
- sqlite3ReleaseTempReg(pParse, rtmp);
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
}else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){
@@ -83369,18 +84027,12 @@ static Bitmask codeOneLoopStart(
pLevel->p1 = iCur;
pLevel->p2 = start;
pLevel->p5 = (pStart==0 && pEnd==0) ?1:0;
- codeRowSetEarly = regRowSet>=0 ? whereRowReadyForOutput(pWC) : 0;
- if( codeRowSetEarly || testOp!=OP_Noop ){
- int r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
- if( testOp!=OP_Noop ){
- sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, r1);
- sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
- }
- if( codeRowSetEarly ){
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1);
- }
- sqlite3ReleaseTempReg(pParse, r1);
+ if( testOp!=OP_Noop ){
+ iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
+ sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
+ sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
}
}else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
/* Case 3: A scan using an index.
@@ -83505,12 +84157,7 @@ static Bitmask codeOneLoopStart(
/* Seek the index cursor to the start of the range. */
nConstraint = nEq;
if( pRangeStart ){
- int dcc = pParse->disableColCache;
- if( pRangeEnd ){
- pParse->disableColCache++;
- }
sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq);
- pParse->disableColCache = dcc;
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
nConstraint++;
}else if( isMinQuery ){
@@ -83536,6 +84183,7 @@ static Bitmask codeOneLoopStart(
*/
nConstraint = nEq;
if( pRangeEnd ){
+ sqlite3ExprCacheRemove(pParse, regBase+nEq);
sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
codeApplyAffinity(pParse, regBase, nEq+1, pIdx);
@@ -83567,20 +84215,17 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
}
+ sqlite3ReleaseTempReg(pParse, r1);
/* Seek the table cursor, if required */
disableTerm(pLevel, pRangeStart);
disableTerm(pLevel, pRangeEnd);
- codeRowSetEarly = regRowSet>=0 ? whereRowReadyForOutput(pWC) : 0;
- if( !omitTable || codeRowSetEarly ){
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
- if( codeRowSetEarly ){
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1);
- }else{
- sqlite3VdbeAddOp2(v, OP_Seek, iCur, r1); /* Deferred seek */
- }
+ if( !omitTable ){
+ iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
+ sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
}
- sqlite3ReleaseTempReg(pParse, r1);
/* Record the instruction used to terminate the loop. Disable
** WHERE clause terms made redundant by the index range scan.
@@ -83603,66 +84248,106 @@ static Bitmask codeOneLoopStart(
** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
**
** In the example, there are three indexed terms connected by OR.
- ** The top of the loop is constructed by creating a RowSet object
- ** and populating it. Then looping over elements of the rowset.
+ ** The top of the loop looks like this:
+ **
+ ** Null 1 # Zero the rowset in reg 1
+ **
+ ** Then, for each indexed term, the following. The arguments to
+ ** RowSetTest are such that the rowid of the current row is inserted
+ ** into the RowSet. If it is already present, control skips the
+ ** Gosub opcode and jumps straight to the code generated by WhereEnd().
+ **
+ ** sqlite3WhereBegin(<term>)
+ ** RowSetTest # Insert rowid into rowset
+ ** Gosub 2 A
+ ** sqlite3WhereEnd()
**
- ** Null 1
- ** # fill RowSet 1 with entries where a=5 using i1
- ** # fill Rowset 1 with entries where b=7 using i2
- ** # fill Rowset 1 with entries where c=11 and d=13 i3 and t1
- ** A: RowSetRead 1, B, 2
- ** Seek i, 2
+ ** Following the above, code to terminate the loop. Label A, the target
+ ** of the Gosub above, jumps to the instruction right after the Goto.
**
- ** The bottom of the loop looks like this:
+ ** Null 1 # Zero the rowset in reg 1
+ ** Goto B # The loop is finished.
+ **
+ ** A: <loop body> # Return data, whatever.
+ **
+ ** Return 2 # Jump back to the Gosub
+ **
+ ** B: <after the loop>
**
- ** Goto 0, A
- ** B:
*/
- int regOrRowset; /* Register holding the RowSet object */
- int regNextRowid; /* Register holding next rowid */
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
- WhereTerm *pOrTerm; /* A single subterm within the OR-clause */
+ WhereTerm *pFinal; /* Final subterm within the OR-clause. */
SrcList oneTab; /* Shortened table list */
+
+ int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
+ int regRowset; /* Register for RowSet object */
+ int regRowid; /* Register holding rowid */
+ int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
+ int iRetInit; /* Address of regReturn init */
+ int ii;
pTerm = pLevel->plan.u.pTerm;
assert( pTerm!=0 );
assert( pTerm->eOperator==WO_OR );
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
pOrWc = &pTerm->u.pOrInfo->wc;
- codeRowSetEarly = (regRowSet>=0 && pWC->nTerm==1) ?1:0;
+ pFinal = &pOrWc->a[pOrWc->nTerm-1];
- if( codeRowSetEarly ){
- regOrRowset = regRowSet;
- }else{
- regOrRowset = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Null, 0, regOrRowset);
- }
+ /* Set up a SrcList containing just the table being scanned by this loop. */
oneTab.nSrc = 1;
oneTab.nAlloc = 1;
oneTab.a[0] = *pTabItem;
- for(j=0, pOrTerm=pOrWc->a; j<pOrWc->nTerm; j++, pOrTerm++){
- WhereInfo *pSubWInfo;
- if( pOrTerm->leftCursor!=iCur && pOrTerm->eOperator!=WO_AND ) continue;
- pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
- WHERE_FILL_ROWSET | WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE,
- regOrRowset);
- if( pSubWInfo ){
- sqlite3WhereEnd(pSubWInfo);
- }
- }
- sqlite3VdbeResolveLabel(v, addrCont);
- if( !codeRowSetEarly ){
- regNextRowid = sqlite3GetTempReg(pParse);
- addrCont =
- sqlite3VdbeAddOp3(v, OP_RowSetRead, regOrRowset,addrBrk,regNextRowid);
- sqlite3VdbeAddOp2(v, OP_Seek, iCur, regNextRowid);
- sqlite3ReleaseTempReg(pParse, regNextRowid);
- /* sqlite3ReleaseTempReg(pParse, regOrRowset); // Preserve the RowSet */
- pLevel->op = OP_Goto;
- pLevel->p2 = addrCont;
- }else{
- pLevel->op = OP_Noop;
+
+ /* Initialize the rowset register to contain NULL. An SQL NULL is
+ ** equivalent to an empty rowset.
+ **
+ ** Also initialize regReturn to contain the address of the instruction
+ ** immediately following the OP_Return at the bottom of the loop. This
+ ** is required in a few obscure LEFT JOIN cases where control jumps
+ ** over the top of the loop into the body of it. In this case the
+ ** correct response for the end-of-loop code (the OP_Return) is to
+ ** fall through to the next instruction, just as an OP_Next does if
+ ** called on an uninitialized cursor.
+ */
+ if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ regRowset = ++pParse->nMem;
+ regRowid = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
+ }
+ iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
+
+ for(ii=0; ii<pOrWc->nTerm; ii++){
+ WhereTerm *pOrTerm = &pOrWc->a[ii];
+ if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
+ WhereInfo *pSubWInfo; /* Info for single OR-term scan */
+
+ /* Loop through table entries that match term pOrTerm. */
+ pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
+ WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE);
+ if( pSubWInfo ){
+ if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
+ int r;
+ r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
+ regRowid, 0);
+ sqlite3VdbeAddOp4(v, OP_RowSetTest, regRowset,
+ sqlite3VdbeCurrentAddr(v)+2,
+ r, SQLITE_INT_TO_PTR(iSet), P4_INT32);
+ }
+ sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
+
+ /* Finish the loop through table entries that match term pOrTerm. */
+ sqlite3WhereEnd(pSubWInfo);
+ }
+ }
}
+ sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
+ /* sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
+ sqlite3VdbeResolveLabel(v, iLoopBody);
+
+ pLevel->op = OP_Return;
+ pLevel->p1 = regReturn;
disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
@@ -83679,7 +84364,6 @@ static Bitmask codeOneLoopStart(
pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
- codeRowSetEarly = 0;
}
notReady &= ~getMask(pWC->pMaskSet, iCur);
@@ -83698,9 +84382,7 @@ static Bitmask codeOneLoopStart(
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
continue;
}
- pParse->disableColCache += k;
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
- pParse->disableColCache -= k;
k = 1;
pTerm->wtFlags |= TERM_CODED;
}
@@ -83712,8 +84394,7 @@ static Bitmask codeOneLoopStart(
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
- sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur);
- sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur);
+ sqlite3ExprCacheClear(pParse);
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
@@ -83724,24 +84405,7 @@ static Bitmask codeOneLoopStart(
pTerm->wtFlags |= TERM_CODED;
}
}
-
- /*
- ** If it was requested to store the results in a rowset and that has
- ** not already been do, then do so now.
- */
- if( regRowSet>=0 && !codeRowSetEarly ){
- int r1 = sqlite3GetTempReg(pParse);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
- sqlite3VdbeAddOp2(v, OP_VRowid, iCur, r1);
- }else
-#endif
- {
- sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
- }
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, r1);
- sqlite3ReleaseTempReg(pParse, r1);
- }
+ sqlite3ReleaseTempReg(pParse, iReleaseReg);
return notReady;
}
@@ -83768,7 +84432,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
for(i=0; i<pWInfo->nLevel; i++){
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
if( pInfo ){
- assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed );
+ /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */
if( pInfo->needToFreeIdxStr ){
sqlite3_free(pInfo->idxStr);
}
@@ -83874,8 +84538,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
SrcList *pTabList, /* A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
- u8 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
- int regRowSet /* Register hold RowSet if WHERE_FILL_ROWSET is set */
+ u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
){
int i; /* Loop counter */
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
@@ -83889,7 +84552,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
int iFrom; /* First unused FROM clause element */
int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */
sqlite3 *db; /* Database connection */
- ExprList *pOrderBy = 0;
/* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask
@@ -83899,10 +84561,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
return 0;
}
- if( ppOrderBy ){
- pOrderBy = *ppOrderBy;
- }
-
/* Allocate and initialize the WhereInfo structure that will become the
** return value. A single allocation is used to store the WhereInfo
** struct, the contents of WhereInfo.a[], the WhereClause structure
@@ -83924,7 +84582,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
- pWInfo->regRowSet = (wctrlFlags & WHERE_FILL_ROWSET) ? regRowSet : -1;
pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
pWInfo->wctrlFlags = wctrlFlags;
pMaskSet = (WhereMaskSet*)&pWC[1];
@@ -84011,8 +84668,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
memset(&bestPlan, 0, sizeof(bestPlan));
bestPlan.rCost = SQLITE_BIG_DBL;
for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){
- int doNotReorder; /* True if this table should not be reordered */
- WhereCost sCost; /* Cost information from bestIndex() */
+ int doNotReorder; /* True if this table should not be reordered */
+ WhereCost sCost; /* Cost information from best[Virtual]Index() */
+ ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
if( once && doNotReorder ) break;
@@ -84021,34 +84679,17 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( j==iFrom ) iFrom++;
continue;
}
+ pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
+
assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTabItem->pTab) ){
- sqlite3_index_info *pVtabIdx; /* Current virtual index */
- sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo;
- sCost.rCost = bestVirtualIndex(pParse, pWC, pTabItem, notReady,
- ppOrderBy ? *ppOrderBy : 0, i==0,
- ppIdxInfo);
- sCost.plan.wsFlags = WHERE_VIRTUALTABLE;
- sCost.plan.u.pVtabIdx = pVtabIdx = *ppIdxInfo;
- if( pVtabIdx && pVtabIdx->orderByConsumed ){
- sCost.plan.wsFlags = WHERE_VIRTUALTABLE | WHERE_ORDERBY;
- }
- sCost.plan.nEq = 0;
- /* (double)2 In case of SQLITE_OMIT_FLOATING_POINT... */
- if( (SQLITE_BIG_DBL/((double)2))<sCost.rCost ){
- /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
- ** inital value of lowestCost in this loop. If it is, then
- ** the (cost<lowestCost) test below will never be true.
- */
- /* (double)2 In case of SQLITE_OMIT_FLOATING_POINT... */
- sCost.rCost = (SQLITE_BIG_DBL/((double)2));
- }
+ sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
+ bestVirtualIndex(pParse, pWC, pTabItem, notReady, pOrderBy, &sCost, pp);
}else
#endif
{
- bestIndex(pParse, pWC, pTabItem, notReady,
- (i==0 && ppOrderBy) ? *ppOrderBy : 0, &sCost);
+ bestBtreeIndex(pParse, pWC, pTabItem, notReady, pOrderBy, &sCost);
}
if( once==0 || sCost.rCost<bestPlan.rCost ){
once = 1;
@@ -84093,7 +84734,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
}
WHERETRACE(("*** Optimizer Finished ***\n"));
- if( db->mallocFailed ){
+ if( pParse->nErr || db->mallocFailed ){
goto whereBeginError;
}
@@ -84276,7 +84917,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Generate loop termination code.
*/
- sqlite3ExprClearColumnCache(pParse, -1);
+ sqlite3ExprCacheClear(pParse);
for(i=pTabList->nSrc-1; i>=0; i--){
pLevel = &pWInfo->a[i];
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
@@ -84303,7 +84944,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLevel->iIdxCur>=0 ){
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
+ if( pLevel->op==OP_Return ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
+ }
sqlite3VdbeJumpHere(v, addr);
}
}
@@ -86513,6 +87158,8 @@ static void yy_reduce(
{
yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
+ yygotominor.yy0.quoted = 0;
+ yygotominor.yy0.dyn = 0;
}
break;
case 37: /* columnid ::= nm */
@@ -88329,10 +88976,12 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
assert( pParse->apVarExpr==0 );
enableLookaside = db->lookaside.bEnabled;
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
+ pParse->sLastToken.quoted = 1;
while( !db->mallocFailed && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = (u8*)&zSql[i];
assert( pParse->sLastToken.dyn==0 );
+ assert( pParse->sLastToken.quoted );
pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
i += pParse->sLastToken.n;
if( i>mxSqlLen ){
@@ -88551,7 +89200,7 @@ SQLITE_API int sqlite3_complete(const char *zSql){
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, },
/* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, },
- /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, },
+ /* 2 EXPLAIN: */ { 0, 2, 2, 1, 3, 1, 1, 1, },
/* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, },
/* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, },
/* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, },
@@ -88968,14 +89617,16 @@ SQLITE_API int sqlite3_initialize(void){
sqlite3GlobalConfig.inProgress = 1;
memset(pHash, 0, sizeof(sqlite3GlobalFunctions));
sqlite3RegisterGlobalFunctions();
- rc = sqlite3_os_init();
+ rc = sqlite3PcacheInitialize();
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_os_init();
+ }
if( rc==SQLITE_OK ){
- rc = sqlite3PcacheInitialize();
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
+ sqlite3GlobalConfig.isInit = 1;
}
sqlite3GlobalConfig.inProgress = 0;
- sqlite3GlobalConfig.isInit = (rc==SQLITE_OK ? 1 : 0);
}
sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
@@ -89017,18 +89668,20 @@ SQLITE_API int sqlite3_initialize(void){
** Undo the effects of sqlite3_initialize(). Must not be called while
** there are outstanding database connections or memory allocations or
** while any part of SQLite is otherwise in use in any thread. This
-** routine is not threadsafe. Not by a long shot.
+** routine is not threadsafe. But it is safe to invoke this routine
+** on when SQLite is already shut down. If SQLite is already shut down
+** when this routine is invoked, then this routine is a harmless no-op.
*/
SQLITE_API int sqlite3_shutdown(void){
- sqlite3GlobalConfig.isMallocInit = 0;
- sqlite3PcacheShutdown();
if( sqlite3GlobalConfig.isInit ){
+ sqlite3GlobalConfig.isMallocInit = 0;
+ sqlite3PcacheShutdown();
sqlite3_os_end();
+ sqlite3_reset_auto_extension();
+ sqlite3MallocEnd();
+ sqlite3MutexEnd();
+ sqlite3GlobalConfig.isInit = 0;
}
- sqlite3_reset_auto_extension();
- sqlite3MallocEnd();
- sqlite3MutexEnd();
- sqlite3GlobalConfig.isInit = 0;
return SQLITE_OK;
}
@@ -89540,37 +90193,41 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){
** argument.
*/
SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
- const char *z;
- switch( rc & 0xff ){
- case SQLITE_ROW:
- case SQLITE_DONE:
- case SQLITE_OK: z = "not an error"; break;
- case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
- case SQLITE_PERM: z = "access permission denied"; break;
- case SQLITE_ABORT: z = "callback requested query abort"; break;
- case SQLITE_BUSY: z = "database is locked"; break;
- case SQLITE_LOCKED: z = "database table is locked"; break;
- case SQLITE_NOMEM: z = "out of memory"; break;
- case SQLITE_READONLY: z = "attempt to write a readonly database"; break;
- case SQLITE_INTERRUPT: z = "interrupted"; break;
- case SQLITE_IOERR: z = "disk I/O error"; break;
- case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
- case SQLITE_FULL: z = "database or disk is full"; break;
- case SQLITE_CANTOPEN: z = "unable to open database file"; break;
- case SQLITE_EMPTY: z = "table contains no data"; break;
- case SQLITE_SCHEMA: z = "database schema has changed"; break;
- case SQLITE_TOOBIG: z = "String or BLOB exceeded size limit"; break;
- case SQLITE_CONSTRAINT: z = "constraint failed"; break;
- case SQLITE_MISMATCH: z = "datatype mismatch"; break;
- case SQLITE_MISUSE: z = "library routine called out of sequence";break;
- case SQLITE_NOLFS: z = "large file support is disabled"; break;
- case SQLITE_AUTH: z = "authorization denied"; break;
- case SQLITE_FORMAT: z = "auxiliary database format error"; break;
- case SQLITE_RANGE: z = "bind or column index out of range"; break;
- case SQLITE_NOTADB: z = "file is encrypted or is not a database";break;
- default: z = "unknown error"; break;
+ static const char* const aMsg[] = {
+ /* SQLITE_OK */ "not an error",
+ /* SQLITE_ERROR */ "SQL logic error or missing database",
+ /* SQLITE_INTERNAL */ 0,
+ /* SQLITE_PERM */ "access permission denied",
+ /* SQLITE_ABORT */ "callback requested query abort",
+ /* SQLITE_BUSY */ "database is locked",
+ /* SQLITE_LOCKED */ "database table is locked",
+ /* SQLITE_NOMEM */ "out of memory",
+ /* SQLITE_READONLY */ "attempt to write a readonly database",
+ /* SQLITE_INTERRUPT */ "interrupted",
+ /* SQLITE_IOERR */ "disk I/O error",
+ /* SQLITE_CORRUPT */ "database disk image is malformed",
+ /* SQLITE_NOTFOUND */ 0,
+ /* SQLITE_FULL */ "database or disk is full",
+ /* SQLITE_CANTOPEN */ "unable to open database file",
+ /* SQLITE_PROTOCOL */ 0,
+ /* SQLITE_EMPTY */ "table contains no data",
+ /* SQLITE_SCHEMA */ "database schema has changed",
+ /* SQLITE_TOOBIG */ "String or BLOB exceeded size limit",
+ /* SQLITE_CONSTRAINT */ "constraint failed",
+ /* SQLITE_MISMATCH */ "datatype mismatch",
+ /* SQLITE_MISUSE */ "library routine called out of sequence",
+ /* SQLITE_NOLFS */ "large file support is disabled",
+ /* SQLITE_AUTH */ "authorization denied",
+ /* SQLITE_FORMAT */ "auxiliary database format error",
+ /* SQLITE_RANGE */ "bind or column index out of range",
+ /* SQLITE_NOTADB */ "file is encrypted or is not a database",
+ };
+ rc &= 0xff;
+ if( ALWAYS(rc>=0) && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){
+ return aMsg[rc];
+ }else{
+ return "unknown error";
}
- return z;
}
/*
@@ -89728,7 +90385,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
(!xFunc && (xFinal && !xStep)) ||
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
- (255<(nName = sqlite3Strlen(db, zFunctionName))) ){
+ (255<(nName = sqlite3Strlen30( zFunctionName))) ){
sqlite3Error(db, SQLITE_ERROR, "bad parameters");
return SQLITE_ERROR;
}
@@ -89854,7 +90511,7 @@ SQLITE_API int sqlite3_overload_function(
const char *zName,
int nArg
){
- int nName = sqlite3Strlen(db, zName);
+ int nName = sqlite3Strlen30(zName);
int rc;
sqlite3_mutex_enter(db->mutex);
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){
@@ -89964,6 +90621,39 @@ SQLITE_API void *sqlite3_rollback_hook(
}
/*
+** This function returns true if main-memory should be used instead of
+** a temporary file for transient pager files and statement journals.
+** The value returned depends on the value of db->temp_store (runtime
+** parameter) and the compile time value of SQLITE_TEMP_STORE. The
+** following table describes the relationship between these two values
+** and this functions return value.
+**
+** SQLITE_TEMP_STORE db->temp_store Location of temporary database
+** ----------------- -------------- ------------------------------
+** 0 any file (return 0)
+** 1 1 file (return 0)
+** 1 2 memory (return 1)
+** 1 0 file (return 0)
+** 2 1 file (return 0)
+** 2 2 memory (return 1)
+** 2 0 memory (return 1)
+** 3 any memory (return 1)
+*/
+SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){
+#if SQLITE_TEMP_STORE==1
+ return ( db->temp_store==2 );
+#endif
+#if SQLITE_TEMP_STORE==2
+ return ( db->temp_store!=1 );
+#endif
+#if SQLITE_TEMP_STORE==3
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+/*
** This routine is called to create a connection to a database BTree
** driver. If zFilename is the name of a file, then that file is
** opened and used. If zFilename is the magic name ":memory:" then
@@ -89973,20 +90663,8 @@ SQLITE_API void *sqlite3_rollback_hook(
** soon as the connection is closed.
**
** A virtual database can be either a disk file (that is automatically
-** deleted when the file is closed) or it an be held entirely in memory,
-** depending on the values of the SQLITE_TEMP_STORE compile-time macro and the
-** db->temp_store variable, according to the following chart:
-**
-** SQLITE_TEMP_STORE db->temp_store Location of temporary database
-** ----------------- -------------- ------------------------------
-** 0 any file
-** 1 1 file
-** 1 2 memory
-** 1 0 file
-** 2 1 file
-** 2 2 memory
-** 2 0 memory
-** 3 any memory
+** deleted when the file is closed) or it an be held entirely in memory.
+** The sqlite3TempInMemory() function is used to determine which.
*/
SQLITE_PRIVATE int sqlite3BtreeFactory(
const sqlite3 *db, /* Main database when opening aux otherwise 0 */
@@ -90007,22 +90685,11 @@ SQLITE_PRIVATE int sqlite3BtreeFactory(
if( db->flags & SQLITE_NoReadlock ){
btFlags |= BTREE_NO_READLOCK;
}
- if( zFilename==0 ){
-#if SQLITE_TEMP_STORE==0
- /* Do nothing */
-#endif
#ifndef SQLITE_OMIT_MEMORYDB
-#if SQLITE_TEMP_STORE==1
- if( db->temp_store==2 ) zFilename = ":memory:";
-#endif
-#if SQLITE_TEMP_STORE==2
- if( db->temp_store!=1 ) zFilename = ":memory:";
-#endif
-#if SQLITE_TEMP_STORE==3
+ if( zFilename==0 && sqlite3TempInMemory(db) ){
zFilename = ":memory:";
-#endif
-#endif /* SQLITE_OMIT_MEMORYDB */
}
+#endif
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
@@ -90158,11 +90825,13 @@ static int createCollation(
** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
*/
- enc2 = enc & ~SQLITE_UTF16_ALIGNED;
- if( enc2==SQLITE_UTF16 ){
+ enc2 = enc;
+ testcase( enc2==SQLITE_UTF16 );
+ testcase( enc2==SQLITE_UTF16_ALIGNED );
+ if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){
enc2 = SQLITE_UTF16NATIVE;
}
- if( (enc2&~3)!=0 ){
+ if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
return SQLITE_MISUSE;
}
@@ -90170,7 +90839,7 @@ static int createCollation(
** sequence. If so, and there are active VMs, return busy. If there
** are no active VMs, invalidate any pre-compiled statements.
*/
- nName = sqlite3Strlen(db, zName);
+ nName = sqlite3Strlen30(zName);
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, nName, 0);
if( pColl && pColl->xCmp ){
if( db->activeVdbeCnt ){
@@ -90307,6 +90976,7 @@ static int openDatabase(
CollSeq *pColl;
int isThreadsafe;
+ *ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ) return rc;
@@ -90366,9 +91036,9 @@ static int openDatabase(
| SQLITE_LoadExtension
#endif
;
- sqlite3HashInit(&db->aCollSeq, 0);
+ sqlite3HashInit(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3HashInit(&db->aModule, 0);
+ sqlite3HashInit(&db->aModule);
#endif
db->pVfs = sqlite3_vfs_find(zVfs);
diff --git a/ext/sqlite3/libsqlite/sqlite3.h b/ext/sqlite3/libsqlite/sqlite3.h
index 9c3e00babd..d56dd07cb0 100644
--- a/ext/sqlite3/libsqlite/sqlite3.h
+++ b/ext/sqlite3/libsqlite/sqlite3.h
@@ -99,8 +99,8 @@ extern "C" {
**
** Requirements: [H10011] [H10014]
*/
-#define SQLITE_VERSION "3.6.13"
-#define SQLITE_VERSION_NUMBER 3006013
+#define SQLITE_VERSION "3.6.14"
+#define SQLITE_VERSION_NUMBER 3006014
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -791,6 +791,11 @@ struct sqlite3_vfs {
** of sqlite3_initialize() does any initialization. All other calls
** are harmless no-ops.
**
+** A call to sqlite3_shutdown() is an "effective" call if it is the first
+** call to sqlite3_shutdown() since the last sqlite3_initialize(). Only
+** an effective call to sqlite3_shutdown() does any deinitialization.
+** All other calls to sqlite3_shutdown() are harmless no-ops.
+**
** Among other things, sqlite3_initialize() shall invoke
** sqlite3_os_init(). Similarly, sqlite3_shutdown()
** shall invoke sqlite3_os_end().
@@ -1218,14 +1223,18 @@ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** triggers are not counted. Use the [sqlite3_total_changes()] function
** to find the total number of changes including changes caused by triggers.
**
+** Changes to a view that are simulated by an [INSTEAD OF trigger]
+** are not counted. Only real table changes are counted.
+**
** A "row change" is a change to a single row of a single table
** caused by an INSERT, DELETE, or UPDATE statement. Rows that
-** are changed as side effects of REPLACE constraint resolution,
-** rollback, ABORT processing, DROP TABLE, or by any other
+** are changed as side effects of [REPLACE] constraint resolution,
+** rollback, ABORT processing, [DROP TABLE], or by any other
** mechanisms do not count as direct row changes.
**
** A "trigger context" is a scope of execution that begins and
-** ends with the script of a trigger. Most SQL statements are
+** ends with the script of a [CREATE TRIGGER | trigger].
+** Most SQL statements are
** evaluated outside of any trigger. This is the "top level"
** trigger context. If a trigger fires from the top level, a
** new trigger context is entered for the duration of that one
@@ -1247,16 +1256,8 @@ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** However, the number returned does not include changes
** caused by subtriggers since those have their own context.
**
-** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. Doing so is much faster than going
-** through and deleting individual elements from the table. Because of this
-** optimization, the deletions in "DELETE FROM table" are not row changes and
-** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
-** functions, regardless of the number of elements that were originally
-** in the table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead. Or recompile using the
-** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the
-** optimization on all queries.
+** See also the [sqlite3_total_changes()] interface and the
+** [count_changes pragma].
**
** Requirements:
** [H12241] [H12243]
@@ -1270,27 +1271,21 @@ int sqlite3_changes(sqlite3*);
/*
** CAPI3REF: Total Number Of Rows Modified {H12260} <S10600>
**
-** This function returns the number of row changes caused by INSERT,
-** UPDATE or DELETE statements since the [database connection] was opened.
-** The count includes all changes from all trigger contexts. However,
-** the count does not include changes used to implement REPLACE constraints,
-** do rollbacks or ABORT processing, or DROP table processing.
+** This function returns the number of row changes caused by [INSERT],
+** [UPDATE] or [DELETE] statements since the [database connection] was opened.
+** The count includes all changes from all
+** [CREATE TRIGGER | trigger] contexts. However,
+** the count does not include changes used to implement [REPLACE] constraints,
+** do rollbacks or ABORT processing, or [DROP TABLE] processing. The
+** count does not rows of views that fire an [INSTEAD OF trigger], though if
+** the INSTEAD OF trigger makes changes of its own, those changes are
+** counted.
** The changes are counted as soon as the statement that makes them is
** completed (when the statement handle is passed to [sqlite3_reset()] or
** [sqlite3_finalize()]).
**
-** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. (This is much faster than going
-** through and deleting individual elements from the table.) Because of this
-** optimization, the deletions in "DELETE FROM table" are not row changes and
-** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
-** functions, regardless of the number of elements that were originally
-** in the table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead. Or recompile using the
-** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the
-** optimization on all queries.
-**
-** See also the [sqlite3_changes()] interface.
+** See also the [sqlite3_changes()] interface and the
+** [count_changes pragma].
**
** Requirements:
** [H12261] [H12263]
@@ -1324,8 +1319,16 @@ int sqlite3_total_changes(sqlite3*);
** that is inside an explicit transaction, then the entire transaction
** will be rolled back automatically.
**
-** A call to sqlite3_interrupt() has no effect on SQL statements
-** that are started after sqlite3_interrupt() returns.
+** The sqlite3_interrupt(D) call is in effect until all currently running
+** SQL statements on [database connection] D complete. Any new SQL statements
+** that are started after the sqlite3_interrupt() call and before the
+** running statements reaches zero are interrupted as if they had been
+** running prior to the sqlite3_interrupt() call. New SQL statements
+** that are started after the running statement count reaches zero are
+** not effected by the sqlite3_interrupt().
+** A call to sqlite3_interrupt(D) that occurs when there are no running
+** SQL statements is a no-op and has no effect on SQL statements
+** that are started after the sqlite3_interrupt() call returns.
**
** Requirements:
** [H12271] [H12272]
@@ -1338,20 +1341,30 @@ void sqlite3_interrupt(sqlite3*);
/*
** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} <S70200>
**
-** These routines are useful for command-line input to determine if the
-** currently entered text seems to form complete a SQL statement or
+** These routines are useful during command-line input to determine if the
+** currently entered text seems to form a complete SQL statement or
** if additional input is needed before sending the text into
-** SQLite for parsing. These routines return true if the input string
+** SQLite for parsing. These routines return 1 if the input string
** appears to be a complete SQL statement. A statement is judged to be
-** complete if it ends with a semicolon token and is not a fragment of a
-** CREATE TRIGGER statement. Semicolons that are embedded within
+** complete if it ends with a semicolon token and is not a prefix of a
+** well-formed CREATE TRIGGER statement. Semicolons that are embedded within
** string literals or quoted identifier names or comments are not
** independent tokens (they are part of the token in which they are
-** embedded) and thus do not count as a statement terminator.
+** embedded) and thus do not count as a statement terminator. Whitespace
+** and comments that follow the final semicolon are ignored.
+**
+** These routines return 0 if the statement is incomplete. If a
+** memory allocation fails, then SQLITE_NOMEM is returned.
**
** These routines do not parse the SQL statements thus
** will not detect syntactically incorrect SQL.
**
+** If SQLite has not been initialized using [sqlite3_initialize()] prior
+** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
+** automatically by sqlite3_complete16(). If that initialization fails,
+** then the return value from sqlite3_complete16() will be non-zero
+** regardless of whether or not the input SQL is complete.
+**
** Requirements: [H10511] [H10512]
**
** The input to [sqlite3_complete()] must be a zero-terminated
@@ -1779,13 +1792,7 @@ void sqlite3_randomness(int N, void *P);
** requested is ok. When the callback returns [SQLITE_DENY], the
** [sqlite3_prepare_v2()] or equivalent call that triggered the
** authorizer will fail with an error message explaining that
-** access is denied. If the authorizer code is [SQLITE_READ]
-** and the callback returns [SQLITE_IGNORE] then the
-** [prepared statement] statement is constructed to substitute
-** a NULL value in place of the table column that would have
-** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
-** return can be used to deny an untrusted user access to individual
-** columns of a table.
+** access is denied.
**
** The first parameter to the authorizer callback is a copy of the third
** parameter to the sqlite3_set_authorizer() interface. The second parameter
@@ -1794,6 +1801,17 @@ void sqlite3_randomness(int N, void *P);
** to the callback are zero-terminated strings that contain additional
** details about the action to be authorized.
**
+** If the action code is [SQLITE_READ]
+** and the callback returns [SQLITE_IGNORE] then the
+** [prepared statement] statement is constructed to substitute
+** a NULL value in place of the table column that would have
+** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
+** return can be used to deny an untrusted user access to individual
+** columns of a table.
+** If the action code is [SQLITE_DELETE] and the callback returns
+** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
+** [truncate optimization] is disabled and all rows are deleted individually.
+**
** An authorizer is used when [sqlite3_prepare | preparing]
** SQL statements from an untrusted source, to ensure that the SQL statements
** do not try to access data they are not allowed to see, or that they do not
@@ -1827,7 +1845,9 @@ void sqlite3_randomness(int N, void *P);
**
** Note that the authorizer callback is invoked only during
** [sqlite3_prepare()] or its variants. Authorization is not
-** performed during statement evaluation in [sqlite3_step()].
+** performed during statement evaluation in [sqlite3_step()], unless
+** as stated in the previous paragraph, sqlite3_step() invokes
+** sqlite3_prepare_v2() to reprepare a statement after a schema change.
**
** Requirements:
** [H12501] [H12502] [H12503] [H12504] [H12505] [H12506] [H12507] [H12510]
@@ -3483,12 +3503,14 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n);
** the name is passed as the second function argument.
**
** The third argument may be one of the constants [SQLITE_UTF8],
-** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied
+** [SQLITE_UTF16LE], or [SQLITE_UTF16BE], indicating that the user-supplied
** routine expects to be passed pointers to strings encoded using UTF-8,
** UTF-16 little-endian, or UTF-16 big-endian, respectively. The
-** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that
+** third argument might also be [SQLITE_UTF16] to indicate that the routine
+** expects pointers to be UTF-16 strings in the native byte order, or the
+** argument can be [SQLITE_UTF16_ALIGNED] if the
** the routine expects pointers to 16-bit word aligned strings
-** of UTF-16 in the native byte order of the host computer.
+** of UTF-16 in the native byte order.
**
** A pointer to the user supplied routine must be passed as the fifth
** argument. If it is NULL, this is the same as deleting the collation
@@ -3513,6 +3535,8 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n);
** collation creation functions or when the [database connection] is closed
** using [sqlite3_close()].
**
+** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
+**
** Requirements:
** [H16603] [H16604] [H16606] [H16609] [H16612] [H16615] [H16618] [H16621]
** [H16624] [H16627] [H16630]
@@ -4066,15 +4090,20 @@ typedef struct sqlite3_module sqlite3_module;
/*
** CAPI3REF: Virtual Table Object {H18000} <S20400>
-** KEYWORDS: sqlite3_module
+** KEYWORDS: sqlite3_module {virtual table module}
** EXPERIMENTAL
**
-** A module is a class of virtual tables. Each module is defined
-** by an instance of the following structure. This structure consists
-** mostly of methods for the module.
+** This structure, sometimes called a a "virtual table module",
+** defines the implementation of a [virtual tables].
+** This structure consists mostly of methods for the module.
**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
+** A virtual table module is created by filling in a persistent
+** instance of this structure and passing a pointer to that instance
+** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
+** The registration remains valid until it is replaced by a different
+** module or until the [database connection] closes. The content
+** of this structure must not change while it is registered with
+** any database connection.
*/
struct sqlite3_module {
int iVersion;
@@ -4112,8 +4141,8 @@ struct sqlite3_module {
** EXPERIMENTAL
**
** The sqlite3_index_info structure and its substructures is used to
-** pass information into and receive the reply from the xBestIndex
-** method of an sqlite3_module. The fields under **Inputs** are the
+** pass information into and receive the reply from the [xBestIndex]
+** method of a [virtual table module]. The fields under **Inputs** are the
** inputs to xBestIndex and are read-only. xBestIndex inserts its
** results into the **Outputs** fields.
**
@@ -4136,17 +4165,19 @@ struct sqlite3_module {
** Information about the ORDER BY clause is stored in aOrderBy[].
** Each term of aOrderBy records a column of the ORDER BY clause.
**
-** The xBestIndex method must fill aConstraintUsage[] with information
+** The [xBestIndex] method must fill aConstraintUsage[] with information
** about what parameters to pass to xFilter. If argvIndex>0 then
** the right-hand side of the corresponding aConstraint[] is evaluated
** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit
** is true, then the constraint is assumed to be fully handled by the
** virtual table and is not checked again by SQLite.
**
-** The idxNum and idxPtr values are recorded and passed into xFilter.
-** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true.
+** The idxNum and idxPtr values are recorded and passed into the
+** [xFilter] method.
+** [sqlite3_free()] is used to free idxPtr if and only iff
+** needToFreeIdxPtr is true.
**
-** The orderByConsumed means that output from xFilter will occur in
+** The orderByConsumed means that output from [xFilter]/[xNext] will occur in
** the correct order to satisfy the ORDER BY clause so that no separate
** sorting step is required.
**
@@ -4154,9 +4185,6 @@ struct sqlite3_module {
** particular lookup. A full scan of a table with N entries should have
** a cost of N. A binary search of a table of N entries should have a
** cost of approximately log(N).
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
*/
struct sqlite3_index_info {
/* Inputs */
@@ -4194,34 +4222,44 @@ struct sqlite3_index_info {
** CAPI3REF: Register A Virtual Table Implementation {H18200} <S20400>
** EXPERIMENTAL
**
-** This routine is used to register a new module name with a
-** [database connection]. Module names must be registered before
-** creating new virtual tables on the module, or before using
-** preexisting virtual tables of the module.
+** This routine is used to register a new [virtual table module] name.
+** Module names must be registered before
+** creating a new [virtual table] using the module, or before using a
+** preexisting [virtual table] for the module.
+**
+** The module name is registered on the [database connection] specified
+** by the first parameter. The name of the module is given by the
+** second parameter. The third parameter is a pointer to
+** 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.
**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
+** This interface has exactly the same effect as calling
+** [sqlite3_create_module_v2()] with a NULL client data destructor.
*/
SQLITE_EXPERIMENTAL int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
- const sqlite3_module *, /* Methods for the module */
- void * /* Client data for xCreate/xConnect */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData /* Client data for xCreate/xConnect */
);
/*
** CAPI3REF: Register A Virtual Table Implementation {H18210} <S20400>
** EXPERIMENTAL
**
-** This routine is identical to the [sqlite3_create_module()] method above,
-** except that it allows a destructor function to be specified. It is
-** even more experimental than the rest of the virtual tables API.
+** This routine is identical to the [sqlite3_create_module()] method,
+** except that it has an extra parameter to specify
+** a destructor function for the client data pointer. SQLite will
+** invoke the destructor function (if it is not NULL) when SQLite
+** no longer needs the pClientData pointer.
*/
SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
- const sqlite3_module *, /* Methods for the module */
- void *, /* Client data for xCreate/xConnect */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData, /* Client data for xCreate/xConnect */
void(*xDestroy)(void*) /* Module destructor function */
);
@@ -4230,8 +4268,9 @@ SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
** KEYWORDS: sqlite3_vtab
** EXPERIMENTAL
**
-** Every module implementation uses a subclass of the following structure
-** to describe a particular instance of the module. Each subclass will
+** Every [virtual table module] implementation uses a subclass
+** of the following structure to describe a particular instance
+** of the [virtual table]. Each subclass will
** be tailored to the specific needs of the module implementation.
** The purpose of this superclass is to define certain fields that are
** common to all module implementations.
@@ -4241,13 +4280,7 @@ SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
** take care that any prior string is freed by a call to [sqlite3_free()]
** prior to assigning a new string to zErrMsg. After the error message
** is delivered up to the client application, the string will be automatically
-** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note
-** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field
-** since virtual tables are commonly implemented in loadable extensions which
-** do not have access to sqlite3MPrintf() or sqlite3Free().
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
+** freed by sqlite3_free() and the zErrMsg field will be zeroed.
*/
struct sqlite3_vtab {
const sqlite3_module *pModule; /* The module for this virtual table */
@@ -4258,20 +4291,21 @@ struct sqlite3_vtab {
/*
** CAPI3REF: Virtual Table Cursor Object {H18020} <S20400>
-** KEYWORDS: sqlite3_vtab_cursor
+** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
** EXPERIMENTAL
**
-** Every module implementation uses a subclass of the following structure
-** to describe cursors that point into the virtual table and are used
+** Every [virtual table module] implementation uses a subclass of the
+** following structure to describe cursors that point into the
+** [virtual table] and are used
** to loop through the virtual table. Cursors are created using the
-** xOpen method of the module. Each module implementation will define
+** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed
+** by the [sqlite3_module.xClose | xClose] method. Cussors are used
+** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
+** of the module. Each module implementation will define
** the content of a cursor structure to suit its own needs.
**
** This superclass exists in order to define fields of the cursor that
** are common to all implementations.
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
*/
struct sqlite3_vtab_cursor {
sqlite3_vtab *pVtab; /* Virtual table of this cursor */
@@ -4282,21 +4316,20 @@ struct sqlite3_vtab_cursor {
** CAPI3REF: Declare The Schema Of A Virtual Table {H18280} <S20400>
** EXPERIMENTAL
**
-** The xCreate and xConnect methods of a module use the following API
+** The [xCreate] and [xConnect] methods of a
+** [virtual table module] call this interface
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
-**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
*/
-SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
/*
** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
** EXPERIMENTAL
**
** Virtual tables can provide alternative implementations of functions
-** using the xFindFunction method. But global versions of those functions
+** using the [xFindFunction] method of the [virtual table module].
+** But global versions of those functions
** must exist in order to be overloaded.
**
** This API makes sure a global version of a function with a particular
@@ -4305,10 +4338,7 @@ SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable)
** of the new function always causes an exception to be thrown. So
** the new function is not good for anything by itself. Its only
** purpose is to be a placeholder function that can be overloaded
-** by virtual tables.
-**
-** This API should be considered part of the virtual table interface,
-** which is experimental and subject to change.
+** by a [virtual table].
*/
SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);